{"id":48514797,"url":"https://github.com/pug523/femtolog","last_synced_at":"2026-04-07T18:33:19.832Z","repository":{"id":302535990,"uuid":"1008491810","full_name":"pug523/femtolog","owner":"pug523","description":"A fast C++ logger","archived":false,"fork":false,"pushed_at":"2026-03-27T09:25:41.000Z","size":2789,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-27T19:33:23.963Z","etag":null,"topics":["async","asynchronous","cpp","cpp20","cross-platform","femtolog","fmtlib","high-performance","log","log-library","logger","logging","low-latency","low-level"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pug523.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-25T16:15:39.000Z","updated_at":"2026-03-27T09:25:45.000Z","dependencies_parsed_at":"2025-08-10T04:05:52.946Z","dependency_job_id":"41178cac-ac39-4618-9b39-4f69f47ba7ed","html_url":"https://github.com/pug523/femtolog","commit_stats":null,"previous_names":["pugur523/femtolog","pug523/femtolog"],"tags_count":1,"template":false,"template_full_name":"pug523/cmake_template","purl":"pkg:github/pug523/femtolog","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pug523%2Ffemtolog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pug523%2Ffemtolog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pug523%2Ffemtolog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pug523%2Ffemtolog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pug523","download_url":"https://codeload.github.com/pug523/femtolog/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pug523%2Ffemtolog/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31524525,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"ssl_error","status_checked_at":"2026-04-07T16:28:06.951Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","asynchronous","cpp","cpp20","cross-platform","femtolog","fmtlib","high-performance","log","log-library","logger","logging","low-latency","low-level"],"created_at":"2026-04-07T18:33:09.981Z","updated_at":"2026-04-07T18:33:19.803Z","avatar_url":"https://github.com/pug523.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=center\u003e\n  femtolog\n\u003c/h1\u003e\n\n[![CI](https://github.com/pugur523/femtolog/actions/workflows/ci.yml/badge.svg)](https://github.com/pugur523/femtolog/actions/workflows/ci.yml)\n[![Issues](https://img.shields.io/github/issues/pugur523/femtolog.svg)](https://github.com/pugur523/femtolog/issues)\n[![License](https://img.shields.io/badge/License-Apache%20License%20Version%202.0-red)](LICENSE)\n[![C++20](https://img.shields.io/badge/C++-20-blue?logo=cplusplus)](https://isocpp.org/)\n[![xmake](https://img.shields.io/badge/xmake-black)](https://xmake.io)\n\u003cbr/\u003e\n\n\u003e Ultra Light High Performance Asynchronous Logger\n\n## Overview\n\n**femtolog** is a blazing-fast, minimal-overhead asynchronous logging library built for performance-critical applications. It leverages zero-cost abstractions, cache-aligned SPSC queues, and compile-time format string serialization.\n\nDesigned for modern C++ projects where every nanosecond counts.\n\n---\n\n## Table of Contents\n\n- [Overview](#-overview)\n- [Table of Contents](#-table-of-contents)\n- [Features](#-features)\n- [Usage](#-usage)\n- [Workflow](#-workflow)\n- [Benchmarks](#-benchmarks)\n  - [System Environment](#system-environment)\n    - [Literal without format](#literal-without-format)\n    - [Format integer](#format-integer)\n    - [Format multi integers](#format-multi-integers)\n    - [Format string](#format-string)\n    - [Format string view](#format-string-view)\n    - [Format mixed](#format-mixed)\n    - [Format large string](#format-large-string)\n- [Installation](#-installation)\n  - [Using CMake](#using-cmake)\n- [Custom Sinks](#-custom-sinks)\n  - [Implement Your Own Sink](#-implement-your-own-sink)\n- [License](#-license)\n- [Credits](#️-credits)\n\n## Features\n\n- Compile-time format string registration\n- True asynchronous logging pipeline\n- Zero dynamic memory allocations on the frontend\n- Dedicated backend worker thread for formatting and output\n- Faster than `spdlog`, and `quill` in benchmark\n\n---\n\n## Usage\n\n`femtolog` supports formatting messages using [fmtlib](https://github.com/fmtlib/fmt).\n\n### Basic Example\n\n```cpp\n#include \"femtolog.h\"\n\nusing namespace femtolog;\n\nint main() {\n  // Initialize the logger\n  Logger\u0026 logger = Logger::logger();\n  logger.init();\n  logger.register_sink\u003cfemtolog::StdoutSink\u003c\u003e\u003e();\n  logger.start_worker();\n\n  // Output \"Hello World\" to console\n  logger.info\u003c\"Hello World\\n\"\u003e();\n\n  logger.stop_worker();\n  logger.clear_sinks();\n\n  return 0;\n}\n```\n\n### Advanced Example\n\n```cpp\n#include \"femtolog.h\"\n\nint main() {\n  // Get thread local logger instance.\n  femtolog::Logger\u0026 logger = femtolog::Logger::logger();\n\n  // Initialize logger and register log sink.\n  femtolog::FemtologOptions options = {\n      .spsc_queue_size = 1024 * 1024 * 4,\n      .backend_format_buffer_size = 1024 * 64,\n      .backend_dequeue_buffer_size = 1024 * 64,\n      .backend_worker_cpu_affinity = 5,\n      .color_mode = femtolog::ColorMode::kAuto,\n  };\n  logger.init(options);\n  logger.register_sink\u003cfemtolog::StdoutSink\u003c\u003e\u003e();\n  logger.register_sink\u003cfemtolog::FileSink\u003e();\n  logger.register_sink\u003cfemtolog::JsonLinesSink\u003c\u003e\u003e();\n  logger.level(\"trace\");\n\n  // Start the backend worker that dequeues logged entries.\n  logger.start_worker();\n\n  std::string username = \"pugur\";\n  float cpu_usage = 42.57f;\n  bool result = true;\n  int error_code = -1;\n\n  // Log messages with compile-time interpreted format strings.\n  logger.trace\u003c\"Hello {}\\n\"\u003e(\"World\");\n  logger.debug\u003c\"Hello World wo formatting\\n\"\u003e();\n  logger.info\u003c\"User \\\"{}\\\" logged in.\\n\"\u003e(username);\n  logger.warn\u003c\"CPU usage is high: {}%\\n\"\u003e(cpu_usage);\n  logger.error\u003c\"Return value is: {}\\n\"\u003e(result);\n\n  logger.fatal\u003c\"Fatal error occured; error code: {}\\n\"\u003e(error_code);\n\n  logger.stop_worker();\n  logger.clear_sinks();\n\n  return 0;\n}\n```\n\n## Workflow\n\nThe logging pipeline consists of a frontend (thread-local logger) and a backend (worker thread):\n\nFormat string literals (`\"...\"`) are hashed at compile time into a `format_id`. Arguments are serialized as a raw byte stream and passed asynchronously from the frontend to the backend through an SPSC queue.\n\n```mermaid\ngraph TD\n    A[Logger - frontend] --\u003e|embed format id by hash at compile time, serialize format args at runtime| B[SPSC Queue]\n    B --\u003e C[Backend Worker - async]\n    C --\u003e D[Deserialize and Format]\n    D --\u003e E[Sink: stdout / files / custom]\n```\n\nThis architecture separates formatting from the hot path of logging, minimizing latency.\n\n## Benchmarks\n\n### System Environment\n\n- **OS**: Ubuntu 22.04 x86_64\n- **CPU**: Intel Core i3 12100 @ 4.3GHz\n- **RAM**: DDR4 3600MHz 64GB\n\nThe following benchmark results were measured using [Google Benchmark](https://github.com/google/benchmark) with Clang-20 -O3 Release build on the above environment. For comparison, results of similar logging benchmarks using the following libraries are also shown:\n\n- [**quill**](https://github.com/odygrd/quill)\n- [**spdlog**](https://github.com/gabime/spdlog)\n\nThe benchmark codes are available in [`//src/bench/`](src/bench/) directory and the detail results of benchmark are archived in [`//src/bench/results/archive`](src/bench/results/archive/) directory.\nBenchmarks are generated in the `//out/build/\u003cplatform\u003e/\u003carch\u003e/bin` directory by setting `FEMTOLOG_BUILD_BENCHMARK` to `true` when building with CMake.\nAfter building, you can run the built benchmarks and collect results by executing `//src/build/scripts/run_bench.py` with the `--format` option. The results will be saved in the `//src/bench/results/` directory in both json and png formats.\n\n#### Literal without format\n\n|   Library    | 50%[ns] | 75%[ns] | 90%[ns] | 95%[ns] | 99%[ns] | 99.9%[ns] |\n| :----------: | :-----: | :-----: | :-----: | :-----: | :-----: | :-------: |\n| **femtolog** |  3.512  |  3.516  |  3.624  |  3.660  |  3.689  |   3.695   |\n|    quill     | 22.873  | 23.911  | 25.149  | 25.562  | 25.892  |  25.967   |\n|    spdlog    | 29.930  | 29.981  | 31.014  | 31.358  | 31.634  |  31.696   |\n\n#### Format integer\n\n|   Library    | 50%[ns] | 75%[ns] | 90%[ns] | 95%[ns] | 99%[ns] | 99.9%[ns] |\n| :----------: | :-----: | :-----: | :-----: | :-----: | :-----: | :-------: |\n| **femtolog** | 10.806  | 11.309  | 11.344  | 11.356  | 11.365  |  11.367   |\n|    quill     | 23.872  | 23.934  | 24.552  | 24.758  | 24.923  |  24.960   |\n|    spdlog    | 46.295  | 46.610  | 48.806  | 49.538  | 50.124  |  50.256   |\n\n#### Format multi integers\n\n|   Library    | 50%[ns] | 75%[ns] | 90%[ns] | 95%[ns] | 99%[ns] | 99.9%[ns] |\n| :----------: | :-----: | :-----: | :-----: | :-----: | :-----: | :-------: |\n| **femtolog** | 11.297  | 13.048  | 13.092  | 13.107  | 13.119  |  13.122   |\n|    quill     | 24.175  | 24.310  | 24.848  | 25.027  | 25.171  |  25.203   |\n|    spdlog    | 65.505  | 67.241  | 69.786  | 70.634  | 71.313  |  71.466   |\n\n#### Format string\n\n|   Library    | 50%[ns] | 75%[ns] | 90%[ns] | 95%[ns] | 99%[ns] | 99.9%[ns] |\n| :----------: | :-----: | :-----: | :-----: | :-----: | :-----: | :-------: |\n| **femtolog** | 13.591  | 14.059  | 14.387  | 14.496  | 14.583  |  14.603   |\n|    quill     | 23.571  | 24.868  | 24.938  | 24.961  | 24.980  |  24.984   |\n|    spdlog    | 49.125  | 50.731  | 50.755  | 50.763  | 50.769  |  50.771   |\n\n#### Format string view\n\n|   Library    | 50%[ns] | 75%[ns] | 90%[ns] | 95%[ns] | 99%[ns] | 99.9%[ns] |\n| :----------: | :-----: | :-----: | :-----: | :-----: | :-----: | :-------: |\n| **femtolog** | 11.867  | 11.928  | 12.045  | 12.085  | 12.116  |  12.123   |\n|    quill     | 24.805  | 24.840  | 24.951  | 24.988  | 25.018  |  25.024   |\n|    spdlog    | 46.054  | 49.631  | 54.423  | 56.020  | 57.297  |  57.585   |\n\n#### Format mixed\n\n|   Library    | 50%[ns] | 75%[ns] | 90%[ns] | 95%[ns] | 99%[ns] | 99.9%[ns] |\n| :----------: | :-----: | :-----: | :-----: | :-----: | :-----: | :-------: |\n| **femtolog** | 11.791  | 12.116  | 12.299  | 12.360  | 12.409  |  12.420   |\n|    quill     | 23.330  | 26.236  | 26.258  | 26.266  | 26.272  |  26.273   |\n|    spdlog    | 111.116 | 115.427 | 117.489 | 118.176 | 118.726 |  118.850  |\n\n#### Format large string\n\n|   Library    | 50%[ns] | 75%[ns] | 90%[ns] | 95%[ns] | 99%[ns] | 99.9%[ns] |\n| :----------: | :-----: | :-----: | :-----: | :-----: | :-----: | :-------: |\n| **femtolog** | 12.107  | 12.393  | 12.845  | 12.996  | 13.117  |  13.144   |\n|    quill     | 22.043  | 22.193  | 22.893  | 23.126  | 23.313  |  23.355   |\n|    spdlog    | 51.425  | 53.556  | 55.591  | 56.269  | 56.812  |  56.934   |\n\n\u003cdiv align=center\u003e\n  \u003cimg src=\"src/bench/results/archive/2025-07-03_20-33-05.png\"\u003e\n\u003c/div\u003e\n\n## Installation\n\n### Using CMake\n\nAdd this repository as a git submodule:\n\n```bash\ngit submodule add https://github.com/pugur523/femtolog.git ./femtolog --recursive\n```\n\nAdd `femtolog` as a subdirectory:\n\n```cmake\nadd_subdirectory(femtolog)\n\ntarget_link_libraries(your_target PRIVATE femtolog)\n```\n\nTo install the compiled library:\n\n```cmake\nset(INSTALL_FEMTOLOG TRUE)\nset(FEMTOLOG_INSTALL_HEADERS TRUE)\nadd_subdirectory(femtolog)\n\ntarget_link_libraries(your_target PRIVATE femtolog)\n```\n\n## Custom Sinks\n\nNeed to log to a database, a network socket, or a ring buffer?\n\n`femtolog` supports plug-and-play custom sinks via a simple interface:\n\n### Implement Your Own Sink\n\nTo define a custom sink, just inherit from `SinkBase` and implement `on_log()`:\n\n```cpp\n#include \"sinks/sink_base.h\"\n\nclass MySink : public femtolog::SinkBase {\n public:\n  void on_log(const LogEntry\u0026 entry, const char* content, size_t len) override {\n    // Write to file, send over network, etc.\n    std::fwrite(content, 1, len, stderr);\n  }\n};\n```\n\nThen register your sink with the logger:\n\n```cpp\nlogger.register_sink\u003cMySink\u003e();\n```\n\nThat's it — your sink will now receive fully formatted log entries, asynchronously, from the backend.\n\n## License\n\n`femtolog` is licensed under the [Apache 2.0 License](LICENSE).\n\n## Credits\n\n- **[zlib](https://github.com/madler/zlib)**\u003cbr/\u003e\n  Used in `FileSink` and `JsonLinesSink` for compressing log files efficiently.\n- **[GoogleTest (gtest)](https://github.com/google/googletest)**\u003cbr/\u003e\n  Serves as the primary unit testing framework for the entire project.\n- **[Google Benchmark](https://github.com/google/benchmark)**\u003cbr/\u003e\n  Used to benchmark `femtolog` against other logging libraries to ensure high performance.\n- **[fmtlib](https://github.com/fmtlib/fmt)**\u003cbr/\u003e\n  Powers the formatting engine behind all log message rendering.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpug523%2Ffemtolog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpug523%2Ffemtolog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpug523%2Ffemtolog/lists"}