|
28 | 28 |
|
29 | 29 | #include <umf.h>
|
30 | 30 |
|
| 31 | +#include "ctl/ctl_internal.h" |
31 | 32 | #include "utils_assert.h"
|
32 | 33 | #include "utils_common.h"
|
33 | 34 | #include "utils_log.h"
|
@@ -61,14 +62,15 @@ char const __umf_str_1__all_cmake_vars[] =
|
61 | 62 | #define MAX_ENV_LEN 2048
|
62 | 63 |
|
63 | 64 | typedef struct {
|
64 |
| - int timestamp; |
65 |
| - int pid; |
| 65 | + bool timestamp; |
| 66 | + bool pid; |
66 | 67 | utils_log_level_t level;
|
67 | 68 | utils_log_level_t flushLevel;
|
68 | 69 | FILE *output;
|
| 70 | + const char *file_name; |
69 | 71 | } utils_log_config_t;
|
70 | 72 |
|
71 |
| -utils_log_config_t loggerConfig = {0, 0, LOG_ERROR, LOG_ERROR, NULL}; |
| 73 | +utils_log_config_t loggerConfig = {0, 0, LOG_ERROR, LOG_ERROR, NULL, NULL}; |
72 | 74 |
|
73 | 75 | static const char *level_to_str(utils_log_level_t l) {
|
74 | 76 | switch (l) {
|
@@ -254,8 +256,10 @@ void utils_log_init(void) {
|
254 | 256 | const char *arg;
|
255 | 257 | if (utils_parse_var(envVar, "output:stdout", NULL)) {
|
256 | 258 | loggerConfig.output = stdout;
|
| 259 | + loggerConfig.file_name = "stdout"; |
257 | 260 | } else if (utils_parse_var(envVar, "output:stderr", NULL)) {
|
258 | 261 | loggerConfig.output = stderr;
|
| 262 | + loggerConfig.file_name = "stderr"; |
259 | 263 | } else if (utils_parse_var(envVar, "output:file", &arg)) {
|
260 | 264 | loggerConfig.output = NULL;
|
261 | 265 | const char *argEnd = strstr(arg, ";");
|
@@ -284,6 +288,7 @@ void utils_log_init(void) {
|
284 | 288 | loggerConfig.output = NULL;
|
285 | 289 | return;
|
286 | 290 | }
|
| 291 | + loggerConfig.file_name = file; |
287 | 292 | } else {
|
288 | 293 | loggerConfig.output = stderr;
|
289 | 294 | LOG_ERR("Logging output not set - logging disabled (UMF_LOG = \"%s\")",
|
@@ -334,3 +339,249 @@ void utils_log_init(void) {
|
334 | 339 | level_to_str(loggerConfig.level), level_to_str(loggerConfig.flushLevel),
|
335 | 340 | bool_to_str(loggerConfig.pid), bool_to_str(loggerConfig.timestamp));
|
336 | 341 | }
|
| 342 | + |
| 343 | +// this is needed for logger unit test |
| 344 | +#ifndef DISABLE_CTL_LOGGER |
| 345 | +static umf_result_t |
| 346 | +CTL_READ_HANDLER(timestamp)(void *ctx, umf_ctl_query_source_t source, void *arg, |
| 347 | + size_t size, umf_ctl_index_utlist_t *indexes) { |
| 348 | + /* suppress unused-parameter errors */ |
| 349 | + (void)source, (void)indexes, (void)ctx; |
| 350 | + |
| 351 | + bool *arg_out = (bool *)arg; |
| 352 | + |
| 353 | + if (arg_out == NULL || size < sizeof(bool)) { |
| 354 | + return UMF_RESULT_ERROR_INVALID_ARGUMENT; |
| 355 | + } |
| 356 | + |
| 357 | + *arg_out = loggerConfig.timestamp; |
| 358 | + return UMF_RESULT_SUCCESS; |
| 359 | +} |
| 360 | + |
| 361 | +static umf_result_t |
| 362 | +CTL_WRITE_HANDLER(timestamp)(void *ctx, umf_ctl_query_source_t source, |
| 363 | + void *arg, size_t size, |
| 364 | + umf_ctl_index_utlist_t *indexes) { |
| 365 | + /* suppress unused-parameter errors */ |
| 366 | + (void)source, (void)indexes, (void)ctx; |
| 367 | + |
| 368 | + bool arg_in = *(bool *)arg; |
| 369 | + |
| 370 | + if (size < sizeof(bool)) { |
| 371 | + return UMF_RESULT_ERROR_INVALID_ARGUMENT; |
| 372 | + } |
| 373 | + |
| 374 | + loggerConfig.timestamp = arg_in; |
| 375 | + LOG_INFO("Logger print timestamp set to %s", |
| 376 | + bool_to_str(loggerConfig.timestamp)); |
| 377 | + return UMF_RESULT_SUCCESS; |
| 378 | +} |
| 379 | + |
| 380 | +static umf_result_t CTL_READ_HANDLER(pid)(void *ctx, |
| 381 | + umf_ctl_query_source_t source, |
| 382 | + void *arg, size_t size, |
| 383 | + umf_ctl_index_utlist_t *indexes) { |
| 384 | + /* suppress unused-parameter errors */ |
| 385 | + (void)source, (void)indexes, (void)ctx; |
| 386 | + |
| 387 | + bool *arg_out = (bool *)arg; |
| 388 | + |
| 389 | + if (arg_out == NULL || size < sizeof(bool)) { |
| 390 | + return UMF_RESULT_ERROR_INVALID_ARGUMENT; |
| 391 | + } |
| 392 | + |
| 393 | + *arg_out = loggerConfig.pid; |
| 394 | + return UMF_RESULT_SUCCESS; |
| 395 | +} |
| 396 | + |
| 397 | +static umf_result_t CTL_WRITE_HANDLER(pid)(void *ctx, |
| 398 | + umf_ctl_query_source_t source, |
| 399 | + void *arg, size_t size, |
| 400 | + umf_ctl_index_utlist_t *indexes) { |
| 401 | + /* suppress unused-parameter errors */ |
| 402 | + (void)source, (void)indexes, (void)ctx; |
| 403 | + |
| 404 | + bool arg_in = *(bool *)arg; |
| 405 | + |
| 406 | + if (size < sizeof(bool)) { |
| 407 | + return UMF_RESULT_ERROR_INVALID_ARGUMENT; |
| 408 | + } |
| 409 | + |
| 410 | + loggerConfig.pid = arg_in; |
| 411 | + LOG_INFO("Logger print pid %s set to", bool_to_str(loggerConfig.pid)); |
| 412 | + return UMF_RESULT_SUCCESS; |
| 413 | +} |
| 414 | + |
| 415 | +static umf_result_t CTL_READ_HANDLER(level)(void *ctx, |
| 416 | + umf_ctl_query_source_t source, |
| 417 | + void *arg, size_t size, |
| 418 | + umf_ctl_index_utlist_t *indexes) { |
| 419 | + /* suppress unused-parameter errors */ |
| 420 | + (void)source, (void)indexes, (void)ctx; |
| 421 | + |
| 422 | + bool *arg_out = (bool *)arg; |
| 423 | + |
| 424 | + if (arg_out == NULL || size < sizeof(utils_log_level_t)) { |
| 425 | + return UMF_RESULT_ERROR_INVALID_ARGUMENT; |
| 426 | + } |
| 427 | + |
| 428 | + *arg_out = loggerConfig.level; |
| 429 | + return UMF_RESULT_SUCCESS; |
| 430 | +} |
| 431 | + |
| 432 | +static umf_result_t CTL_WRITE_HANDLER(level)(void *ctx, |
| 433 | + umf_ctl_query_source_t source, |
| 434 | + void *arg, size_t size, |
| 435 | + umf_ctl_index_utlist_t *indexes) { |
| 436 | + /* suppress unused-parameter errors */ |
| 437 | + (void)source, (void)indexes, (void)ctx; |
| 438 | + |
| 439 | + utils_log_level_t *arg_in = (utils_log_level_t *)arg; |
| 440 | + |
| 441 | + if (arg_in == NULL || *arg_in < LOG_DEBUG || *arg_in > LOG_FATAL || |
| 442 | + size < sizeof(int)) { |
| 443 | + return UMF_RESULT_ERROR_INVALID_ARGUMENT; |
| 444 | + } |
| 445 | + |
| 446 | + utils_log_level_t old = loggerConfig.level; |
| 447 | + |
| 448 | + // if new log level is higher then LOG_INFO print log before changing log level |
| 449 | + // so if user changes from LOG_INFO to higher log level, it will get information about change anyway |
| 450 | + if (*arg_in > LOG_INFO) { |
| 451 | + LOG_INFO("Logger level changed from %s to %s", level_to_str(old), |
| 452 | + level_to_str(*arg_in)); |
| 453 | + loggerConfig.level = *arg_in; |
| 454 | + } else { |
| 455 | + loggerConfig.level = *arg_in; |
| 456 | + LOG_INFO("Logger level changed from %s to %s", level_to_str(old), |
| 457 | + level_to_str(loggerConfig.level)); |
| 458 | + } |
| 459 | + |
| 460 | + return UMF_RESULT_SUCCESS; |
| 461 | +} |
| 462 | + |
| 463 | +static umf_result_t |
| 464 | +CTL_READ_HANDLER(flush_level)(void *ctx, umf_ctl_query_source_t source, |
| 465 | + void *arg, size_t size, |
| 466 | + umf_ctl_index_utlist_t *indexes) { |
| 467 | + /* suppress unused-parameter errors */ |
| 468 | + (void)source, (void)indexes, (void)ctx; |
| 469 | + |
| 470 | + utils_log_level_t *arg_out = (utils_log_level_t *)arg; |
| 471 | + |
| 472 | + if (arg_out == NULL || size < sizeof(utils_log_level_t)) { |
| 473 | + return UMF_RESULT_ERROR_INVALID_ARGUMENT; |
| 474 | + } |
| 475 | + |
| 476 | + *arg_out = loggerConfig.flushLevel; |
| 477 | + return UMF_RESULT_SUCCESS; |
| 478 | +} |
| 479 | + |
| 480 | +static umf_result_t |
| 481 | +CTL_WRITE_HANDLER(flush_level)(void *ctx, umf_ctl_query_source_t source, |
| 482 | + void *arg, size_t size, |
| 483 | + umf_ctl_index_utlist_t *indexes) { |
| 484 | + /* suppress unused-parameter errors */ |
| 485 | + (void)source, (void)indexes, (void)ctx; |
| 486 | + |
| 487 | + utils_log_level_t *arg_in = (utils_log_level_t *)arg; |
| 488 | + |
| 489 | + if (arg_in == NULL || *arg_in < LOG_DEBUG || *arg_in > LOG_FATAL || |
| 490 | + size < sizeof(int)) { |
| 491 | + return UMF_RESULT_ERROR_INVALID_ARGUMENT; |
| 492 | + } |
| 493 | + |
| 494 | + loggerConfig.flushLevel = *arg_in; |
| 495 | + LOG_INFO("Logger flush level set to %s", |
| 496 | + level_to_str(loggerConfig.flushLevel)); |
| 497 | + return UMF_RESULT_SUCCESS; |
| 498 | +} |
| 499 | + |
| 500 | +static umf_result_t CTL_READ_HANDLER(output)(void *ctx, |
| 501 | + umf_ctl_query_source_t source, |
| 502 | + void *arg, size_t size, |
| 503 | + umf_ctl_index_utlist_t *indexes) { |
| 504 | + /* suppress unused-parameter errors */ |
| 505 | + (void)source, (void)indexes, (void)ctx; |
| 506 | + |
| 507 | + const char **arg_out = (const char **)arg; |
| 508 | + if (arg_out == NULL || size < sizeof(const char *)) { |
| 509 | + return UMF_RESULT_ERROR_INVALID_ARGUMENT; |
| 510 | + } |
| 511 | + |
| 512 | + if (loggerConfig.output == NULL) { |
| 513 | + *arg_out = "logger_disabled"; |
| 514 | + return UMF_RESULT_SUCCESS; |
| 515 | + } |
| 516 | + |
| 517 | + *arg_out = loggerConfig.file_name; |
| 518 | + return UMF_RESULT_SUCCESS; |
| 519 | +} |
| 520 | + |
| 521 | +static umf_result_t CTL_WRITE_HANDLER(output)(void *ctx, |
| 522 | + umf_ctl_query_source_t source, |
| 523 | + void *arg, size_t size, |
| 524 | + umf_ctl_index_utlist_t *indexes) { |
| 525 | + /* suppress unused-parameter errors */ |
| 526 | + (void)source, (void)indexes, (void)ctx; |
| 527 | + |
| 528 | + const char *arg_in = *(const char **)arg; |
| 529 | + if (size < sizeof(const char *)) { |
| 530 | + return UMF_RESULT_ERROR_INVALID_ARGUMENT; |
| 531 | + } |
| 532 | + |
| 533 | + FILE *oldHandle = loggerConfig.output; |
| 534 | + const char *oldName = |
| 535 | + loggerConfig.file_name ? loggerConfig.file_name : "disabled"; |
| 536 | + |
| 537 | + if (arg_in == NULL) { |
| 538 | + if (loggerConfig.output) { |
| 539 | + LOG_INFO("Logger disabled"); |
| 540 | + if (oldHandle != stdout && oldHandle != stderr) { |
| 541 | + fclose(oldHandle); |
| 542 | + } |
| 543 | + loggerConfig.output = NULL; |
| 544 | + loggerConfig.file_name = NULL; |
| 545 | + } |
| 546 | + return UMF_RESULT_SUCCESS; |
| 547 | + } |
| 548 | + |
| 549 | + FILE *newHandle = NULL; |
| 550 | + |
| 551 | + if (strcmp(arg_in, "stdout") == 0) { |
| 552 | + newHandle = stdout; |
| 553 | + loggerConfig.file_name = "stdout"; |
| 554 | + } else if (strcmp(arg_in, "stderr") == 0) { |
| 555 | + newHandle = stderr; |
| 556 | + loggerConfig.file_name = "stderr"; |
| 557 | + } else { |
| 558 | + newHandle = fopen(arg_in, "a"); |
| 559 | + if (!newHandle) { |
| 560 | + return UMF_RESULT_ERROR_INVALID_ARGUMENT; |
| 561 | + } |
| 562 | + loggerConfig.file_name = arg_in; |
| 563 | + } |
| 564 | + |
| 565 | + loggerConfig.output = newHandle; |
| 566 | + LOG_INFO("Logger output changed from %s to %s", oldName, |
| 567 | + loggerConfig.file_name); |
| 568 | + |
| 569 | + if (oldHandle && oldHandle != stdout && oldHandle != stderr) { |
| 570 | + fclose(oldHandle); |
| 571 | + } |
| 572 | + |
| 573 | + return UMF_RESULT_SUCCESS; |
| 574 | +} |
| 575 | + |
| 576 | +static const struct ctl_argument CTL_ARG(timestamp) = CTL_ARG_BOOLEAN; |
| 577 | +static const struct ctl_argument CTL_ARG(pid) = CTL_ARG_BOOLEAN; |
| 578 | +static const struct ctl_argument CTL_ARG(level) = CTL_ARG_INT; |
| 579 | +static const struct ctl_argument CTL_ARG(flush_level) = CTL_ARG_INT; |
| 580 | +static const struct ctl_argument |
| 581 | + CTL_ARG(output) = CTL_ARG_STRING(MAX_FILE_PATH); |
| 582 | + |
| 583 | +const umf_ctl_node_t CTL_NODE(logger)[] = { |
| 584 | + CTL_LEAF_RW(timestamp), CTL_LEAF_RW(pid), CTL_LEAF_RW(level), |
| 585 | + CTL_LEAF_RW(flush_level), CTL_LEAF_RW(output), CTL_NODE_END, |
| 586 | +}; |
| 587 | +#endif |
0 commit comments