new cobra to python bot (still sending to statsd)
values + string building can be done in python (we are embedding it)
This commit is contained in:
parent
c45b197c85
commit
615f1778c3
@ -2,7 +2,7 @@ FROM alpine:3.12 as build
|
|||||||
|
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
gcc g++ musl-dev linux-headers \
|
gcc g++ musl-dev linux-headers \
|
||||||
cmake mbedtls-dev make zlib-dev ninja
|
cmake mbedtls-dev make zlib-dev python3-dev ninja
|
||||||
|
|
||||||
RUN addgroup -S app && \
|
RUN addgroup -S app && \
|
||||||
adduser -S -G app app && \
|
adduser -S -G app app && \
|
||||||
@ -20,7 +20,7 @@ RUN make ws_mbedtls_install && \
|
|||||||
|
|
||||||
FROM alpine:3.12 as runtime
|
FROM alpine:3.12 as runtime
|
||||||
|
|
||||||
RUN apk add --no-cache libstdc++ mbedtls ca-certificates && \
|
RUN apk add --no-cache libstdc++ mbedtls ca-certificates python3 && \
|
||||||
addgroup -S app && \
|
addgroup -S app && \
|
||||||
adduser -S -G app app
|
adduser -S -G app app
|
||||||
|
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
All changes to this project will be documented in this file.
|
All changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
=======
|
||||||
|
## [9.8.2] - 2020-06-24
|
||||||
|
|
||||||
|
(cobra bots) new cobra metrics bot to send data to statsd using Python for processing the message
|
||||||
|
|
||||||
## [9.8.1] - 2020-06-19
|
## [9.8.1] - 2020-06-19
|
||||||
|
|
||||||
(cobra metrics to statsd bot) fps slow frame info : do not include os name
|
(cobra metrics to statsd bot) fps slow frame info : do not include os name
|
||||||
|
@ -10,6 +10,7 @@ set (IXBOTS_SOURCES
|
|||||||
ixbots/IXCobraToStdoutBot.cpp
|
ixbots/IXCobraToStdoutBot.cpp
|
||||||
ixbots/IXCobraMetricsToStatsdBot.cpp
|
ixbots/IXCobraMetricsToStatsdBot.cpp
|
||||||
ixbots/IXCobraMetricsToRedisBot.cpp
|
ixbots/IXCobraMetricsToRedisBot.cpp
|
||||||
|
ixbots/IXCobraToPythonBot.cpp
|
||||||
ixbots/IXStatsdClient.cpp
|
ixbots/IXStatsdClient.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,6 +22,7 @@ set (IXBOTS_HEADERS
|
|||||||
ixbots/IXCobraToStdoutBot.h
|
ixbots/IXCobraToStdoutBot.h
|
||||||
ixbots/IXCobraMetricsToStatsdBot.h
|
ixbots/IXCobraMetricsToStatsdBot.h
|
||||||
ixbots/IXCobraMetricsToRedisBot.h
|
ixbots/IXCobraMetricsToRedisBot.h
|
||||||
|
ixbots/IXCobraToPythonBot.h
|
||||||
ixbots/IXStatsdClient.h
|
ixbots/IXStatsdClient.h
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,6 +36,8 @@ if (NOT JSONCPP_FOUND)
|
|||||||
set(JSONCPP_INCLUDE_DIRS ../third_party/jsoncpp)
|
set(JSONCPP_INCLUDE_DIRS ../third_party/jsoncpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(Python COMPONENTS Development)
|
||||||
|
|
||||||
set(IXBOTS_INCLUDE_DIRS
|
set(IXBOTS_INCLUDE_DIRS
|
||||||
.
|
.
|
||||||
..
|
..
|
||||||
@ -43,6 +47,7 @@ set(IXBOTS_INCLUDE_DIRS
|
|||||||
../ixredis
|
../ixredis
|
||||||
../ixsentry
|
../ixsentry
|
||||||
${JSONCPP_INCLUDE_DIRS}
|
${JSONCPP_INCLUDE_DIRS}
|
||||||
${SPDLOG_INCLUDE_DIRS})
|
${SPDLOG_INCLUDE_DIRS}
|
||||||
|
${Python_INCLUDE_DIRS})
|
||||||
|
|
||||||
target_include_directories( ixbots PUBLIC ${IXBOTS_INCLUDE_DIRS} )
|
target_include_directories( ixbots PUBLIC ${IXBOTS_INCLUDE_DIRS} )
|
||||||
|
343
ixbots/ixbots/IXCobraToPythonBot.cpp
Normal file
343
ixbots/ixbots/IXCobraToPythonBot.cpp
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
/*
|
||||||
|
* IXCobraToPythonBot.cpp
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "IXCobraToPythonBot.h"
|
||||||
|
|
||||||
|
#include "IXCobraBot.h"
|
||||||
|
#include "IXStatsdClient.h"
|
||||||
|
#include <chrono>
|
||||||
|
#include <ixcobra/IXCobraConnection.h>
|
||||||
|
#include <ixcore/utils/IXCoreLogger.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
//
|
||||||
|
// I cannot get Windows to easily build on CI (github action) so support
|
||||||
|
// is disabled for now. It should be a simple fix
|
||||||
|
// (linking error about missing debug build)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#define PY_SSIZE_T_CLEAN
|
||||||
|
#include <Python.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// This function is unused at this point. It produce a correct output,
|
||||||
|
// but triggers memory leaks when called repeateadly, as the reference counting
|
||||||
|
// Python functions are not used properly
|
||||||
|
//
|
||||||
|
PyObject* jsonToPythonObject(const Json::Value& val)
|
||||||
|
{
|
||||||
|
switch(val.type())
|
||||||
|
{
|
||||||
|
case Json::nullValue:
|
||||||
|
{
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Json::intValue:
|
||||||
|
{
|
||||||
|
return PyLong_FromLong(val.asInt64());
|
||||||
|
}
|
||||||
|
|
||||||
|
case Json::uintValue:
|
||||||
|
{
|
||||||
|
return PyLong_FromLong(val.asUInt64());
|
||||||
|
}
|
||||||
|
|
||||||
|
case Json::realValue:
|
||||||
|
{
|
||||||
|
return PyFloat_FromDouble(val.asDouble());
|
||||||
|
}
|
||||||
|
|
||||||
|
case Json::stringValue:
|
||||||
|
{
|
||||||
|
return PyUnicode_FromString(val.asCString());
|
||||||
|
}
|
||||||
|
|
||||||
|
case Json::booleanValue:
|
||||||
|
{
|
||||||
|
return val.asBool() ? Py_True : Py_False;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Json::arrayValue:
|
||||||
|
{
|
||||||
|
PyObject* list = PyList_New(val.size());
|
||||||
|
Py_ssize_t i = 0;
|
||||||
|
for (auto&& it = val.begin(); it != val.end(); ++it)
|
||||||
|
{
|
||||||
|
PyList_SetItem(list, i++, jsonToPythonObject(*it));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Json::objectValue:
|
||||||
|
{
|
||||||
|
PyObject* dict = PyDict_New();
|
||||||
|
for (auto&& it = val.begin(); it != val.end(); ++it)
|
||||||
|
{
|
||||||
|
PyObject* key = jsonToPythonObject(it.key());
|
||||||
|
PyObject* value = jsonToPythonObject(*it);
|
||||||
|
|
||||||
|
PyDict_SetItem(dict, key, value);
|
||||||
|
}
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ix
|
||||||
|
{
|
||||||
|
int64_t cobra_to_python_bot(const ix::CobraBotConfig& config,
|
||||||
|
StatsdClient& statsdClient,
|
||||||
|
const std::string& scriptPath)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
CoreLogger::error("Command is disabled on Windows.");
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
|
CobraBot bot;
|
||||||
|
Py_InitializeEx(0); // 0 arg so that we do not install signal handlers
|
||||||
|
// which prevent us from using Ctrl-C
|
||||||
|
|
||||||
|
size_t lastIndex = scriptPath.find_last_of(".");
|
||||||
|
std::string modulePath = scriptPath.substr(0, lastIndex);
|
||||||
|
|
||||||
|
PyObject* pyModuleName = PyUnicode_DecodeFSDefault(modulePath.c_str());
|
||||||
|
|
||||||
|
if (pyModuleName == nullptr)
|
||||||
|
{
|
||||||
|
CoreLogger::error("Python error: Cannot decode file system path");
|
||||||
|
PyErr_Print();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import module
|
||||||
|
PyObject* pyModule = PyImport_Import(pyModuleName);
|
||||||
|
Py_DECREF(pyModuleName);
|
||||||
|
if (pyModule == nullptr)
|
||||||
|
{
|
||||||
|
CoreLogger::error("Python error: Cannot import module.");
|
||||||
|
CoreLogger::error("Module name cannot countain dash characters.");
|
||||||
|
CoreLogger::error("Is PYTHONPATH set correctly ?");
|
||||||
|
PyErr_Print();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// module main funtion name is named 'run'
|
||||||
|
const std::string entryPoint("run");
|
||||||
|
PyObject* pyFunc = PyObject_GetAttrString(pyModule, entryPoint.c_str());
|
||||||
|
|
||||||
|
if (!pyFunc)
|
||||||
|
{
|
||||||
|
CoreLogger::error("run symbol is missing from module.");
|
||||||
|
PyErr_Print();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PyCallable_Check(pyFunc))
|
||||||
|
{
|
||||||
|
CoreLogger::error("run symbol is not a function.");
|
||||||
|
PyErr_Print();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bot.setOnBotMessageCallback(
|
||||||
|
[&statsdClient, pyFunc]
|
||||||
|
(const Json::Value& msg,
|
||||||
|
const std::string& /*position*/,
|
||||||
|
std::atomic<bool>& /*throttled*/,
|
||||||
|
std::atomic<bool>& fatalCobraError,
|
||||||
|
std::atomic<uint64_t>& sentCount) -> void {
|
||||||
|
if (msg["device"].isNull())
|
||||||
|
{
|
||||||
|
CoreLogger::info("no device entry, skipping event");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg["id"].isNull())
|
||||||
|
{
|
||||||
|
CoreLogger::info("no id entry, skipping event");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Invoke python script here. First build function parameters, a tuple
|
||||||
|
//
|
||||||
|
const int kVersion = 1; // We can bump this and let the interface evolve
|
||||||
|
|
||||||
|
PyObject *pyArgs = PyTuple_New(2);
|
||||||
|
PyTuple_SetItem(pyArgs, 0, PyLong_FromLong(kVersion)); // First argument
|
||||||
|
|
||||||
|
//
|
||||||
|
// It would be better to create a Python object (a dictionary)
|
||||||
|
// from the json msg, but it is simpler to serialize it to a string
|
||||||
|
// and decode it on the Python side of the fence
|
||||||
|
//
|
||||||
|
PyObject* pySerializedJson = PyUnicode_FromString(msg.toStyledString().c_str());
|
||||||
|
PyTuple_SetItem(pyArgs, 1, pySerializedJson); // Second argument
|
||||||
|
|
||||||
|
// Invoke the python routine
|
||||||
|
PyObject* pyList = PyObject_CallObject(pyFunc, pyArgs);
|
||||||
|
|
||||||
|
// Error calling the function
|
||||||
|
if (pyList == nullptr)
|
||||||
|
{
|
||||||
|
fatalCobraError = true;
|
||||||
|
CoreLogger::error("run() function call failed. Input msg: ");
|
||||||
|
auto serializedMsg = msg.toStyledString();
|
||||||
|
CoreLogger::error(serializedMsg);
|
||||||
|
PyErr_Print();
|
||||||
|
CoreLogger::error("================");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalid return type
|
||||||
|
if (!PyList_Check(pyList))
|
||||||
|
{
|
||||||
|
fatalCobraError = true;
|
||||||
|
CoreLogger::error("run() return type should be a list");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The result is a list of dict containing sufficient info
|
||||||
|
// to send messages to statsd
|
||||||
|
auto listSize = PyList_Size(pyList);
|
||||||
|
|
||||||
|
for (Py_ssize_t i = 0 ; i < listSize; ++i)
|
||||||
|
{
|
||||||
|
PyObject* dict = PyList_GetItem(pyList, i);
|
||||||
|
|
||||||
|
// Make sure this is a dict
|
||||||
|
if (!PyDict_Check(dict))
|
||||||
|
{
|
||||||
|
fatalCobraError = true;
|
||||||
|
CoreLogger::error("list element is not a dict");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Retrieve object kind
|
||||||
|
//
|
||||||
|
PyObject* pyKind = PyDict_GetItemString(dict, "kind");
|
||||||
|
if (!PyUnicode_Check(pyKind))
|
||||||
|
{
|
||||||
|
fatalCobraError = true;
|
||||||
|
CoreLogger::error("kind entry is not a string");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string kind(PyUnicode_AsUTF8(pyKind));
|
||||||
|
|
||||||
|
bool counter = false;
|
||||||
|
bool gauge = false;
|
||||||
|
bool timing = false;
|
||||||
|
|
||||||
|
if (kind == "counter")
|
||||||
|
{
|
||||||
|
counter = true;
|
||||||
|
}
|
||||||
|
else if (kind == "gauge")
|
||||||
|
{
|
||||||
|
gauge = true;
|
||||||
|
}
|
||||||
|
else if (kind == "timing")
|
||||||
|
{
|
||||||
|
timing = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fatalCobraError = true;
|
||||||
|
CoreLogger::error(std::string("invalid kind entry: ") + kind +
|
||||||
|
". Supported ones are counter, gauge, timing");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Retrieve object key
|
||||||
|
//
|
||||||
|
PyObject* pyKey = PyDict_GetItemString(dict, "key");
|
||||||
|
if (!PyUnicode_Check(pyKey))
|
||||||
|
{
|
||||||
|
fatalCobraError = true;
|
||||||
|
CoreLogger::error("key entry is not a string");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string key(PyUnicode_AsUTF8(pyKey));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Retrieve object value and send data to statsd
|
||||||
|
//
|
||||||
|
PyObject* pyValue = PyDict_GetItemString(dict, "value");
|
||||||
|
|
||||||
|
// Send data to statsd
|
||||||
|
if (PyFloat_Check(pyValue))
|
||||||
|
{
|
||||||
|
double value = PyFloat_AsDouble(pyValue);
|
||||||
|
|
||||||
|
if (counter)
|
||||||
|
{
|
||||||
|
statsdClient.count(key, value);
|
||||||
|
}
|
||||||
|
else if (gauge)
|
||||||
|
{
|
||||||
|
statsdClient.gauge(key, value);
|
||||||
|
}
|
||||||
|
else if (timing)
|
||||||
|
{
|
||||||
|
statsdClient.timing(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (PyLong_Check(pyValue))
|
||||||
|
{
|
||||||
|
long value = PyLong_AsLong(pyValue);
|
||||||
|
|
||||||
|
if (counter)
|
||||||
|
{
|
||||||
|
statsdClient.count(key, value);
|
||||||
|
}
|
||||||
|
else if (gauge)
|
||||||
|
{
|
||||||
|
statsdClient.gauge(key, value);
|
||||||
|
}
|
||||||
|
else if (timing)
|
||||||
|
{
|
||||||
|
statsdClient.timing(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fatalCobraError = true;
|
||||||
|
CoreLogger::error("value entry is neither an int or a float");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sentCount++; // should we update this for each statsd object sent ?
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_DECREF(pyArgs);
|
||||||
|
Py_DECREF(pyList);
|
||||||
|
});
|
||||||
|
|
||||||
|
bool status = bot.run(config);
|
||||||
|
|
||||||
|
// Cleanup - we should do something similar in all exit case ...
|
||||||
|
Py_DECREF(pyFunc);
|
||||||
|
Py_DECREF(pyModule);
|
||||||
|
Py_FinalizeEx();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
19
ixbots/ixbots/IXCobraToPythonBot.h
Normal file
19
ixbots/ixbots/IXCobraToPythonBot.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* IXCobraMetricsToStatsdBot.h
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <ixbots/IXStatsdClient.h>
|
||||||
|
#include "IXCobraBotConfig.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ix
|
||||||
|
{
|
||||||
|
int64_t cobra_to_python_bot(const ix::CobraBotConfig& config,
|
||||||
|
StatsdClient& statsdClient,
|
||||||
|
const std::string& scriptPath);
|
||||||
|
} // namespace ix
|
@ -6,4 +6,4 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define IX_WEBSOCKET_VERSION "9.8.1"
|
#define IX_WEBSOCKET_VERSION "9.8.2"
|
||||||
|
4
makefile
4
makefile
@ -29,10 +29,10 @@ ws_mbedtls_install:
|
|||||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; ninja install)
|
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; ninja install)
|
||||||
|
|
||||||
ws:
|
ws:
|
||||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. ; ninja install)
|
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. && ninja install)
|
||||||
|
|
||||||
ws_install:
|
ws_install:
|
||||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. ; make -j 4 install)
|
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. && make -j 4 install)
|
||||||
|
|
||||||
ws_openssl:
|
ws_openssl:
|
||||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_OPEN_SSL=1 .. ; make -j 4)
|
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_OPEN_SSL=1 .. ; make -j 4)
|
||||||
|
@ -91,6 +91,15 @@ if (JSONCPP_FOUND)
|
|||||||
target_link_libraries(ixwebsocket_unittest ${JSONCPP_LIBRARIES})
|
target_link_libraries(ixwebsocket_unittest ${JSONCPP_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(Python COMPONENTS Development)
|
||||||
|
if (NOT Python_FOUND)
|
||||||
|
message(FATAL_ERROR "Python3 not found")
|
||||||
|
endif()
|
||||||
|
message("Python_FOUND:${Python_FOUND}")
|
||||||
|
message("Python_VERSION:${Python_VERSION}")
|
||||||
|
message("Python_Development_FOUND:${Python_Development_FOUND}")
|
||||||
|
message("Python_LIBRARIES:${Python_LIBRARIES}")
|
||||||
|
|
||||||
# library with the most dependencies come first
|
# library with the most dependencies come first
|
||||||
target_link_libraries(ixwebsocket_unittest ixbots)
|
target_link_libraries(ixwebsocket_unittest ixbots)
|
||||||
target_link_libraries(ixwebsocket_unittest ixsnake)
|
target_link_libraries(ixwebsocket_unittest ixsnake)
|
||||||
@ -102,5 +111,8 @@ target_link_libraries(ixwebsocket_unittest ixcrypto)
|
|||||||
target_link_libraries(ixwebsocket_unittest ixcore)
|
target_link_libraries(ixwebsocket_unittest ixcore)
|
||||||
|
|
||||||
target_link_libraries(ixwebsocket_unittest spdlog)
|
target_link_libraries(ixwebsocket_unittest spdlog)
|
||||||
|
if (NOT WIN32)
|
||||||
|
target_link_libraries(ixwebsocket_unittest ${Python_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
install(TARGETS ixwebsocket_unittest DESTINATION bin)
|
install(TARGETS ixwebsocket_unittest DESTINATION bin)
|
||||||
|
@ -32,6 +32,15 @@ if (NOT JSONCPP_FOUND)
|
|||||||
set(JSONCPP_SOURCES ../third_party/jsoncpp/jsoncpp.cpp)
|
set(JSONCPP_SOURCES ../third_party/jsoncpp/jsoncpp.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(Python COMPONENTS Development)
|
||||||
|
if (NOT Python_FOUND)
|
||||||
|
message(FATAL_ERROR "Python3 not found")
|
||||||
|
endif()
|
||||||
|
message("Python_FOUND:${Python_FOUND}")
|
||||||
|
message("Python_VERSION:${Python_VERSION}")
|
||||||
|
message("Python_Development_FOUND:${Python_Development_FOUND}")
|
||||||
|
message("Python_LIBRARIES:${Python_LIBRARIES}")
|
||||||
|
|
||||||
add_executable(ws
|
add_executable(ws
|
||||||
../third_party/msgpack11/msgpack11.cpp
|
../third_party/msgpack11/msgpack11.cpp
|
||||||
../third_party/cpp-linenoise/linenoise.cpp
|
../third_party/cpp-linenoise/linenoise.cpp
|
||||||
@ -71,6 +80,9 @@ target_link_libraries(ws ixcrypto)
|
|||||||
target_link_libraries(ws ixcore)
|
target_link_libraries(ws ixcore)
|
||||||
|
|
||||||
target_link_libraries(ws spdlog)
|
target_link_libraries(ws spdlog)
|
||||||
|
if (NOT WIN32)
|
||||||
|
target_link_libraries(ws ${Python_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
if (JSONCPP_FOUND)
|
if (JSONCPP_FOUND)
|
||||||
target_include_directories(ws PUBLIC ${JSONCPP_INCLUDE_DIRS})
|
target_include_directories(ws PUBLIC ${JSONCPP_INCLUDE_DIRS})
|
||||||
|
29
ws/ws.cpp
29
ws/ws.cpp
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <cli11/CLI11.hpp>
|
#include <cli11/CLI11.hpp>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <ixbots/IXCobraToPythonBot.h>
|
||||||
#include <ixbots/IXCobraToSentryBot.h>
|
#include <ixbots/IXCobraToSentryBot.h>
|
||||||
#include <ixbots/IXCobraToStatsdBot.h>
|
#include <ixbots/IXCobraToStatsdBot.h>
|
||||||
#include <ixbots/IXCobraToStdoutBot.h>
|
#include <ixbots/IXCobraToStdoutBot.h>
|
||||||
@ -121,6 +122,7 @@ int main(int argc, char** argv)
|
|||||||
std::string project;
|
std::string project;
|
||||||
std::string key;
|
std::string key;
|
||||||
std::string logfile;
|
std::string logfile;
|
||||||
|
std::string scriptPath;
|
||||||
ix::SocketTLSOptions tlsOptions;
|
ix::SocketTLSOptions tlsOptions;
|
||||||
ix::CobraConfig cobraConfig;
|
ix::CobraConfig cobraConfig;
|
||||||
ix::CobraBotConfig cobraBotConfig;
|
ix::CobraBotConfig cobraBotConfig;
|
||||||
@ -352,6 +354,16 @@ int main(int argc, char** argv)
|
|||||||
addTLSOptions(cobra2statsd);
|
addTLSOptions(cobra2statsd);
|
||||||
addCobraBotConfig(cobra2statsd);
|
addCobraBotConfig(cobra2statsd);
|
||||||
|
|
||||||
|
CLI::App* cobra2python = app.add_subcommand("cobra_to_python", "Cobra to python");
|
||||||
|
cobra2python->fallthrough();
|
||||||
|
cobra2python->add_option("--host", hostname, "Statsd host");
|
||||||
|
cobra2python->add_option("--port", statsdPort, "Statsd port");
|
||||||
|
cobra2python->add_option("--prefix", prefix, "Statsd prefix");
|
||||||
|
cobra2python->add_option("--script", scriptPath, "Python script path")->check(CLI::ExistingPath);
|
||||||
|
cobra2python->add_option("--pidfile", pidfile, "Pid file");
|
||||||
|
addTLSOptions(cobra2python);
|
||||||
|
addCobraBotConfig(cobra2python);
|
||||||
|
|
||||||
CLI::App* cobraMetrics2statsd = app.add_subcommand("cobra_metrics_to_statsd", "Cobra metrics to statsd");
|
CLI::App* cobraMetrics2statsd = app.add_subcommand("cobra_metrics_to_statsd", "Cobra metrics to statsd");
|
||||||
cobraMetrics2statsd->fallthrough();
|
cobraMetrics2statsd->fallthrough();
|
||||||
cobraMetrics2statsd->add_option("--host", hostname, "Statsd host");
|
cobraMetrics2statsd->add_option("--host", hostname, "Statsd host");
|
||||||
@ -590,6 +602,23 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (app.got_subcommand("cobra_to_python"))
|
||||||
|
{
|
||||||
|
ix::StatsdClient statsdClient(hostname, statsdPort, prefix, verbose);
|
||||||
|
|
||||||
|
std::string errMsg;
|
||||||
|
bool initialized = statsdClient.init(errMsg);
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
spdlog::error(errMsg);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = (int) ix::cobra_to_python_bot(
|
||||||
|
cobraBotConfig, statsdClient, scriptPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (app.got_subcommand("cobra_metrics_to_statsd"))
|
else if (app.got_subcommand("cobra_metrics_to_statsd"))
|
||||||
{
|
{
|
||||||
ix::StatsdClient statsdClient(hostname, statsdPort, prefix, verbose);
|
ix::StatsdClient statsdClient(hostname, statsdPort, prefix, verbose);
|
||||||
|
Loading…
Reference in New Issue
Block a user