From 62a28fd36e260d4966246934db8d24908858a3a5 Mon Sep 17 00:00:00 2001 From: Martin Vogel Date: Sun, 28 Jun 2026 13:05:05 +0200 Subject: [PATCH] fix(logging): use local log schema Signed-off-by: Martin Vogel --- src/foundation/log.c | 38 ++++++++++---------------------------- tests/test_httpd.c | 6 +++--- tests/test_log.c | 27 ++++++++++++++------------- tests/test_mcp.c | 9 ++++----- 4 files changed, 31 insertions(+), 49 deletions(-) diff --git a/src/foundation/log.c b/src/foundation/log.c index fd916524a..fc4bb6c9e 100644 --- a/src/foundation/log.c +++ b/src/foundation/log.c @@ -111,21 +111,6 @@ static const char *level_str(CBMLogLevel level) { } } -static const char *severity_str(CBMLogLevel level) { - switch (level) { - case CBM_LOG_DEBUG: - return "DEBUG"; - case CBM_LOG_INFO: - return "INFO"; - case CBM_LOG_WARN: - return "WARNING"; - case CBM_LOG_ERROR: - return "ERROR"; - default: - return "DEFAULT"; - } -} - static void append_char(char *buf, size_t bufsz, size_t *pos, char ch) { if (*pos < bufsz - 1) { buf[*pos] = ch; @@ -231,10 +216,8 @@ void cbm_log(CBMLogLevel level, const char *msg, ...) { va_start(args, msg); if (g_log_format == CBM_LOG_FORMAT_JSON) { - append_raw(line_buf, sizeof(line_buf), &pos, "{\"severity\":"); - append_json_string(line_buf, sizeof(line_buf), &pos, severity_str(level)); - append_raw(line_buf, sizeof(line_buf), &pos, ",\"message\":"); - append_json_string(line_buf, sizeof(line_buf), &pos, msg ? msg : ""); + append_raw(line_buf, sizeof(line_buf), &pos, "{\"level\":"); + append_json_string(line_buf, sizeof(line_buf), &pos, level_str(level)); append_raw(line_buf, sizeof(line_buf), &pos, ",\"event\":"); append_json_string(line_buf, sizeof(line_buf), &pos, msg ? msg : ""); for (;;) { @@ -299,13 +282,13 @@ void cbm_log_mcp_request(const char *method, const char *tool_name, bool is_erro char duration_ms[CBM_SZ_32]; snprintf(duration_ms, sizeof(duration_ms), "%" PRId64, duration_us / 1000); if (tool_name && tool_name[0] != '\0') { - cbm_log(is_error ? CBM_LOG_WARN : CBM_LOG_INFO, "mcp.request", "rpc.system", "jsonrpc", - "rpc.method", method ? method : "", "mcp.tool.name", tool_name, "status", + cbm_log(is_error ? CBM_LOG_WARN : CBM_LOG_INFO, "mcp.request", "protocol", "jsonrpc", + "method", method ? method : "", "tool", tool_name, "status", is_error ? "error" : "ok", "duration_ms", duration_ms, NULL); } else { - cbm_log(is_error ? CBM_LOG_WARN : CBM_LOG_INFO, "mcp.request", "rpc.system", "jsonrpc", - "rpc.method", method ? method : "", "status", is_error ? "error" : "ok", - "duration_ms", duration_ms, NULL); + cbm_log(is_error ? CBM_LOG_WARN : CBM_LOG_INFO, "mcp.request", "protocol", "jsonrpc", + "method", method ? method : "", "status", is_error ? "error" : "ok", "duration_ms", + duration_ms, NULL); } } @@ -329,8 +312,7 @@ void cbm_log_http_request(const char *component, const char *method, const char level = CBM_LOG_WARN; } - cbm_log(level, "http.request", "component", component ? component : "", "http.request.method", - method ? method : "", "url.path", safe_path, "http.response.status_code", status_buf, - "duration_ms", duration_buf, "http.request.body.size", request_buf, - "http.response.body.size", response_buf, NULL); + cbm_log(level, "http.request", "component", component ? component : "", "method", + method ? method : "", "path", safe_path, "status", status_buf, "duration_ms", + duration_buf, "request_bytes", request_buf, "response_bytes", response_buf, NULL); } diff --git a/tests/test_httpd.c b/tests/test_httpd.c index 8aea6ccdf..d5609786f 100644 --- a/tests/test_httpd.c +++ b/tests/test_httpd.c @@ -569,9 +569,9 @@ TEST(ui_server_access_log_redacts_query) { ASSERT_NOT_NULL(strstr(httpd_log_buf, "msg=http.request")); ASSERT_NOT_NULL(strstr(httpd_log_buf, "component=graph_ui")); - ASSERT_NOT_NULL(strstr(httpd_log_buf, "http.request.method=GET")); - ASSERT_NOT_NULL(strstr(httpd_log_buf, "url.path=/definitely/not/here")); - ASSERT_NOT_NULL(strstr(httpd_log_buf, "http.response.status_code=404")); + ASSERT_NOT_NULL(strstr(httpd_log_buf, "method=GET")); + ASSERT_NOT_NULL(strstr(httpd_log_buf, "path=/definitely/not/here")); + ASSERT_NOT_NULL(strstr(httpd_log_buf, "status=404")); ASSERT_NULL(strstr(httpd_log_buf, "token")); ASSERT_NULL(strstr(httpd_log_buf, "secret")); PASS(); diff --git a/tests/test_log.c b/tests/test_log.c index 5a1fdb7aa..562768567 100644 --- a/tests/test_log.c +++ b/tests/test_log.c @@ -126,8 +126,8 @@ TEST(log_json_output) { cbm_log_set_format(CBM_LOG_FORMAT_TEXT); cbm_log_set_level(CBM_LOG_INFO); - ASSERT(cbm_str_contains_raw(output, "\"severity\":\"INFO\"")); - ASSERT(cbm_str_contains_raw(output, "\"message\":\"test.msg\"")); + ASSERT(cbm_str_contains_raw(output, "\"level\":\"info\"")); + ASSERT(cbm_str_contains_raw(output, "\"event\":\"test.msg\"")); ASSERT(cbm_str_contains_raw(output, "\"key1\":\"val1\"")); ASSERT(cbm_str_contains_raw(output, "\"key2\":\"line\\nbreak\"")); PASS(); @@ -174,12 +174,13 @@ TEST(log_operational_helpers) { cbm_log_set_level(CBM_LOG_INFO); ASSERT(cbm_str_contains_raw(output, "msg=mcp.request")); - ASSERT(cbm_str_contains_raw(output, "rpc.method=tools/call")); - ASSERT(cbm_str_contains_raw(output, "mcp.tool.name=search_graph")); + ASSERT(cbm_str_contains_raw(output, "protocol=jsonrpc")); + ASSERT(cbm_str_contains_raw(output, "method=tools/call")); + ASSERT(cbm_str_contains_raw(output, "tool=search_graph")); ASSERT(cbm_str_contains_raw(output, "msg=http.request")); - ASSERT(cbm_str_contains_raw(output, "http.request.method=GET")); - ASSERT(cbm_str_contains_raw(output, "url.path=/api/layout")); - ASSERT(cbm_str_contains_raw(output, "http.response.status_code=200")); + ASSERT(cbm_str_contains_raw(output, "method=GET")); + ASSERT(cbm_str_contains_raw(output, "path=/api/layout")); + ASSERT(cbm_str_contains_raw(output, "status=200")); PASS(); } @@ -197,16 +198,16 @@ TEST(log_format_from_env) { PASS(); } -TEST(log_format_is_explicit_only) { +TEST(log_format_unset_keeps_current) { cbm_unsetenv("CBM_LOG_FORMAT"); - cbm_setenv("ENVIRONMENT", "production", 1); - cbm_setenv("K_SERVICE", "cbm", 1); + cbm_log_set_format(CBM_LOG_FORMAT_JSON); + cbm_log_init_from_env(); + ASSERT_EQ(cbm_log_get_format(), CBM_LOG_FORMAT_JSON); + cbm_log_set_format(CBM_LOG_FORMAT_TEXT); cbm_log_init_from_env(); ASSERT_EQ(cbm_log_get_format(), CBM_LOG_FORMAT_TEXT); - cbm_unsetenv("ENVIRONMENT"); - cbm_unsetenv("K_SERVICE"); PASS(); } @@ -294,7 +295,7 @@ SUITE(log) { RUN_TEST(log_sink_tee_keeps_stderr); RUN_TEST(log_operational_helpers); RUN_TEST(log_format_from_env); - RUN_TEST(log_format_is_explicit_only); + RUN_TEST(log_format_unset_keeps_current); RUN_TEST(log_level_from_env_textual); RUN_TEST(log_level_from_env_numeric); RUN_TEST(log_level_from_env_invalid_ignored); diff --git a/tests/test_mcp.c b/tests/test_mcp.c index 554c444d7..ab728eb86 100644 --- a/tests/test_mcp.c +++ b/tests/test_mcp.c @@ -422,9 +422,8 @@ TEST(server_handle_logs_request_without_params) { cbm_mcp_server_t *srv = cbm_mcp_server_new(NULL); char *resp = - cbm_mcp_server_handle(srv, - "{\"jsonrpc\":\"2.0\",\"id\":210,\"method\":\"tools/list\"," - "\"params\":{\"token\":\"secret\"}}"); + cbm_mcp_server_handle(srv, "{\"jsonrpc\":\"2.0\",\"id\":210,\"method\":\"tools/list\"," + "\"params\":{\"token\":\"secret\"}}"); ASSERT_NOT_NULL(resp); free(resp); cbm_mcp_server_free(srv); @@ -433,8 +432,8 @@ TEST(server_handle_logs_request_without_params) { cbm_log_set_level(prev_level); ASSERT_NOT_NULL(strstr(mcp_log_buf, "msg=mcp.request")); - ASSERT_NOT_NULL(strstr(mcp_log_buf, "rpc.system=jsonrpc")); - ASSERT_NOT_NULL(strstr(mcp_log_buf, "rpc.method=tools/list")); + ASSERT_NOT_NULL(strstr(mcp_log_buf, "protocol=jsonrpc")); + ASSERT_NOT_NULL(strstr(mcp_log_buf, "method=tools/list")); ASSERT_NOT_NULL(strstr(mcp_log_buf, "status=ok")); ASSERT_NULL(strstr(mcp_log_buf, "token")); ASSERT_NULL(strstr(mcp_log_buf, "secret"));