{"id":13418487,"url":"https://github.com/emilk/loguru","last_synced_at":"2025-05-15T07:03:40.313Z","repository":{"id":29156869,"uuid":"32687193","full_name":"emilk/loguru","owner":"emilk","description":"A lightweight C++ logging library","archived":false,"fork":false,"pushed_at":"2024-07-01T07:58:15.000Z","size":1005,"stargazers_count":1827,"open_issues_count":90,"forks_count":267,"subscribers_count":57,"default_branch":"master","last_synced_at":"2025-05-15T07:02:42.943Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emilk.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}},"created_at":"2015-03-22T17:45:23.000Z","updated_at":"2025-05-12T14:35:29.000Z","dependencies_parsed_at":"2024-11-28T00:45:29.526Z","dependency_job_id":null,"html_url":"https://github.com/emilk/loguru","commit_stats":{"total_commits":249,"total_committers":53,"mean_commits":4.69811320754717,"dds":0.5863453815261044,"last_synced_commit":"4adaa185883e3c04da25913579c451d3c32cfac1"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emilk%2Floguru","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emilk%2Floguru/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emilk%2Floguru/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emilk%2Floguru/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emilk","download_url":"https://codeload.github.com/emilk/loguru/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254291961,"owners_count":22046424,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-07-30T22:01:02.839Z","updated_at":"2025-05-15T07:03:39.900Z","avatar_url":"https://github.com/emilk.png","language":"C++","readme":"# Loguru: a lightweight and flexible C++ logging library.\n\n[![Build status](https://ci.appveyor.com/api/projects/status/hret4rx3xakjs7j4?svg=true)](https://ci.appveyor.com/project/emilk/loguru)\n\n## At a glance\n\n![Loguru terminal output](docs/terminal_colors.png)\n\n## Documentation\nDocumentation can be found at https://emilk.github.io/loguru/index.html.\n\n## License\nThis software is in the public domain. Where that dedication is not recognized, you are granted a perpetual, irrevocable license to copy, modify and distribute it as you see fit.\n\nLoguru is also available under [The Unlicense](https://choosealicense.com/licenses/unlicense/).\n\nThat being said, I would appreciate credit!\nIf you find Loguru useful, tweet me at @ernerfeldt mail me at emil.ernerfeldt@gmail.com.\n\n## Why another logging library?\nI have yet to come across a nice, light-weight logging library for C++ that does everything I want. So I made one!\n\nIn particular, I want logging that produces logs that are both human-readable and easily grep:ed. I also want to be able to hook into the logging process to print some of the more severe messages on-screen in my app (for dev-purposes).\n\n## Features:\n* Simple integration\n\t* Just two files: `loguru.hpp` and `loguru.cpp`.\n\t* Either build and link `loguru.cpp` or just `#include \u003cloguru.cpp\u003e` in one of your own .cpp files.\n* Small, simple library.\n\t* Small header with no `#include`s for **fast compile times** (see separate heading).\n\t* No dependencies.\n\t* Cross-platform\n* Flexible:\n\t* User can install callbacks for logging (e.g. to draw log messages on screen in a game).\n\t* User can install callbacks for fatal error (e.g. to pause an attached debugger or throw an exception).\n* Support multiple file outputs, either trunc or append:\n\t* e.g. a logfile with just the latest run at low verbosity (high readability).\n\t* e.g. a full logfile at highest verbosity which is appended to on every run.\n* Full featured:\n\t* Verbosity levels.\n\t* Supports assertions: `CHECK_F(fp != nullptr, \"Failed to open '%s'\", filename)`\n\t* Supports abort: `ABORT_F(\"Something went wrong, debug value is %d\", value)`.\n* Stack traces printed on abort.\n\t* Stack traces are cleaned up somewhat.\n\t\t* Before cleanup: `some_function_name(std::__1::vector\u003cstd::__1::basic_string\u003cchar, std::__1::char_traits\u003cchar\u003e, std::__1::allocator\u003cchar\u003e \u003e, std::__1::allocator\u003cstd::__1::basic_string\u003cchar, std::__1::char_traits\u003cchar\u003e, std::__1::allocator\u003cchar\u003e \u003e \u003e \u003e const\u0026)`\n\t\t* After cleanup: `some_function_name(std::vector\u003cstd::string\u003e const\u0026)`\n\t* Stack traces are printed [the right way](http://yellerapp.com/posts/2015-01-22-upside-down-stacktraces.html):\n\t\t* Chronological order with the most relevant at the end.\n* (most) signals writes stack traces.\n* Fast:\n\t- When configured in unbuffered mode (loguru::g_flush_interval_ms = 0):\n\t\t+ 6-8 us when logging to stderr + file (rMBP + SSD + Clang).\n\t\t+ About 25%-75% faster than GLOG on my MacBook Pro (Clang).\n\t\t+ About the same as GLOG on my Linux Desktop (GCC).\n\t- With loguru::g_flush_interval_ms set to ~100 ms:\n\t\t+ 3-5 us when logging to stderr + file (rMBP + SSD + Clang).\n\t\t+ About twice as fast as GLOG.\n* Drop-in replacement for most of GLOG (except for setup code).\n* Choose between using printf-style or std::cout-style formatting.\n* Compile-time checked printf-formating (on supported compilers).\n* Support for [fmtlib](https://github.com/fmtlib/fmt) formatting.\n\t* Add `#define LOGURU_USE_FMTLIB 1`, before including `loguru.hpp`\n\t* You also need to set up the `fmtlib` include directory for building as well as linking against `fmtlib`, alternatively use the `FMT_HEADER_ONLY` preprocessor definition.\n* Assertion failures are marked with `noreturn` for the benefit of the static analyzer and optimizer.\n* All logging also written to stderr.\n\t* With colors on supported terminals.\n* Thread-safe.\n* Can be configured to either:\n\t* Flush every `loguru::g_flush_interval_ms` in a background thread\n\t* Flushes output on each call so you won't miss anything even on hard crashes (and still faster than buffered GLOG!).\n* Prefixes each log line with:\n\t* Date and time to millisecond precision.\n\t* Application uptime to millisecond precision.\n\t* Thread name or id (you can set the name with `loguru::set_thread_name`).\n\t* File and line.\n\t* Log level.\n\t* Indentation (see *Scopes*).\n* Error context:\n\t* Catch the values of local variables and print them only on a crash (see *Error context*).\n* Scopes (see *Scopes*).\n* grep:able logs:\n\t* Each line has all the info you need (e.g. date).\n\t* You can easily filter out high verbosity levels after the fact.\n\n\n## Compiling\n\nJust include \u003cloguru.hpp\u003e where you want to use Loguru.\nThen either compile and link with `loguru.cpp` or in one .cpp file: `#include \u003cloguru.cpp\u003e`\nMake sure you compile with `-std=c++11 -lpthread -ldl` on relevant environments.\n\n## CMake Instructions\n\nLoguru can be added to an existing CMake project in three ways\n\n1. `add_subdirectory()`\n2. `FetchContent()`\n3. `find_package()`\n\nSee [CMake example](./loguru_cmake_example/CMakeLists.txt) for a demonstration.\n\n## Usage\n\n``` C++\n#include \u003cloguru.hpp\u003e\n\n…\n\n// Optional, but useful to time-stamp the start of the log.\n// Will also detect verbosity level on command line as -v.\nloguru::init(argc, argv);\n\n// Put every log message in \"everything.log\":\nloguru::add_file(\"everything.log\", loguru::Append, loguru::Verbosity_MAX);\n\n// Only log INFO, WARNING, ERROR and FATAL to \"latest_readable.log\":\nloguru::add_file(\"latest_readable.log\", loguru::Truncate, loguru::Verbosity_INFO);\n\n// Only show most relevant things on stderr:\nloguru::g_stderr_verbosity = 1;\n\nLOG_SCOPE_F(INFO, \"Will indent all log messages within this scope.\");\nLOG_F(INFO, \"I'm hungry for some %.3f!\", 3.14159);\nLOG_F(2, \"Will only show if verbosity is 2 or higher\");\nVLOG_F(get_log_level(), \"Use vlog for dynamic log level (integer in the range 0-9, inclusive)\");\nLOG_IF_F(ERROR, badness, \"Will only show if badness happens\");\nauto fp = fopen(filename, \"r\");\nCHECK_F(fp != nullptr, \"Failed to open file '%s'\", filename);\nCHECK_GT_F(length, 0); // Will print the value of `length` on failure.\nCHECK_EQ_F(a, b, \"You can also supply a custom message, like to print something: %d\", a + b);\n\n// Each function also comes with a version prefixed with D for Debug:\nDCHECK_F(expensive_check(x)); // Only checked #if !NDEBUG\nDLOG_F(INFO, \"Only written in debug-builds\");\n\n// Turn off writing to stderr:\nloguru::g_stderr_verbosity = loguru::Verbosity_OFF;\n\n// Turn off writing err/warn in red:\nloguru::g_colorlogtostderr = false;\n\n// Throw exceptions instead of aborting on CHECK fails:\nloguru::set_fatal_handler([](const loguru::Message\u0026 message){\n\tthrow std::runtime_error(std::string(message.prefix) + message.message);\n});\n```\n\nIf you prefer logging with streams:\n\n``` C++\n#define LOGURU_WITH_STREAMS 1\n#include \u003cloguru.hpp\u003e\n...\nLOG_S(INFO) \u003c\u003c \"Look at my custom object: \" \u003c\u003c a.cross(b);\nCHECK_EQ_S(pi, 3.14) \u003c\u003c \"Maybe it is closer to \" \u003c\u003c M_PI;\n```\n\nFor more info, see [the official documentation](https://emilk.github.io/loguru/index.html).\n\n## Grep:able logs\n``` bash\n# Only show warnings, errors and fatal messages:\ncat logfile.txt | egrep \"[^0-9]\\|\"\n\n# Ignore verbosity-levels 4 and above:\ncat logfile.txt | egrep \"[^4-9]\\|\"\n\n# Only show verbosity-level 6:\ncat logfile.txt | egrep \"6\\|\"\n\n# Only show messages from the main thread:\ncat logfile.txt | egrep \"\\[main thread     \\]\"\n```\n\n## No includes in loguru.hpp\nI abhor logging libraries that `#include`'s everything from `iostream` to `windows.h` into every compilation unit in your project. Logging should be frequent in your source code, and thus as lightweight as possible. Loguru's header has *no #includes*. This means it will not slow down the compilation of your project.\n\nIn a test of a medium-sized project, including `loguru.hpp` instead of `glog/logging.hpp` everywhere gave about 10% speedup in compilation times.\n\nNote, however, that this gives you the bare-bones version of Loguru with printf-style logging. If you want `std::ostream` style logging (or GLOG functionality) you need to `#define LOGURU_WITH_STREAMS 1` before `#include \u003cloguru.hpp\u003e`, and that will make `loguru.hpp` include `\u003csstream\u003e`. No away around it!\n\n## Scopes\nThe library supports scopes for indenting the log-file. Here's an example:\n\n``` C++\nint main(int argc, char* argv[])\n{\n\tloguru::init(argc, argv);\n\tLOG_SCOPE_FUNCTION(INFO);\n\tLOG_F(INFO, \"Doing some stuff...\");\n\tfor (int i=0; i\u003c2; ++i) {\n\t\tVLOG_SCOPE_F(1, \"Iteration %d\", i);\n\t\tauto result = some_expensive_operation();\n\t\tLOG_IF_F(WARNING, result == BAD, \"Bad result\");\n\t}\n\tLOG_F(INFO, \"Time to go!\");\n\treturn 0;\n}\n```\n\n\nThis will output:\n\n```\n\t     loguru.cpp:184      0| arguments:       ./loguru_test test -v1\n\t     loguru.cpp:185      0| Verbosity level: 1\n\t     loguru.cpp:186      0| -----------------------------------\n\tloguru_test.cpp:108      0| { int main_test(int, char **)\n\tloguru_test.cpp:109      0| .   Doing some stuff...\n\tloguru_test.cpp:111      1| .   { Iteration 0\n\tloguru_test.cpp:111      1| .   } 0.133 s: Iteration 0\n\tloguru_test.cpp:111      1| .   { Iteration 1\n\tloguru_test.cpp:113      0| .   .   Bad result\n\tloguru_test.cpp:111      1| .   } 0.134 s: Iteration 1\n\tloguru_test.cpp:115      0| .   Time to go!\n\tloguru_test.cpp:108      0| } 0.267 s: int main_test(int, char **)\n```\n\n\n# `ERROR_CONTEXT`\nYou can also optionally log things ONLY if there is a crash. This is a very useful feature:\n\n```\n\tvoid process_file(const char* filename)\n\t{\n\t\tERROR_CONTEXT(\"filename\", filename);\n\t\tparse_file(filename); // Only if this crashes will filename be logged.\n\t}\n```\n\n\n## Streams vs printf\nSome logging libraries only supports stream style logging, not printf-style. This means that what in Loguru is:\n\n``` C++\nLOG_F(INFO, \"Some float: %+05.3f\", number);\n```\n\nin Glog becomes something along the lines of:\n\n``` C++\nLOG(INFO) \u003c\u003c \"Some float: \" \u003c\u003c std::setfill('0') \u003c\u003c std::setw(5) \u003c\u003c std::setprecision(3) \u003c\u003c number;\n```\n\nLoguru allows you to use whatever style you prefer.\n","funding_links":[],"categories":["TODO scan for Android support in followings","Logging","C++","进程间通信","Libraries"],"sub_categories":["日志","Logging"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femilk%2Floguru","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femilk%2Floguru","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femilk%2Floguru/lists"}