armink/EasyLogger: a C logging library sized for microcontrollers
An ultra-lightweight(ROM<1.6K, RAM<0.3k), high-performance C/C++ log library. | 一款超轻量级(ROM<1.6K, RAM<0.3k)、高性能的 C/C++ 日志库
At a glance
- What is it?
- EasyLogger is an MIT-licensed C/C++ log library that claims ROM under 1.6K and RAM under 0.3K, aimed at firmware that cannot afford a general-purpose logger. The trade-off is a single global configuration and plugin-based extras.
- Who is it for?
- Pick EasyLogger when the target is a bare-metal board or an RTOS task where a general-purpose C logger would not fit, and when you accept one global configuration. Do not pick it if you need per-subsystem logger instances or log levels that vary per module at runtime, because the README states the parameter configuration and output method are singletons.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 48 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The firmware logging problem EasyLogger targets
On a desktop, a logger is a convenience. On a Cortex-M class board, it competes with the application for flash and SRAM, and every formatting call sits in the path of a real-time loop. General-purpose C/C++ loggers such as log4c and zlog assume more headroom than a small embedded target usually has. EasyLogger is written for that gap: the README describes it as an ultra-lightweight, high-performance C/C++ log library suited to resource-sensitive projects, naming IoT products, wearables and smart home devices. The stated budget is ROM under 1.6K and RAM under 0.3K. The intended user is a firmware engineer who wants leveled, tagged, timestamped output over a UART or into flash, without pulling in a file system or a dynamic allocation scheme. The README is explicit that the feature set is deliberately smaller than log4c or zlog, and that extra behaviour arrives as plugins rather than in the core.
How the core, the output routine and the plugins fit together
The core is a single configuration instance. The README states that parameter configuration and output method are singletons, meaning one global configuration applies process-wide. That keeps the code small, and the README acknowledges the cost directly: this mode cannot support complex output arrangements. Log levels follow Android Logcat numbering, where 0 is Assert and 5 is Verbose, with Error, Warn, Info and Debug in between. Filtering happens on three axes: tag, level and keyword. Tags are the project's answer to module classification, set per file, module or feature. Level control is two-tier: a static level fixed by macro at compile time, and a dynamic level changed through the API at runtime. The output format is assembled from selectable fields including level, timestamp, tag, process information, thread information, file path, line number and method name, and each level can have its own format. Output itself is not hardcoded to a terminal. The README says that with a port, any output method is possible, which is why the demo covers a terminal, a file and flash. Two caveats are stated in the README: RAW format and hexdump output do not support tag or keyword filtering, and the file plugin needs a file system while the flash plugin does not.
Installing EasyLogger and getting a first log line out
There is no package manager step documented. The README points to the repository itself and to the demo at demo/os/rt-thread/stm32f10x/, and it directs readers to the porting document at docs/zh/port/kernel.md before use. The README also says to read the documentation before porting and using the library. So the practical install is: clone the repository, copy the easylogger/ directory into your project, and add its sources to your build. The exact source list and include paths are what the porting document covers, not the README, so treat docs/zh/port/kernel.md as the authority for your toolchain.
The first real step is configuration. The README names elog_cfg.h as the file where per-level colours and font styles are set, which tells you that this header is the central compile-time configuration point.
elog_cfg.hNext you provide the output routine. The README describes output as something the user ports, so the library needs a function that writes a formatted buffer to your UART or other sink. The porting document is where the required signature and the initialisation call are specified; the README does not print them, and inventing them here would be guesswork.
Finally, set the compile-time level and log. Levels are numbered 0 for Assert up to 5 for Verbose, so a build that wants Info and above, and nothing more verbose, is a macro change in elog_cfg.h. After that, a log call with a tag and a level produces a line whose fields are whatever your format configuration selected. What you should see is a line carrying the level letter, for example [I] for Info, plus whichever of timestamp, tag, file path or line number you enabled.
What the singleton design rules out
The limitation is stated plainly in the README and it is structural, not a missing feature. Because configuration and output are singletons, you cannot give one module verbose logging and another module error-only logging through separate logger objects. Filtering by tag softens this, since tags let you classify output by file or module, but the filter itself is global state. The same applies to output: one sink at a time in the core, with additional behaviour such as file rotation or flash storage arriving through plugins. A second limitation concerns filtering coverage. RAW and hexdump output bypass tag and keyword filtering, so if you plan to dump binary payloads and also want keyword filtering over the same stream, those are separate paths. A third is documentation language: the README's documentation links point into docs/zh/, and the porting and API documents referenced are the Chinese-language files. If your team cannot read them, the README alone does not contain the porting interface. Finally, the README notes that synchronous output, which is the original design, can slow a platform down when output speed is low. The roadmap entry for asynchronous output is marked as completed, so asynchronous and buffered modes exist, but the README does not document their configuration.
EasyLogger against log4c and zlog, and against rolling your own
The README makes the comparison itself: against log4c and zlog, EasyLogger has simpler functionality and fewer interfaces, but is faster to learn, with more practical features added through plugins. That is a real difference in approach rather than a slogan. log4c and zlog are general-purpose C logging frameworks with richer configuration surfaces, which is exactly what costs code size. EasyLogger inverts the priority: a minimal core with a stated ROM and RAM budget, and optional plugins for file archiving and flash storage. The second alternative is the one most firmware teams actually use, a printf macro wrapped around a UART write. That costs almost nothing and needs no porting, but it gives you no level control, no tag filtering, no runtime level changes and no built-in path to persistent logs. EasyLogger's value over the macro is the two-tier level switch and the filter axes; its value over log4c and zlog is the footprint. If neither the filtering nor the level control matters to your project, the macro is the honest choice.
Maintenance, licence and upgrade cost
The repository is not archived and the last push was on 2026-08-13, so the tree is being touched. The release history tells a different story: 2.2.0 dates from 2019-11-30, 2.1.0 from 2019-07-29 and 2.0.0 from 2017-10-02. Tagged releases have been static for years while the default branch has seen later commits, which means anyone tracking a release number is on a 2019 codebase. Budget for reading the commit history rather than the release notes if you need recent changes. The licence is MIT, Copyright (c) [email protected], which permits commercial and closed-source use provided the copyright and permission notice are retained; that is the standard reading of MIT and not legal advice, so have your own process confirm notice handling if you ship binaries. One upgrade consideration is specific to this project: the Flash plugin depends on the separate EasyFlash library, so a plugin upgrade can drag in a second dependency with its own release cadence. The README's roadmap also lists unfinished items, including a file-system configuration file, a cross-platform log assistant and an Arduino library, so those should not be assumed present.
Editorial conclusion
Pick EasyLogger when the target is a bare-metal board or an RTOS task where a general-purpose C logger would not fit, and when you accept one global configuration. Do not pick it if you need per-subsystem logger instances or log levels that vary per module at runtime, because the README states the parameter configuration and output method are singletons. Before porting, read docs/zh/port/kernel.md and confirm your platform has an output routine you can register, and check whether the Flash plugin's EasyFlash dependency is acceptable for your storage layout.
Frequently asked questions
How much ROM and RAM does EasyLogger use?
The README states ROM under 1.6K and RAM under 0.3K, which is the basis for calling it ultra-lightweight. Actual figures depend on your compiler, the output format fields you enable and whether you use plugins.
Does EasyLogger support asynchronous logging?
The README describes log output as thread-safe and supporting both asynchronous and buffered output modes. It also notes that synchronous output, the original design, can slow down platforms with low output speed, and the roadmap entry for asynchronous output is marked as done.
Can EasyLogger write logs to flash without a file system?
Yes, through the Flash plugin, which uses the Flash operation interfaces provided by the EasyFlash library and stores logs directly in flash without a file system. The README notes this suits small embedded devices that lack a file system, and that the plugin adds EasyFlash as a dependency.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/armink-easylogger)