Thanks to visit codestin.com
Credit goes to github.com

Skip to content

single header and source for getting thread id, time, and callstack for each logging. It can also track all allocations so that you can detect unfreed memory and double frees. You can also get a clean overview of the time used in each tklog_timer seciton.

Notifications You must be signed in to change notification settings

ThobiasKnudsen/tklog

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tklog - Lightweight Configurable Logging Library for C

tklog is a single-header/single-source (.h + .c) logging library for C programs. It provides thread-safe, flexible logging with compile-time configuration for minimal runtime overhead. Features include customizable log prefixes (level, timestamp, thread ID, file/line), multiple log levels, optional call-stack tracing, memory leak detection, and performance timing.

Designed for embedded and performance-critical applications, tklog avoids dynamic allocation in the hot path and supports cross-platform use (Linux, macOS, Windows via MinGW).

Features

  • Log Levels: DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY.
  • Customizable Prefixes (compile-time):
    • Log level (e.g., [DEBUG]).
    • Relative timestamp (ms since program start).
    • Thread ID (pthread_self()).
    • File and line number, with optional call-stack tracing (e.g., a.c:12 → b.c:88).
  • Output Flexibility: Default to stdout via printf; customizable via callback function.
  • Optional Exit-on-Log: Automatically exit on high-severity logs (e.g., ERROR).
  • Scope Tracing: Automatic call-stack tracking with TKLOG_SCOPE macro.
  • Memory Tracking: Override malloc/free etc. to detect leaks; dumps on exit or signals (SIGSEGV, SIGABRT, SIGINT).
  • Performance Timer: Track execution time for code blocks with TKLOG_TIMER macro; reports totals, averages, and call paths.
  • Thread-Safe: Uses pthread_mutex for serialization.
  • Cross-Platform Timing: High-resolution timers (QueryPerformanceCounter on Windows, CLOCK_MONOTONIC on POSIX).
  • Zero Runtime Config: All behavior decided at compile-time via macros for optimal performance.

Requirements

  • C99 or later.
  • pthread (for threading; available on Linux/macOS/Windows via MinGW).
  • Standard C library.
  • For memory/timer: Additional allocations (minimal).
  • External dependency for timer: verstable.h (a simple hash table library; not included—implement or replace).

Installation

  1. Copy tklog.h and tklog.c to your project.
  2. Include tklog.h in source files where logging is needed.
  3. Compile tklog.c into your project (e.g., gcc main.c tklog.c -lpthread -o app).

No installation or linking required beyond standard libs.

Configuration

All configuration is compile-time via preprocessor macros. Define them in your build system (e.g., CMake add_compile_definitions) or before including tklog.h.

Basic Flags

  • TKLOG_SHOW_LOG_LEVEL: Include log level in output (default: enabled).
  • TKLOG_SHOW_TIME: Include relative timestamp (default: enabled).
  • TKLOG_SHOW_THREAD: Include thread ID (default: enabled).
  • TKLOG_SHOW_PATH: Include file:line (with call-stack if TKLOG_SCOPE enabled; default: enabled).

Override defaults globally with TKLOG_STATIC_FLAGS (bitmask):

add_compile_definitions(TKLOG_STATIC_FLAGS=(TKLOG_SHOW_LOG_LEVEL|TKLOG_SHOW_TIME))

Per-Level Enables

Enable/disable specific log levels:

  • TKLOG_DEBUG, TKLOG_INFO, TKLOG_NOTICE: Log these levels.
  • TKLOG_WARNING, TKLOG_ERROR, TKLOG_CRITICAL, TKLOG_ALERT, TKLOG_EMERGENCY: Log or exit (see below).

Undefined levels expand to ((void)0) (no-op).

Exit-on-Log

For high-severity levels, use TKLOG_EXIT_ON_<LEVEL> (e.g., TKLOG_EXIT_ON_ERROR) to log and exit(-1) instead of just logging. Overrides the plain TKLOG_<LEVEL>.

Advanced Options

  • TKLOG_OUTPUT_FN: Custom output callback (default: tklog_output_stdio writing to stdout).
  • TKLOG_OUTPUT_USERPTR: User data for callback (default: NULL).
  • TKLOG_MEMORY: Enable memory tracking (overrides stdlib allocators).
  • TKLOG_MEMORY_PRINT_ON_EXIT: Dump leaks on atexit (requires TKLOG_MEMORY).
  • TKLOG_SCOPE: Enable scope-based call-stack tracing.
  • TKLOG_TIMER: Enable performance timing (requires verstable.h for hash tables).

Example CMake:

target_compile_definitions(my_target PRIVATE
    TKLOG_SHOW_LOG_LEVEL
    TKLOG_SHOW_TIME
    TKLOG_MEMORY
    TKLOG_SCOPE
)

Usage

Basic Logging

Include tklog.h and use level-specific macros:

#include "tklog.h"

int main() {
    tklog_info("Program started");
    int x = 42;
    tklog_debug("Value of x: %d", x);
    if (x < 0) {
        tklog_error("Negative value!");
    }
    return 0;
}

Output (with defaults):

INFO     | 0ms | tid 140735327123456 | main.c:8 | Program started
DEBUG    | 0ms | tid 140735327123456 | main.c:10 | Value of x: 42

Custom Output

Define a callback:

bool my_logger(const char *msg, void *user) {
    FILE *logfile = (FILE *)user;
    return fputs(msg, logfile) != EOF;
}

// Before including tklog.h
#define TKLOG_OUTPUT_FN my_logger
#define TKLOG_OUTPUT_USERPTR logfile

