@cryptotaxi247 / netdata-1 / commits / ea11d403b

add cpu usage charts for statsd and web threads

Costa Tsaousis (ktsaou) committed Feb 13, 2018 at 01:26 UTC ea11d403b38f8336a744820be41b5e32c055bb8b
4 files changed +208 -44
src/socket.c
+45 -7
@@ -1163,6 +1163,10 @@ int poll_default_snd_callback(POLLINFO *pi, short int *events) {
1163 return 0;
1164 }
1165
1166 +void poll_default_tmr_callback(void *timer_data) {
1167 + (void)timer_data;
1168 +}
1169 +
1170 static void poll_events_cleanup(void *data) {
1171 POLLJOB *p = (POLLJOB *)data;
1172
@@ -1336,16 +1340,21 @@ void poll_events(LISTEN_SOCKETS *sockets
1340 , void (*del_callback)(POLLINFO *pi)
1341 , int (*rcv_callback)(POLLINFO *pi, short int *events)
1342 , int (*snd_callback)(POLLINFO *pi, short int *events)
1343 + , void (*tmr_callback)(void *timer_data)
1344 , SIMPLE_PATTERN *access_list
1345 , void *data
1341 - , time_t tcp_request_timeout
1342 - , time_t tcp_idle_timeout
1346 + , time_t tcp_request_timeout_seconds
1347 + , time_t tcp_idle_timeout_seconds
1348 + , time_t timer_milliseconds
1349 + , void *timer_data
1350 ) {
1351 if(!sockets || !sockets->opened) {
1352 error("POLLFD: internal error: no listening sockets are opened");
1353 return;
1354 }
1355
1356 + if(timer_milliseconds <= 0) timer_milliseconds = 0;
1357 +
1358 int retval;
1359
1360 POLLJOB p = {
@@ -1356,16 +1365,20 @@ void poll_events(LISTEN_SOCKETS *sockets
1365 .inf = NULL,
1366 .first_free = NULL,
1367
1359 - .complete_request_timeout = tcp_request_timeout,
1360 - .idle_timeout = tcp_idle_timeout,
1361 - .checks_every = (tcp_idle_timeout / 3) + 1,
1368 + .complete_request_timeout = tcp_request_timeout_seconds,
1369 + .idle_timeout = tcp_idle_timeout_seconds,
1370 + .checks_every = (tcp_idle_timeout_seconds / 3) + 1,
1371
1372 .access_list = access_list,
1373
1374 + .timer_milliseconds = timer_milliseconds,
1375 + .timer_data = timer_data,
1376 +
1377 .add_callback = add_callback?add_callback:poll_default_add_callback,
1378 .del_callback = del_callback?del_callback:poll_default_del_callback,
1379 .rcv_callback = rcv_callback?rcv_callback:poll_default_rcv_callback,
1368 - .snd_callback = snd_callback?snd_callback:poll_default_snd_callback
1380 + .snd_callback = snd_callback?snd_callback:poll_default_snd_callback,
1381 + .tmr_callback = tmr_callback?tmr_callback:poll_default_tmr_callback
1382 };
1383
1384 size_t i;
@@ -1391,10 +1404,35 @@ void poll_events(LISTEN_SOCKETS *sockets
1404 int timeout_ms = 1000; // in milliseconds
1405 time_t last_check = now_boottime_sec();
1406
1407 + usec_t timer_usec = timer_milliseconds * USEC_PER_MS;
1408 + usec_t now_usec = 0, next_timer_usec = 0, last_timer_usec = 0;
1409 + if(unlikely(timer_usec)) {
1410 + now_usec = now_boottime_usec();
1411 + next_timer_usec = now_usec - (now_usec % timer_usec) + timer_usec;
1412 + }
1413 +
1414 netdata_thread_cleanup_push(poll_events_cleanup, &p);
1415
1416 while(!netdata_exit) {
1397 - debug(D_POLLFD, "POLLFD: LISTENER: Waiting on %zu sockets...", p.max + 1);
1417 + if(unlikely(timer_usec)) {
1418 + now_usec = now_boottime_usec();
1419 +
1420 + if(unlikely(timer_usec && now_usec >= next_timer_usec)) {
1421 + debug(D_POLLFD, "Calling timer callback after %zu usec", (size_t)(now_usec - last_timer_usec));
1422 + last_timer_usec = now_usec;
1423 + p.tmr_callback(p.timer_data);
1424 + now_usec = now_boottime_usec();
1425 + next_timer_usec = now_usec - (now_usec % timer_usec) + timer_usec;
1426 + }
1427 +
1428 + usec_t dt_usec = next_timer_usec - now_usec;
1429 + if(dt_usec > 1000 * USEC_PER_MS)
1430 + timeout_ms = 1000;
1431 + else
1432 + timeout_ms = (int)(dt_usec / USEC_PER_MS);
1433 + }
1434 +
1435 + debug(D_POLLFD, "POLLFD: LISTENER: Waiting on %zu sockets for %zu ms...", p.max + 1, (size_t)timeout_ms);
1436 retval = poll(p.fds, p.max + 1, timeout_ms);
1437 time_t now = now_boottime_sec();
1438
src/socket.h
+9 -2
@@ -105,6 +105,9 @@ struct poll {
105 time_t idle_timeout;
106 time_t checks_every;
107
108 + time_t timer_milliseconds;
109 + void *timer_data;
110 +
111 struct pollfd *fds;
112 struct pollinfo *inf;
113 struct pollinfo *first_free;
@@ -115,6 +118,7 @@ struct poll {
118 void (*del_callback)(POLLINFO *pi);
119 int (*rcv_callback)(POLLINFO *pi, short int *events);
120 int (*snd_callback)(POLLINFO *pi, short int *events);
121 + void (*tmr_callback)(void *timer_data);
122 };
123
124 #define pollinfo_from_slot(p, slot) (&((p)->inf[(slot)]))
@@ -143,10 +147,13 @@ extern void poll_events(LISTEN_SOCKETS *sockets
147 , void (*del_callback)(POLLINFO *pi)
148 , int (*rcv_callback)(POLLINFO *pi, short int *events)
149 , int (*snd_callback)(POLLINFO *pi, short int *events)
150 + , void (*tmr_callback)(void *timer_data)
151 , SIMPLE_PATTERN *access_list
152 , void *data
148 - , time_t tcp_request_timeout
149 - , time_t tcp_idle_timeout
153 + , time_t tcp_request_timeout_seconds
154 + , time_t tcp_idle_timeout_seconds
155 + , time_t timer_milliseconds
156 + , void *timer_data
157 );
158
159 #endif //NETDATA_SOCKET_H
src/statsd.c
+108 -35
@@ -220,6 +220,15 @@ typedef struct statsd_app {
220 // --------------------------------------------------------------------------------------------------------------------
221 // global statsd data
222
223 +struct collection_thread_status {
224 + int status;
225 + netdata_thread_t thread;
226 + struct rusage rusage;
227 + RRDSET *st_cpu;
228 + RRDDIM *rd_user;
229 + RRDDIM *rd_system;
230 +};
231 +
232 static struct statsd {
233 STATSD_INDEX gauges;
234 STATSD_INDEX counters;
@@ -258,8 +267,7 @@ static struct statsd {
267 char *histogram_percentile_str;
268
269 int threads;
261 - int *collection_threads_status;
262 - netdata_thread_t *collection_threads;
270 + struct collection_thread_status *collection_threads_status;
271
272 LISTEN_SOCKETS sockets;
273 } statsd = {
@@ -331,7 +339,6 @@ static struct statsd {
339 .histogram_increase_step = 10,
340 .threads = 0,
341 .collection_threads_status = NULL,
334 - .collection_threads = NULL,
342 .sockets = {
343 .config_section = CONFIG_SECTION_STATSD,
344 .default_bind_to = "udp:localhost tcp:localhost",
@@ -909,6 +916,11 @@ static int statsd_snd_callback(POLLINFO *pi, short int *events) {
916 return -1;
917 }
918
919 +static void statsd_timer_callback(void *timer_data) {
920 + struct collection_thread_status *status = timer_data;
921 + getrusage(RUSAGE_THREAD, &status->rusage);
922 +}
923 +
924 // --------------------------------------------------------------------------------------------------------------------
925 // statsd child thread to collect metrics from network
926
@@ -931,13 +943,13 @@ void statsd_collector_thread_cleanup(void *data) {
943 }
944
945 void *statsd_collector_thread(void *ptr) {
934 - int *running = (int *)ptr;
935 - *running = 1;
946 + struct collection_thread_status *status = ptr;
947 + status->status = 1;
948
949 info("STATSD collector thread started with taskid %d", gettid());
950
951 struct statsd_udp *d = callocz(sizeof(struct statsd_udp), 1);
940 - d->running = running;
952 + d->running = &status->status;
953
954 netdata_thread_cleanup_push(statsd_collector_thread_cleanup, d);
955
@@ -961,10 +973,13 @@ void *statsd_collector_thread(void *ptr) {
973 , statsd_del_callback
974 , statsd_rcv_callback
975 , statsd_snd_callback
976 + , statsd_timer_callback
977 , NULL
978 , (void *)d
979 , 0 // tcp request timeout, 0 = disabled
980 , statsd.tcp_idle_timeout // tcp idle timeout, 0 = disabled
981 + , statsd.update_every * 1000
982 + , ptr // timer_data
983 );
984
985 netdata_thread_cleanup_pop(1);
@@ -2038,12 +2053,12 @@ static void statsd_main_cleanup(void *data) {
2053 static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
2054 info("cleaning up...");
2055
2041 - if (statsd.collection_threads && statsd.collection_threads_status) {
2056 + if (statsd.collection_threads_status) {
2057 int i;
2058 for (i = 0; i < statsd.threads; i++) {
2044 - if(statsd.collection_threads_status[i]) {
2059 + if(statsd.collection_threads_status[i].status) {
2060 info("STATSD: stopping data collection thread %d...", i + 1);
2046 - netdata_thread_cancel(statsd.collection_threads[i]);
2061 + netdata_thread_cancel(statsd.collection_threads_status[i].thread);
2062 }
2063 else {
2064 info("STATSD: data collection thread %d found stopped.", i + 1);
@@ -2152,14 +2167,13 @@ void *statsd_main(void *ptr) {
2167 goto cleanup;
2168 }
2169
2155 - statsd.collection_threads_status = callocz((size_t)statsd.threads, sizeof(int));
2156 - statsd.collection_threads = callocz((size_t)statsd.threads, sizeof(netdata_thread_t));
2170 + statsd.collection_threads_status = callocz((size_t)statsd.threads, sizeof(struct collection_thread_status));
2171
2172 int i;
2173 for(i = 0; i < statsd.threads ;i++) {
2174 char tag[NETDATA_THREAD_TAG_MAX + 1];
2175 snprintfz(tag, NETDATA_THREAD_TAG_MAX, "STATSD_COLLECTOR[%d]", i + 1);
2162 - netdata_thread_create(&statsd.collection_threads[i], tag, NETDATA_THREAD_OPTION_DEFAULT, statsd_collector_thread, &statsd.collection_threads_status[i]);
2176 + netdata_thread_create(&statsd.collection_threads_status[i].thread, tag, NETDATA_THREAD_OPTION_DEFAULT, statsd_collector_thread, &statsd.collection_threads_status[i]);
2177 }
2178
2179 // ----------------------------------------------------------------------------------------------------------------
@@ -2173,9 +2187,9 @@ void *statsd_main(void *ptr) {
2187 , NULL
2188 , "Metrics in the netdata statsd database"
2189 , "metrics"
2176 - , "netdata"
2190 + , "statsd"
2191 , "stats"
2178 - , 132000
2192 + , 132010
2193 , statsd.update_every
2194 , RRDSET_TYPE_STACKED
2195 );
@@ -2194,9 +2208,9 @@ void *statsd_main(void *ptr) {
2208 , NULL
2209 , "Events processed by the netdata statsd server"
2210 , "events/s"
2197 - , "netdata"
2211 + , "statsd"
2212 , "stats"
2199 - , 132001
2213 + , 132011
2214 , statsd.update_every
2215 , RRDSET_TYPE_STACKED
2216 );
@@ -2217,9 +2231,9 @@ void *statsd_main(void *ptr) {
2231 , NULL
2232 , "Read operations made by the netdata statsd server"
2233 , "reads/s"
2220 - , "netdata"
2234 + , "statsd"
2235 , "stats"
2222 - , 132002
2236 + , 132012
2237 , statsd.update_every
2238 , RRDSET_TYPE_STACKED
2239 );
@@ -2236,7 +2250,7 @@ void *statsd_main(void *ptr) {
2250 , "kilobits/s"
2251 , "netdata"
2252 , "stats"
2239 - , 132003
2253 + , 132013
2254 , statsd.update_every
2255 , RRDSET_TYPE_STACKED
2256 );
@@ -2253,7 +2267,7 @@ void *statsd_main(void *ptr) {
2267 , "packets/s"
2268 , "netdata"
2269 , "stats"
2256 - , 132004
2270 + , 132014
2271 , statsd.update_every
2272 , RRDSET_TYPE_STACKED
2273 );
@@ -2268,9 +2282,9 @@ void *statsd_main(void *ptr) {
2282 , NULL
2283 , "statsd server TCP connects and disconnects"
2284 , "events"
2271 - , "netdata"
2285 + , "statsd"
2286 , "stats"
2273 - , 132005
2287 + , 132015
2288 , statsd.update_every
2289 , RRDSET_TYPE_LINE
2290 );
@@ -2285,9 +2299,9 @@ void *statsd_main(void *ptr) {
2299 , NULL
2300 , "statsd server TCP connected sockets"
2301 , "connected"
2288 - , "netdata"
2302 + , "statsd"
2303 , "stats"
2290 - , 132006
2304 + , 132016
2305 , statsd.update_every
2306 , RRDSET_TYPE_LINE
2307 );
@@ -2301,14 +2315,59 @@ void *statsd_main(void *ptr) {
2315 , NULL
2316 , "Private metric charts created by the netdata statsd server"
2317 , "charts"
2304 - , "netdata"
2318 + , "statsd"
2319 , "stats"
2306 - , 132010
2320 + , 132020
2321 , statsd.update_every
2322 , RRDSET_TYPE_AREA
2323 );
2324 RRDDIM *rd_pcharts = rrddim_add(st_pcharts, "charts", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2325
2326 + RRDSET *stcpu_thread = rrdset_create_localhost(
2327 + "netdata"
2328 + , "plugin_statsd_charting_cpu"
2329 + , NULL
2330 + , "statsd"
2331 + , "netdata.statsd_cpu"
2332 + , "NetData statsd charting thread CPU usage"
2333 + , "milliseconds/s"
2334 + , "statsd"
2335 + , "stats"
2336 + , 132001
2337 + , statsd.update_every
2338 + , RRDSET_TYPE_STACKED
2339 + );
2340 +
2341 + RRDDIM *rd_user = rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
2342 + RRDDIM *rd_system = rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
2343 + struct rusage thread;
2344 +
2345 + for(i = 0; i < statsd.threads ;i++) {
2346 + char id[100 + 1];
2347 + char title[100 + 1];
2348 +
2349 + snprintfz(id, 100, "plugin_statsd_collector%d_cpu", i + 1);
2350 + snprintfz(title, 100, "NetData statsd collector thread No %d CPU usage", i + 1);
2351 +
2352 + statsd.collection_threads_status[i].st_cpu = rrdset_create_localhost(
2353 + "netdata"
2354 + , id
2355 + , NULL
2356 + , "statsd"
2357 + , "netdata.statsd_cpu"
2358 + , title
2359 + , "milliseconds/s"
2360 + , "statsd"
2361 + , "stats"
2362 + , 132002 + i
2363 + , statsd.update_every
2364 + , RRDSET_TYPE_STACKED
2365 + );
2366 +
2367 + statsd.collection_threads_status[i].rd_user = rrddim_add(statsd.collection_threads_status[i].st_cpu, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
2368 + statsd.collection_threads_status[i].rd_system = rrddim_add(statsd.collection_threads_status[i].st_cpu, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
2369 + }
2370 +
2371 // ----------------------------------------------------------------------------------------------------------------
2372 // statsd thread to turn metrics into charts
2373
@@ -2327,10 +2386,12 @@ void *statsd_main(void *ptr) {
2386
2387 statsd_update_all_app_charts();
2388
2389 + getrusage(RUSAGE_THREAD, &thread);
2390 +
2391 if(unlikely(netdata_exit))
2392 break;
2393
2333 - if(hb_dt) {
2394 + if(likely(hb_dt)) {
2395 rrdset_next(st_metrics);
2396 rrdset_next(st_events);
2397 rrdset_next(st_reads);
@@ -2339,6 +2400,9 @@ void *statsd_main(void *ptr) {
2400 rrdset_next(st_tcp_connects);
2401 rrdset_next(st_tcp_connected);
2402 rrdset_next(st_pcharts);
2403 + rrdset_next(stcpu_thread);
2404 + for(i = 0; i < statsd.threads ;i++)
2405 + rrdset_next(statsd.collection_threads_status[i].st_cpu);
2406 }
2407
2408 rrddim_set_by_pointer(st_metrics, rd_metrics_gauge, (collected_number)statsd.gauges.metrics);
@@ -2347,6 +2411,7 @@ void *statsd_main(void *ptr) {
2411 rrddim_set_by_pointer(st_metrics, rd_metrics_meter, (collected_number)statsd.meters.metrics);
2412 rrddim_set_by_pointer(st_metrics, rd_metrics_histogram, (collected_number)statsd.histograms.metrics);
2413 rrddim_set_by_pointer(st_metrics, rd_metrics_set, (collected_number)statsd.sets.metrics);
2414 + rrdset_done(st_metrics);
2415
2416 rrddim_set_by_pointer(st_events, rd_events_gauge, (collected_number)statsd.gauges.events);
2417 rrddim_set_by_pointer(st_events, rd_events_counter, (collected_number)statsd.counters.events);
@@ -2356,31 +2421,39 @@ void *statsd_main(void *ptr) {
2421 rrddim_set_by_pointer(st_events, rd_events_set, (collected_number)statsd.sets.events);
2422 rrddim_set_by_pointer(st_events, rd_events_unknown, (collected_number)statsd.unknown_types);
2423 rrddim_set_by_pointer(st_events, rd_events_errors, (collected_number)statsd.socket_errors);
2424 + rrdset_done(st_events);
2425
2426 rrddim_set_by_pointer(st_reads, rd_reads_tcp, (collected_number)statsd.tcp_socket_reads);
2427 rrddim_set_by_pointer(st_reads, rd_reads_udp, (collected_number)statsd.udp_socket_reads);
2428 + rrdset_done(st_reads);
2429
2430 rrddim_set_by_pointer(st_bytes, rd_bytes_tcp, (collected_number)statsd.tcp_bytes_read);
2431 rrddim_set_by_pointer(st_bytes, rd_bytes_udp, (collected_number)statsd.udp_bytes_read);
2432 + rrdset_done(st_bytes);
2433
2434 rrddim_set_by_pointer(st_packets, rd_packets_tcp, (collected_number)statsd.tcp_packets_received);
2435 rrddim_set_by_pointer(st_packets, rd_packets_udp, (collected_number)statsd.udp_packets_received);
2436 + rrdset_done(st_packets);
2437
2438 rrddim_set_by_pointer(st_tcp_connects, rd_tcp_connects, (collected_number)statsd.tcp_socket_connects);
2439 rrddim_set_by_pointer(st_tcp_connects, rd_tcp_disconnects, (collected_number)statsd.tcp_socket_disconnects);
2440 + rrdset_done(st_tcp_connects);
2441
2442 rrddim_set_by_pointer(st_tcp_connected, rd_tcp_connected, (collected_number)statsd.tcp_socket_connected);
2443 + rrdset_done(st_tcp_connected);
2444
2445 rrddim_set_by_pointer(st_pcharts, rd_pcharts, (collected_number)statsd.private_charts);
2375 -
2376 - rrdset_done(st_metrics);
2377 - rrdset_done(st_events);
2378 - rrdset_done(st_reads);
2379 - rrdset_done(st_bytes);
2380 - rrdset_done(st_packets);
2381 - rrdset_done(st_tcp_connects);
2382 - rrdset_done(st_tcp_connected);
2446 rrdset_done(st_pcharts);
2447 +
2448 + rrddim_set_by_pointer(stcpu_thread, rd_user, thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
2449 + rrddim_set_by_pointer(stcpu_thread, rd_system, thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
2450 + rrdset_done(stcpu_thread);
2451 +
2452 + for(i = 0; i < statsd.threads ;i++) {
2453 + rrddim_set_by_pointer(statsd.collection_threads_status[i].st_cpu, statsd.collection_threads_status[i].rd_user, statsd.collection_threads_status[i].rusage.ru_utime.tv_sec * 1000000ULL + statsd.collection_threads_status[i].rusage.ru_utime.tv_usec);
2454 + rrddim_set_by_pointer(statsd.collection_threads_status[i].st_cpu, statsd.collection_threads_status[i].rd_system, statsd.collection_threads_status[i].rusage.ru_stime.tv_sec * 1000000ULL + statsd.collection_threads_status[i].rusage.ru_stime.tv_usec);
2455 + rrdset_done(statsd.collection_threads_status[i].st_cpu);
2456 + }
2457 }
2458
2459 cleanup:
src/web_server.c
+46
@@ -893,6 +893,7 @@ void *socket_listen_main_single_threaded(void *ptr) {
893 struct web_server_static_threaded_worker {
894 netdata_thread_t thread;
895
896 + int id;
897 int running;
898
899 volatile size_t connected;
@@ -1106,6 +1107,46 @@ static int web_server_snd_callback(POLLINFO *pi, short int *events) {
1107 return web_server_check_client_status(w);
1108 }
1109
1110 +static void web_server_tmr_callback(void *timer_data) {
1111 + worker_private = (struct web_server_static_threaded_worker *)timer_data;
1112 +
1113 + static __thread RRDSET *st = NULL;
1114 + static __thread RRDDIM *rd_user = NULL, *rd_system = NULL;
1115 +
1116 + if(unlikely(!st)) {
1117 + char id[100 + 1];
1118 + char title[100 + 1];
1119 +
1120 + snprintfz(id, 100, "web_thread%d_cpu", worker_private->id + 1);
1121 + snprintfz(title, 100, "NetData web server thread No %d CPU usage", worker_private->id + 1);
1122 +
1123 + st = rrdset_create_localhost(
1124 + "netdata"
1125 + , id
1126 + , NULL
1127 + , "web"
1128 + , "netdata.web_cpu"
1129 + , title
1130 + , "milliseconds/s"
1131 + , "web"
1132 + , "stats"
1133 + , 132000 + worker_private->id
1134 + , default_rrd_update_every
1135 + , RRDSET_TYPE_STACKED
1136 + );
1137 +
1138 + rd_user = rrddim_add(st, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
1139 + rd_system = rrddim_add(st, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
1140 + }
1141 + else
1142 + rrdset_next(st);
1143 +
1144 + struct rusage rusage;
1145 + getrusage(RUSAGE_THREAD, &rusage);
1146 + rrddim_set_by_pointer(st, rd_user, rusage.ru_utime.tv_sec * 1000000ULL + rusage.ru_utime.tv_usec);
1147 + rrddim_set_by_pointer(st, rd_system, rusage.ru_stime.tv_sec * 1000000ULL + rusage.ru_stime.tv_usec);
1148 + rrdset_done(st);
1149 +}
1150
1151 // ----------------------------------------------------------------------------
1152 // web server worker thread
@@ -1138,10 +1179,13 @@ void *socket_listen_main_static_threaded_worker(void *ptr) {
1179 , web_server_del_callback
1180 , web_server_rcv_callback
1181 , web_server_snd_callback
1182 + , web_server_tmr_callback
1183 , web_allow_connections_from
1184 , NULL
1185 , web_client_first_request_timeout
1186 , web_client_timeout
1187 + , default_rrd_update_every * 1000 // timer_milliseconds
1188 + , ptr // timer_data
1189 );
1190
1191 netdata_thread_cleanup_pop(1);
@@ -1213,6 +1257,8 @@ void *socket_listen_main_static_threaded(void *ptr) {
1257
1258 int i;
1259 for(i = 1; i < static_threaded_workers_count; i++) {
1260 + static_workers_private_data[i].id = i;
1261 +
1262 char tag[50 + 1];
1263 snprintfz(tag, 50, "WEB_SERVER[static%d]", i+1);
1264