2019-04-09 06:52:20 +02:00
|
|
|
/*
|
|
|
|
* ws_cobra_to_statsd.cpp
|
|
|
|
* Author: Benjamin Sergeant
|
|
|
|
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
|
|
|
#include <chrono>
|
|
|
|
#include <thread>
|
|
|
|
#include <atomic>
|
|
|
|
#include <vector>
|
2019-04-21 20:20:17 +02:00
|
|
|
#include <ixcobra/IXCobraConnection.h>
|
2019-04-09 06:52:20 +02:00
|
|
|
|
2019-05-10 21:33:21 +02:00
|
|
|
#include <spdlog/spdlog.h>
|
2019-04-09 06:52:20 +02:00
|
|
|
|
2019-06-03 05:46:20 +02:00
|
|
|
#ifndef _WIN32
|
|
|
|
#include <statsd_client.h>
|
|
|
|
#endif
|
|
|
|
|
2019-04-09 06:52:20 +02:00
|
|
|
namespace ix
|
|
|
|
{
|
2019-04-12 01:03:05 +02:00
|
|
|
// fields are command line argument that can be specified multiple times
|
2019-04-09 06:52:20 +02:00
|
|
|
std::vector<std::string> parseFields(const std::string& fields)
|
|
|
|
{
|
|
|
|
std::vector<std::string> tokens;
|
|
|
|
|
|
|
|
// Split by \n
|
|
|
|
std::string token;
|
|
|
|
std::stringstream tokenStream(fields);
|
|
|
|
|
|
|
|
while (std::getline(tokenStream, token))
|
|
|
|
{
|
|
|
|
tokens.push_back(token);
|
|
|
|
}
|
|
|
|
|
|
|
|
return tokens;
|
|
|
|
}
|
|
|
|
|
2019-04-12 01:03:05 +02:00
|
|
|
//
|
|
|
|
// Extract an attribute from a Json Value.
|
|
|
|
// extractAttr("foo.bar", {"foo": {"bar": "baz"}}) => baz
|
|
|
|
//
|
2019-04-09 06:52:20 +02:00
|
|
|
std::string extractAttr(const std::string& attr,
|
|
|
|
const Json::Value& jsonValue)
|
|
|
|
{
|
|
|
|
// Split by .
|
|
|
|
std::string token;
|
|
|
|
std::stringstream tokenStream(attr);
|
|
|
|
|
|
|
|
Json::Value val(jsonValue);
|
|
|
|
|
|
|
|
while (std::getline(tokenStream, token, '.'))
|
|
|
|
{
|
|
|
|
val = val[token];
|
|
|
|
}
|
|
|
|
|
|
|
|
return val.asString();
|
|
|
|
}
|
|
|
|
|
|
|
|
int ws_cobra_to_statsd_main(const std::string& appkey,
|
|
|
|
const std::string& endpoint,
|
|
|
|
const std::string& rolename,
|
|
|
|
const std::string& rolesecret,
|
|
|
|
const std::string& channel,
|
2019-08-02 00:22:24 +02:00
|
|
|
const std::string& filter,
|
2019-04-09 06:52:20 +02:00
|
|
|
const std::string& host,
|
|
|
|
int port,
|
|
|
|
const std::string& prefix,
|
|
|
|
const std::string& fields,
|
|
|
|
bool verbose)
|
|
|
|
{
|
|
|
|
ix::CobraConnection conn;
|
|
|
|
conn.configure(appkey, endpoint,
|
|
|
|
rolename, rolesecret,
|
|
|
|
ix::WebSocketPerMessageDeflateOptions(true));
|
|
|
|
conn.connect();
|
|
|
|
|
|
|
|
auto tokens = parseFields(fields);
|
|
|
|
|
|
|
|
// statsd client
|
|
|
|
// test with netcat as a server: `nc -ul 8125`
|
2019-04-12 01:03:05 +02:00
|
|
|
bool statsdBatch = true;
|
2019-06-03 05:46:20 +02:00
|
|
|
#ifndef _WIN32
|
2019-04-12 01:03:05 +02:00
|
|
|
statsd::StatsdClient statsdClient(host, port, prefix, statsdBatch);
|
2019-06-03 05:46:20 +02:00
|
|
|
#else
|
|
|
|
int statsdClient;
|
|
|
|
#endif
|
2019-04-09 06:52:20 +02:00
|
|
|
|
|
|
|
Json::FastWriter jsonWriter;
|
|
|
|
uint64_t msgCount = 0;
|
|
|
|
|
|
|
|
conn.setEventCallback(
|
2019-08-02 00:22:24 +02:00
|
|
|
[&conn, &channel, &filter, &jsonWriter, &statsdClient, verbose, &tokens, &prefix, &msgCount]
|
2019-04-09 06:52:20 +02:00
|
|
|
(ix::CobraConnectionEventType eventType,
|
|
|
|
const std::string& errMsg,
|
|
|
|
const ix::WebSocketHttpHeaders& headers,
|
|
|
|
const std::string& subscriptionId)
|
|
|
|
{
|
|
|
|
if (eventType == ix::CobraConnection_EventType_Open)
|
|
|
|
{
|
2019-05-10 21:33:21 +02:00
|
|
|
spdlog::info("Subscriber connected");
|
2019-04-19 18:48:46 +02:00
|
|
|
|
|
|
|
for (auto it : headers)
|
|
|
|
{
|
2019-05-10 21:33:21 +02:00
|
|
|
spdlog::info("{}: {}", it.first, it.second);
|
2019-04-19 18:48:46 +02:00
|
|
|
}
|
2019-04-09 06:52:20 +02:00
|
|
|
}
|
2019-04-12 01:03:05 +02:00
|
|
|
if (eventType == ix::CobraConnection_EventType_Closed)
|
|
|
|
{
|
2019-05-10 21:33:21 +02:00
|
|
|
spdlog::info("Subscriber closed");
|
2019-04-12 01:03:05 +02:00
|
|
|
}
|
2019-04-09 06:52:20 +02:00
|
|
|
else if (eventType == ix::CobraConnection_EventType_Authenticated)
|
|
|
|
{
|
2019-05-10 21:33:21 +02:00
|
|
|
spdlog::info("Subscriber authenticated");
|
2019-08-02 00:22:24 +02:00
|
|
|
conn.subscribe(channel, filter,
|
2019-04-19 18:48:46 +02:00
|
|
|
[&jsonWriter, &statsdClient,
|
2019-04-09 06:52:20 +02:00
|
|
|
verbose, &tokens, &prefix, &msgCount]
|
|
|
|
(const Json::Value& msg)
|
|
|
|
{
|
|
|
|
if (verbose)
|
|
|
|
{
|
2019-05-10 21:33:21 +02:00
|
|
|
spdlog::info(jsonWriter.write(msg));
|
2019-04-09 06:52:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string id;
|
|
|
|
for (auto&& attr : tokens)
|
|
|
|
{
|
|
|
|
id += ".";
|
|
|
|
id += extractAttr(attr, msg);
|
|
|
|
}
|
|
|
|
|
2019-05-10 21:33:21 +02:00
|
|
|
spdlog::info("{} {}{}", msgCount++, prefix, id);
|
2019-04-09 06:52:20 +02:00
|
|
|
|
2019-06-03 05:46:20 +02:00
|
|
|
#ifndef _WIN32
|
2019-04-09 06:52:20 +02:00
|
|
|
statsdClient.count(id, 1);
|
2019-06-03 05:46:20 +02:00
|
|
|
#endif
|
2019-04-09 06:52:20 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
else if (eventType == ix::CobraConnection_EventType_Subscribed)
|
|
|
|
{
|
2019-05-10 21:33:21 +02:00
|
|
|
spdlog::info("Subscriber: subscribed to channel {}", subscriptionId);
|
2019-04-09 06:52:20 +02:00
|
|
|
}
|
|
|
|
else if (eventType == ix::CobraConnection_EventType_UnSubscribed)
|
|
|
|
{
|
2019-05-10 21:33:21 +02:00
|
|
|
spdlog::info("Subscriber: unsubscribed from channel {}", subscriptionId);
|
2019-04-09 06:52:20 +02:00
|
|
|
}
|
|
|
|
else if (eventType == ix::CobraConnection_EventType_Error)
|
|
|
|
{
|
2019-05-10 21:33:21 +02:00
|
|
|
spdlog::error("Subscriber: error {}", errMsg);
|
2019-04-09 06:52:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
2019-04-12 01:03:05 +02:00
|
|
|
std::chrono::duration<double, std::milli> duration(1000);
|
2019-04-09 06:52:20 +02:00
|
|
|
std::this_thread::sleep_for(duration);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|