return 0;
}
+
+typedef struct td_metrics_parser_state {
+ td_metrics* metrics;
+ const td_metrics_parser* parser;
+} td_metrics_parser_state;
+
+static int __td_metrics_parse_file(td_ctx* ctx, td_file* self,
+ unsigned long lineno, char* line, size_t length, void* data) {
+ const td_metrics_parser_state* state = data;
+ int r;
+
+ // The parsed value
+ union {
+ int64_t _int64;
+ uint64_t _uint64;
+ double _double;
+ } value;
+
+ // Skip processing empty lines
+ if (!length)
+ return 0;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+
+ // Run the parser
+ for (const td_metrics_parser* p = state->parser; p->field; p++) {
+ switch (p->type) {
+ case TD_METRIC_UINT64:
+ r = sscanf(line, p->pattern, &value._uint64);
+ break;
+
+ case TD_METRIC_INT64:
+ r = sscanf(line, p->pattern, &value._int64);
+ break;
+
+ case TD_METRIC_FLOAT:
+ r = sscanf(line, p->pattern, &value._double);
+ break;
+
+ // We currently don't support the other types
+ default:
+ return -ENOTSUP;
+ }
+
+ // Continue if we could not match a value
+ if (r < 1)
+ continue;
+
+ // Submit the value if we could match
+ switch (p->type) {
+ case TD_METRIC_UINT64:
+ return td_metrics_push_uint64(state->metrics, p->field, value._uint64);
+
+ case TD_METRIC_INT64:
+ return td_metrics_push_int64(state->metrics, p->field, value._int64);
+
+ case TD_METRIC_FLOAT:
+ return td_metrics_push_float(state->metrics, p->field, value._double);
+
+ // We currently don't support the other types
+ default:
+ return -ENOTSUP;
+ }
+ }
+
+#pragma GCC diagnostic pop
+
+ return 0;
+}
+
+int td_metrics_parse_file(td_metrics* self, td_file* file, const td_metrics_parser* parser) {
+ td_metrics_parser_state state = {
+ .metrics = self,
+ .parser = parser,
+ };
+
+ return td_file_walk(file, __td_metrics_parse_file, &state);
+}
const void* value;
} td_metric_value;
+typedef struct td_metrics_parser {
+ // Field
+ const char* field;
+
+ // Type
+ td_metric_type type;
+
+ // Pattern
+ const char* pattern;
+} td_metrics_parser;
+
#define VALUES(...) ((const td_metric_value[]) { __VA_ARGS__, { NULL } })
#define VALUE(field, type, value) { field, type, value }
int __td_metrics_serialize(td_metrics* self, char* buffer, size_t length);
+// Parser
+
+#define METRICS(...) ((const td_metrics_parser[]) { __VA_ARGS__ { NULL } })
+
+#define METRIC(field, type, pattern) { field, type, pattern }
+#define METRIC_INT64(field, pattern) METRIC(field, TD_METRIC_INT64, pattern)
+#define METRIC_UINT64(field, pattern) METRIC(field, TD_METRIC_UINT64, pattern)
+#define METRIC_FLOAT(field, pattern) METRIC(field, TD_METRIC_FLOAT, pattern)
+
+int td_metrics_parse_file(td_metrics* self, td_file* file, const td_metrics_parser* parser);
+
#endif /* TELEMETRY_METRICS_H */
#include "command.h"
#include "ctx.h"
#include "daemon.h"
+#include "metrics.h"
#include "source.h"
#include "string.h"
#include "time.h"
return td_daemon_submit_metrics(self->daemon, metrics);
}
+int td_source_parse_metrics(td_source* self, const char* object,
+ td_file* file, const td_metrics_parser* parser) {
+ td_metrics* metrics = NULL;
+ int r;
+
+ // Create a new metrics object
+ r = td_source_create_metrics(self, &metrics, object);
+ if (r < 0)
+ goto ERROR;
+
+ // Parse the metrics
+ r = td_metrics_parse_file(metrics, file, parser);
+ if (r < 0)
+ goto ERROR;
+
+ // Submit the metrics
+ r = td_source_submit_metrics(self, metrics);
+ if (r < 0)
+ goto ERROR;
+
+ERROR:
+ if (metrics)
+ td_metrics_unref(metrics);
+
+ return r;
+}
+
static int td_source_create_database(td_source* self, const char* path, const char* source) {
td_args* args = NULL;
char min[24];
int td_source_run_command(td_source* self, const char** argv,
td_command_success_callback callback, void* data);
+int td_source_parse_metrics(td_source* self, const char* object,
+ td_file* file, const td_metrics_parser* parser);
+
int td_source_submit_metrics(td_source* self, td_metrics* metrics);
int td_source_submit_values(td_source* self,
const char* object, const td_metric_value* values);