Files
data-collection-terminal/opcua-expoter/main.cpp
2024-08-28 09:26:25 +08:00

145 lines
3.9 KiB
C++

#include <iostream>
#include <open62541/client.h>
#include <prometheus/exposer.h>
#include <prometheus/registry.h>
#include <prometheus/counter.h>
#include <spdlog/spdlog.h>
#include <yaml-cpp/yaml.h>
#include <CivetServer.h>
#include <string>
#include <filesystem>
#include "client/client.h"
#include "collector/collector.h"
class MetricsHandle : public CivetHandler {
public:
explicit MetricsHandle(std::shared_ptr<collector> coll) : coll_(coll) {
}
bool handleGet(CivetServer *server, struct mg_connection *conn) override {
std::string json = to_string(coll_->getMetricsJson());
mg_send_http_ok(conn, "application/json", json.size());
mg_write(conn, json.c_str(), json.size());
return true;
}
private:
std::shared_ptr<collector> coll_;
};
class SimulationHandle : public CivetHandler {
public:
explicit SimulationHandle(std::shared_ptr<collector> coll) : coll_(coll) {
}
bool handleGet(CivetServer *server, struct mg_connection *conn) override {
auto name = getMetric(conn);
auto context = to_string(coll_->simulationConfig(name));
mg_send_http_ok(conn, "application/json", context.size());
mg_write(conn, context.c_str(), context.size());
return true;
}
bool handlePost(CivetServer *server, struct mg_connection *conn) override {
auto name = getMetric(conn);
auto json = getPostJson(conn);
coll_->setSimulationConfig(name, json);
mg_send_http_ok(conn, "application/json", 0);
return true;
}
protected:
std::string getMetric(mg_connection *conn) {
const struct mg_request_info *req_info = mg_get_request_info(conn);
if (nullptr != req_info->query_string) {
return req_info->query_string;
}
return {};
}
nlohmann::json getPostJson(mg_connection *conn) {
const struct mg_request_info *req_info = mg_get_request_info(conn);
auto size = req_info->content_length + 1;
char *buff = new char[size];
mg_read(conn, buff, size);
auto ret = nlohmann::json::parse(buff, buff + size - 1, nullptr, false);
delete[] buff;
return ret;
}
private:
std::shared_ptr<collector> coll_;
};
int main(int argc, char *argv[]) {
mg_init_library(0);
spdlog::info("OPC-UA Exporter");
std::string config_file_name = "./opcua.yml";
#ifdef Debug
spdlog::set_level(spdlog::level::trace);
#endif
if (2 == argc) {
config_file_name = argv[1];
}
if (!std::filesystem::exists(config_file_name)) {
spdlog::error("the config file({}) not exists.", config_file_name);
return EXIT_FAILURE;
}
YAML::Node config = YAML::LoadFile(config_file_name);
auto exposer_bind_addr = config["exposer"]["bind"].as<std::string>("0.0.0.0:8090");
auto exposer_thread_num = config["exposer"]["thread"].as<std::size_t>(2);
spdlog::info("exposer bind addr : {}", exposer_bind_addr);
spdlog::info("exposer thread number : {}", exposer_thread_num);
prometheus::Exposer exposer{exposer_bind_addr, exposer_thread_num};
std::vector<std::string> civetOptions = {
{"listening_ports"},
{config["api"]["port"].as<std::string>("8080")}
};
CivetServer webServer(civetOptions);
auto ua_edp = config["opcua"]["endpoint"].as<std::string>();
if (ua_edp.empty()) {
spdlog::error("the opc ua endpoint not exists.");
return EXIT_FAILURE;
}
auto ua_client = std::make_shared<client>(ua_edp);
auto opc_collector = std::make_shared<collector>(config["metrics"], ua_client);
exposer.RegisterCollectable(opc_collector);
auto metricsHandle = MetricsHandle(opc_collector);
auto simulationHandle = SimulationHandle(opc_collector);
webServer.addHandler(
"/api/metrics",
metricsHandle
);
webServer.addHandler(
"/api/simulate",
simulationHandle
);
ua_client->run();
return 0;
}