propagate netdata version with streaming; add netdata version to prometheus metrics; fixes #3519
Costa Tsaousis (ktsaou) committed
Mar 11, 2018 at 23:46 UTC
5f2514675334e52cabd9fe5677f44d325e3b9b37
9 files changed
+103
-16
src/backend_prometheus.c
+3
@@ -110,12 +110,15 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
110
111
char labels[PROMETHEUS_LABELS_MAX + 1] = "";
112
if(allhosts) {
113
+ buffer_sprintf(wb, "netdata_info{instance=\"%s\",application=\"%s\",version=\"%s\"}\n", hostname, host->program_name, host->program_version);
114
if(host->tags && *(host->tags))
115
buffer_sprintf(wb, "netdata_host_tags{instance=\"%s\",%s} 1 %llu\n", hostname, host->tags, now_realtime_usec() / USEC_PER_MS);
116
117
snprintfz(labels, PROMETHEUS_LABELS_MAX, ",instance=\"%s\"", hostname);
118
}
119
else {
120
+ buffer_sprintf(wb, "netdata_info{application=\"%s\",version=\"%s\"}\n", host->program_name, host->program_version);
121
+
122
if(host->tags && *(host->tags))
123
buffer_sprintf(wb, "netdata_host_tags{%s} 1 %llu\n", host->tags, now_realtime_usec() / USEC_PER_MS);
124
}
src/health.c
+1
-4
@@ -348,7 +348,6 @@ static void health_main_cleanup(void *ptr) {
348
}
349
350
void *health_main(void *ptr) {
351
- BUFFER *wb = buffer_create(100);
351
netdata_thread_cleanup_push(health_main_cleanup, ptr);
352
353
int min_run_every = (int)config_get_number(CONFIG_SECTION_HEALTH, "run at least every seconds", 10);
@@ -421,7 +420,7 @@ void *health_main(void *ptr) {
420
int value_is_null = 0;
421
422
int ret = rrdset2value_api_v1(rc->rrdset
424
- , wb
423
+ , NULL
424
, &rc->value
425
, rc->dimensions
426
, 1
@@ -733,8 +732,6 @@ void *health_main(void *ptr) {
732
733
} // forever
734
736
- buffer_free(wb);
737
-
735
netdata_thread_cleanup_pop(1);
736
return NULL;
737
}
src/rrd.h
+4
@@ -432,6 +432,8 @@ struct rrdhost {
432
char *cache_dir; // the directory to save RRD cache files
433
char *varlib_dir; // the directory to save health log
434
435
+ char *program_name; // the program name that collects metrics for this host
436
+ char *program_version; // the program version that collects metrics for this host
437
438
// ------------------------------------------------------------------------
439
// streaming of data to remote hosts - rrdpush
@@ -557,6 +559,8 @@ extern RRDHOST *rrdhost_find_or_create(
559
, const char *os
560
, const char *timezone
561
, const char *tags
562
+ , const char *program_name
563
+ , const char *program_version
564
, int update_every
565
, long history
566
, RRD_MEMORY_MODE mode
src/rrd2json.c
+7
-5
@@ -128,7 +128,7 @@ void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb) {
128
",\n\t\"custom_info\": \"%s\""
129
",\n\t\"charts\": {"
130
, host->hostname
131
- , program_version
131
+ , host->program_version
132
, host->os
133
, host->timezone
134
, host->rrd_update_every
@@ -1849,10 +1849,12 @@ int rrdset2value_api_v1(
1849
return 400;
1850
}
1851
1852
- if(r->result_options & RRDR_RESULT_OPTION_RELATIVE)
1853
- buffer_no_cacheable(wb);
1854
- else if(r->result_options & RRDR_RESULT_OPTION_ABSOLUTE)
1855
- buffer_cacheable(wb);
1852
+ if(wb) {
1853
+ if (r->result_options & RRDR_RESULT_OPTION_RELATIVE)
1854
+ buffer_no_cacheable(wb);
1855
+ else if (r->result_options & RRDR_RESULT_OPTION_ABSOLUTE)
1856
+ buffer_cacheable(wb);
1857
+ }
1858
1859
options = rrdr_check_options(r, options, dimensions);
1860
src/rrdhost.c
+32
@@ -111,6 +111,8 @@ RRDHOST *rrdhost_create(const char *hostname,
111
const char *os,
112
const char *timezone,
113
const char *tags,
114
+ const char *program_name,
115
+ const char *program_version,
116
int update_every,
117
long entries,
118
RRD_MEMORY_MODE memory_mode,
@@ -146,6 +148,9 @@ RRDHOST *rrdhost_create(const char *hostname,
148
rrdhost_init_os(host, os);
149
rrdhost_init_timezone(host, timezone);
150
rrdhost_init_tags(host, tags);
151
+
152
+ host->program_name = strdupz((program_name && *program_name)?program_name:"unknown");
153
+ host->program_version = strdupz((program_version && *program_version)?program_version:"unknown");
154
host->registry_hostname = strdupz((registry_hostname && *registry_hostname)?registry_hostname:hostname);
155
156
avl_init_lock(&(host->rrdset_root_index), rrdset_compare);
@@ -265,6 +270,8 @@ RRDHOST *rrdhost_create(const char *hostname,
270
", os '%s'"
271
", timezone '%s'"
272
", tags '%s'"
273
+ ", program_name '%s'"
274
+ ", program_version '%s'"
275
", update every %d"
276
", memory mode %s"
277
", history entries %ld"
@@ -282,6 +289,8 @@ RRDHOST *rrdhost_create(const char *hostname,
289
, host->os
290
, host->timezone
291
, (host->tags)?host->tags:""
292
+ , host->program_name
293
+ , host->program_version
294
, host->rrd_update_every
295
, rrd_memory_mode_name(host->rrd_memory_mode)
296
, host->rrd_history_entries
@@ -309,6 +318,8 @@ RRDHOST *rrdhost_find_or_create(
318
, const char *os
319
, const char *timezone
320
, const char *tags
321
+ , const char *program_name
322
+ , const char *program_version
323
, int update_every
324
, long history
325
, RRD_MEMORY_MODE mode
@@ -329,6 +340,8 @@ RRDHOST *rrdhost_find_or_create(
340
, os
341
, timezone
342
, tags
343
+ , program_name
344
+ , program_version
345
, update_every
346
, history
347
, mode
@@ -343,12 +356,27 @@ RRDHOST *rrdhost_find_or_create(
356
host->health_enabled = health_enabled;
357
358
if(strcmp(host->hostname, hostname) != 0) {
359
+ info("Host '%s' has been renamed to '%s'. If this is not intentional it may mean multiple hosts are using the same machine_guid.", host->hostname, hostname);
360
char *t = host->hostname;
361
host->hostname = strdupz(hostname);
362
host->hash_hostname = simple_hash(host->hostname);
363
freez(t);
364
}
365
366
+ if(strcmp(host->program_name, program_name) != 0) {
367
+ info("Host '%s' switched program name from '%s' to '%s'", host->hostname, host->program_name, program_name);
368
+ char *t = host->program_name;
369
+ host->program_name = strdupz(program_name);
370
+ freez(t);
371
+ }
372
+
373
+ if(strcmp(host->program_version, program_version) != 0) {
374
+ info("Host '%s' switched program version from '%s' to '%s'", host->hostname, host->program_version, program_version);
375
+ char *t = host->program_version;
376
+ host->program_version = strdupz(program_version);
377
+ freez(t);
378
+ }
379
+
380
if(host->rrd_update_every != update_every)
381
error("Host '%s' has an update frequency of %d seconds, but the wanted one is %d seconds. Restart netdata here to apply the new settings.", host->hostname, host->rrd_update_every, update_every);
382
@@ -424,6 +452,8 @@ void rrd_init(char *hostname) {
452
, os_type
453
, netdata_configured_timezone
454
, config_get(CONFIG_SECTION_BACKEND, "host tags", "")
455
+ , program_name
456
+ , program_version
457
, default_rrd_update_every
458
, default_rrd_history_entries
459
, default_rrd_memory_mode
@@ -533,6 +563,8 @@ void rrdhost_free(RRDHOST *host) {
563
freez((void *)host->tags);
564
freez((void *)host->os);
565
freez((void *)host->timezone);
566
+ freez(host->program_version);
567
+ freez(host->program_name);
568
freez(host->cache_dir);
569
freez(host->varlib_dir);
570
freez(host->rrdpush_send_api_key);
src/rrdpush.c
+38
-4
@@ -364,7 +364,7 @@ static int rrdpush_sender_thread_connect_to_master(RRDHOST *host, int default_po
364
char http[HTTP_HEADER_SIZE + 1];
365
snprintfz(http, HTTP_HEADER_SIZE,
366
"STREAM key=%s&hostname=%s®istry_hostname=%s&machine_guid=%s&update_every=%d&os=%s&timezone=%s&tags=%s HTTP/1.1\r\n"
367
- "User-Agent: netdata-push-service/%s\r\n"
367
+ "User-Agent: %s/%s\r\n"
368
"Accept: */*\r\n\r\n"
369
, host->rrdpush_send_api_key
370
, host->hostname
@@ -374,7 +374,8 @@ static int rrdpush_sender_thread_connect_to_master(RRDHOST *host, int default_po
374
, host->os
375
, host->timezone
376
, (host->tags)?host->tags:""
377
- , program_version
377
+ , host->program_name
378
+ , host->program_version
379
);
380
381
if(send_timeout(host->rrdpush_sender_socket, http, strlen(http), 0, timeout) == -1) {
@@ -721,7 +722,20 @@ static RRDPUSH_MULTIPLE_CONNECTIONS_STRATEGY get_multiple_connections_strategy(s
722
return ret;
723
}
724
724
-static int rrdpush_receive(int fd, const char *key, const char *hostname, const char *registry_hostname, const char *machine_guid, const char *os, const char *timezone, const char *tags, int update_every, char *client_ip, char *client_port) {
725
+static int rrdpush_receive(int fd
726
+ , const char *key
727
+ , const char *hostname
728
+ , const char *registry_hostname
729
+ , const char *machine_guid
730
+ , const char *os
731
+ , const char *timezone
732
+ , const char *tags
733
+ , const char *program_name
734
+ , const char *program_version
735
+ , int update_every
736
+ , char *client_ip
737
+ , char *client_port
738
+) {
739
RRDHOST *host;
740
int history = default_rrd_history_entries;
741
RRD_MEMORY_MODE mode = default_rrd_memory_mode;
@@ -773,6 +787,8 @@ static int rrdpush_receive(int fd, const char *key, const char *hostname, const
787
, os
788
, timezone
789
, tags
790
+ , program_name
791
+ , program_version
792
, update_every
793
, history
794
, mode
@@ -911,6 +927,8 @@ struct rrdpush_thread {
927
char *tags;
928
char *client_ip;
929
char *client_port;
930
+ char *program_name;
931
+ char *program_version;
932
int update_every;
933
};
934
@@ -931,6 +949,8 @@ static void rrdpush_receiver_thread_cleanup(void *ptr) {
949
freez(rpt->tags);
950
freez(rpt->client_ip);
951
freez(rpt->client_port);
952
+ freez(rpt->program_name);
953
+ freez(rpt->program_version);
954
freez(rpt);
955
}
956
}
@@ -950,6 +970,8 @@ static void *rrdpush_receiver_thread(void *ptr) {
970
, rpt->os
971
, rpt->timezone
972
, rpt->tags
973
+ , rpt->program_name
974
+ , rpt->program_version
975
, rpt->update_every
976
, rpt->client_ip
977
, rpt->client_port
@@ -1088,7 +1110,7 @@ int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url
1110
}
1111
}
1112
1091
- struct rrdpush_thread *rpt = mallocz(sizeof(struct rrdpush_thread));
1113
+ struct rrdpush_thread *rpt = callocz(1, sizeof(struct rrdpush_thread));
1114
rpt->fd = w->ifd;
1115
rpt->key = strdupz(key);
1116
rpt->hostname = strdupz(hostname);
@@ -1100,6 +1122,18 @@ int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url
1122
rpt->client_ip = strdupz(w->client_ip);
1123
rpt->client_port = strdupz(w->client_port);
1124
rpt->update_every = update_every;
1125
+
1126
+ if(w->user_agent && w->user_agent[0]) {
1127
+ char *t = strchr(w->user_agent, '/');
1128
+ if(t && *t) {
1129
+ *t = '\0';
1130
+ t++;
1131
+ }
1132
+
1133
+ rpt->program_name = strdupz(w->user_agent);
1134
+ if(t && *t) rpt->program_version = strdupz(t);
1135
+ }
1136
+
1137
netdata_thread_t thread;
1138
1139
debug(D_SYSTEM, "starting STREAM receive thread.");
src/web_client.c
+11
-3
@@ -142,6 +142,8 @@ void web_client_request_done(struct web_client *w) {
142
w->origin[0] = '*';
143
w->origin[1] = '\0';
144
145
+ freez(w->user_agent); w->user_agent = NULL;
146
+
147
w->mode = WEB_CLIENT_MODE_NORMAL;
148
149
w->tcp_cork = 0;
@@ -722,14 +724,15 @@ const char *web_response_code_to_string(int code) {
724
}
725
}
726
725
-static inline char *http_header_parse(struct web_client *w, char *s) {
726
- static uint32_t hash_origin = 0, hash_connection = 0, hash_accept_encoding = 0, hash_donottrack = 0;
727
+static inline char *http_header_parse(struct web_client *w, char *s, int parse_useragent) {
728
+ static uint32_t hash_origin = 0, hash_connection = 0, hash_accept_encoding = 0, hash_donottrack = 0, hash_useragent = 0;
729
730
if(unlikely(!hash_origin)) {
731
hash_origin = simple_uhash("Origin");
732
hash_connection = simple_uhash("Connection");
733
hash_accept_encoding = simple_uhash("Accept-Encoding");
734
hash_donottrack = simple_uhash("DNT");
735
+ hash_useragent = simple_uhash("User-Agent");
736
}
737
738
char *e = s;
@@ -772,6 +775,9 @@ static inline char *http_header_parse(struct web_client *w, char *s) {
775
if(*v == '0') web_client_disable_donottrack(w);
776
else if(*v == '1') web_client_enable_donottrack(w);
777
}
778
+ else if(parse_useragent && hash == hash_useragent && !strcasecmp(s, "User-Agent")) {
779
+ w->user_agent = strdupz(v);
780
+ }
781
#ifdef NETDATA_WITH_ZLIB
782
else if(hash == hash_accept_encoding && !strcasecmp(s, "Accept-Encoding")) {
783
if(web_enable_gzip) {
@@ -871,7 +877,9 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
877
}
878
879
// another header line
874
- s = http_header_parse(w, s);
880
+ s = http_header_parse(w, s,
881
+ (w->mode == WEB_CLIENT_MODE_STREAM) // parse user agent
882
+ );
883
}
884
}
885
src/web_client.h
+1
@@ -144,6 +144,7 @@ struct web_client {
144
char cookie1[NETDATA_WEB_REQUEST_COOKIE_SIZE+1];
145
char cookie2[NETDATA_WEB_REQUEST_COOKIE_SIZE+1];
146
char origin[NETDATA_WEB_REQUEST_ORIGIN_HEADER_SIZE+1];
147
+ char *user_agent;
148
149
struct response response;
150
src/web_server.c
+6
@@ -106,6 +106,8 @@ static void web_client_zero(struct web_client *w) {
106
buffer_flush(b2);
107
buffer_flush(b3);
108
109
+ freez(w->user_agent);
110
+
111
// zero everything
112
memset(w, 0, sizeof(struct web_client));
113
@@ -119,6 +121,7 @@ static void web_client_free(struct web_client *w) {
121
buffer_free(w->response.header_output);
122
buffer_free(w->response.header);
123
buffer_free(w->response.data);
124
+ freez(w->user_agent);
125
freez(w);
126
}
127
@@ -342,6 +345,9 @@ static void web_client_initialize_connection(struct web_client *w) {
345
web_client_update_acl_matches(w);
346
347
w->origin[0] = '*'; w->origin[1] = '\0';
348
+ w->cookie1[0] = '\0'; w->cookie2[0] = '\0';
349
+ freez(w->user_agent); w->user_agent = NULL;
350
+
351
web_client_enable_wait_receive(w);
352
353
log_connection(w, "CONNECTED");