diff --git a/docs/api/cn/http.md b/docs/api/cn/http.md index ccb22623..6d73ffc3 100644 --- a/docs/api/cn/http.md +++ b/docs/api/cn/http.md @@ -1844,6 +1844,63 @@ node 字段选填,不填此字段时 core 不可以为 false,此时仅切换 } ``` +## 修改全局日志等级 + +*PUT* /api/v2/log/global + +### 请求头部 + +**Authorization** Bearer \ + +### 响应状态 + +* 200 OK +* 500 + * 1001 内部错误 + * 1010 程序繁忙 + +### 请求体 + +```json +{ + "level": "debug", +} +``` + +::: tip +修改所有节点以及核心的日志等级。 +::: + +### 响应 + +```json +{ + "error": 0 +} +``` + +## 获取全局日志等级 + +*GET* /api/v2/log/global + +### 请求头部 + +**Authorization** Bearer \ + +### 响应状态 + +* 200 +* 500 + * 1001 服务器内部错误 + +### 响应 + +```json +{ + "level": "info", +} +``` + ## 批量添加 Drivers *PUT* /api/v2/global/drivers diff --git a/docs/api/english/http.md b/docs/api/english/http.md index 0422336d..22233bc3 100644 --- a/docs/api/english/http.md +++ b/docs/api/english/http.md @@ -1825,6 +1825,63 @@ The node field is optional. If this field is not filled in, the core cannot be f } ``` +## Update global log level + +*PUT* /api/v2/log/global + +### Request Headers + +**Authorization** Bearer \ + +### Response Status + +* 200 OK +* 500 + * 1001 internal error + * 1010 is busy + +### Body + +```json +{ + "level": "debug", +} +``` + +::: tip +Update log level of all nodes, including the core log level. +::: + +### Response + +```json +{ + "error": 0 +} +``` + +## Get global log level + +*GET* /api/v2/log/global + +### Request Headers + +**Authorization** Bearer \ + +### Response Status + +* 200 +* 500 + * 1001 internal error + +### Response + +```json +{ + "level": "info", +} +``` + ## Get file list information *GET* /api/v2/file/info diff --git a/include/neuron/msg.h b/include/neuron/msg.h index 858b46a4..ec7ff28b 100644 --- a/include/neuron/msg.h +++ b/include/neuron/msg.h @@ -127,6 +127,8 @@ typedef enum neu_reqresp_type { NEU_REQ_ADD_DRIVERS, NEU_REQ_UPDATE_LOG_LEVEL, + NEU_REQ_UPDATE_GLOBAL_LOG_LEVEL, + NEU_REQ_UPDATE_NODE_LOG_LEVEL, NEU_REQ_PRGFILE_UPLOAD, NEU_REQ_PRGFILE_PROCESS, @@ -265,10 +267,12 @@ static const char *neu_reqresp_type_string_t[] = { [NEU_REQ_ADD_DRIVERS] = "NEU_REQ_ADD_DRIVERS", - [NEU_REQ_UPDATE_LOG_LEVEL] = "NEU_REQ_UPDATE_LOG_LEVEL", - [NEU_REQ_PRGFILE_UPLOAD] = "NEU_REQ_PRGFILE_UPLOAD", - [NEU_REQ_PRGFILE_PROCESS] = "NEU_REQ_PRGFILE_PROCESS", - [NEU_RESP_PRGFILE_PROCESS] = "NEU_RESP_PRGFILE_PROCESS", + [NEU_REQ_UPDATE_LOG_LEVEL] = "NEU_REQ_UPDATE_LOG_LEVEL", + [NEU_REQ_UPDATE_GLOBAL_LOG_LEVEL] = "NEU_REQ_UPDATE_GLOBAL_LOG_LEVEL", + [NEU_REQ_UPDATE_NODE_LOG_LEVEL] = "NEU_REQ_UPDATE_NODE_LOG_LEVEL", + [NEU_REQ_PRGFILE_UPLOAD] = "NEU_REQ_PRGFILE_UPLOAD", + [NEU_REQ_PRGFILE_PROCESS] = "NEU_REQ_PRGFILE_PROCESS", + [NEU_RESP_PRGFILE_PROCESS] = "NEU_RESP_PRGFILE_PROCESS", [NEU_REQ_SCAN_TAGS] = "NEU_REQ_SCAN_TAGS", [NEU_RESP_SCAN_TAGS] = "NEU_RESP_SCAN_TAGS", @@ -1573,6 +1577,14 @@ typedef struct neu_req_update_log_level { bool core; } neu_req_update_log_level_t; +typedef struct neu_req_update_global_log_level { + int log_level; +} neu_req_update_global_log_level_t; + +typedef struct neu_req_update_node_log_level { + int log_level; +} neu_req_update_node_log_level_t; + void neu_msg_gen(neu_reqresp_head_t *header, void *data); inline static void neu_msg_exchange(neu_reqresp_head_t *header) diff --git a/plugins/restful/handle.c b/plugins/restful/handle.c index c1462ccc..f124fdb9 100644 --- a/plugins/restful/handle.c +++ b/plugins/restful/handle.c @@ -414,6 +414,18 @@ static struct neu_http_handler rest_handlers[] = { .url = "/api/v2/log/level", .value.handler = handle_log_level, }, + { + .method = NEU_HTTP_METHOD_PUT, + .type = NEU_HTTP_HANDLER_FUNCTION, + .url = "/api/v2/log/global", + .value.handler = handle_global_log_level, + }, + { + .method = NEU_HTTP_METHOD_GET, + .type = NEU_HTTP_HANDLER_FUNCTION, + .url = "/api/v2/log/global", + .value.handler = handle_get_global_log_level, + }, { .method = NEU_HTTP_METHOD_GET, .type = NEU_HTTP_HANDLER_FUNCTION, diff --git a/plugins/restful/log_handle.c b/plugins/restful/log_handle.c index 9ba8dd30..eb58d5fd 100644 --- a/plugins/restful/log_handle.c +++ b/plugins/restful/log_handle.c @@ -31,6 +31,7 @@ #include #include +#include "core/manager.h" #include "define.h" #include "errcodes.h" #include "handle.h" @@ -104,6 +105,96 @@ void handle_log_level(nng_aio *aio) }) } +void handle_global_log_level(nng_aio *aio) +{ + neu_plugin_t *plugin = neu_rest_get_plugin(); + + NEU_PROCESS_HTTP_REQUEST_VALIDATE_JWT( + aio, neu_json_update_global_log_level_req_t, + neu_json_decode_update_global_log_level_req, { + neu_reqresp_head_t header = { 0 }; + neu_req_update_global_log_level_t cmd = { 0 }; + int log_level = -1; + + if (0 == strcmp(req->log_level, NEU_LOG_LEVEL_DEBUG)) { + log_level = ZLOG_LEVEL_DEBUG; + } else if (0 == strcmp(req->log_level, NEU_LOG_LEVEL_INFO)) { + log_level = ZLOG_LEVEL_INFO; + } else if (0 == strcmp(req->log_level, NEU_LOG_LEVEL_NOTICE)) { + log_level = ZLOG_LEVEL_NOTICE; + } else if (0 == strcmp(req->log_level, NEU_LOG_LEVEL_WARN)) { + log_level = ZLOG_LEVEL_WARN; + } else if (0 == strcmp(req->log_level, NEU_LOG_LEVEL_ERROR)) { + log_level = ZLOG_LEVEL_ERROR; + } else if (0 == strcmp(req->log_level, NEU_LOG_LEVEL_FATAL)) { + log_level = ZLOG_LEVEL_FATAL; + } else { + nlog_error("Failed to set global log_level, invalid level: %s", + req->log_level); + } + + if (log_level == -1) { + NEU_JSON_RESPONSE_ERROR(NEU_ERR_PARAM_IS_WRONG, { + neu_http_response(aio, error_code.error, result_error); + }); + } else { + header.ctx = aio; + header.type = NEU_REQ_UPDATE_GLOBAL_LOG_LEVEL; + header.otel_trace_type = NEU_OTEL_TRACE_TYPE_REST_COMM; + cmd.log_level = log_level; + + nlog_info( + "Setting global log level to %s for core and all drivers", + req->log_level); + + int ret = neu_plugin_op(plugin, header, &cmd); + if (ret != 0) { + NEU_JSON_RESPONSE_ERROR(NEU_ERR_IS_BUSY, { + neu_http_response(aio, NEU_ERR_IS_BUSY, result_error); + }); + } + } + }) +} + +void handle_get_global_log_level(nng_aio *aio) +{ + NEU_VALIDATE_JWT(aio); + + int global_log_level = neu_manager_get_global_log_level(); + const char *log_level_str = "unknown"; + + switch (global_log_level) { + case ZLOG_LEVEL_DEBUG: + log_level_str = NEU_LOG_LEVEL_DEBUG; + break; + case ZLOG_LEVEL_INFO: + log_level_str = NEU_LOG_LEVEL_INFO; + break; + case ZLOG_LEVEL_NOTICE: + log_level_str = NEU_LOG_LEVEL_NOTICE; + break; + case ZLOG_LEVEL_WARN: + log_level_str = NEU_LOG_LEVEL_WARN; + break; + case ZLOG_LEVEL_ERROR: + log_level_str = NEU_LOG_LEVEL_ERROR; + break; + case ZLOG_LEVEL_FATAL: + log_level_str = NEU_LOG_LEVEL_FATAL; + break; + default: + log_level_str = "unknown"; + break; + } + + char json_response[256]; + snprintf(json_response, sizeof(json_response), "{\"level\":\"%s\"}", + log_level_str); + + neu_http_ok(aio, json_response); +} + void handle_log_list(nng_aio *aio) { NEU_VALIDATE_JWT(aio); diff --git a/plugins/restful/log_handle.h b/plugins/restful/log_handle.h index 8d6ea49a..1a9e2f44 100644 --- a/plugins/restful/log_handle.h +++ b/plugins/restful/log_handle.h @@ -24,6 +24,8 @@ // void handle_get_log(nng_aio *aio); void handle_log_level(nng_aio *aio); +void handle_global_log_level(nng_aio *aio); +void handle_get_global_log_level(nng_aio *aio); void handle_log_list(nng_aio *aio); void handle_log_file(nng_aio *aio); diff --git a/plugins/restful/rest.c b/plugins/restful/rest.c index da46ba0f..4d6a2752 100644 --- a/plugins/restful/rest.c +++ b/plugins/restful/rest.c @@ -34,6 +34,7 @@ #include "handle.h" #include "normal_handle.h" #include "otel/otel_manager.h" +#include "parser/neu_json_log.h" #include "plugin_handle.h" #include "rest.h" #include "rw_handle.h" diff --git a/src/adapter/adapter.c b/src/adapter/adapter.c index 88ee8155..42999841 100644 --- a/src/adapter/adapter.c +++ b/src/adapter/adapter.c @@ -1572,6 +1572,25 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data) break; } + case NEU_REQ_UPDATE_NODE_LOG_LEVEL: { + neu_req_update_node_log_level_t *cmd = + (neu_req_update_node_log_level_t *) &header[1]; + + adapter->log_level = cmd->log_level; + zlog_level_switch(neu_plugin_to_plugin_common(adapter->plugin)->log, + cmd->log_level); + + struct timeval tv = { 0 }; + gettimeofday(&tv, NULL); + adapter->timestamp_lev = tv.tv_sec; + + nlog_debug("Node %s log level updated to %d", + neu_plugin_to_plugin_common(adapter->plugin)->name, + cmd->log_level); + + neu_msg_free((neu_msg_t *) header); + break; + } case NEU_REQ_PRGFILE_UPLOAD: { adapter->module->intf_funs->request( adapter->plugin, (neu_reqresp_head_t *) header, &header[1]); diff --git a/src/base/msg_internal.h b/src/base/msg_internal.h index 077c24e4..51aa37cb 100644 --- a/src/base/msg_internal.h +++ b/src/base/msg_internal.h @@ -100,6 +100,8 @@ extern "C" { XX(NEU_REQRESP_NODE_DELETED, neu_reqresp_node_deleted_t) \ XX(NEU_REQ_ADD_DRIVERS, neu_req_driver_array_t) \ XX(NEU_REQ_UPDATE_LOG_LEVEL, neu_req_update_log_level_t) \ + XX(NEU_REQ_UPDATE_GLOBAL_LOG_LEVEL, neu_req_update_global_log_level_t) \ + XX(NEU_REQ_UPDATE_NODE_LOG_LEVEL, neu_req_update_node_log_level_t) \ XX(NEU_REQ_PRGFILE_UPLOAD, neu_req_prgfile_upload_t) \ XX(NEU_REQ_PRGFILE_PROCESS, neu_req_prgfile_process_t) \ XX(NEU_RESP_PRGFILE_PROCESS, neu_resp_prgfile_process_t) \ diff --git a/src/core/manager.c b/src/core/manager.c index 53727ef8..90f101c1 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -82,6 +82,15 @@ uint16_t neu_manager_get_port() return port++; } +int neu_manager_get_global_log_level() +{ + extern neu_manager_t *g_manager; + if (g_manager != NULL) { + return g_manager->log_level; + } + return ZLOG_LEVEL_INFO; +} + neu_manager_t *neu_manager_create() { int rv = 0; @@ -1606,6 +1615,61 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data) break; } + case NEU_REQ_UPDATE_GLOBAL_LOG_LEVEL: { + neu_req_update_global_log_level_t *cmd = + (neu_req_update_global_log_level_t *) &header[1]; + + nlog_info("Setting global log level to %d for core and all nodes", + cmd->log_level); + + manager->log_level = cmd->log_level; + nlog_level_change(manager->log_level); + + UT_array *nodes = neu_node_manager_get_all(manager->node_manager); + if (nodes != NULL) { + neu_resp_node_info_t *node_info = NULL; + while ((node_info = (neu_resp_node_info_t *) utarray_next( + nodes, node_info)) != NULL) { + neu_reqresp_head_t node_header = { 0 }; + neu_req_update_node_log_level_t node_cmd = { 0 }; + + node_header.type = NEU_REQ_UPDATE_NODE_LOG_LEVEL; + node_header.ctx = NULL; + node_header.otel_trace_type = header->otel_trace_type; + node_header.monitor = false; + strcpy(node_header.sender, "manager"); + strcpy(node_header.receiver, node_info->node); + + node_cmd.log_level = cmd->log_level; + + neu_msg_t *node_msg = neu_msg_new(NEU_REQ_UPDATE_NODE_LOG_LEVEL, + &node_header, &node_cmd); + if (node_msg != NULL) { + struct sockaddr_un addr = neu_node_manager_get_addr( + manager->node_manager, node_info->node); + int ret = + neu_send_msg_to(manager->server_fd, &addr, node_msg); + if (ret != 0) { + nlog_warn("Failed to send global log level update to " + "node %s, ret: %d", + node_info->node, ret); + neu_msg_free(node_msg); + } else { + nlog_debug("Sent global log level update to node %s", + node_info->node); + } + } + } + utarray_free(nodes); + } + + neu_resp_error_t e = { .error = NEU_ERR_SUCCESS }; + header->type = NEU_RESP_ERROR; + neu_msg_exchange(header); + reply(manager, header, &e); + + break; + } case NEU_REQ_ADD_NODE_EVENT: case NEU_REQ_DEL_NODE_EVENT: case NEU_REQ_NODE_CTL_EVENT: diff --git a/src/core/manager.h b/src/core/manager.h index 8f7c8c25..20449a9f 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -30,5 +30,6 @@ neu_manager_t *neu_manager_create(); void neu_manager_destroy(neu_manager_t *manager); uint16_t neu_manager_get_port(); +int neu_manager_get_global_log_level(); #endif diff --git a/src/parser/neu_json_log.c b/src/parser/neu_json_log.c index 58b2f3d1..70c256b6 100644 --- a/src/parser/neu_json_log.c +++ b/src/parser/neu_json_log.c @@ -27,10 +27,12 @@ #include "json/json.h" +#include "msg.h" #include "neu_json_log.h" #include "utils/log.h" #include "utils/utarray.h" #include "utils/utextend.h" +#include "utils/zlog.h" int neu_json_decode_update_log_level_req( char *buf, neu_json_update_log_level_req_t **result) @@ -103,6 +105,54 @@ void neu_json_decode_update_log_level_req_free( } } +int neu_json_decode_update_global_log_level_req( + char *buf, neu_json_update_global_log_level_req_t **result) +{ + int ret = 0; + void *json_obj = neu_json_decode_new(buf); + + neu_json_update_global_log_level_req_t *req = + calloc(1, sizeof(neu_json_update_global_log_level_req_t)); + if (req == NULL) { + return -1; + } + + neu_json_elem_t req_elems[] = { { + .name = "level", + .t = NEU_JSON_STR, + } }; + + ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_elems), + req_elems); + if (ret != 0) { + goto decode_fail; + } + + req->log_level = req_elems[0].v.val_str; + *result = req; + goto decode_exit; + +decode_fail: + free(req); + ret = -1; +decode_exit: + if (json_obj != NULL) { + neu_json_decode_free(json_obj); + } + return ret; +} + +void neu_json_decode_update_global_log_level_req_free( + neu_json_update_global_log_level_req_t *req) +{ + if (req->log_level != NULL) { + free(req->log_level); + } + if (req != NULL) { + free(req); + } +} + int neu_json_encode_log_list_resp(void *json_object, void *param) { int ret = 0; diff --git a/src/parser/neu_json_log.h b/src/parser/neu_json_log.h index e111f741..d4072e45 100644 --- a/src/parser/neu_json_log.h +++ b/src/parser/neu_json_log.h @@ -39,6 +39,10 @@ typedef struct { bool core; } neu_json_update_log_level_req_t; +typedef struct { + char *log_level; +} neu_json_update_global_log_level_req_t; + typedef struct { int64_t page_count; int n_row; @@ -55,6 +59,12 @@ void neu_json_decode_update_log_level_req_free( neu_json_update_log_level_req_t *req); int neu_json_decode_update_log_level_req( char *buf, neu_json_update_log_level_req_t **result); + +void neu_json_decode_update_global_log_level_req_free( + neu_json_update_global_log_level_req_t *req); +int neu_json_decode_update_global_log_level_req( + char *buf, neu_json_update_global_log_level_req_t **result); + int neu_json_encode_log_list_resp(void *json_object, void *param); #ifdef __cplusplus