Scope Tracing (TKLOG_SCOPE)

Wrap code blocks to auto-push/pop call path:

// Just use these for time tracking:
tklog_timer_start();
[code]
tklog_timer_stop();

Output:

  0ms |     57 calls | 0.004ms avg | tsm.c:1206
  0ms |     57 calls | 0.004ms avg |     tsm.c:1206 to tsm.c:1243
  0ms |      0 calls | 0.000ms avg | test_tsm.c:188
 95ms |  53225 calls | 0.002ms avg | tsm.c:1011
 95ms |  53225 calls | 0.002ms avg |     tsm.c:1011 to tsm.c:1038
  1ms |    182 calls | 0.007ms avg | tsm.c:1249
  1ms |    181 calls | 0.007ms avg |     tsm.c:1249 to tsm.c:1345
  0ms |      1 calls | 0.015ms avg |     tsm.c:1249 to tsm.c:1330
  7ms | 196872 calls | 0.000ms avg | tsm.c:900
  7ms | 196872 calls | 0.000ms avg |     tsm.c:900 to tsm.c:904
  2ms |  70000 calls | 0.000ms avg | tsm.c:943
  0ms |      6 calls | 0.001ms avg |     tsm.c:943 to tsm.c:954
  2ms |  69994 calls | 0.000ms avg |     tsm.c:943 to tsm.c:966
411ms |  69311 calls | 0.006ms avg | test_tsm.c:194
  0ms |      2 calls | 0.002ms avg |     test_tsm.c:194 to test_tsm.c:362
  0ms |     25 calls | 0.011ms avg |     test_tsm.c:194 to test_tsm.c:486
131ms |  17481 calls | 0.008ms avg |     test_tsm.c:194 to test_tsm.c:253
  1ms |    182 calls | 0.009ms avg |     test_tsm.c:194 to test_tsm.c:370
  0ms |    205 calls | 0.001ms avg |     test_tsm.c:194 to test_tsm.c:315
 45ms |  15994 calls | 0.003ms avg |     test_tsm.c:194 to test_tsm.c:498
  0ms |      6 calls | 0.002ms avg |     test_tsm.c:194 to test_tsm.c:200
  0ms |      1 calls | 0.003ms avg |     test_tsm.c:194 to test_tsm.c:294
  0ms |     57 calls | 0.010ms avg |     test_tsm.c:194 to test_tsm.c:572
  0ms |      1 calls | 0.419ms avg |     test_tsm.c:194 to test_tsm.c:581
  0ms |    628 calls | 0.000ms avg |     test_tsm.c:194 to test_tsm.c:450
  3ms |   6792 calls | 0.000ms avg |     test_tsm.c:194 to test_tsm.c:283
  3ms |   6794 calls | 0.000ms avg |     test_tsm.c:194 to test_tsm.c:343
215ms |   1463 calls | 0.147ms avg |     test_tsm.c:194 to test_tsm.c:424
  0ms |    522 calls | 0.001ms avg |     test_tsm.c:194 to test_tsm.c:278
  7ms |  17108 calls | 0.000ms avg |     test_tsm.c:194 to test_tsm.c:258
  0ms |   2050 calls | 0.000ms avg |     test_tsm.c:194 to test_tsm.c:505
 10ms |   5810 calls | 0.002ms avg | tsm.c:1434
 10ms |   5810 calls | 0.002ms avg |     tsm.c:1434 to tsm.c:1489
 96ms |  29101 calls | 0.003ms avg | tsm.c:1085
 96ms |  29101 calls | 0.003ms avg |     tsm.c:1085 to tsm.c:1129
  0ms |   1399 calls | 0.000ms avg | tsm.c:981
  0ms |   1399 calls | 0.000ms avg |     tsm.c:981 to tsm.c:1005
  1ms |  70000 calls | 0.000ms avg | test_tsm.c:190
  1ms |  70000 calls | 0.000ms avg |     test_tsm.c:190 to test_tsm.c:193

Memory Tracking (TKLOG_MEMORY)

Automatically tracks allocations. Use like normal:

char *str = strdup("hello");  // Tracked
free(str);                    // Untracked → error log + exit

On exit/signals, dumps unfreed memory:

unfreed memory:
	5ms | tid 123 | address 0x7f8b4000 | 6 bytes | at main.c:10

Dumps include timestamp, thread, address, size, and allocation path (with scopes). Warning: Nested allocs in tklog internals use original functions to avoid recursion.

Performance Timer (TKLOG_TIMER)

Time code blocks and report aggregates:

tklog_timer_init();  // Once at startup

tklog_timer_start();
sleep(1);
tklog_timer_stop();

tklog_timer_print();  // At end

Output:

1000ms | 1 calls | 1000.000ms avg | main.c:10
1000ms | 1 calls | 1000.000ms avg |     main.c:10 to main.c:12

Tracks per-location totals, counts, averages, and full call paths. Clear data: tklog_timer_clear().

Examples

See examples/ (not included; create simple mains testing each feature).

Limitations

  • Timer requires verstable.h (simple string-keyed hash table).
  • Memory tracking adds overhead; disable for production.
  • Call-stack limited to 128-char paths; grows dynamically.
  • No log rotation/file output (use custom callback).
  • Windows support via MinGW; test thoroughly.

License

MIT License (assumed; adjust as needed). See LICENSE for details.

Contributing

Fork, PR improvements (e.g., more platforms, JSON output).

About

single header and source for getting thread id, time, and callstack for each logging. It can also track all allocations so that you can detect unfreed memory and double frees. You can also get a clean overview of the time used in each tklog_timer seciton.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published