@cryptotaxi247 / netdata-1 / commits / 011b31747

netdata now detects current timezone and reports it to the dashboard; it also streams it to upstream netdata servers; #2698

Costa Tsaousis (ktsaou) committed Oct 8, 2017 at 17:35 UTC 011b3174743d6d55922537532fb33fbb6d80f395
7 files changed +117 -10
src/common.c
+1
@@ -17,6 +17,7 @@ char *netdata_configured_cache_dir = NULL;
17 char *netdata_configured_varlib_dir = NULL;
18 char *netdata_configured_home_dir = NULL;
19 char *netdata_configured_host_prefix = NULL;
20 +char *netdata_configured_timezone = NULL;
21
22 int enable_ksm = 1;
23
src/common.h
+1
@@ -238,6 +238,7 @@ extern char *netdata_configured_cache_dir;
238 extern char *netdata_configured_varlib_dir;
239 extern char *netdata_configured_home_dir;
240 extern char *netdata_configured_host_prefix;
241 +extern char *netdata_configured_timezone;
242
243 extern void netdata_fix_chart_id(char *s);
244 extern void netdata_fix_chart_name(char *s);
src/main.c
+82 -5
@@ -496,6 +496,87 @@ static void get_netdata_configured_variables() {
496 get_system_pid_max();
497 }
498
499 +static void get_system_timezone(void) {
500 + // avoid flood calls to stat(/etc/localtime)
501 + // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux
502 + const char *tz = getenv("TZ");
503 + if(!tz || !*tz)
504 + setenv("TZ", config_get(CONFIG_SECTION_GLOBAL, "TZ environment variable", ":/etc/localtime"), 0);
505 +
506 + char buffer[FILENAME_MAX + 1];
507 + const char *timezone = NULL;
508 + ssize_t ret;
509 +
510 + // use the TZ variable
511 + if(tz && *tz && *tz != ':') {
512 + timezone = tz;
513 + // info("TIMEZONE: using TZ variable '%s'", timezone);
514 + }
515 +
516 + // use the contents of /etc/timezone
517 + if(!timezone && !read_file("/etc/timezone", buffer, FILENAME_MAX)) {
518 + timezone = buffer;
519 + // info("TIMEZONE: using the contents of /etc/timezone: '%s'", timezone);
520 + }
521 +
522 + // read the link /etc/localtime
523 + if(!timezone && (ret = readlink("/etc/localtime", buffer, FILENAME_MAX)) > 0) {
524 + buffer[ret] = '\0';
525 +
526 + char *cmp = "/usr/share/zoneinfo/";
527 + size_t cmp_len = strlen(cmp);
528 +
529 + if(!strncmp(buffer, cmp, cmp_len) && buffer[cmp_len]) {
530 + timezone = &buffer[cmp_len];
531 + // info("TIMEZONE: using the link of /etc/localtime: '%s'", timezone);
532 + }
533 + }
534 +
535 + // find the timezone from strftime()
536 + if(!timezone) {
537 + time_t t;
538 + struct tm *tmp, tmbuf;
539 +
540 + t = now_realtime_sec();
541 + tmp = localtime_r(&t, &tmbuf);
542 +
543 + if (tmp != NULL) {
544 + if(strftime(buffer, FILENAME_MAX, "%Z", tmp) == 0)
545 + buffer[0] = '\0';
546 + else {
547 + buffer[FILENAME_MAX] = '\0';
548 + timezone = buffer;
549 + // info("TIMEZONE: using strftime(): '%s'", timezone);
550 + }
551 + }
552 + }
553 +
554 + if(timezone && *timezone) {
555 + // make sure it does not have illegal characters
556 + // info("TIMEZONE: fixing '%s'", timezone);
557 +
558 + char tmp[strlen(timezone) + 1];
559 + char *d = tmp;
560 + *d = '\0';
561 +
562 + while(*timezone) {
563 + if(isalnum(*timezone) || *timezone == '_' || *timezone == '/')
564 + *d++ = *timezone++;
565 + else
566 + timezone++;
567 + }
568 + *d = '\0';
569 + strcpy(buffer, tmp);
570 + timezone = buffer;
571 + // info("TIMEZONE: fixed as '%s'", timezone);
572 + }
573 +
574 + if(!timezone || !*timezone)
575 + timezone = "unknown";
576 +
577 + netdata_configured_timezone = config_get(CONFIG_SECTION_GLOBAL, "timezone", timezone);
578 +}
579 +
580 void set_global_environment() {
581 {
582 char b[16];
@@ -513,11 +594,7 @@ void set_global_environment() {
594 setenv("HOME" , verify_required_directory(netdata_configured_home_dir), 1);
595 setenv("NETDATA_HOST_PREFIX", netdata_configured_host_prefix, 1);
596
516 - // avoid flood calls to stat(/etc/localtime)
517 - // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux
518 - const char *tz = getenv("TZ");
519 - if(!tz || !*tz)
520 - setenv("TZ", config_get(CONFIG_SECTION_GLOBAL, "TZ environment variable", ":/etc/localtime"), 0);
597 + get_system_timezone();
598
599 // set the path we need
600 char path[1024 + 1], *p = getenv("PATH");
src/rrd.h
+2
@@ -410,6 +410,7 @@ struct rrdhost {
410
411 const char *os; // the O/S type of the host
412 const char *tags; // tags for this host
413 + const char *timezone; // the timezone of the host
414
415 uint32_t flags; // flags about this RRDHOST
416
@@ -541,6 +542,7 @@ extern RRDHOST *rrdhost_find_or_create(
542 , const char *registry_hostname
543 , const char *guid
544 , const char *os
545 + , const char *timezone
546 , const char *tags
547 , int update_every
548 , long history
src/rrd2json.c
+2
@@ -92,6 +92,7 @@ void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb) {
92 "\t\"hostname\": \"%s\""
93 ",\n\t\"version\": \"%s\""
94 ",\n\t\"os\": \"%s\""
95 + ",\n\t\"timezone\": \"%s\""
96 ",\n\t\"update_every\": %d"
97 ",\n\t\"history\": %ld"
98 ",\n\t\"custom_info\": \"%s\""
@@ -99,6 +100,7 @@ void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb) {
100 , host->hostname
101 , program_version
102 , host->os
103 + , host->timezone
104 , host->rrd_update_every
105 , host->rrd_history_entries
106 , custom_dashboard_info_js_filename
src/rrdhost.c
+18 -1
@@ -86,6 +86,15 @@ static inline void rrdhost_init_os(RRDHOST *host, const char *os) {
86 freez(old);
87 }
88
89 +static inline void rrdhost_init_timezone(RRDHOST *host, const char *timezone) {
90 + if(host->timezone && timezone && !strcmp(host->timezone, timezone))
91 + return;
92 +
93 + void *old = (void *)host->timezone;
94 + host->timezone = strdupz((timezone && *timezone)?timezone:"unknown");
95 + freez(old);
96 +}
97 +
98 static inline void rrdhost_init_machine_guid(RRDHOST *host, const char *machine_guid) {
99 strncpy(host->machine_guid, machine_guid, GUID_LEN);
100 host->machine_guid[GUID_LEN] = '\0';
@@ -100,6 +109,7 @@ RRDHOST *rrdhost_create(const char *hostname,
109 const char *registry_hostname,
110 const char *guid,
111 const char *os,
112 + const char *timezone,
113 const char *tags,
114 int update_every,
115 long entries,
@@ -134,6 +144,7 @@ RRDHOST *rrdhost_create(const char *hostname,
144 rrdhost_init_hostname(host, hostname);
145 rrdhost_init_machine_guid(host, guid);
146 rrdhost_init_os(host, os);
147 + rrdhost_init_timezone(host, timezone);
148 rrdhost_init_tags(host, tags);
149 host->registry_hostname = strdupz((registry_hostname && *registry_hostname)?registry_hostname:hostname);
150
@@ -251,7 +262,8 @@ RRDHOST *rrdhost_create(const char *hostname,
262 }
263 else {
264 info("Host '%s' (at registry as '%s') with guid '%s' initialized"
254 - ", os %s"
265 + ", os '%s'"
266 + ", timezone '%s'"
267 ", tags '%s'"
268 ", update every %d"
269 ", memory mode %s"
@@ -268,6 +280,7 @@ RRDHOST *rrdhost_create(const char *hostname,
280 , host->registry_hostname
281 , host->machine_guid
282 , host->os
283 + , host->timezone
284 , (host->tags)?host->tags:""
285 , host->rrd_update_every
286 , rrd_memory_mode_name(host->rrd_memory_mode)
@@ -294,6 +307,7 @@ RRDHOST *rrdhost_find_or_create(
307 , const char *registry_hostname
308 , const char *guid
309 , const char *os
310 + , const char *timezone
311 , const char *tags
312 , int update_every
313 , long history
@@ -313,6 +327,7 @@ RRDHOST *rrdhost_find_or_create(
327 , registry_hostname
328 , guid
329 , os
330 + , timezone
331 , tags
332 , update_every
333 , history
@@ -404,6 +419,7 @@ void rrd_init(char *hostname) {
419 , registry_get_this_machine_hostname()
420 , registry_get_this_machine_guid()
421 , os_type
422 + , netdata_configured_timezone
423 , config_get(CONFIG_SECTION_BACKEND, "host tags", "")
424 , default_rrd_update_every
425 , default_rrd_history_entries
@@ -510,6 +526,7 @@ void rrdhost_free(RRDHOST *host) {
526
527 freez((void *)host->tags);
528 freez((void *)host->os);
529 + freez((void *)host->timezone);
530 freez(host->cache_dir);
531 freez(host->varlib_dir);
532 freez(host->rrdpush_send_api_key);
src/rrdpush.c
+11 -4
@@ -294,7 +294,7 @@ static int rrdpush_sender_thread_connect_to_master(RRDHOST *host, int default_po
294 #define HTTP_HEADER_SIZE 8192
295 char http[HTTP_HEADER_SIZE + 1];
296 snprintfz(http, HTTP_HEADER_SIZE,
297 - "STREAM key=%s&hostname=%s&registry_hostname=%s&machine_guid=%s&update_every=%d&os=%s&tags=%s HTTP/1.1\r\n"
297 + "STREAM key=%s&hostname=%s&registry_hostname=%s&machine_guid=%s&update_every=%d&os=%s&timezone=%s&tags=%s HTTP/1.1\r\n"
298 "User-Agent: netdata-push-service/%s\r\n"
299 "Accept: */*\r\n\r\n"
300 , host->rrdpush_send_api_key
@@ -303,6 +303,7 @@ static int rrdpush_sender_thread_connect_to_master(RRDHOST *host, int default_po
303 , host->machine_guid
304 , default_rrd_update_every
305 , host->os
306 + , host->timezone
307 , (host->tags)?host->tags:""
308 , program_version
309 );
@@ -634,7 +635,7 @@ static void log_stream_connection(const char *client_ip, const char *client_port
635 log_access("STREAM: %d '[%s]:%s' '%s' host '%s' api key '%s' machine guid '%s'", gettid(), client_ip, client_port, msg, host, api_key, machine_guid);
636 }
637
637 -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 *tags, int update_every, char *client_ip, char *client_port) {
638 +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) {
639 RRDHOST *host;
640 int history = default_rrd_history_entries;
641 RRD_MEMORY_MODE mode = default_rrd_memory_mode;
@@ -680,6 +681,7 @@ static int rrdpush_receive(int fd, const char *key, const char *hostname, const
681 , registry_hostname
682 , machine_guid
683 , os
684 + , timezone
685 , tags
686 , update_every
687 , history
@@ -803,6 +805,7 @@ struct rrdpush_thread {
805 char *registry_hostname;
806 char *machine_guid;
807 char *os;
808 + char *timezone;
809 char *tags;
810 char *client_ip;
811 char *client_port;
@@ -820,7 +823,7 @@ static void *rrdpush_receiver_thread(void *ptr) {
823
824
825 info("STREAM %s [%s]:%s: receive thread created (task id %d)", rpt->hostname, rpt->client_ip, rpt->client_port, gettid());
823 - rrdpush_receive(rpt->fd, rpt->key, rpt->hostname, rpt->registry_hostname, rpt->machine_guid, rpt->os, rpt->tags, rpt->update_every, rpt->client_ip, rpt->client_port);
826 + rrdpush_receive(rpt->fd, rpt->key, rpt->hostname, rpt->registry_hostname, rpt->machine_guid, rpt->os, rpt->timezone, rpt->tags, rpt->update_every, rpt->client_ip, rpt->client_port);
827 info("STREAM %s [receive from [%s]:%s]: receive thread ended (task id %d)", rpt->hostname, rpt->client_ip, rpt->client_port, gettid());
828
829 freez(rpt->key);
@@ -828,6 +831,7 @@ static void *rrdpush_receiver_thread(void *ptr) {
831 freez(rpt->registry_hostname);
832 freez(rpt->machine_guid);
833 freez(rpt->os);
834 + freez(rpt->timezone);
835 freez(rpt->tags);
836 freez(rpt->client_ip);
837 freez(rpt->client_port);
@@ -863,7 +867,7 @@ int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url
867
868 info("STREAM [receive from [%s]:%s]: new client connection.", w->client_ip, w->client_port);
869
866 - char *key = NULL, *hostname = NULL, *registry_hostname = NULL, *machine_guid = NULL, *os = "unknown", *tags = NULL;
870 + char *key = NULL, *hostname = NULL, *registry_hostname = NULL, *machine_guid = NULL, *os = "unknown", *timezone = "unknown", *tags = NULL;
871 int update_every = default_rrd_update_every;
872 char buf[GUID_LEN + 1];
873
@@ -887,6 +891,8 @@ int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url
891 update_every = (int)strtoul(value, NULL, 0);
892 else if(!strcmp(name, "os"))
893 os = value;
894 + else if(!strcmp(name, "timezone"))
895 + timezone = value;
896 else if(!strcmp(name, "tags"))
897 tags = value;
898 else
@@ -968,6 +974,7 @@ int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url
974 rpt->registry_hostname = strdupz((registry_hostname && *registry_hostname)?registry_hostname:hostname);
975 rpt->machine_guid = strdupz(machine_guid);
976 rpt->os = strdupz(os);
977 + rpt->timezone = strdupz(timezone);
978 rpt->tags = (tags)?strdupz(tags):NULL;
979 rpt->client_ip = strdupz(w->client_ip);
980 rpt->client_port = strdupz(w->client_port);