Просмотр исходного кода

Add a Google Cloud Pub/Sub connector to the exporting engine (#8855)

* Implement formatters

* Add specific configuration options

* Add the connector to the Autotools and CMake configuration

* Initialize a connector instance

* Publish netdata metrics

* Fix internal stats

* Add unit tests

* Improve the documentation
Vladimir Kobal 4 лет назад
Родитель
Сommit
b5f8c224a9

+ 56 - 1
CMakeLists.txt

@@ -252,6 +252,23 @@ find_library(HAVE_KINESIS aws-cpp-sdk-kinesis)
 # later we use:
 # ${HAVE_KINESIS}
 
+# -----------------------------------------------------------------------------
+# Detect libgrpc
+
+pkg_check_modules(GRPC grpc)
+# later we use:
+# ${GRPCF_LIBRARIES}
+# ${GRPC_CFLAGS_OTHER}
+# ${GRPC_INCLUDE_DIRS}
+
+# -----------------------------------------------------------------------------
+# Detect libgoogleapis_cpp_pubsub_protos
+
+pkg_check_modules(PUBSUB googleapis_cpp_pubsub_protos)
+# later we use:
+# ${PUBSUB_LIBRARIES}
+# ${PUBSUB_CFLAGS_OTHER}
+# ${PUBSUB_INCLUDE_DIRS}
 
 # -----------------------------------------------------------------------------
 # Detect libprotobuf
@@ -662,6 +679,13 @@ set(KINESIS_EXPORTING_FILES
         exporting/aws_kinesis/aws_kinesis_put_record.h
         )
 
+set(PUBSUB_EXPORTING_FILES
+        exporting/pubsub/pubsub.c
+        exporting/pubsub/pubsub.h
+        exporting/pubsub/pubsub_publish.cc
+        exporting/pubsub/pubsub_publish.h
+        )
+
 set(MONGODB_EXPORTING_FILES
         exporting/mongodb/mongodb.c
         exporting/mongodb/mongodb.h
@@ -758,6 +782,25 @@ ELSE()
     message(STATUS "kinesis backend: disabled (requires AWS SDK for C++)")
 ENDIF()
 
+# -----------------------------------------------------------------------------
+# Pub/Sub exporting connector
+
+IF(GRPC_LIBRARIES AND PUBSUB_LIBRARIES)
+    SET(ENABLE_EXPORTING_PUBSUB True)
+ELSE()
+    SET(ENABLE_EXPORTING_PUBSUB False)
+ENDIF()
+
+IF(ENABLE_EXPORTING_PUBSUB)
+    message(STATUS "pubsub exporting connector: enabled")
+    list(APPEND NETDATA_FILES ${PUBSUB_EXPORTING_FILES})
+    list(APPEND NETDATA_COMMON_LIBRARIES ${GRPC_LIBRARIES} ${PUBSUB_LIBRARIES})
+    list(APPEND NETDATA_COMMON_INCLUDE_DIRS ${GRPC_INCLUDE_DIRS} ${PUBSUB_INCLUDE_DIRS})
+    list(APPEND NETDATA_COMMON_CFLAGS ${GRPC_CFLAGS_OTHER} ${PUBSUB_CFLAGS_OTHER})
+ELSE()
+    message(STATUS "pubsub exporting connector: disabled (requires grpc and googleapis)")
+ENDIF()
+
 # -----------------------------------------------------------------------------
 # prometheus remote write backend
 
@@ -867,7 +910,7 @@ ELSEIF(MACOS)
 
 ENDIF()
 
-IF(ENABLE_BACKEND_KINESIS OR ENABLE_BACKEND_PROMETHEUS_REMOTE_WRITE)
+IF(ENABLE_BACKEND_KINESIS OR ENABLE_EXPORTING_PUBSUB OR ENABLE_BACKEND_PROMETHEUS_REMOTE_WRITE)
     set_property(TARGET netdata PROPERTY CXX_STANDARD 11)
     set_property(TARGET netdata PROPERTY CMAKE_CXX_STANDARD_REQUIRED ON)
 ENDIF()
@@ -1040,6 +1083,7 @@ if(BUILD_TESTING)
     set(TEST_NAME exporting_engine)
     set(PROMETHEUS_REMOTE_WRITE_LINK_OPTIONS)
     set(KINESIS_LINK_OPTIONS)
+    set(PUBSUB_LINK_OPTIONS)
     set(MONGODB_LINK_OPTIONS)
 if(ENABLE_BACKEND_PROMETHEUS_REMOTE_WRITE)
     list(APPEND EXPORTING_ENGINE_FILES ${PROMETHEUS_REMOTE_WRITE_EXPORTING_FILES} ${PROTO_SRCS} ${PROTO_HDRS})
@@ -1061,6 +1105,16 @@ if(ENABLE_BACKEND_KINESIS)
         -Wl,--wrap=kinesis_get_result
     )
 endif()
+if(ENABLE_EXPORTING_PUBSUB)
+    list(APPEND EXPORTING_ENGINE_FILES ${PUBSUB_EXPORTING_FILES})
+    list(
+        APPEND PUBSUB_LINK_OPTIONS
+        -Wl,--wrap=pubsub_init
+        -Wl,--wrap=pubsub_add_message
+        -Wl,--wrap=pubsub_publish
+        -Wl,--wrap=pubsub_get_result
+    )
+endif()
 if(MONGOC_LIBRARIES)
     list(APPEND EXPORTING_ENGINE_FILES ${MONGODB_EXPORTING_FILES})
     list(
@@ -1116,6 +1170,7 @@ endif()
         -Wl,--wrap=send_main_rusage
         ${PROMETHEUS_REMOTE_WRITE_LINK_OPTIONS}
         ${KINESIS_LINK_OPTIONS}
+        ${PUBSUB_LINK_OPTIONS}
         ${MONGODB_LINK_OPTIONS}
     )
     target_link_libraries(${TEST_NAME}_testdriver libnetdata ${NETDATA_COMMON_LIBRARIES} ${CMOCKA_LIBRARIES})

+ 22 - 0
Makefile.am

@@ -531,6 +531,13 @@ KINESIS_EXPORTING_FILES = \
     exporting/aws_kinesis/aws_kinesis_put_record.h \
     $(NULL)
 
+PUBSUB_EXPORTING_FILES = \
+    exporting/pubsub/pubsub.c \
+    exporting/pubsub/pubsub.h \
+    exporting/pubsub/pubsub_publish.cc \
+    exporting/pubsub/pubsub_publish.h \
+    $(NULL)
+
 MONGODB_EXPORTING_FILES = \
     exporting/mongodb/mongodb.c \
     exporting/mongodb/mongodb.h \
@@ -752,6 +759,11 @@ if ENABLE_BACKEND_KINESIS
     netdata_LDADD += $(OPTIONAL_KINESIS_LIBS)
 endif
 
+if ENABLE_EXPORTING_PUBSUB
+    netdata_SOURCES += $(PUBSUB_EXPORTING_FILES)
+    netdata_LDADD += $(OPTIONAL_PUBSUB_LIBS)
+endif
+
 if ENABLE_BACKEND_PROMETHEUS_REMOTE_WRITE
     netdata_SOURCES += $(PROMETHEUS_REMOTE_WRITE_BACKEND_FILES) $(PROMETHEUS_REMOTE_WRITE_EXPORTING_FILES)
     netdata_LDADD += $(OPTIONAL_PROMETHEUS_REMOTE_WRITE_LIBS)
@@ -906,6 +918,16 @@ if ENABLE_BACKEND_KINESIS
         -Wl,--wrap=kinesis_get_result \
         $(NULL)
 endif
+if ENABLE_EXPORTING_PUBSUB
+    exporting_tests_exporting_engine_testdriver_SOURCES += $(PUBSUB_EXPORTING_FILES)
+    exporting_tests_exporting_engine_testdriver_LDADD += $(OPTIONAL_PUBSUB_LIBS)
+    exporting_tests_exporting_engine_testdriver_LDFLAGS += \
+        -Wl,--wrap=pubsub_init \
+        -Wl,--wrap=pubsub_add_message \
+        -Wl,--wrap=pubsub_publish \
+        -Wl,--wrap=pubsub_get_result \
+        $(NULL)
+endif
 if ENABLE_BACKEND_MONGODB
     exporting_tests_exporting_engine_testdriver_SOURCES += $(MONGODB_EXPORTING_FILES)
     exporting_tests_exporting_engine_testdriver_LDADD += $(OPTIONAL_MONGOC_LIBS)

+ 62 - 3
configure.ac

@@ -77,6 +77,12 @@ AC_ARG_ENABLE(
     ,
     [enable_backend_kinesis="detect"]
 )
+AC_ARG_ENABLE(
+    [exporting-pubsub],
+    [AS_HELP_STRING([--enable-exporting-pubsub], [enable pubsub exporting connector @<:@default autodetect@:>@])],
+    ,
+    [enable_exporting_pubsub="detect"]
+)
 AC_ARG_ENABLE(
     [backend-prometheus-remote-write],
     [AS_HELP_STRING([--enable-backend-prometheus-remote-write], [enable prometheus remote write backend @<:@default autodetect@:>@])],
@@ -1064,6 +1070,54 @@ AC_MSG_RESULT([${enable_backend_kinesis}])
 AM_CONDITIONAL([ENABLE_BACKEND_KINESIS], [test "${enable_backend_kinesis}" = "yes"])
 
 
+# -----------------------------------------------------------------------------
+# Pub/Sub exporting connector - googleapis
+
+PKG_CHECK_MODULES(
+    [GRPC],
+    [grpc],
+    [have_libgrpc=yes],
+    [have_libgrpc=no]
+)
+
+PKG_CHECK_MODULES(
+    [PUBSUB],
+    [googleapis_cpp_pubsub_protos],
+    [have_pubsub_protos=yes],
+    [have_pubsub_protos=no]
+)
+
+AC_PATH_PROG([CXX_BINARY], [${CXX}], [no])
+AS_IF(
+    [test x"${CXX_BINARY}" == x"no"],
+    [have_CXX_compiler=no],
+    [have_CXX_compiler=yes]
+)
+
+test "${enable_pubsub}" = "yes" -a "${have_grpc}" != "yes" && \
+    AC_MSG_ERROR([libgrpc required but not found. try installing grpc])
+
+test "${enable_pubsub}" = "yes" -a "${have_pubsub_protos}" != "yes" && \
+    AC_MSG_ERROR([libgoogleapis_cpp_pubsub_protos required but not found. try installing googleapis])
+
+test "${enable_backend_prometheus_remote_write}" = "yes" -a "${have_CXX_compiler}" != "yes" && \
+    AC_MSG_ERROR([C++ compiler required but not found. try installing g++])
+
+AC_MSG_CHECKING([if pubsub exporting connector should be enabled])
+if test "${enable_exporting_pubsub}" != "no" -a "${have_pubsub_protos}" = "yes" -a "${have_CXX_compiler}" = "yes"; then
+    enable_exporting_pubsub="yes"
+    AC_DEFINE([ENABLE_EXPORTING_PUBSUB], [1], [Pub/Sub API usability])
+    OPTIONAL_PUBSUB_CFLAGS="${GRPC_CFLAGS} ${PUBSUB_CFLAGS}"
+    CXX11FLAG="-std=c++11"
+    OPTIONAL_PUBSUB_LIBS="${GRPC_LIBS} ${PUBSUB_LIBS}"
+else
+    enable_pubsub="no"
+fi
+
+AC_MSG_RESULT([${enable_exporting_pubsub}])
+AM_CONDITIONAL([ENABLE_EXPORTING_PUBSUB], [test "${enable_exporting_pubsub}" = "yes"])
+
+
 # -----------------------------------------------------------------------------
 # Prometheus remote write backend - libprotobuf, libsnappy, protoc
 
@@ -1223,7 +1277,9 @@ AC_MSG_RESULT([${enable_lto}])
 
 # -----------------------------------------------------------------------------
 
-AM_CONDITIONAL([ENABLE_CXX_LINKER], [test "${enable_backend_kinesis}" = "yes" -o "${enable_backend_prometheus_remote_write}" = "yes"])
+AM_CONDITIONAL([ENABLE_CXX_LINKER], [test "${enable_backend_kinesis}" = "yes" \
+                                     -o "${enable_exporting_pubsub}" = "yes" \
+                                     -o "${enable_backend_prometheus_remote_write}" = "yes"])
 
 AC_DEFINE_UNQUOTED([NETDATA_USER], ["${with_user}"], [use this user to drop privileged])
 
@@ -1253,8 +1309,8 @@ AC_SUBST([webdir])
 
 CFLAGS="${CFLAGS} ${OPTIONAL_MATH_CFLAGS} ${OPTIONAL_NFACCT_CFLAGS} ${OPTIONAL_ZLIB_CFLAGS} ${OPTIONAL_UUID_CFLAGS} \
     ${OPTIONAL_LIBCAP_CFLAGS} ${OPTIONAL_IPMIMONITORING_CFLAGS} ${OPTIONAL_CUPS_CFLAGS} ${OPTIONAL_XENSTAT_FLAGS} \
-    ${OPTIONAL_KINESIS_CFLAGS} ${OPTIONAL_PROMETHEUS_REMOTE_WRITE_CFLAGS} ${OPTIONAL_MONGOC_CFLAGS} ${LWS_CFLAGS} \
-	${OPTIONAL_JSONC_STATIC_CFLAGS}"
+    ${OPTIONAL_KINESIS_CFLAGS} ${OPTIONAL_PUBSUB_CFLAGS} ${OPTIONAL_PROMETHEUS_REMOTE_WRITE_CFLAGS} \
+    ${OPTIONAL_MONGOC_CFLAGS} ${LWS_CFLAGS} ${OPTIONAL_JSONC_STATIC_CFLAGS}"
 
 CXXFLAGS="${CFLAGS} ${CXX11FLAG}"
 
@@ -1295,6 +1351,8 @@ AC_SUBST([OPTIONAL_XENSTAT_CFLAGS])
 AC_SUBST([OPTIONAL_XENSTAT_LIBS])
 AC_SUBST([OPTIONAL_KINESIS_CFLAGS])
 AC_SUBST([OPTIONAL_KINESIS_LIBS])
+AC_SUBST([OPTIONAL_PUBSUB_CFLAGS])
+AC_SUBST([OPTIONAL_PUBSUB_LIBS])
 AC_SUBST([OPTIONAL_PROMETHEUS_REMOTE_WRITE_CFLAGS])
 AC_SUBST([OPTIONAL_PROMETHEUS_REMOTE_WRITE_LIBS])
 AC_SUBST([OPTIONAL_MONGOC_CFLAGS])
@@ -1373,6 +1431,7 @@ AC_CONFIG_FILES([
     exporting/prometheus/Makefile
     exporting/prometheus/remote_write/Makefile
     exporting/aws_kinesis/Makefile
+    exporting/pubsub/Makefile
     exporting/mongodb/Makefile
     exporting/tests/Makefile
     health/Makefile

+ 1 - 0
exporting/Makefile.am

@@ -10,6 +10,7 @@ SUBDIRS = \
     opentsdb \
     prometheus \
     aws_kinesis \
+    pubsub \
     mongodb \
     $(NULL)
 

+ 7 - 0
exporting/exporting_engine.h

@@ -50,6 +50,7 @@ typedef enum exporting_connector_types {
     EXPORTING_CONNECTOR_TYPE_JSON,                    // Stores the data using JSON.
     EXPORTING_CONNECTOR_TYPE_PROMETHEUS_REMOTE_WRITE, // The user selected to use Prometheus backend
     EXPORTING_CONNECTOR_TYPE_KINESIS,                 // Send message to AWS Kinesis
+    EXPORTING_CONNECTOR_TYPE_PUBSUB,                  // Send message to Google Cloud Pub/Sub
     EXPORTING_CONNECTOR_TYPE_MONGODB,                 // Send data to MongoDB collection
     EXPORTING_CONNECTOR_TYPE_NUM                      // Number of backend types
 } EXPORTING_CONNECTOR_TYPE;
@@ -87,6 +88,12 @@ struct aws_kinesis_specific_config {
     char *secure_key;
 };
 
+struct pubsub_specific_config {
+    char *credentials_file;
+    char *project_id;
+    char *topic_id;
+};
+
 struct mongodb_specific_config {
     char *database;
     char *collection;

+ 10 - 0
exporting/init_connectors.c

@@ -13,6 +13,10 @@
 #include "aws_kinesis/aws_kinesis.h"
 #endif
 
+#if ENABLE_EXPORTING_PUBSUB
+#include "pubsub/pubsub.h"
+#endif
+
 #if HAVE_MONGOC
 #include "mongodb/mongodb.h"
 #endif
@@ -58,6 +62,12 @@ int init_connectors(struct engine *engine)
 #if HAVE_KINESIS
                 if (init_aws_kinesis_instance(instance) != 0)
                     return 1;
+#endif
+                break;
+            case EXPORTING_CONNECTOR_TYPE_PUBSUB:
+#if ENABLE_EXPORTING_PUBSUB
+                if (init_pubsub_instance(instance) != 0)
+                    return 1;
 #endif
                 break;
             case EXPORTING_CONNECTOR_TYPE_MONGODB:

+ 8 - 0
exporting/pubsub/Makefile.am

@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+AUTOMAKE_OPTIONS = subdir-objects
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+dist_noinst_DATA = \
+    README.md \
+    $(NULL)

+ 39 - 0
exporting/pubsub/README.md

@@ -0,0 +1,39 @@
+<!--
+---
+title: "Export metrics to Google Cloud Pub/Sub Service"
+custom_edit_url: https://github.com/netdata/netdata/edit/master/exporting/pubsub/README.md
+---
+-->
+
+# Export metrics to Google Cloud Pub/Sub Service
+
+## Prerequisites
+
+To use the Pub/Sub service for metric collecting and processing, you should first
+[install](https://github.com/googleapis/cpp-cmakefiles) Google Cloud Platform C++ Proto Libraries.
+Pub/Sub support is also dependent on the dependencies of those libraries, like `protobuf` and `grpc`. Next, Netdata
+should be re-installed from the source. The installer will detect that the required libraries are now available.
+
+## Configuration
+
+To enable data sending to the Pub/Sub service, run `./edit-config exporting.conf` in the Netdata configuration directory
+and set the following options:
+
+```conf
+[pubsub:my_instance]
+    enabled = yes
+    destination = pubsub.googleapis.com
+    credentials file = /etc/netdata/google_cloud_credentials.json
+    project id = my_project
+    topic id = my_topic
+```
+
+Set the `destination` option to a Pub/Sub service endpoint. `pubsub.googleapis.com` is the default one.
+
+Next, create the credentials JSON file by following Google Cloud's [authentication guide]
+(https://cloud.google.com/docs/authentication/getting-started#creating_a_service_account). The user running the Agent
+(typically `netdata`) needs read access to `google_cloud_credentials.json`, which you can set with
+`chmod 400 google_cloud_credentials.json; chown netdata google_cloud_credentials.json`. Set the `credentials file`
+option to the full path of the file.
+
+[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fexporting%2Fpubsub%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>)

+ 155 - 0
exporting/pubsub/pubsub.c

@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "pubsub.h"
+
+/**
+ * Initialize Pub/Sub connector instance
+ *
+ * @param instance an instance data structure.
+ * @return Returns 0 on success, 1 on failure.
+ */
+int init_pubsub_instance(struct instance *instance)
+{
+    instance->worker = pubsub_connector_worker;
+
+    instance->start_batch_formatting = NULL;
+    instance->start_host_formatting = format_host_labels_json_plaintext;
+    instance->start_chart_formatting = NULL;
+
+
+    if (EXPORTING_OPTIONS_DATA_SOURCE(instance->config.options) == EXPORTING_SOURCE_DATA_AS_COLLECTED)
+        instance->metric_formatting = format_dimension_collected_json_plaintext;
+    else
+        instance->metric_formatting = format_dimension_stored_json_plaintext;
+
+    instance->end_chart_formatting = NULL;
+    instance->end_host_formatting = flush_host_labels;
+    instance->end_batch_formatting = NULL;
+
+    instance->send_header = NULL;
+    instance->check_response = NULL;
+
+    instance->buffer = (void *)buffer_create(0);
+    if (!instance->buffer) {
+        error("EXPORTING: cannot create buffer for Pub/Sub exporting connector instance %s", instance->config.name);
+        return 1;
+    }
+    uv_mutex_init(&instance->mutex);
+    uv_cond_init(&instance->cond_var);
+
+    struct pubsub_specific_data *connector_specific_data = callocz(1, sizeof(struct pubsub_specific_data));
+    instance->connector_specific_data = (void *)connector_specific_data;
+
+    struct pubsub_specific_config *connector_specific_config =
+        (struct pubsub_specific_config *)instance->config.connector_specific_config;
+    char error_message[ERROR_LINE_MAX + 1] = "";
+    if (pubsub_init(
+            (void *)connector_specific_data, error_message, instance->config.destination,
+            connector_specific_config->credentials_file, connector_specific_config->project_id,
+            connector_specific_config->topic_id)) {
+        error(
+            "EXPORTING: Cannot initialize a Pub/Sub publisher for instance %s: %s",
+            instance->config.name, error_message);
+        return 1;
+    }
+
+    return 0;
+}
+
+/**
+ * Pub/Sub connector worker
+ *
+ * Runs in a separate thread for every instance.
+ *
+ * @param instance_p an instance data structure.
+ */
+void pubsub_connector_worker(void *instance_p)
+{
+    struct instance *instance = (struct instance *)instance_p;
+    struct pubsub_specific_config *connector_specific_config = instance->config.connector_specific_config;
+    struct pubsub_specific_data *connector_specific_data = instance->connector_specific_data;
+
+    while (!netdata_exit) {
+        struct stats *stats = &instance->stats;
+        char error_message[ERROR_LINE_MAX + 1] = "";
+
+        uv_mutex_lock(&instance->mutex);
+        uv_cond_wait(&instance->cond_var, &instance->mutex);
+
+        // reset the monitoring chart counters
+        stats->received_bytes =
+        stats->sent_bytes =
+        stats->sent_metrics =
+        stats->lost_metrics =
+        stats->receptions =
+        stats->transmission_successes =
+        stats->transmission_failures =
+        stats->data_lost_events =
+        stats->lost_bytes =
+        stats->reconnects = 0;
+
+        BUFFER *buffer = (BUFFER *)instance->buffer;
+        size_t buffer_len = buffer_strlen(buffer);
+
+        stats->buffered_bytes = buffer_len;
+
+        if (pubsub_add_message(instance->connector_specific_data, (char *)buffer_tostring(buffer))) {
+            error("EXPORTING: Instance %s: Cannot add data to a message", instance->config.name);
+
+            stats->data_lost_events++;
+            stats->lost_metrics += stats->buffered_metrics;
+            stats->lost_bytes += buffer_len;
+
+            goto cleanup;
+        }
+
+        debug(
+            D_BACKEND, "EXPORTING: pubsub_publish(): project = %s, topic = %s, buffer = %zu",
+            connector_specific_config->project_id, connector_specific_config->topic_id, buffer_len);
+
+        if (pubsub_publish((void *)connector_specific_data, error_message, stats->buffered_metrics, buffer_len)) {
+            error("EXPORTING: Instance: %s: Cannot publish a message: %s", instance->config.name, error_message);
+
+            stats->transmission_failures++;
+            stats->data_lost_events++;
+            stats->lost_metrics += stats->buffered_metrics;
+            stats->lost_bytes += buffer_len;
+
+            goto cleanup;
+        }
+
+        stats->sent_bytes = buffer_len;
+        stats->transmission_successes++;
+
+        size_t sent_metrics = 0, lost_metrics = 0, sent_bytes = 0, lost_bytes = 0;
+
+        if (unlikely(pubsub_get_result(
+                connector_specific_data, error_message, &sent_metrics, &sent_bytes, &lost_metrics, &lost_bytes))) {
+            // oops! we couldn't send (all or some of the) data
+            error("EXPORTING: %s", error_message);
+            error(
+                "EXPORTING: failed to write data to service '%s'. Willing to write %zu bytes, wrote %zu bytes.",
+                instance->config.destination, lost_bytes, sent_bytes);
+
+            stats->transmission_failures++;
+            stats->data_lost_events++;
+            stats->lost_metrics += lost_metrics;
+            stats->lost_bytes += lost_bytes;
+        } else {
+            stats->receptions++;
+            stats->sent_metrics = sent_metrics;
+        }
+
+    cleanup:
+        send_internal_metrics(instance);
+
+        buffer_flush(buffer);
+        stats->buffered_metrics = 0;
+
+        uv_mutex_unlock(&instance->mutex);
+
+#ifdef UNIT_TESTING
+        break;
+#endif
+    }
+}

+ 13 - 0
exporting/pubsub/pubsub.h

@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_EXPORTING_PUBSUB_H
+#define NETDATA_EXPORTING_PUBSUB_H
+
+#include "exporting/exporting_engine.h"
+#include "exporting/json/json.h"
+#include "pubsub_publish.h"
+
+int init_pubsub_instance(struct instance *instance);
+void pubsub_connector_worker(void *instance_p);
+
+#endif //NETDATA_EXPORTING_PUBSUB_H

Некоторые файлы не были показаны из-за большого количества измененных файлов