MCPcopy Create free account
hub / github.com/DeusData/codebase-memory-mcp / handle_logs

Function handle_logs

src/ui/http_server.c:477–548  ·  view source on GitHub ↗

GET /api/logs?lines=N — returns last N log lines */

Source from the content-addressed store, hash-verified

475
476/* GET /api/logs?lines=N — returns last N log lines */
477static void handle_logs(cbm_http_conn_t *c, const cbm_http_req_t *req) {
478 char lines_str[16] = {0};
479 int max_lines = 100;
480 if (cbm_http_query_param(req->query, "lines", lines_str, (int)sizeof(lines_str))) {
481 int v = atoi(lines_str);
482 if (v > 0 && v <= LOG_RING_SIZE)
483 max_lines = v;
484 }
485
486 cbm_mutex_lock(&g_log_mutex);
487 int count = g_log_count < max_lines ? g_log_count : max_lines;
488 int start = (g_log_head - count + LOG_RING_SIZE) % LOG_RING_SIZE;
489 int total = g_log_count;
490
491 /* Copy lines under lock.
492 *
493 * JSON escaping expands '"', '\\' and '\n' to two bytes each, so an
494 * line made mostly of those serialises to roughly twice its stored length.
495 * The previous budget of LOG_LINE_MAX + 10 per line under-counted that by
496 * half. Ring contents come from indexer stderr, which is not escaped on
497 * ingest and can legitimately contain both doubling characters — a POSIX
498 * filename may.
499 *
500 * Budget the escaped worst case, and clamp the framing writes below anyway
501 * so the size calculation is not the only thing keeping pos in range. */
502 size_t buf_size = (size_t)count * (2 * LOG_LINE_MAX + 8) + 64;
503 char *buf = malloc(buf_size);
504 if (!buf) {
505 cbm_mutex_unlock(&g_log_mutex);
506 cbm_http_replyf(c, 500, g_cors, "oom");
507 return;
508 }
509
510 int pos = 0;
511 http_appendf(buf, buf_size, &pos, "{\"lines\":[");
512 for (int i = 0; i < count; i++) {
513 int idx = (start + i) % LOG_RING_SIZE;
514 if (i > 0)
515 http_appendf(buf, buf_size, &pos, ",");
516 /* Escape quotes in log lines */
517 http_appendf(buf, buf_size, &pos, "\"");
518 for (int j = 0; g_log_ring[idx][j] && (size_t)pos < buf_size - 10; j++) {
519 char ch = g_log_ring[idx][j];
520 if (ch == '"') {
521 buf[pos++] = '\\';
522 buf[pos++] = '"';
523 } else if (ch == '\\') {
524 buf[pos++] = '\\';
525 buf[pos++] = '\\';
526 } else if (ch == '\n') {
527 buf[pos++] = '\\';
528 buf[pos++] = 'n';
529 } else {
530 buf[pos++] = ch;
531 }
532 }
533 http_appendf(buf, buf_size, &pos, "\"");
534 }

Callers 1

dispatch_requestFunction · 0.85

Calls 5

cbm_http_query_paramFunction · 0.85
cbm_mutex_lockFunction · 0.85
cbm_mutex_unlockFunction · 0.85
cbm_http_replyfFunction · 0.85
http_appendfFunction · 0.85

Tested by

no test coverage detected