daemon-status-18 (#19876)
* daemon-status-18 * potential fix for uv thread names missing * add restarts, reliability, status and thread_id to sentry; added stack traces backend to agent-events post * add stack traces backend information; remove _ND_ from fields and ignore ECS compatibility for the moment * properly check for PJERR * make sure cleanup and exit does not return on linux
Costa Tsaousis committed
Mar 17, 2025 at 11:26 UTC
d4ec716a9c52ca5d03218d0ff55b179013e83521
11 files changed
+375
-191
src/daemon/daemon-shutdown.c
+6
-5
@@ -378,11 +378,12 @@ void netdata_cleanup_and_exit(EXIT_REASON reason, const char *action, const char
378
#endif
379
380
#ifdef ENABLE_SENTRY
381
- if (!ret || !shutdown_on_fatal()) {
382
- nd_sentry_fini();
383
- curl_global_cleanup();
384
- exit(ret);
385
- }
381
+ if(ret)
382
+ shutdown_on_fatal();
383
+
384
+ nd_sentry_fini();
385
+ curl_global_cleanup();
386
+ exit(ret);
387
#else
388
if(ret)
389
_exit(ret);
src/daemon/daemon-status-file.c
+194
-133
@@ -161,37 +161,42 @@ static void daemon_status_file_to_json(BUFFER *wb, DAEMON_STATUS_FILE *ds) {
161
162
dsf_acquire(*ds);
163
164
- buffer_json_member_add_datetime_rfc3339(wb, "@timestamp", ds->timestamp_ut, true); // ECS
165
- buffer_json_member_add_uint64(wb, "version", STATUS_FILE_VERSION); // custom
164
+ buffer_json_member_add_datetime_rfc3339(wb, "@timestamp", ds->timestamp_ut, true);
165
+ buffer_json_member_add_uint64(wb, "version", STATUS_FILE_VERSION);
166
167
- buffer_json_member_add_object(wb, "agent"); // ECS
167
+ buffer_json_member_add_object(wb, "agent");
168
{
169
- buffer_json_member_add_uuid(wb, "id", ds->host_id.uuid); // ECS
170
- buffer_json_member_add_uuid_compact(wb, "ephemeral_id", ds->invocation.uuid); // ECS
171
- buffer_json_member_add_string(wb, "version", ds->version); // ECS
169
+ buffer_json_member_add_uuid(wb, "id", ds->host_id.uuid);
170
+ buffer_json_member_add_uuid_compact(wb, "ephemeral_id", ds->invocation.uuid);
171
+ buffer_json_member_add_string(wb, "version", ds->version);
172
173
- buffer_json_member_add_time_t(wb, "uptime", ds->uptime); // custom
173
+ buffer_json_member_add_time_t(wb, "uptime", ds->uptime);
174
175
- buffer_json_member_add_uuid(wb, "ND_node_id", ds->node_id.uuid); // custom
176
- buffer_json_member_add_uuid(wb, "ND_claim_id", ds->claim_id.uuid); // custom
177
- buffer_json_member_add_uint64(wb, "ND_restarts", ds->restarts); // custom
175
+ buffer_json_member_add_uuid(wb, "node_id", ds->node_id.uuid);
176
+ buffer_json_member_add_uuid(wb, "claim_id", ds->claim_id.uuid);
177
+ buffer_json_member_add_uint64(wb, "restarts", ds->restarts);
178
179
- ND_PROFILE_2json(wb, "ND_profile", ds->profile); // custom
180
- buffer_json_member_add_string(wb, "ND_status", DAEMON_STATUS_2str(ds->status)); // custom
181
- EXIT_REASON_2json(wb, "ND_exit_reason", ds->exit_reason); // custom
179
+ ND_PROFILE_2json(wb, "profile", ds->profile);
180
+ buffer_json_member_add_string(wb, "status", DAEMON_STATUS_2str(ds->status));
181
+ EXIT_REASON_2json(wb, "exit_reason", ds->exit_reason);
182
183
- buffer_json_member_add_string_or_empty(wb, "ND_install_type", ds->install_type); // custom
183
+ buffer_json_member_add_string_or_empty(wb, "install_type", ds->install_type);
184
185
if(ds->v >= 14) {
186
- buffer_json_member_add_string(wb, "ND_db_mode", rrd_memory_mode_name(ds->db_mode)); // custom
187
- buffer_json_member_add_uint64(wb, "ND_db_tiers", ds->db_tiers); // custom
188
- buffer_json_member_add_boolean(wb, "ND_kubernetes", ds->kubernetes); // custom
186
+ buffer_json_member_add_string(wb, "db_mode", rrd_memory_mode_name(ds->db_mode));
187
+ buffer_json_member_add_uint64(wb, "db_tiers", ds->db_tiers);
188
+ buffer_json_member_add_boolean(wb, "kubernetes", ds->kubernetes);
189
}
190
191
if(ds->v >= 16)
192
- buffer_json_member_add_boolean(wb, "ND_sentry_available", ds->sentry_available); // custom
192
+ buffer_json_member_add_boolean(wb, "sentry_available", ds->sentry_available);
193
194
- buffer_json_member_add_object(wb, "ND_timings"); // custom
194
+ if(ds->v >= 18) {
195
+ buffer_json_member_add_int64(wb, "reliability", ds->reliability);
196
+ buffer_json_member_add_string(wb, "stack_traces", ds->stack_traces);
197
+ }
198
+
199
+ buffer_json_member_add_object(wb, "timings");
200
{
201
buffer_json_member_add_time_t(wb, "init", ds->timings.init);
202
buffer_json_member_add_time_t(wb, "exit", ds->timings.exit);
@@ -200,28 +205,28 @@ static void daemon_status_file_to_json(BUFFER *wb, DAEMON_STATUS_FILE *ds) {
205
}
206
buffer_json_object_close(wb);
207
203
- buffer_json_member_add_object(wb, "host"); // ECS
208
+ buffer_json_member_add_object(wb, "host");
209
{
210
buffer_json_member_add_uuid_compact(wb, "id", ds->machine_id.uuid);
206
- buffer_json_member_add_string_or_empty(wb, "architecture", ds->architecture); // ECS
207
- buffer_json_member_add_string_or_empty(wb, "virtualization", ds->virtualization); // custom
208
- buffer_json_member_add_string_or_empty(wb, "container", ds->container); // custom
209
- buffer_json_member_add_time_t(wb, "uptime", ds->boottime); // ECS
211
+ buffer_json_member_add_string_or_empty(wb, "architecture", ds->architecture);
212
+ buffer_json_member_add_string_or_empty(wb, "virtualization", ds->virtualization);
213
+ buffer_json_member_add_string_or_empty(wb, "container", ds->container);
214
+ buffer_json_member_add_time_t(wb, "uptime", ds->boottime);
215
211
- buffer_json_member_add_object(wb, "boot"); // ECS
216
+ buffer_json_member_add_object(wb, "boot");
217
{
213
- buffer_json_member_add_uuid_compact(wb, "id", ds->boot_id.uuid); // ECS
218
+ buffer_json_member_add_uuid_compact(wb, "id", ds->boot_id.uuid);
219
}
220
buffer_json_object_close(wb);
221
217
- buffer_json_member_add_object(wb, "memory"); // custom
222
+ buffer_json_member_add_object(wb, "memory");
223
if(OS_SYSTEM_MEMORY_OK(ds->memory)) {
224
buffer_json_member_add_uint64(wb, "total", ds->memory.ram_total_bytes);
225
buffer_json_member_add_uint64(wb, "free", ds->memory.ram_available_bytes);
226
}
227
buffer_json_object_close(wb);
228
224
- buffer_json_member_add_object(wb, "disk"); // ECS
229
+ buffer_json_member_add_object(wb, "disk");
230
{
231
buffer_json_member_add_object(wb, "db");
232
if (OS_SYSTEM_DISK_SPACE_OK(ds->var_cache)) {
@@ -237,18 +242,18 @@ static void daemon_status_file_to_json(BUFFER *wb, DAEMON_STATUS_FILE *ds) {
242
}
243
buffer_json_object_close(wb);
244
240
- buffer_json_member_add_object(wb, "os"); // ECS
245
+ buffer_json_member_add_object(wb, "os");
246
{
242
- buffer_json_member_add_string(wb, "type", DAEMON_OS_TYPE_2str(ds->os_type)); // ECS
243
- buffer_json_member_add_string_or_empty(wb, "kernel", ds->kernel_version); // ECS
244
- buffer_json_member_add_string_or_empty(wb, "name", ds->os_name); // ECS
245
- buffer_json_member_add_string_or_empty(wb, "version", ds->os_version); // ECS
246
- buffer_json_member_add_string_or_empty(wb, "family", ds->os_id); // ECS
247
- buffer_json_member_add_string_or_empty(wb, "platform", ds->os_id_like); // ECS
247
+ buffer_json_member_add_string(wb, "type", DAEMON_OS_TYPE_2str(ds->os_type));
248
+ buffer_json_member_add_string_or_empty(wb, "kernel", ds->kernel_version);
249
+ buffer_json_member_add_string_or_empty(wb, "name", ds->os_name);
250
+ buffer_json_member_add_string_or_empty(wb, "version", ds->os_version);
251
+ buffer_json_member_add_string_or_empty(wb, "family", ds->os_id);
252
+ buffer_json_member_add_string_or_empty(wb, "platform", ds->os_id_like);
253
}
254
buffer_json_object_close(wb);
255
251
- buffer_json_member_add_object(wb, "fatal"); // custom
256
+ buffer_json_member_add_object(wb, "fatal");
257
{
258
buffer_json_member_add_uint64(wb, "line", ds->fatal.line);
259
buffer_json_member_add_string_or_empty(wb, "filename", ds->fatal.filename);
@@ -256,6 +261,7 @@ static void daemon_status_file_to_json(BUFFER *wb, DAEMON_STATUS_FILE *ds) {
261
buffer_json_member_add_string_or_empty(wb, "message", ds->fatal.message);
262
buffer_json_member_add_string_or_empty(wb, "errno", ds->fatal.errno_str);
263
buffer_json_member_add_string_or_empty(wb, "thread", ds->fatal.thread);
264
+ buffer_json_member_add_uint64(wb, "thread_id", ds->fatal.thread_id);
265
buffer_json_member_add_string_or_empty(wb, "stack_trace", ds->fatal.stack_trace);
266
267
if(ds->v >= 16) {
@@ -269,17 +275,17 @@ static void daemon_status_file_to_json(BUFFER *wb, DAEMON_STATUS_FILE *ds) {
275
}
276
buffer_json_object_close(wb);
277
272
- buffer_json_member_add_array(wb, "dedup"); // custom
278
+ buffer_json_member_add_array(wb, "dedup");
279
{
280
for(size_t i = 0; i < _countof(ds->dedup.slot); i++) {
281
if (ds->dedup.slot[i].timestamp_ut == 0)
282
continue;
283
278
- buffer_json_add_array_item_object(wb); // custom
284
+ buffer_json_add_array_item_object(wb);
285
{
280
- buffer_json_member_add_datetime_rfc3339(wb, "@timestamp", ds->dedup.slot[i].timestamp_ut, true); // custom
281
- buffer_json_member_add_uint64(wb, "hash", ds->dedup.slot[i].hash); // custom
282
- buffer_json_member_add_boolean(wb, "sentry", ds->dedup.slot[i].sentry); // custom
286
+ buffer_json_member_add_datetime_rfc3339(wb, "@timestamp", ds->dedup.slot[i].timestamp_ut, true);
287
+ buffer_json_member_add_uint64(wb, "hash", ds->dedup.slot[i].hash);
288
+ buffer_json_member_add_boolean(wb, "sentry", ds->dedup.slot[i].sentry);
289
}
290
buffer_json_object_close(wb);
291
}
@@ -312,37 +318,52 @@ static bool daemon_status_file_from_json(json_object *jobj, void *data, BUFFER *
318
bool required_v14 = version >= 14 ? strict : false;
319
bool required_v16 = version >= 16 ? strict : false;
320
bool required_v17 = version >= 17 ? strict : false;
321
+ bool required_v18 = version >= 18 ? strict : false;
322
323
// Parse timestamp
324
JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "@timestamp", datetime, error, required_v1);
325
if(datetime[0])
326
ds->timestamp_ut = rfc3339_parse_ut(datetime, NULL);
327
328
+ const char *profile_key = version >= 18 ? "profile" : "ND_profile";
329
+ const char *status_key = version >= 18 ? "status" : "ND_status";
330
+ const char *exit_reason_key = version >= 18 ? "exit_reason" : "ND_exit_reason";
331
+ const char *node_id_key = version >= 18 ? "node_id" : "ND_node_id";
332
+ const char *claim_id_key = version >= 18 ? "claim_id" : "ND_claim_id";
333
+ const char *install_type_key = version >= 18 ? "install_type" : "ND_install_type";
334
+ const char *timings_key = version >= 18 ? "timings" : "ND_timings";
335
+ const char *restarts_key = version >= 18 ? "restarts" : "ND_restarts";
336
+ const char *db_mode_key = version >= 18 ? "db_mode" : "ND_db_mode";
337
+ const char *db_tiers_key = version >= 18 ? "db_tiers" : "ND_db_tiers";
338
+ const char *kubernetes_key = version >= 18 ? "kubernetes" : "ND_kubernetes";
339
+ const char *sentry_available_key = version >= 18 ? "sentry_available" : "ND_sentry_available";
340
+
341
// Parse agent object
342
JSONC_PARSE_SUBOBJECT(jobj, path, "agent", error, required_v1, {
343
JSONC_PARSE_TXT2UUID_OR_ERROR_AND_RETURN(jobj, path, "id", ds->host_id.uuid, error, required_v1);
344
JSONC_PARSE_TXT2UUID_OR_ERROR_AND_RETURN(jobj, path, "ephemeral_id", ds->invocation.uuid, error, required_v1);
345
JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "version", ds->version, error, required_v1);
346
JSONC_PARSE_UINT64_OR_ERROR_AND_RETURN(jobj, path, "uptime", ds->uptime, error, required_v1);
327
- JSONC_PARSE_ARRAY_OF_TXT2BITMAP_OR_ERROR_AND_RETURN(jobj, path, "ND_profile", ND_PROFILE_2id_one, ds->profile, error, required_v1);
328
- JSONC_PARSE_TXT2ENUM_OR_ERROR_AND_RETURN(jobj, path, "ND_status", DAEMON_STATUS_2id, ds->status, error, required_v1);
329
- JSONC_PARSE_ARRAY_OF_TXT2BITMAP_OR_ERROR_AND_RETURN(jobj, path, "ND_exit_reason", EXIT_REASON_2id_one, ds->exit_reason, error, required_v1);
330
- JSONC_PARSE_TXT2UUID_OR_ERROR_AND_RETURN(jobj, path, "ND_node_id", ds->node_id.uuid, error, required_v1);
331
- JSONC_PARSE_TXT2UUID_OR_ERROR_AND_RETURN(jobj, path, "ND_claim_id", ds->claim_id.uuid, error, required_v1);
332
- JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "ND_install_type", ds->install_type, error, required_v3);
333
-
334
- JSONC_PARSE_SUBOBJECT(jobj, path, "ND_timings", error, required_v1, {
347
+
348
+ JSONC_PARSE_ARRAY_OF_TXT2BITMAP_OR_ERROR_AND_RETURN(jobj, path, profile_key, ND_PROFILE_2id_one, ds->profile, error, required_v1);
349
+ JSONC_PARSE_TXT2ENUM_OR_ERROR_AND_RETURN(jobj, path, status_key, DAEMON_STATUS_2id, ds->status, error, required_v1);
350
+ JSONC_PARSE_ARRAY_OF_TXT2BITMAP_OR_ERROR_AND_RETURN(jobj, path, exit_reason_key, EXIT_REASON_2id_one, ds->exit_reason, error, required_v1);
351
+ JSONC_PARSE_TXT2UUID_OR_ERROR_AND_RETURN(jobj, path, node_id_key, ds->node_id.uuid, error, required_v1);
352
+ JSONC_PARSE_TXT2UUID_OR_ERROR_AND_RETURN(jobj, path, claim_id_key, ds->claim_id.uuid, error, required_v1);
353
+ JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, install_type_key, ds->install_type, error, required_v3);
354
+
355
+ JSONC_PARSE_SUBOBJECT(jobj, path, timings_key, error, required_v1, {
356
JSONC_PARSE_UINT64_OR_ERROR_AND_RETURN(jobj, path, "init", ds->timings.init, error, required_v1);
357
JSONC_PARSE_UINT64_OR_ERROR_AND_RETURN(jobj, path, "exit", ds->timings.exit, error, required_v1);
358
});
359
360
if(version >= 4)
340
- JSONC_PARSE_UINT64_OR_ERROR_AND_RETURN(jobj, path, "ND_restarts", ds->restarts, error, required_v4);
361
+ JSONC_PARSE_UINT64_OR_ERROR_AND_RETURN(jobj, path, restarts_key, ds->restarts, error, required_v4);
362
363
if(version >= 14) {
343
- JSONC_PARSE_TXT2ENUM_OR_ERROR_AND_RETURN(jobj, path, "ND_db_mode", rrd_memory_mode_id, ds->db_mode, error, required_v14);
344
- JSONC_PARSE_UINT64_OR_ERROR_AND_RETURN(jobj, path, "ND_db_tiers", ds->db_tiers, error, required_v14);
345
- JSONC_PARSE_BOOL_OR_ERROR_AND_RETURN(jobj, path, "ND_kubernetes", ds->kubernetes, error, required_v14);
364
+ JSONC_PARSE_TXT2ENUM_OR_ERROR_AND_RETURN(jobj, path, db_mode_key, rrd_memory_mode_id, ds->db_mode, error, required_v14);
365
+ JSONC_PARSE_UINT64_OR_ERROR_AND_RETURN(jobj, path, db_tiers_key, ds->db_tiers, error, required_v14);
366
+ JSONC_PARSE_BOOL_OR_ERROR_AND_RETURN(jobj, path, kubernetes_key, ds->kubernetes, error, required_v14);
367
}
368
else {
369
ds->db_mode = default_rrd_memory_mode;
@@ -351,9 +372,13 @@ static bool daemon_status_file_from_json(json_object *jobj, void *data, BUFFER *
372
}
373
374
if(version >= 17)
354
- JSONC_PARSE_BOOL_OR_ERROR_AND_RETURN(jobj, path, "ND_sentry_available", ds->sentry_available, error, required_v17);
375
+ JSONC_PARSE_BOOL_OR_ERROR_AND_RETURN(jobj, path, sentry_available_key, ds->sentry_available, error, required_v17);
376
else if(version == 16)
377
JSONC_PARSE_BOOL_OR_ERROR_AND_RETURN(jobj, path, "ND_sentry", ds->sentry_available, error, required_v16);
378
+ if(version >= 18) {
379
+ JSONC_PARSE_INT64_OR_ERROR_AND_RETURN(jobj, path, "reliability", ds->reliability, error, required_v18);
380
+ JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "stack_traces", ds->stack_traces, error, required_v18);
381
+ }
382
});
383
384
// Parse host object
@@ -408,12 +433,14 @@ static bool daemon_status_file_from_json(json_object *jobj, void *data, BUFFER *
433
JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "errno", ds->fatal.errno_str, error, required_v3);
434
JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "thread", ds->fatal.thread, error, required_v5);
435
411
- if(version >= 16) {
436
+ if(version >= 16)
437
JSONC_PARSE_TXT2ENUM_OR_ERROR_AND_RETURN(jobj, path, "signal_code", SIGNAL_CODE_2id_h, ds->fatal.signal_code, error, required_v16);
413
- }
414
- if(version >= 17) {
438
+
439
+ if(version >= 17)
440
JSONC_PARSE_TXT2ENUM_OR_ERROR_AND_RETURN(jobj, path, "sentry", SIGNAL_CODE_2id_h, ds->fatal.sentry, error, required_v17);
416
- }
441
+
442
+ if(version >= 18)
443
+ JSONC_PARSE_UINT64_OR_ERROR_AND_RETURN(jobj, path, "thread_id", ds->fatal.thread_id, error, required_v18);
444
});
445
446
// Parse the last posted object
@@ -451,6 +478,85 @@ static bool daemon_status_file_from_json(json_object *jobj, void *data, BUFFER *
478
// --------------------------------------------------------------------------------------------------------------------
479
// get the current status
480
481
+static void daemon_status_file_migrate_once(void) {
482
+ FUNCTION_RUN_ONCE();
483
+
484
+ dsf_acquire(last_session_status);
485
+ dsf_acquire(session_status);
486
+
487
+ strncpyz(session_status.version, NETDATA_VERSION, sizeof(session_status.version) - 1);
488
+ session_status.machine_id = os_machine_id();
489
+
490
+ {
491
+ char *install_type = NULL, *prebuilt_arch = NULL, *prebuilt_dist = NULL;
492
+ get_install_type_internal(&install_type, &prebuilt_arch, &prebuilt_dist);
493
+
494
+ if(install_type)
495
+ strncpyz(session_status.install_type, install_type, sizeof(session_status.install_type) - 1);
496
+
497
+ freez(prebuilt_arch);
498
+ freez(prebuilt_dist);
499
+ freez(install_type);
500
+ }
501
+
502
+#if defined(ENABLE_SENTRY)
503
+ session_status.sentry_available = true;
504
+#else
505
+ session_status.sentry_available = false;
506
+#endif
507
+
508
+ session_status.boot_id = os_boot_id();
509
+ if(!UUIDeq(session_status.boot_id, last_session_status.boot_id) && os_boot_ids_match(session_status.boot_id, last_session_status.boot_id)) {
510
+ // there is a slight difference in boot_id, but it is still the same boot
511
+ // copy the last boot_id
512
+ session_status.boot_id = last_session_status.boot_id;
513
+ }
514
+
515
+ session_status.claim_id = last_session_status.claim_id;
516
+ session_status.node_id = last_session_status.node_id;
517
+ session_status.host_id = last_session_status.host_id;
518
+ if(UUIDiszero(session_status.host_id)) {
519
+ const char *machine_guid = registry_get_this_machine_guid(false);
520
+ if(machine_guid && *machine_guid) {
521
+ if (uuid_parse_flexi(machine_guid, session_status.host_id.uuid) != 0)
522
+ session_status.host_id = UUID_ZERO;
523
+ }
524
+ }
525
+
526
+ strncpyz(session_status.architecture, last_session_status.architecture, sizeof(session_status.architecture) - 1);
527
+ strncpyz(session_status.virtualization, last_session_status.virtualization, sizeof(session_status.virtualization) - 1);
528
+ strncpyz(session_status.container, last_session_status.container, sizeof(session_status.container) - 1);
529
+ strncpyz(session_status.kernel_version, last_session_status.kernel_version, sizeof(session_status.kernel_version) - 1);
530
+ strncpyz(session_status.os_name, last_session_status.os_name, sizeof(session_status.os_name) - 1);
531
+ strncpyz(session_status.os_version, last_session_status.os_version, sizeof(session_status.os_version) - 1);
532
+ strncpyz(session_status.os_id, last_session_status.os_id, sizeof(session_status.os_id) - 1);
533
+ strncpyz(session_status.os_id_like, last_session_status.os_id_like, sizeof(session_status.os_id_like) - 1);
534
+
535
+ session_status.restarts = last_session_status.restarts + 1;
536
+ session_status.reliability = last_session_status.reliability;
537
+
538
+ bool crashed = last_session_status.status != DAEMON_STATUS_NONE && last_session_status.status != DAEMON_STATUS_EXITED;
539
+ bool exited_with_fatal = last_session_status.status == DAEMON_STATUS_EXITED && last_session_status.exit_reason != EXIT_REASON_NONE && !is_exit_reason_normal(last_session_status.exit_reason);
540
+ if(crashed || exited_with_fatal) {
541
+ if(session_status.reliability > 0) session_status.reliability = 0;
542
+ session_status.reliability--;
543
+ }
544
+ else {
545
+ if(session_status.reliability < 0) session_status.reliability = 0;
546
+ session_status.reliability++;
547
+ }
548
+
549
+ if(last_session_status.v == STATUS_FILE_VERSION) {
550
+ for (size_t i = 0; i < _countof(session_status.dedup.slot); i++)
551
+ session_status.dedup.slot[i] = last_session_status.dedup.slot[i];
552
+ }
553
+
554
+ strncpyz(session_status.stack_traces, capture_stack_trace_backend(), sizeof(session_status.stack_traces) - 1);
555
+
556
+ dsf_release(last_session_status);
557
+ dsf_release(session_status);
558
+}
559
+
560
static void daemon_status_file_refresh(DAEMON_STATUS status) {
561
usec_t now_ut = now_realtime_usec();
562
@@ -479,15 +585,6 @@ static void daemon_status_file_refresh(DAEMON_STATUS status) {
585
if(session_status.status == DAEMON_STATUS_EXITING)
586
session_status.timings.exit = (time_t)((now_ut - session_status.timings.exit_started_ut + USEC_PER_SEC/2) / USEC_PER_SEC);
587
482
- strncpyz(session_status.version, NETDATA_VERSION, sizeof(session_status.version) - 1);
483
-
484
- session_status.boot_id = os_boot_id();
485
- if(!UUIDeq(session_status.boot_id, last_session_status.boot_id) && os_boot_ids_match(session_status.boot_id, last_session_status.boot_id)) {
486
- // there is a slight difference in boot_id, but it is still the same boot
487
- // copy the last boot_id
488
- session_status.boot_id = last_session_status.boot_id;
489
- }
490
-
588
session_status.boottime = now_boottime_sec();
589
session_status.uptime = now_realtime_sec() - netdata_start_time;
590
session_status.timestamp_ut = now_ut;
@@ -495,76 +592,14 @@ static void daemon_status_file_refresh(DAEMON_STATUS status) {
592
session_status.db_mode = default_rrd_memory_mode;
593
session_status.db_tiers = nd_profile.storage_tiers;
594
498
-#if defined(ENABLE_SENTRY)
499
- session_status.sentry_available = true;
500
-#else
501
- session_status.sentry_available = false;
502
-#endif
503
-
595
session_status.claim_id = claim_id_get_uuid();
596
597
if(localhost) {
507
- session_status.host_id = localhost->host_id;
508
- session_status.node_id = localhost->node_id;
509
- }
510
- else if(!UUIDiszero(last_session_status.host_id))
511
- session_status.host_id = last_session_status.host_id;
512
- else {
513
- const char *machine_guid = registry_get_this_machine_guid(false);
514
- if(machine_guid && *machine_guid) {
515
- if (uuid_parse_flexi(machine_guid, session_status.host_id.uuid) != 0)
516
- session_status.host_id = UUID_ZERO;
517
- }
518
- else
519
- session_status.host_id = UUID_ZERO;
520
- }
598
+ if(!UUIDiszero(localhost->host_id))
599
+ session_status.host_id = localhost->host_id;
600
522
- if(UUIDiszero(session_status.machine_id))
523
- session_status.machine_id = os_machine_id();
524
-
525
- // copy items from the old status if they are not set
526
- if(UUIDiszero(session_status.claim_id))
527
- session_status.claim_id = last_session_status.claim_id;
528
- if(UUIDiszero(session_status.node_id))
529
- session_status.node_id = last_session_status.node_id;
530
- if(UUIDiszero(session_status.host_id))
531
- session_status.host_id = last_session_status.host_id;
532
- if(!session_status.architecture[0] && last_session_status.architecture[0])
533
- strncpyz(session_status.architecture, last_session_status.architecture, sizeof(session_status.architecture) - 1);
534
- if(!session_status.virtualization[0] && last_session_status.virtualization[0])
535
- strncpyz(session_status.virtualization, last_session_status.virtualization, sizeof(session_status.virtualization) - 1);
536
- if(!session_status.container[0] && last_session_status.container[0])
537
- strncpyz(session_status.container, last_session_status.container, sizeof(session_status.container) - 1);
538
- if(!session_status.kernel_version[0] && last_session_status.kernel_version[0])
539
- strncpyz(session_status.kernel_version, last_session_status.kernel_version, sizeof(session_status.kernel_version) - 1);
540
- if(!session_status.os_name[0] && last_session_status.os_name[0])
541
- strncpyz(session_status.os_name, last_session_status.os_name, sizeof(session_status.os_name) - 1);
542
- if(!session_status.os_version[0] && last_session_status.os_version[0])
543
- strncpyz(session_status.os_version, last_session_status.os_version, sizeof(session_status.os_version) - 1);
544
- if(!session_status.os_id[0] && last_session_status.os_id[0])
545
- strncpyz(session_status.os_id, last_session_status.os_id, sizeof(session_status.os_id) - 1);
546
- if(!session_status.os_id_like[0] && last_session_status.os_id_like[0])
547
- strncpyz(session_status.os_id_like, last_session_status.os_id_like, sizeof(session_status.os_id_like) - 1);
548
- if(!session_status.restarts)
549
- session_status.restarts = last_session_status.restarts + 1;
550
-
551
- if(last_session_status.v == STATUS_FILE_VERSION) {
552
- if (!session_status.dedup.slot[0].timestamp_ut || !session_status.dedup.slot[0].hash) {
553
- for (size_t i = 0; i < _countof(session_status.dedup.slot); i++)
554
- session_status.dedup.slot[i] = last_session_status.dedup.slot[i];
555
- }
556
- }
557
-
558
- if(!session_status.install_type[0]) {
559
- char *install_type = NULL, *prebuilt_arch = NULL, *prebuilt_dist = NULL;
560
- get_install_type_internal(&install_type, &prebuilt_arch, &prebuilt_dist);
561
-
562
- if(install_type)
563
- strncpyz(session_status.install_type, install_type, sizeof(session_status.install_type) - 1);
564
-
565
- freez(prebuilt_arch);
566
- freez(prebuilt_dist);
567
- freez(install_type);
601
+ if(!UUIDiszero(localhost->node_id))
602
+ session_status.node_id = localhost->node_id;
603
}
604
605
get_daemon_status_fields_from_system_info(&session_status);
@@ -993,6 +1028,7 @@ void daemon_status_file_init(void) {
1028
static_save_buffer_init();
1029
mallocz_register_out_of_memory_cb(daemon_status_file_out_of_memory);
1030
daemon_status_file_load(&last_session_status);
1031
+ daemon_status_file_migrate_once();
1032
}
1033
1034
void daemon_status_file_check_crash(void) {
@@ -1261,6 +1297,9 @@ void daemon_status_file_register_fatal(const char *filename, const char *functio
1297
exit_initiated_add(EXIT_REASON_FATAL);
1298
session_status.exit_reason |= EXIT_REASON_FATAL;
1299
1300
+ if(!session_status.fatal.thread_id)
1301
+ session_status.fatal.thread_id = gettid_cached();
1302
+
1303
copy_and_clean_thread_name_if_empty(&session_status, nd_thread_tag());
1304
1305
if(filename && *filename)
@@ -1337,6 +1376,9 @@ bool daemon_status_file_deadly_signal_received(EXIT_REASON reason, SIGNAL_CODE c
1376
if(code)
1377
session_status.fatal.signal_code = code;
1378
1379
+ if(!session_status.fatal.thread_id)
1380
+ session_status.fatal.thread_id = gettid_cached();
1381
+
1382
copy_and_clean_thread_name_if_empty(&session_status, nd_thread_tag_async_safe());
1383
1384
dsf_release(session_status);
@@ -1465,11 +1507,30 @@ const char *daemon_status_file_get_fatal_stack_trace(void) {
1507
return session_status.fatal.stack_trace;
1508
}
1509
1510
+const char *daemon_status_file_get_stack_trace_backend(void) {
1511
+ return session_status.stack_traces;
1512
+}
1513
+
1514
const char *daemon_status_file_get_fatal_thread(void) {
1515
return session_status.fatal.thread;
1516
}
1517
1518
+pid_t daemon_status_file_get_fatal_thread_id(void) {
1519
+ return session_status.fatal.thread_id;
1520
+}
1521
+
1522
long daemon_status_file_get_fatal_line(void) {
1523
return session_status.fatal.line;
1524
}
1525
1526
+DAEMON_STATUS daemon_status_file_get_status(void) {
1527
+ return session_status.status;
1528
+}
1529
+
1530
+size_t daemon_status_file_get_restarts(void) {
1531
+ return session_status.restarts;
1532
+}
1533
+
1534
+ssize_t daemon_status_file_get_reliability(void) {
1535
+ return session_status.reliability;
1536
+}
src/daemon/daemon-status-file.h
+11
-2
@@ -7,7 +7,7 @@
7
#include "daemon/config/netdata-conf-profile.h"
8
#include "database/rrd-database-mode.h"
9
10
-#define STATUS_FILE_VERSION 17
10
+#define STATUS_FILE_VERSION 18
11
12
typedef enum {
13
DAEMON_STATUS_NONE,
@@ -44,7 +44,8 @@ typedef struct daemon_status_file {
44
time_t boottime; // system boottime
45
time_t uptime; // netdata uptime
46
usec_t timestamp_ut; // the timestamp of the status file
47
- size_t restarts; // the number of times this agent has restarted
47
+ size_t restarts; // the number of times this agent has restarted (ever)
48
+ ssize_t reliability; // consecutive restarts: > 0 reliable, < 0 crashing
49
50
ND_UUID boot_id; // the boot id of the system
51
ND_UUID invocation; // the netdata invocation id generated the file
@@ -74,6 +75,8 @@ typedef struct daemon_status_file {
75
char os_id_like[64]; // ECS: os.platform
76
bool read_system_info;
77
78
+ char stack_traces[15]; // the backend for capturing stack traces
79
+
80
struct {
81
SPINLOCK spinlock;
82
long line;
@@ -83,6 +86,7 @@ typedef struct daemon_status_file {
86
char message[512];
87
char stack_trace[2048];
88
char thread[ND_THREAD_TAG_MAX + 1];
89
+ pid_t thread_id;
90
SIGNAL_CODE signal_code;
91
bool sentry; // true when the error was also reported to sentry
92
} fatal;
@@ -129,6 +133,11 @@ const char *daemon_status_file_get_fatal_message(void);
133
const char *daemon_status_file_get_fatal_errno(void);
134
const char *daemon_status_file_get_fatal_stack_trace(void);
135
const char *daemon_status_file_get_fatal_thread(void);
136
+const char *daemon_status_file_get_stack_trace_backend(void);
137
+pid_t daemon_status_file_get_fatal_thread_id(void);
138
long daemon_status_file_get_fatal_line(void);
139
+DAEMON_STATUS daemon_status_file_get_status(void);
140
+size_t daemon_status_file_get_restarts(void);
141
+ssize_t daemon_status_file_get_reliability(void);
142
143
#endif //NETDATA_DAEMON_STATUS_FILE_H
src/daemon/libuv_workers.c
+3
@@ -86,6 +86,9 @@ static void register_libuv_worker_jobs_internal(void) {
86
// netdatacli
87
worker_register_job_name(UV_EVENT_SCHEDULE_CMD, "schedule command");
88
89
+ // make sure we have the right thread id
90
+ gettid_uncached();
91
+
92
static int workers = 0;
93
int worker_id = __atomic_add_fetch(&workers, 1, __ATOMIC_RELAXED);
94
src/daemon/sentry-native/sentry-native.c
+138
-43
@@ -17,34 +17,99 @@ void nd_sentry_crash_report(bool enable) {
17
nd_sentry_crash_report_enabled = enable;
18
}
19
20
-static sentry_value_t nd_sentry_on_crash(
21
- const sentry_ucontext_t *uctx __maybe_unused, // provides the user-space context of the crash
22
- sentry_value_t event, // used the same way as in `before_send`
23
- void *closure __maybe_unused // user-data that you can provide at configuration time
24
-) {
20
+// --------------------------------------------------------------------------------------------------------------------
21
+// helpers
22
+
23
+static void nd_sentry_set_tag(const char *key, const char *value) {
24
+ if (!value || !*value)
25
+ return;
26
+
27
+ sentry_set_tag(key, value);
28
+}
29
+
30
+static void nd_sentry_set_tag_int64(const char *key, int64_t value) {
31
+ if(!value)
32
+ return;
33
+
34
+ char buf[UINT64_MAX_LENGTH];
35
+ print_int64(buf, value);
36
+ nd_sentry_set_tag(key, buf);
37
+}
38
+
39
+static void nd_sentry_set_tag_uint64(const char *key, uint64_t value) {
40
+ if(!value)
41
+ return;
42
+
43
+ char buf[UINT64_MAX_LENGTH];
44
+ print_uint64(buf, value);
45
+ nd_sentry_set_tag(key, buf);
46
+}
47
+
48
+static void nd_sentry_set_tag_uuid(const char *key, const ND_UUID uuid) {
49
+ if(UUIDiszero(uuid))
50
+ return;
51
+
52
+ char uuid_str[UUID_STR_LEN];
53
+ uuid_unparse_lower(uuid.uuid, uuid_str);
54
+ nd_sentry_set_tag(key, uuid_str);
55
+}
56
+
57
+static void nd_sentry_set_tag_uuid_compact(const char *key, const ND_UUID uuid) {
58
+ if(UUIDiszero(uuid))
59
+ return;
60
+
61
+ char uuid_str[UUID_COMPACT_STR_LEN];
62
+ uuid_unparse_lower_compact(uuid.uuid, uuid_str);
63
+ nd_sentry_set_tag(key, uuid_str);
64
+}
65
+
66
+static void nd_sentry_set_tag_uptime(void) {
67
+ nd_sentry_set_tag_int64("uptime", now_realtime_sec() - netdata_start_time);
68
+}
69
+
70
+static void nd_sentry_set_tag_status(void) {
71
+ nd_sentry_set_tag("status", DAEMON_STATUS_2str(daemon_status_file_get_status()));
72
+}
73
+
74
+// --------------------------------------------------------------------------------------------------------------------
75
+// sentry hooks
76
+
77
+static sentry_value_t nd_sentry_on_hook(sentry_value_t event) {
78
// IMPORTANT: this function is called from a signal handler
79
80
+ // sentry enables a custom allocator for their use,
81
+ // that is async signal safe, so the sentry API is available here.
82
+
83
if (!nd_sentry_crash_report_enabled) {
84
sentry_value_decref(event);
85
return sentry_value_new_null();
86
}
87
88
+ nd_sentry_set_tag_status();
89
+ nd_sentry_set_tag_uptime();
90
+ nd_sentry_set_tag("thread", daemon_status_file_get_fatal_thread());
91
+ nd_sentry_set_tag_uint64("thread_id", daemon_status_file_get_fatal_thread_id());
92
+
93
return event;
94
}
95
96
+static sentry_value_t nd_sentry_on_crash(
97
+ const sentry_ucontext_t *uctx __maybe_unused, // provides the user-space context of the crash
98
+ sentry_value_t event, // used the same way as in `before_send`
99
+ void *closure __maybe_unused) { // user-data that you can provide at configuration time
100
+ return nd_sentry_on_hook(event);
101
+}
102
+
103
static sentry_value_t nd_sentry_before_send(
104
sentry_value_t event,
105
void *hint __maybe_unused,
106
void *closure __maybe_unused) {
39
-
40
- if (!nd_sentry_crash_report_enabled) {
41
- sentry_value_decref(event);
42
- return sentry_value_new_null();
43
- }
44
-
45
- return event;
107
+ return nd_sentry_on_hook(event);
108
}
109
110
+// --------------------------------------------------------------------------------------------------------------------
111
+// sentry initialization
112
+
113
void nd_sentry_init(void) {
114
if (!analytics_check_enabled())
115
return;
@@ -76,43 +141,42 @@ void nd_sentry_init(void) {
141
// ----------------------------------------------------------------------------------------------------------------
142
// initialization
143
79
- nd_cleanup_fatal_signals();
144
+ nd_cleanup_deadly_signals(); // remove our signal handlers, so that sentry will not hook back to us
145
sentry_init(options);
81
- nd_initialize_signals(true);
146
+ nd_initialize_signals(true); // add our signal handlers, we will hook back to sentry
147
148
// ----------------------------------------------------------------------------------------------------------------
149
// tags
150
86
- sentry_set_tag("install_type", daemon_status_file_get_install_type());
87
- sentry_set_tag("architecture", daemon_status_file_get_architecture());
88
- sentry_set_tag("virtualization", daemon_status_file_get_virtualization());
89
- sentry_set_tag("container", daemon_status_file_get_container());
90
- sentry_set_tag("os_name", daemon_status_file_get_os_name());
91
- sentry_set_tag("os_version", daemon_status_file_get_os_version());
92
- sentry_set_tag("os_id", daemon_status_file_get_os_id());
93
- sentry_set_tag("os_id_like", daemon_status_file_get_os_id_like());
151
+ nd_sentry_set_tag("install_type", daemon_status_file_get_install_type());
152
+ nd_sentry_set_tag("architecture", daemon_status_file_get_architecture());
153
+ nd_sentry_set_tag("virtualization", daemon_status_file_get_virtualization());
154
+ nd_sentry_set_tag("container", daemon_status_file_get_container());
155
+ nd_sentry_set_tag("os_name", daemon_status_file_get_os_name());
156
+ nd_sentry_set_tag("os_version", daemon_status_file_get_os_version());
157
+ nd_sentry_set_tag("os_id", daemon_status_file_get_os_id());
158
+ nd_sentry_set_tag("os_id_like", daemon_status_file_get_os_id_like());
159
160
// profile
161
CLEAN_BUFFER *profile = buffer_create(0, NULL);
162
ND_PROFILE_2buffer(profile, nd_profile_detect_and_configure(false), " ");
98
- sentry_set_tag("profile", buffer_tostring(profile));
163
+ nd_sentry_set_tag("profile", buffer_tostring(profile));
164
165
// db_mode
101
- sentry_set_tag("db_mode", rrd_memory_mode_name(default_rrd_memory_mode));
166
+ nd_sentry_set_tag("db_mode", rrd_memory_mode_name(default_rrd_memory_mode));
167
168
// db_tiers
104
- char tiers[UINT64_MAX_LENGTH];
105
- print_uint64(tiers, nd_profile.storage_tiers);
106
- sentry_set_tag("db_tiers", tiers);
169
+ nd_sentry_set_tag_int64("db_tiers", (int64_t)nd_profile.storage_tiers);
170
108
- // invocation_id
109
- ND_UUID invocation_id = nd_log_get_invocation_id();
110
- char invocation_str[UUID_COMPACT_STR_LEN];
111
- uuid_unparse_lower_compact(invocation_id.uuid, invocation_str);
112
- sentry_set_tag("ephemeral_id", invocation_str);
171
+ // ephemeral_id
172
+ nd_sentry_set_tag_uuid_compact("ephemeral_id", nd_log_get_invocation_id());
173
174
// agent_events_version
115
- sentry_set_tag("agent_events_version", TOSTRING(STATUS_FILE_VERSION));
175
+ nd_sentry_set_tag("agent_events_version", TOSTRING(STATUS_FILE_VERSION));
176
+
177
+ nd_sentry_set_tag_uint64("restarts", daemon_status_file_get_restarts());
178
+ nd_sentry_set_tag_int64("reliability", daemon_status_file_get_reliability());
179
+ nd_sentry_set_tag("stack_traces", daemon_status_file_get_stack_trace_backend());
180
}
181
182
void nd_sentry_fini(void) {
@@ -128,6 +192,36 @@ void nd_sentry_set_user(const char *guid) {
192
sentry_set_user(user);
193
}
194
195
+// --------------------------------------------------------------------------------------------------------------------
196
+// sentry breadcrumbs
197
+
198
+static void nd_sentry_add_key_value_charp(sentry_value_t data, const char *key, const char *value) {
199
+ if (!value || !*value)
200
+ return;
201
+
202
+ sentry_value_set_by_key(data, key, sentry_value_new_string(value));
203
+}
204
+
205
+static void nd_sentry_add_key_value_int64(sentry_value_t data, const char *key, int64_t value) {
206
+ if (!value)
207
+ return;
208
+
209
+ char buf[UINT64_MAX_LENGTH];
210
+ print_int64(buf, value);
211
+
212
+ sentry_value_set_by_key(data, key, sentry_value_new_string(buf));
213
+}
214
+
215
+static void nd_sentry_add_key_value_uint64(sentry_value_t data, const char *key, uint64_t value) {
216
+ if (!value)
217
+ return;
218
+
219
+ char buf[UINT64_MAX_LENGTH];
220
+ print_uint64(buf, value);
221
+
222
+ sentry_value_set_by_key(data, key, sentry_value_new_string(buf));
223
+}
224
+
225
void nd_sentry_add_fatal_message_as_breadcrumb(void) {
226
if (!analytics_check_enabled())
227
return;
@@ -136,6 +230,8 @@ void nd_sentry_add_fatal_message_as_breadcrumb(void) {
230
if(!function || !*function)
231
function = "unknown";
232
233
+ nd_sentry_set_tag_uptime();
234
+
235
// Set the transaction name to the function where the error occurred
236
// this should be low cardinality
237
sentry_set_transaction(function);
@@ -146,16 +242,15 @@ void nd_sentry_add_fatal_message_as_breadcrumb(void) {
242
sentry_value_t crumb = sentry_value_new_breadcrumb("fatal", "fatal() event details");
243
244
sentry_value_t data = sentry_value_new_object();
149
- sentry_value_set_by_key(data, "message", sentry_value_new_string(daemon_status_file_get_fatal_message()));
150
- sentry_value_set_by_key(data, "function", sentry_value_new_string(daemon_status_file_get_fatal_function()));
151
- sentry_value_set_by_key(data, "filename", sentry_value_new_string(daemon_status_file_get_fatal_filename()));
152
- sentry_value_set_by_key(data, "thread", sentry_value_new_string(daemon_status_file_get_fatal_thread()));
153
-
154
- char line[UINT64_MAX_LENGTH];
155
- print_uint64(line, daemon_status_file_get_fatal_line());
156
- sentry_value_set_by_key(data, "line", sentry_value_new_string(line));
157
- sentry_value_set_by_key(data, "errno", sentry_value_new_string(daemon_status_file_get_fatal_errno()));
158
- sentry_value_set_by_key(data, "stack_trace", sentry_value_new_string(daemon_status_file_get_fatal_stack_trace()));
245
+ nd_sentry_add_key_value_charp(data, "message", daemon_status_file_get_fatal_message());
246
+ nd_sentry_add_key_value_charp(data, "function", daemon_status_file_get_fatal_function());
247
+ nd_sentry_add_key_value_charp(data, "filename", daemon_status_file_get_fatal_filename());
248
+ nd_sentry_add_key_value_charp(data, "thread", daemon_status_file_get_fatal_thread());
249
+ nd_sentry_add_key_value_uint64(data, "thread_id", daemon_status_file_get_fatal_thread_id());
250
+ nd_sentry_add_key_value_int64(data, "line", daemon_status_file_get_fatal_line());
251
+ nd_sentry_add_key_value_charp(data, "errno", daemon_status_file_get_fatal_errno());
252
+ nd_sentry_add_key_value_charp(data, "stack_trace", daemon_status_file_get_fatal_stack_trace());
253
+ nd_sentry_add_key_value_charp(data, "status", DAEMON_STATUS_2str(daemon_status_file_get_status()));
254
255
sentry_value_set_by_key(crumb, "data", data);
256
sentry_add_breadcrumb(crumb);
src/daemon/signal-handler.c
+1
-1
@@ -138,7 +138,7 @@ static void posix_unmask_my_signals(void) {
138
netdata_log_error("SIGNAL: cannot unmask netdata signals");
139
}
140
141
-void nd_cleanup_fatal_signals(void) {
141
+void nd_cleanup_deadly_signals(void) {
142
struct sigaction act;
143
memset(&act, 0, sizeof(struct sigaction));
144
src/daemon/signal-handler.h
+1
-1
@@ -3,7 +3,7 @@
3
#ifndef NETDATA_SIGNAL_HANDLER_H
4
#define NETDATA_SIGNAL_HANDLER_H 1
5
6
-void nd_cleanup_fatal_signals(void);
6
+void nd_cleanup_deadly_signals(void);
7
void nd_initialize_signals(bool chain_existing);
8
void nd_process_signals(void) NORETURN;
9
src/database/engine/cache.c
+3
-3
@@ -2468,7 +2468,7 @@ void pgc_open_cache_to_journal_v2(PGC *cache, Word_t section, unsigned datafile_
2468
2469
size_t current_extent_index_id;
2470
Pvoid_t *PValue = JudyLIns(&JudyL_extents_pos, xio->pos, PJE0);
2471
- if(!PValue || *PValue == PJERR)
2471
+ if(!PValue || PValue == PJERR)
2472
fatal("Corrupted JudyL extents pos");
2473
2474
struct jv2_extents_info *ei;
@@ -2492,7 +2492,7 @@ void pgc_open_cache_to_journal_v2(PGC *cache, Word_t section, unsigned datafile_
2492
// update the metrics JudyL
2493
2494
PValue = JudyLIns(&JudyL_metrics, page->metric_id, PJE0);
2495
- if(!PValue || *PValue == PJERR)
2495
+ if(!PValue || PValue == PJERR)
2496
fatal("Corrupted JudyL metrics");
2497
2498
struct jv2_metrics_info *mi;
@@ -2518,7 +2518,7 @@ void pgc_open_cache_to_journal_v2(PGC *cache, Word_t section, unsigned datafile_
2518
}
2519
2520
PValue = JudyLIns(&mi->JudyL_pages_by_start_time, page->start_time_s, PJE0);
2521
- if(!PValue || *PValue == PJERR)
2521
+ if(!PValue || PValue == PJERR)
2522
fatal("Corrupted JudyL metric pages");
2523
2524
if(!*PValue) {
src/libnetdata/log/nd_log-stacktrace.c
+12
@@ -12,6 +12,10 @@ bool nd_log_forked = false;
12
#endif
13
#include <libunwind.h>
14
15
+const char *capture_stack_trace_backend(void) {
16
+ return "libunwind";
17
+}
18
+
19
void capture_stack_trace_init(void) {
20
unw_set_caching_policy(unw_local_addr_space, UNW_CACHE_NONE);
21
}
@@ -80,6 +84,10 @@ void capture_stack_trace(BUFFER *wb) {
84
85
#elif defined(HAVE_BACKTRACE)
86
87
+const char *capture_stack_trace_backend(void) {
88
+ return "backtrace";
89
+}
90
+
91
bool capture_stack_trace_available(void) {
92
return true;
93
}
@@ -151,6 +159,10 @@ void capture_stack_trace(BUFFER *wb) {
159
160
#else
161
162
+const char *capture_stack_trace_backend(void) {
163
+ return "none";
164
+}
165
+
166
bool capture_stack_trace_available(void) {
167
return false;
168
}
src/libnetdata/log/nd_log.h
+1
@@ -38,6 +38,7 @@ void capture_stack_trace_init(void);
38
void capture_stack_trace_flush(void);
39
bool capture_stack_trace_available(void);
40
bool capture_stack_trace_is_async_signal_safe(void);
41
+const char *capture_stack_trace_backend(void);
42
43
typedef void (*log_event_t)(const char *filename, const char *function, const char *message, const char *errno_str, const char *stack_trace, long line);
44
void nd_log_register_fatal_data_cb(log_event_t cb);
src/libnetdata/threads/threads.c
+5
-3
@@ -150,9 +150,11 @@ void nd_thread_tag_set(const char *tag) {
150
151
// --------------------------------------------------------------------------------------------------------------------
152
153
-static __thread bool libuv_name_set = false;
154
-void uv_thread_set_name_np(const char* name) {
155
- if(libuv_name_set) return;
153
+void uv_thread_set_name_np(const char *name) {
154
+ static __thread bool libuv_name_set = false;
155
+
156
+ if(!name || !*name || (libuv_name_set && _nd_thread_os_name[0]))
157
+ return;
158
159
strncpyz(_nd_thread_os_name, name, sizeof(_nd_thread_os_name) - 1);
160
os_set_thread_name(_nd_thread_os_name);