ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
log/log.h
Go to the documentation of this file.
1
24#pragma once
25
26#include <stdarg.h>
27#include <ascii-chat/atomic.h>
28// Use atomic.h API for all platforms (C and C++)
29// atomic_t is available in both C and C++ contexts
30#define LOG_ATOMIC_UINT64 atomic_t
31#ifdef NDEBUG
32#define LOG_ATOMIC_UINT64_INIT(val) {.impl = (uint64_t)0}
33#else
34// In debug mode, atomic_t has debug fields that need initialization
35#define LOG_ATOMIC_UINT64_INIT(val) \
36 {.impl = (uint64_t)0, \
37 .last_store_time_ns = (uint64_t)0, \
38 .last_load_time_ns = (uint64_t)0, \
39 .store_count = (uint64_t)0, \
40 .load_count = (uint64_t)0, \
41 .cas_count = (uint64_t)0, \
42 .cas_success_count = (uint64_t)0, \
43 .fetch_count = (uint64_t)0}
44#endif
45#include <stdbool.h>
46#include <stdint.h>
47#include <time.h>
48#include "../platform/socket.h"
49#include "../platform/system.h"
50
51/* Forward declarations */
52struct crypto_context_t;
53struct color_scheme_t; /* Opaque - full definition in ui/colors.h, only included in logging.c */
55struct session_log_buffer; /* Opaque - full definition in session/session_log_buffer.h */
57
58/* Include log types (must be before network/log.h to avoid circular dependency) */
59#include "types.h"
60
61#include "../network/log.h"
62
63#ifndef NDEBUG
65#define DEFAULT_LOG_LEVEL LOG_DEBUG
66#else
68#define DEFAULT_LOG_LEVEL LOG_INFO
69#endif
70
72#define MAX_LOG_SIZE (3 * 1024 * 1024)
73
75#define MAX_TERMINAL_BUFFER_SIZE (64 * 1024)
76
78#define MAX_TERMINAL_BUFFER_ENTRIES 256
79
80/* ============================================================================
81 * Logging Buffer Size Constants
82 * ============================================================================
83 * Named constants for internal buffer sizes. Messages exceeding these sizes
84 * will be truncated with no error indication.
85 */
86
88#define LOG_MSG_BUFFER_SIZE 4096
89
91#define LOG_MMAP_MSG_BUFFER_SIZE 1024
92
94#define LOG_HEADER_BUFFER_SIZE 512
95
97#define LOG_TIMESTAMP_BUFFER_SIZE 32
98
99/* ============================================================================
100 * Compile-Time Log Level Stripping
101 * ============================================================================
102 * By default, all log levels are compiled in (LOG_DEV) so that runtime
103 * verbosity flags like -vvv work in both debug and release builds.
104 *
105 * Define LOG_COMPILE_LEVEL to strip logs at compile-time for smaller binaries:
106 * -DLOG_COMPILE_LEVEL=LOG_INFO -> Strip DEV and DEBUG
107 * -DLOG_COMPILE_LEVEL=LOG_WARN -> Strip DEV, DEBUG, and INFO
108 * -DLOG_COMPILE_LEVEL=LOG_DEV -> Keep all log levels (default)
109 */
110#ifndef LOG_COMPILE_LEVEL
112#define LOG_COMPILE_LEVEL LOG_DEV
113#endif
114
116typedef struct {
117 bool use_stderr; /* true for stderr, false for stdout */
118 char *message; /* Formatted message (heap allocated) */
120
121/* Implementation details (g_log struct, color arrays) are in logging.c */
122
140
141#ifdef __cplusplus
142extern "C" {
143#endif
144
159void log_init(const char *filename, log_level_t level, bool force_stderr, bool use_mmap);
160
165void log_destroy(void);
166
175void log_system_init(void);
176
185void log_system_destroy(void);
186
192void log_set_level(log_level_t level);
193
200
209asciichat_error_t log_set_format(const char *format_str, bool console_only);
210
217
223bool log_get_terminal_output(void);
224
237
243bool log_get_force_stderr(void);
244
252void log_disable_file_output(void);
253
260void log_truncate_if_large(void);
261
272void log_msg(log_level_t level, const char *file, int line, const char *func, const char *fmt, ...);
273
287void log_terminal_msg(log_level_t level, const char *file, int line, const char *func, const char *fmt, ...);
288
297void log_plain_msg(const char *fmt, ...);
298
307void log_plain_stderr_msg(const char *fmt, ...);
308
318void log_plain_stdout_msg(const char *fmt, ...);
319
329void log_plain_stderr_nonewline_msg(const char *fmt, ...);
330
339void log_file_msg(const char *fmt, ...);
340
353void log_labeled(const char *label, log_color_t color, const char *message, ...);
354
361const char *log_level_color(log_color_t color);
362
370const char **log_get_color_array(void);
371
379
388void log_init_colors(void);
389
399void log_set_color_scheme(const color_scheme_t *scheme);
400
418bool log_lock_terminal(void);
419
429void log_unlock_terminal(bool previous_state);
430
441void log_set_flush_delay(unsigned int delay_ms);
442
450char *format_message(const char *format, va_list args);
451
458size_t get_current_time_formatted(char *time_buf);
459
470asciichat_error_t log_network_message(socket_t sockfd, const struct crypto_context_t *crypto_ctx, log_level_t level,
471 remote_log_direction_t direction, const char *fmt, ...);
472
486asciichat_error_t log_net_message(socket_t sockfd, const struct crypto_context_t *crypto_ctx, log_level_t level,
487 remote_log_direction_t direction, const char *file, int line, const char *func,
488 const char *fmt, ...);
489
505#ifdef NDEBUG
506#define log_as(level, ...) log_msg(level, NULL, 0, NULL, __VA_ARGS__)
507#else
508#define log_as(level, ...) log_msg(level, __FILE__, __LINE__, __func__, __VA_ARGS__)
509#endif
510
519#define log_only(bitmask, level, ...) \
520 ({ \
521 if ((bitmask) & LOG_BIT(level)) \
522 log_as(level, __VA_ARGS__); \
523 })
524
533#if LOG_COMPILE_LEVEL <= LOG_DEV
534#define log_dev(...) log_only(LOG_BIT(LOG_DEV), LOG_DEV, __VA_ARGS__)
535#else
536#define log_dev(...) ((void)0)
537#endif
538
547#if LOG_COMPILE_LEVEL <= LOG_DEBUG
548#define log_debug(...) log_only(LOG_BIT(LOG_DEBUG), LOG_DEBUG, __VA_ARGS__)
549#else
550#define log_debug(...) ((void)0)
551#endif
552
560#if LOG_COMPILE_LEVEL <= LOG_INFO
561#define log_info(...) log_only(LOG_BIT(LOG_INFO), LOG_INFO, __VA_ARGS__)
562#else
563#define log_info(...) ((void)0)
564#endif
565
573#if LOG_COMPILE_LEVEL <= LOG_WARN
574#define log_warn(...) log_only(LOG_BIT(LOG_WARN), LOG_WARN, __VA_ARGS__)
575#else
576#define log_warn(...) ((void)0)
577#endif
578
586#if LOG_COMPILE_LEVEL <= LOG_ERROR
587#define log_error(...) log_only(LOG_BIT(LOG_ERROR), LOG_ERROR, __VA_ARGS__)
588#else
589#define log_error(...) ((void)0)
590#endif
591
599#define log_fatal(...) log_only(LOG_BIT(LOG_FATAL), LOG_FATAL, __VA_ARGS__)
600
618#define log_plain(...) log_plain_msg(__VA_ARGS__)
619
625#define log_plain_stderr(...) log_plain_stderr_msg(__VA_ARGS__)
626
632#define log_plain_stdout(...) log_plain_stdout_msg(__VA_ARGS__)
633
639#define log_plain_stderr_nonewline(...) log_plain_stderr_nonewline_msg(__VA_ARGS__)
640
646#define log_file(...) log_file_msg(__VA_ARGS__)
647
667#ifdef NDEBUG
668#define log_every(log_level, interval_us, fmt, ...) \
669 do { \
670 static LOG_ATOMIC_UINT64 _log_every_last_time = LOG_ATOMIC_UINT64_INIT(0); \
671 uint64_t _log_every_now = platform_get_monotonic_time_us(); \
672 uint64_t _log_every_last = atomic_load_u64(&_log_every_last_time); \
673 if (_log_every_now - _log_every_last >= (uint64_t)(interval_us)) { \
674 if (atomic_cas_u64(&_log_every_last_time, &_log_every_last, _log_every_now)) { \
675 log_msg(LOG_##log_level, NULL, 0, NULL, fmt, ##__VA_ARGS__); \
676 } \
677 } \
678 } while (0)
679#else
680#define log_every(log_level, interval_us, fmt, ...) \
681 do { \
682 static LOG_ATOMIC_UINT64 _log_every_last_time = LOG_ATOMIC_UINT64_INIT(0); \
683 uint64_t _log_every_now = platform_get_monotonic_time_us(); \
684 uint64_t _log_every_last = atomic_load_u64(&_log_every_last_time); \
685 if (_log_every_now - _log_every_last >= (uint64_t)(interval_us)) { \
686 if (atomic_cas_u64(&_log_every_last_time, &_log_every_last, _log_every_now)) { \
687 log_msg(LOG_##log_level, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__); \
688 } \
689 } \
690 } while (0)
691#endif
692
699#define log_dev_every(interval_us, fmt, ...) log_every(DEV, interval_us, fmt, ##__VA_ARGS__)
700
702#define log_debug_every(interval_us, fmt, ...) log_every(DEBUG, interval_us, fmt, ##__VA_ARGS__)
703
705#define log_info_every(interval_us, fmt, ...) log_every(INFO, interval_us, fmt, ##__VA_ARGS__)
706
708#define log_warn_every(interval_us, fmt, ...) log_every(WARN, interval_us, fmt, ##__VA_ARGS__)
709
711#define log_error_every(interval_us, fmt, ...) log_every(ERROR, interval_us, fmt, ##__VA_ARGS__)
712
714#define log_fatal_every(interval_us, fmt, ...) log_every(FATAL, interval_us, fmt, ##__VA_ARGS__)
715
736#ifdef NDEBUG
737#define log_nth(log_level, n, fmt, ...) \
738 do { \
739 static LOG_ATOMIC_UINT64 _log_nth_counter = LOG_ATOMIC_UINT64_INIT(0); \
740 uint64_t _log_nth_count = atomic_load_u64(&_log_nth_counter); \
741 uint64_t _log_nth_new = _log_nth_count + 1; \
742 atomic_store_u64(&_log_nth_counter, _log_nth_new); \
743 if (_log_nth_new % (uint64_t)(n) == 0) { \
744 log_msg(LOG_##log_level, NULL, 0, NULL, fmt, ##__VA_ARGS__); \
745 } \
746 } while (0)
747#else
748#define log_nth(log_level, n, fmt, ...) \
749 do { \
750 static LOG_ATOMIC_UINT64 _log_nth_counter = LOG_ATOMIC_UINT64_INIT(0); \
751 uint64_t _log_nth_count = atomic_load_u64(&_log_nth_counter); \
752 uint64_t _log_nth_new = _log_nth_count + 1; \
753 atomic_store_u64(&_log_nth_counter, _log_nth_new); \
754 if (_log_nth_new % (uint64_t)(n) == 0) { \
755 log_msg(LOG_##log_level, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__); \
756 } \
757 } while (0)
758#endif
759
777#ifdef NDEBUG
778#define log_once(log_level, fmt, ...) \
779 do { \
780 static LOG_ATOMIC_UINT64 _log_once_counter = LOG_ATOMIC_UINT64_INIT(0); \
781 uint64_t _log_once_count = atomic_load_u64(&_log_once_counter); \
782 if (_log_once_count == 0) { \
783 atomic_store_u64(&_log_once_counter, 1); \
784 log_msg(LOG_##log_level, NULL, 0, NULL, fmt, ##__VA_ARGS__); \
785 } \
786 } while (0)
787#else
788#define log_once(log_level, fmt, ...) \
789 do { \
790 static LOG_ATOMIC_UINT64 _log_once_counter = LOG_ATOMIC_UINT64_INIT(0); \
791 uint64_t _log_once_count = atomic_load_u64(&_log_once_counter); \
792 if (_log_once_count == 0) { \
793 atomic_store_u64(&_log_once_counter, 1); \
794 log_msg(LOG_##log_level, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__); \
795 } \
796 } while (0)
797#endif
798
805#define log_dev_nth(n, fmt, ...) log_nth(DEV, n, fmt, ##__VA_ARGS__)
806
808#define log_debug_nth(n, fmt, ...) log_nth(DEBUG, n, fmt, ##__VA_ARGS__)
809
811#define log_info_nth(n, fmt, ...) log_nth(INFO, n, fmt, ##__VA_ARGS__)
812
814#define log_warn_nth(n, fmt, ...) log_nth(WARN, n, fmt, ##__VA_ARGS__)
815
817#define log_error_nth(n, fmt, ...) log_nth(ERROR, n, fmt, ##__VA_ARGS__)
818
820#define log_fatal_nth(n, fmt, ...) log_nth(FATAL, n, fmt, ##__VA_ARGS__)
821
830#define log_dev_once(fmt, ...) log_once(DEV, fmt, ##__VA_ARGS__)
831
833#define log_debug_once(fmt, ...) log_once(DEBUG, fmt, ##__VA_ARGS__)
834
836#define log_info_once(fmt, ...) log_once(INFO, fmt, ##__VA_ARGS__)
837
839#define log_warn_once(fmt, ...) log_once(WARN, fmt, ##__VA_ARGS__)
840
842#define log_error_once(fmt, ...) log_once(ERROR, fmt, ##__VA_ARGS__)
843
845#define log_fatal_once(fmt, ...) log_once(FATAL, fmt, ##__VA_ARGS__)
846
849/* LOGGING_INTERNAL_ERROR macro is defined in logging.c (internal use only) */
850
851/* Network logging convenience macros (log_*_net) are defined in src/server/client.h
852 * since they require access to client_info_t. The base function log_net_message()
853 * is available here for generic use. */
854
855/* ============================================================================
856 * Lock-Free MMAP Logging
857 * ============================================================================ */
858
859/* Forward declaration - full definition in log/mmap.h */
860struct log_mmap_config;
862
883
893
900void log_disable_mmap(void);
901
913void log_shutdown_begin(void);
914
921void log_shutdown_end(void);
922
930void log_cleanup_colors(void);
931
942
950
961
984size_t log_recolor_plain_entry(const char *plain_line, char *colored_buf, size_t buf_size);
985
986/* ============================================================================
987 * Internal Utilities (used by log formatting modules)
988 * ============================================================================ */
989
996const char *get_level_string_padded(log_level_t level);
997
998// Console-only logging helper (text or JSON, no file output)
999// For signal handlers and initialization paths where file logging is not safe
1000// Automatically chooses between text and JSON based on --json flag
1001// Captures call site (file, line, function) for better debugging
1002void log_console_impl(log_level_t level, const char *file, int line, const char *func, const char *message);
1003#define log_console(level, message) log_console_impl((level), __FILE__, __LINE__, __func__, (message))
1004
1019void *log_get_template(void);
1020
1021/* Include crypto.h at the end to avoid circular dependency with time.h */
1022#include "../crypto/crypto.h"
1023
1024#ifdef __cplusplus
1025}
1026#endif
1027
/* logging */
⚛️ Atomic operations abstraction layer with debug tracking
bool enabled
Is filtering active?
Definition grep.c:84
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:49
void log_truncate_if_large(void)
Manually truncate large log files.
Definition log/log.c:807
void log_plain_stderr_nonewline_msg(const char *fmt,...)
Plain logging to stderr without trailing newline.
Definition log/log.c:1375
void log_plain_msg(const char *fmt,...)
Plain logging without timestamps or levels.
Definition log/log.c:1215
bool log_get_terminal_output(void)
Get current terminal output setting.
Definition log/log.c:717
asciichat_error_t log_enable_mmap(const char *log_path)
Enable lock-free mmap-based logging.
Definition log/log.c:1765
void log_init_colors(void)
Initialize logging color system with current terminal capabilities.
Definition log/log.c:1671
void log_system_init(void)
Initialize the logging system internal state (system-level init)
Definition log/log.c:669
void log_msg(log_level_t level, const char *file, int line, const char *func, const char *fmt,...)
Log a message at a specific level.
Definition log/log.c:1019
void log_shutdown_end(void)
End shutdown phase - restore previous logging settings.
Definition log/log.c:1806
void log_destroy(void)
Destroy the logging system and close log file.
Definition log/log.c:624
void log_set_force_stderr(bool enabled)
Force all terminal log output to stderr.
Definition log/log.c:721
enum remote_log_direction remote_log_direction_t
Remote log packet direction enumeration.
log_level_t log_get_level(void)
Get the current minimum log level.
Definition log/log.c:696
const char ** log_get_color_array(void)
Get the appropriate color array based on terminal capabilities.
Definition log/log.c:1630
const char * log_level_color(log_color_t color)
Get color string for a given color enum.
Definition log/log.c:1656
void log_set_flush_delay(unsigned int delay_ms)
Set the delay between flushing buffered log entries.
Definition log/log.c:803
session_log_buffer_t * log_get_session_log_buffer(void)
Get the currently registered session log buffer.
Definition log/log.c:1857
char * format_message(const char *format, va_list args)
Format a message using va_list.
Definition log/log.c:248
log_color_t
Color enum for logging - indexes into color arrays.
Definition log/log.h:130
void log_cleanup_colors(void)
Clean up compiled color scheme.
Definition log/log.c:1822
void log_shutdown_begin(void)
Begin shutdown phase - disable console logging but keep file logging.
Definition log/log.c:1795
void log_disable_file_output(void)
Disable file output and use stderr instead.
Definition log/log.c:733
bool log_get_force_stderr(void)
Get current force_stderr setting.
Definition log/log.c:725
void log_set_level(log_level_t level)
Set the minimum log level.
Definition log/log.c:691
size_t log_recolor_plain_entry(const char *plain_line, char *colored_buf, size_t buf_size)
Recolor a plain (non-colored) log line with proper ANSI codes.
Definition log/log.c:1871
void log_clear_session_log_buffer(void)
Unregister the session log buffer.
Definition log/log.c:1847
void log_plain_stdout_msg(const char *fmt,...)
Plain logging to stdout with newline.
Definition log/log.c:1453
void log_set_session_log_buffer(session_log_buffer_t *buf)
Register a session log buffer with the logger.
Definition log/log.c:1838
void log_system_destroy(void)
Shutdown the logging system internal state (system-level cleanup)
Definition log/log.c:686
void log_init(const char *filename, log_level_t level, bool force_stderr, bool use_mmap)
Initialize the logging system.
Definition log/log.c:533
asciichat_error_t log_net_message(socket_t sockfd, const struct crypto_context_t *crypto_ctx, log_level_t level, remote_log_direction_t direction, const char *file, int line, const char *func, const char *fmt,...)
Log a message to all destinations (network, file, and terminal).
Definition log/log.c:1560
bool log_lock_terminal(void)
Lock terminal output for exclusive access by the calling thread.
Definition log/log.c:787
asciichat_error_t log_network_message(socket_t sockfd, const struct crypto_context_t *crypto_ctx, log_level_t level, remote_log_direction_t direction, const char *fmt,...)
Send a formatted log message over the network.
Definition log/log.c:1550
log_level_t
Logging levels enumeration.
Definition types.h:29
void log_labeled(const char *label, log_color_t color, const char *message,...)
Print a labeled message with color.
asciichat_error_t log_set_format(const char *format_str, bool console_only)
Set a custom log format string.
Definition log/log.c:744
size_t get_current_time_formatted(char *time_buf)
Get current time as formatted string.
Definition log/log.c:216
asciichat_error_t log_enable_mmap_sized(const char *log_path, size_t max_size)
Enable lock-free mmap logging with custom file size.
Definition log/log.c:1769
void log_file_msg(const char *fmt,...)
Log to file only, no stderr output.
Definition log/log.c:1467
void log_disable_mmap(void)
Disable mmap logging and return to mutex-based logging.
Definition log/log.c:1784
void log_set_terminal_output(bool enabled)
Control stderr output to terminal.
Definition log/log.c:700
void * log_get_template(void)
Get the current log format template (opaque pointer)
Definition log/log.c:2156
void log_set_color_scheme(const color_scheme_t *scheme)
Set the color scheme for logging output.
Definition log/log.c:1728
void log_plain_stderr_msg(const char *fmt,...)
Plain logging to stderr with newline.
Definition log/log.c:1361
void log_redetect_terminal_capabilities(void)
Re-detect terminal capabilities after logging is initialized.
Definition log/log.c:1602
void log_unlock_terminal(bool previous_state)
Release terminal lock and flush buffered messages.
Definition log/log.c:796
void log_terminal_msg(log_level_t level, const char *file, int line, const char *func, const char *fmt,...)
Log a message to terminal only (no file output)
Definition log/log.c:1194
@ LOG_COLOR_RESET
Definition log/log.h:138
@ LOG_COLOR_GREY
Definition log/log.h:137
@ LOG_COLOR_FATAL
Definition log/log.h:136
@ LOG_COLOR_ERROR
Definition log/log.h:135
@ LOG_COLOR_DEV
Definition log/log.h:131
@ LOG_COLOR_DEBUG
Definition log/log.h:132
@ LOG_COLOR_INFO
Definition log/log.h:133
@ LOG_COLOR_WARN
Definition log/log.h:134
int socket_t
const char * get_level_string_padded(log_level_t level)
Get padded log level string (internal utility for formatting)
Definition log/log.c:149
void log_console_impl(log_level_t level, const char *file, int line, const char *func, const char *message)
Definition log/log.c:2120
action_args_t args
ClangTool/LibTooling compatibility shim for stdbool.h.
Color scheme definition.
Definition colorscheme.h:62
Cryptographic context structure.
A single buffered log entry.
Definition log/log.h:116
char * message
Definition log/log.h:118
bool use_stderr
Definition log/log.h:117
Configuration for mmap logging.
Definition log/mmap.h:51
size_t max_size
Definition log/mmap.h:53
const char * log_path
Definition log/mmap.h:52
Internal circular buffer structure.
⏱️ High-precision timing utilities using sokol_time.h and uthash
Log level types and constants.