Mini-async-log-c - Mini async log C port. Now with C++ wrappers.

Overview

Description

A C11/C++11 low-latency wait-free producer (when using Thread Local Storage) asynchronous textual data logger with type-safe strings.

Based on the lessons learned on its older C++-only counterpart "mini-async-log".

AFAIK, this may be the fastest generic data logger for C or C++.

Features

Common:

  • Dual C/C++ library. The main implementation is C11.

  • wait-free fast-path (when using thread-local storage).

  • Very high performance. I have not found yet a faster data logger from the consumer side. Even when comparing against non-textual ones. The benchmarks live on a separate project:

    https://github.com/RafaGago/logger-bench

  • Various memory (log entry) sources: Thread Local Storage buffer, common bounded buffer (configurable to have one for each CPU) and custom log entry allocators (defaults to the heap's malloc/free).

  • Can customize each and every allocation made. It's able to receive two allocators, one for allocating log entries and another to allocate the internals. You get a pointer to the allocator on each allocation/deallocation call made, so additional data/state can be attached after the structure.

  • Type-safe format strings. On C11 achieved through C11 type-generic expressions and (unfortunately) brutal preprocessor abusing.

  • Not a singleton. No hidden threads: the client application can run the logger's consumer loop from an existing (maybe shared for other purposes) thread if desired.

  • Basic security features: Log entry rate limiting and newline removal.

  • Extensible log destinations (sinks).

  • Compile-time removable severities.

  • Lazy evaluated parameters. If the log call is filtered out because of a low severity the parameters don't get evaluated (macros).

  • Able to log strings/memory ranges by passing ownership, so the serialization overhead becomes a pointer. A destruction callback that frees resources has to be provided in this mode of operation.

  • Program runtime not affected by clock changes. Doesn't use any non-monotonic blocking mechanism.

  • Log files not affected by clock changes. The log files have a monotonic clock. Conversion to calendar time is possible by using a timestamp embedded on the file name.

  • Decent test coverage.

C++ only:

  • The instance control functions can be selected to return error codes, matching more or less the C interface, or to throw exceptions.

    This logger can be used in projects with non-throwing coding standards. Projects that are willing to use exceptions can write less error handling boilerplate by enabling the exception based interface. The logging functions are error-code based only (noexcept), as they are free functions on the fast-path.

  • Can log std::ostream-able types by value or wrapped in a smart pointer.

  • Can log std::string, smart pointers to std::string and smart pointers to std::vector containing arithmetic types.

  • It allows adding custom logging for additional data types.

  • It almost doesn't leak any C function or data type to the global namespace, and the few they do are prefixed with "malc_".

Design

The life of a log message under this logger is.

At compile time

  • The format string is validated (C++ only).

  • A "static const" data structure is created containing the format string, the severity, a code for each data type and the number of compressed datatypes (if enabled). All the previous data can be passed with just the overhead of one pointer.

At run time

  • A log call is made.

  • The passed arguments are stored on the stack after being passed through a type-specific conversion function, which leaves the data type ready to serialize and to retrieve it size on the wire. The conversion function is most cases just doing nothing. Easy for the compiler to optimize away.

  • The required payload size for serializing the unformatted log entry is computed, taking as input the transformed type on the step above. For simple cases it's just a compile time constant (sizeof (type)). Again easy to be optimized away.

  • Memory for an intrusive linked list node and all the serialization payload is requested from the logger in a single contiguous memory chunk.

  • The pointer to the "static const" data structure and the payload data is serialized on the memory chunk after the intrusive linked list node (unused at this point).

  • The intrusive node is passed to the logging queue.

  • At some point the consumer thread fetches the node, deserializes it, applies formatting, forwards it to the log destinations/sinks and then frees the node memory.

The log queue

It's the well known Dmitry Vyukov's intrusive MPSC queue. Wait-free producers. Blocking consumer. Perfect for this use case. Very good performance under low contention and good performance when contended.

The memory

3 configurable memory sources:

  • Thread Local Storage. A per-thread bounded SPSC array-based cache-friendly memory queue that has to be explictly iniatized by each thread using it.

  • Global bounded size queue. Again a Dmitry Vyukov queue. This time it's MPMC one but broken in prepare-commit blocks and with a custom modification to accept variable-size allocations (at the expense of fairness unfortunately). Can be configured to use one queue per CPU to try to fight contention. This queue has extremely good performance on the uncontended case but doesn't scale as good as the modern Linux heap allocator under big contention from many threads. It's included because bounded queues are desirable sometimes.

  • Allocator. Defaults to the heap but can allocate from any user-provided source.

All three sources can be used together, separately or mixed. The priority order is: TLS, bounded, allocator.

Formatting

This is already hinted, there is no formatting on the producer-side. It happens on the consumer side and its cost is masked by file-io.

Usage Quickstart

Look at the examples folder.

https://github.com/RafaGago/mini-async-log-c/tree/master/example/src

Log format strings

The format strings have this (common) bracket delimited form:

"this is value 1: {} and this is value 2: {}"

The opening brace '{' is escaped by doubling it. The close brace doesn't need escaping.

Depending on the data type modifiers inside the brackets are accepted. Those try to match own printf's modifiers.

As a reminder, "printf" format strings are composed like this:

%[flags]\[width][.precision]\[length]specifier

Where the valid chars for each field are (on C99):

  • flags: #, 0, +, -

  • width: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

  • precision: ., 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, .*

  • length: h, hh, l, ll, j, z, t, L

  • specifiers: d, i, u , o, x, X, f, F, e, E, g, G, a, A, c, s, p, n, %

Malc autodetecs the datatypes passed to the log strings, so the "length" modifiers and signedness "specifiers" are never required. Which specifiers can be used on which data type is also restricted only to those that make sense.

Malc adds a non-numeric precision specifier: 'w'

'w' represents the maximum digit count excluding sign that the maximum value of a given type can have. It is aware if the type is going to be printed in decimal, hexadecimal or octal base.

On malc there are two precision modifier groups [0-9], w. Both of them are mutually exclusive. Only one of them can be specified, the result of not doing so is undefined.

Next comes a summary of the valid modifiers for each type.

integrals (or std::vector of integrals)

  • flags: #, 0, +, -

  • width: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

  • precision: ., 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, w

  • specifiers: o, x, X

floating point (or std::vector of floating point)

  • flags: #, 0, +, -

  • width: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

  • precision: ., 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

  • specifiers: f, F, e, E, g, G, a, A

others

Other types, like pointers, strings, etc. accept no modifiers.

examples

"this is a fixed 8 char width 0-padded integer: {08}"

"hex 8 char width zero padded integer: {08x}"

"0-padded integer to the digits that the datatype's max/min value has: {.w}"

"0-padded hex integer to the datatype's nibble count: {.wx}"

"Escaped open brace: {{"

Build and test

Linux

Meson is used.

debian/ubuntu example:

git submodule update --init --recursive

sudo apt install ninja-build python3-pip
sudo -H pip3 install meson

MYBUILDDIR=build
meson $MYBUILDDIR  --buildtype=release
ninja -C $MYBUILDDIR
ninja -C $MYBUILDDIR test

Windows

Acquire meson and ninja, if you are already using Python on Windows you may want to intall meson by using a python package manager (e.g. pip) and then install Ninja (ninja-build) separately.

If you don't, the easiest way to add all the dependecies is to download meson + Ninja as an MSI installer from meson's site:

https://mesonbuild.com/Getting-meson.html

Once you have meson installed the same steps as on Linux apply. Notice that:

  • meson can generate Visual Studio solutions.

  • If you use meson with Ninja and the Microsoft compiler you need to export the Visual Studio environment before. This is done by running "vcvarsall.bat" or "vcvars32.bat/vcvars64.bat" depending on the Visual Studio version you have installed. In my machine with 2019 Community it lies in:

    "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"

Without build system (untested)

Compile every file under "src" and use "include" as include dir. This will still have challenges:

  • Compiling the "base-library" dependency. It follows the same structure. Compile everything under "src" and include "include". Statically link with the "base", "nonblock" and "time extras" libraries.

  • Generating "include/malc/config.h", a sample from my machine as of now:

#ifndef __MALC_CONFIG_H__
#define __MALC_CONFIG_H__

/* autogenerated file, don't edit */

#define MALC_VERSION_MAJOR 1
#define MALC_VERSION_MINOR 0
#define MALC_VERSION_REV   0
#define MALC_VERSION_STR   "1.0.0"
#define MALC_BUILTIN_COMPRESSION 0
#define MALC_PTR_MSB_BYTES_CUT_COUNT 0

#endif /* __MALC_CONFIG_H__ */

Linking

This library links to a tiny own utility library that I use for C resources that aren't project specific, so I can reuse them.

Both "malc" and this library are meant to be statically linked to your project.

If you run

DESTDIR=$PWD/dummy-install ninja -C $MYBUILDDIR install

You may see these files on the library section:

└── lib
    └── x86_64-linux-gnu
        ├── libbl-base.a
        ├── libbl-getopt.a
        ├── libbl-nonblock.a
        ├── libbl-serial.a
        ├── libbl-taskqueue.a
        ├── libbl-time-extras.a
        ├── libcmocka.a
        ├── libmalc.a
        ├── libmalcpp.a
        └── pkgconfig
            ├── bl-base.pc
            ├── bl-getopt.pc
            ├── bl-nonblock.pc
            ├── bl-serial.pc
            ├── bl-taskqueue.pc
            ├── bl-time-extras.pc
            ├── malc.pc
            └── malcpp.pc

Your C project will need to link against: "libbl-time-extras.a", "libbl-base.a" "libbl-nonblock.a" and "libmalc.a". Your C++ project will need also to link "libmalcpp.a".

Some useful build parameters and compile time macros

Build parameters (meson)

See "meson_options.txt". These parameters end up on "include/malc/config.h".

Compile time macros

  • "malc_fileline"

    Prepends the file and the line to the log entry literal.

    log_error (malc_fileline "Something happended").
  • MALC_STRIP_LOG_[DEBUG|TRACE|NOTICE|WARNING|ERROR|CRITICAL]

    Removes all the log entries with a serverity less or equal that the one specified.

  • MALC_NO_SHORT_LOG_MACROS

    Malc defines both logging macros called e.g. "malc_error" and "log_error", when "MALC_NO_SHORT_LOG_MACROS" is defined "log_" prefixed macros aren't defined.

  • MALC_CUSTOM_LOGGER_INSTANCE_EXPRESSION

    On the macros that doesn't take a malc instance explictly (those that don't have the "_i" suffix) malc invokes an macro containing an expression to get the logger instance. By default this macro contains "get_malc_instance()", so it retrieves the logger instance by a call to a function called "get_malc_instance()" that has to be provided by the user.

    To use an expression other than "get_malc_instance()" define the MALC_CUSTOM_LOGGER_INSTANCE_EXPRESSION.

    Notice that on C this expression has to return a pointer, on C++ it has to return a reference.

Gotchas

Crash handling

This library doesn't install any crash handlers because in my opionion it is out of the scope of a logging library.

If you want to terminate and flush the logger from a signal/exception handler, you can call "malc_terminate (ptr, false)" from there.

Lazy-evaluation of parameters

Both the C and the C++ log functions doesn't have function-like semantics:

  • The passed parameters are only evaluated if the log entry is going to be logged. Log entries can be filtered out by severity or in case of the "log_|severity|_if" macro family if the conditional parameter is evaluated to be "false".

  • As with the C "assert" macro, log entries can be stripped at compile time by defining the "MALC_STRIP_LOG_|SEVERITY|" macro family.

This is deliberate, so you can place expensive function calls as log arguments.

Asynchronous logging

When timestamping at the producer thread is enabled (the default is platform dependant), there is the theoretical possibility that some entries show timestamps that go backwards in time some fractions of a second. This is expected. Consider this case:

  • Thread 1: gets timestamp.

  • Thread 1: gets preempted by the OS scheduler.

  • Thread 2: gets timestamp.

  • Thread 2: posts the log entry into the queue.

  • Thread 1: is schedulead again

  • Thread 1: posts the log entry into the queue.

A big mutex on the queue wouldn't theoretically show this behavior, but then:

  • The timestamp would get more jitter, as it will account the time waiting for the mutex.

  • This logger wouldn't perform as it does.

Thread safety of values passed by reference to the logger

All values passed by pointer to malc are assumed to never be modified again by any other thread. The results of doing so are undefined.

Tradeoffs

When using this library remember that this is an asynchronous logger designed to optimize the caller/producer site. Consider if your application really needs an asynchronous logger and if performance at the call site is more important than the added complexity of having an asynchronous logger.

Tradeoffs:

  • It trades code size at the call site for performance. On C each log macro call puts at least one branch and two function calls with error code checks at the calling site. This is without counting parameters. For each parameter there is at least a (hopefully optimized away) call to "memcpy" too.

    On C++ it does exactly the same operations, but considering the language standards I wouldn't call it more bloated than any other implementation using variadic templates for logging the calls.

  • Some C++ features may be harder to implement because the core is C. Time will tell.

You might also like...
C++Now 2012 PresentationsC++Now 2012 Presentations - Presentation materials presented at C++Now 2012.

C++Now! 2012 Presentations and Papers Monday Presentations Jeff Garland:Library in a Week (I) Leor Zolman: A Whirlwind Overview of C++11 Boris Schaeli

Fix some extrinsic parameter importing problems. 6-axis IMU works now. Lidar without ring works now.

LVI-SAM-MODIFIED This repository is a modified version of LVI-SAM. Modification Add function to get extrinsic parameters.The original code assumes the

Simple application log library. supporting multiple log levels, custom output  & flash memory support.
Simple application log library. supporting multiple log levels, custom output & flash memory support.

ArduinoLog - C++ Log library for Arduino devices An minimalistic Logging framework for Arduino-compatible embedded systems. ArduinoLog is a minimalist

Port-Fin(port finder) is a tool which scans for open and closed port on a website/host.
Port-Fin(port finder) is a tool which scans for open and closed port on a website/host.

Port-Fin(port finder) is a tool which scans for open and closed port on a website/host. This tool scans the state of the well known/common ports.

A project designed for the esp8266 D1 Mini or the esp8266 D1 Mini PRO to provide a wifi http server and dns server.
A project designed for the esp8266 D1 Mini or the esp8266 D1 Mini PRO to provide a wifi http server and dns server.

PS4 Server 9.00 This is a project designed for the esp8266 D1 Mini or the esp8266 D1 Mini PRO to provide a wifi http server and dns server. this is fo

A modern port of Turbo Vision 2.0, the classical framework for text-based user interfaces. Now cross-platform and with Unicode support.
A modern port of Turbo Vision 2.0, the classical framework for text-based user interfaces. Now cross-platform and with Unicode support.

Turbo Vision A modern port of Turbo Vision 2.0, the classical framework for text-based user interfaces. Now cross-platform and with Unicode support. I

IntX is a C++11 port of IntX arbitrary precision Integer library with speed, about O(N * log N) multiplication/division algorithms implementation.

IntX IntX is a C++11 port of IntX arbitrary precision Integer library with speed, about O(N * log N) multiplication/division algorithms implementation

Thin C++-flavored wrappers for the CUDA Runtime API

cuda-api-wrappers: Thin C++-flavored wrappers for the CUDA runtime API Branch Build Status: Master | Development: nVIDIA's Runtime API for CUDA is int

PcapPlusPlus is a multiplatform C++ library for capturing, parsing and crafting of network packets. It is designed to be efficient, powerful and easy to use. It provides C++ wrappers for the most popular packet processing engines such as libpcap, WinPcap, DPDK and PF_RING.
🎮 C Bindings/Wrappers for Apple's METAL framework

Apple's Metal for C C Wrapper for Apple's METAL framework. This library is C bindings of Metal API (MetalGL). Since OpenGL is deprecated, this library

🎮 C Bindings/Wrappers for Apple's METAL framework

Apple's Metal for C C Wrapper for Apple's METAL framework. This library is C bindings of Metal API (MetalGL). Since OpenGL is deprecated, this library

C++ wrappers for SIMD intrinsics and parallelized, optimized mathematical functions (SSE, AVX, NEON, AVX512)

C++ wrappers for SIMD intrinsics and parallelized, optimized mathematical functions (SSE, AVX, NEON, AVX512)

Toolkit for software engineers to Deploy AI Systems Yourself (DAISY). DaisyKit SDK is the core of models and algorithms, which can be used to develop wrappers and applications for different platforms: mobile, embedded or web browsers.
autogen bindings to Raylib 4.0 and convenience wrappers on top. Requires use of `unsafe`

Raylib-CsLo Raylib-CsLo LowLevel autogen bindings to Raylib 4.0 and convenience wrappers on top. Requires use of unsafe A focus on performance. No run

Async++ concurrency framework for C++11

Async++ Async++ is a lightweight concurrency framework for C++11. The concept was inspired by the Microsoft PPL library and the N3428 C++ standard pro

Mongoose Embedded Web Server Library - a multi-protocol embedded networking library with TCP/UDP, HTTP, WebSocket,  MQTT built-in protocols, async DNS resolver, and non-blocking API.
Mongoose Embedded Web Server Library - a multi-protocol embedded networking library with TCP/UDP, HTTP, WebSocket, MQTT built-in protocols, async DNS resolver, and non-blocking API.

Mongoose - Embedded Web Server / Embedded Networking Library Mongoose is a networking library for C/C++. It implements event-driven non-blocking APIs

Async & Concurrent Servers implemented in C

Concurrent servers in c Imlementation of concurrent severs in c from scratch using this awesome blog as a tutorial. Project Structure . ├── readme.md

Example programs for Talking Async videos

Talking Async Example programs for the Talking Async videos, which can be found on YouTube. Episode 1: Why C++20 is the Awesomest Language for Network

A PostgreSQL extension providing an async networking interface accessible via SQL using a background worker and curl.

pg_net is a PostgreSQL extension exposing a SQL interface for async networking with a focus on scalability and UX.

Comments
  • C++ compiling & CMake integration & Linking order of static dependencies

    C++ compiling & CMake integration & Linking order of static dependencies

    Hi, I had some issues using your library in a small project of mine. I solved those issues and I thought I'd share here.

    Setup

    Ubuntu 19.10 gcc 9.2.1 cmake 3.17.0 meson 0.53.2 ninja 1.9.0

    Issue compiling the standalone project (standard)

    $ cd mini-async-log-c
    $ meson build --buildtype=release
    $ ninja -C build
    

    I get the following error:

    In file included from ../subprojects/base_library/include/bl/base/thread.h:12,
                     from ../subprojects/base_library/test/src/bl/base/time_test.c:6:
    ../subprojects/base_library/include/bl/base/impl/thread_c11.h: At top level:
    ../subprojects/base_library/include/bl/base/impl/thread_c11.h:52:48: error: unknown type name ‘bl_tss_cleanup_func’
       52 | static inline bl_err bl_tss_init (bl_tss* key, bl_tss_cleanup_func cleanup)
          |                                                ^~~~~~~~~~~~~~~~~~~
    

    Cause

    It seems that there is a discrepancy in the implementation files when using C11 threads instead of POSIX threads in the base-library dependency: bl/base/impl/thread_C11.h bl/base/impl/tss_posix.h

    The implementation choice is defined in bl/base/thread.h which depends on bl/base/platform.h and since I use a recent version of gcc (I guess ?) the choice is made to enable BL_HAS_C11_THREAD.

    NB: Interestingly this issue didn't arise when I tried to compile logger-bench and base-library as a standalone but I didn't dig much farther. NBB: malcpp did not compile with logger-bench though :(

    Solution

    I first chose the quick and dirty way of switching the preprocessor directives in bl/base/thread.h to give priority to the use of POSIX threads. I ended up with this error:

    c++ -Isubprojects/base_library/b3ec909@@[email protected] -Isubprojects/base_library -I../subprojects/base_library -I../subprojects/base_library/include -I../subprojects/base_library/src -I../subprojects/base_library/test/src -I../subprojects/base_library/gitmodules/relacy -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -std=c++11 -O3 -pthread -MD -MQ 'subprojects/base_library/b3ec909@@[email protected]/test_src_bl_mpmc_bpm_relacy_mpmc_bpm_relacy.cpp.o' -MF 'subprojects/base_library/b3ec909@@[email protected]/test_src_bl_mpmc_bpm_relacy_mpmc_bpm_relacy.cpp.o.d' -o 'subprojects/base_library/b3ec909@@[email protected]/test_src_bl_mpmc_bpm_relacy_mpmc_bpm_relacy.cpp.o' -c ../subprojects/base_library/test/src/bl/mpmc_bpm_relacy/mpmc_bpm_relacy.cpp
    ../subprojects/base_library/test/src/bl/mpmc_bpm_relacy/mpmc_bpm_relacy.cpp:304:10: fatal error: relacy/relacy.hpp: No such file or directory
      304 | #include <relacy/relacy.hpp>
          |          ^~~~~~~~~~~~~~~~~~~
    

    With this error, I gave up the idea of using a C threading implementation since the logger would eventually be used in a C++ library.

    Issue compiling the standalone project (C++ implementation)

    I use the -xc++ flag to force gcc to compile c++ code regardless of the compiled file:

    $ cd mini-async-log-c
    $ CFLAGS=-xc++ meson build --buildtype=release
    $ ninja -C build
    

    I end up with a bunch of compiling errors related to the use of cmocka as unit testing framework (not reproduced here). Next try without building the tests:

    $ cd mini-async-log-c
    $ CFLAGS=-xc++ meson build --buildtype=release -Dbare=true
    $ ninja -C build
    

    I get this kind of error:

    ../subprojects/base_library/src/bl/base/dynamic_string_replace.c:178:1: error: jump to label ‘destroy_bl_dynarray’
      178 | destroy_bl_dynarray:
          | ^~~~~~~~~~~~~~~~~~~
    ../subprojects/base_library/src/bl/base/dynamic_string_replace.c:162:10: note:   from here
      162 |     goto destroy_bl_dynarray;
          |          ^~~~~~~~~~~~~~~~~~~
    ../subprojects/base_library/src/bl/base/dynamic_string_replace.c:164:9: note:   crosses initialization of ‘char* rptr_prev’
      164 |   char* rptr_prev   = s->da.str + bl_dstr_len (s);
          |         ^~~~~~~~~
    

    Cause

    This was caused by the use of goto labels that jumped over the declaration with initialization of temporary variables which seems to be allowed in C but not in C++. In the malc project:

    In the base-library project:

    Solution

    I went the q-a-d way again and (stupidly) rewrote the branching logic in those code segments using flags to emulate the goto mechanism. I later stumbled on one of your commit or in-code commentary specifying that the goto mechanism was intended to improve code readability and it did... quite a lot.

    I gave another try at solving this and simply created local scopes for the temporary variables jumped over by gotos. It did solve the goto issue.

    Issue compiling the standalone project (C++ implementation #2)

    So, again:

    $ cd mini-async-log-c
    $ CFLAGS=-xc++ meson build --buildtype=release -Dbare=true
    $ ninja -C build
    

    And this time I'm met with this kind of error:

    ../subprojects/base_library/src/bl/serial/serial_posix.c: In function ‘bl_err bl_serial_init(bl_serial**, bl_uword, const bl_alloc_tbl*)’:
    ../subprojects/base_library/include/bl/base/allocator.h:54:29: error: invalid conversion from ‘void*’ to ‘bl_serial*’ [-fpermissive]
       54 |   (bl_alloc_tbl_ptr)->alloc ((bytes), (bl_alloc_tbl_ptr))
          |   ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          |                             |
          |                             void*
    

    I didn't search this one through a lot and directly went:

    $ cd mini-async-log-c
    $ CFLAGS="-xc++ -fpermissive" meson build --prefix=/ --buildtype=release -Dbare=true
    $ ninja -C build
    

    And thus, I was able to compile the logger. Now to the CMake integration.

    CMake integration & Linking order

    This part is more for those interested by using this logger inside a CMake project. So, having everything compiled, I installed it with the complete compile + install command being:

    $ cd mini-async-log-c
    $ CFLAGS="-xc++ -fpermissive" meson build --prefix=/ --buildtype=release -Dbare=true
    $ ninja -C build
    $ DESTDIR=$PWD/install ninja -C build install
    

    And, based on the README, I wrote my Findmini-async-log-c.cmake and managed to gather everything as STATIC IMPORTED libraries. I created an INTERFACE target to regroup everything under the same umbrella like this:

    add_library(mini-async-log-c INTERFACE IMPORTED)
    target_link_libraries(mini-async-log-c
        INTERFACE
            malc
            malcpp
            bl-base
            bl-nonblock
            bl-time-extras
            Threads::Threads
    )
    

    I used your example hello-malcpp.cpp inside my project to test the integration. In doing so, I did stumble on some linking error like:

    /usr/bin/ld: /home//mini-async-log-c/install/lib/x86_64-linux-gnu/libmalcpp.a(src_malcpp_destinations.cpp.o): in function `malcpp::array_dst::size() const':
    destinations.cpp:(.text+0x99): undefined reference to `malc_array_dst_size'
    

    Which appeared to be related to my wrong ordering of static libraries when creating my umbrella target.
    Furthermore I got some errors looking like:

    /usr/bin/ld: /home//mini-async-log-c/install/lib/x86_64-linux-gnu/libmalc.a(src_malc_entry_parser.c.o): in function `push_obj_data(void*, char const*, char const*, malc_obj_log_data const*)':
    entry_parser.c:(.text+0x598): undefined reference to `bl_itostr_dyn_arr'
    

    Those errors stemed from the dependency on bl-tostr library from base-library, I added it to the mini-async-log-c target and got this target which, linked with the example, could compile:

    add_library(mini-async-log-c INTERFACE IMPORTED)
    target_link_libraries(mini-async-log-c
        INTERFACE
            malcpp
            malc
            bl-tostr
            bl-nonblock
            bl-time-extras
            bl-base
            Threads::Threads
    )
    

    And that's it !

    Sorry for the big chunk of text, I hope you'll find some interesting feedback in it. And thanks for releasing this project, now having everything setup, I can't wait to give it an in-depth try.

    NB: I attached the Findmini-async-log-c.cmake for those interested. You can use it as such:

    list(INSERT CMAKE_MODULE_PATH 0 "path/to/find/modules")
    set(mini-async-log-c_ROOT "abs/path/to/mini-async-log-c" CACHE PATH "Location of the mini-async-log-c library")
    find_package(mini-async-log-c MODULE)
    
    opened by GeoffreyRobert 10
  • Production Ready?

    Production Ready?

    Is this library production ready or should the original mal be used instead? Which branch is best to be used? It looks like there's no ci builds etc for this.

    question 
    opened by andrewkcorcoran 9
  • stress test: Missing messages for small message counts.

    stress test: Missing messages for small message counts.

    Steps to reproduce:

    Modify the stress test utility to use a thread only (to reproduce it faster) and use a very high number of iterations of only one message with TLS.

    What has been discovered so far:

    -It seems to only happen for small message counts, it points to be an initialization/shutdown problem only. -It seems to happen when running only producer thread. -Fortunately it's reproductible on Debug mode. -If malc.c is modified to keep track of the messages that it gets (on static variables properly initialized each time) and trigger assertions there, it shows that when the error is triggered there isn't a single message coming to the queue (the message itself + the TLS buffer init/deinit command messages). -The TLS creation functions are reporting no errors.

    Platform:

    -Linux (Ubuntu 16-04 x64).

    To check:

    -If it happens when using the heap -> TLS issue.

    opened by RafaGago 1
Owner
null
log4cplus is a simple to use C++ logging API providing thread-safe, flexible, and arbitrarily granular control over log management and configuration. It is modelled after the Java log4j API.

% log4cplus README Short Description log4cplus is a simple to use C++17 logging API providing thread--safe, flexible, and arbitrarily granular control

null 1.4k Jan 4, 2023
Example program using eBPF to log data being based in using shell pipes

Example program using eBPF to log data being based in using shell pipes (|)

pat_h/to/file 35 Oct 21, 2022
A revised version of NanoLog which writes human readable log file, and is easier to use.

NanoLogLite NanoLogLite is a revised version of NanoLog, and is easier to use without performance compromise. The major changes are: NanoLogLite write

Meng Rao 26 Nov 22, 2022
Log engine for c plus plus

PTCLogs library PTCLogs is a library for pretty and configurable logs. Installation To install the library (headers and .so file), clone this repo and

Pedro Tavares de Carvalho 12 May 20, 2022
Cute Log is a C++ Library that competes to be a unique logging tool.

Cute Log Cute Log is a C++ Library that competes to be a unique logging tool. Version: 2 Installation Click "Code" on the main repo page (This one.).

null 3 Oct 13, 2022
Compressed Log Processor (CLP) is a free tool capable of compressing text logs and searching the compressed logs without decompression.

CLP Compressed Log Processor (CLP) is a tool capable of losslessly compressing text logs and searching the compressed logs without decompression. To l

null 516 Dec 30, 2022
View and log aoe-api requests and responses

aoe4_socketspy View and log aoe-api requests and responses Part 1: https://www.codereversing.com/blog/archives/420 Part 2: https://www.codereversing.c

Alex Abramov 10 Nov 1, 2022
Sagan - a multi-threads, high performance log analysis engine

Sagan - Sagan is a multi-threads, high performance log analysis engine. At it's core, Sagan similar to Suricata/Snort but with logs rather than network packets.

Quadrant Information Security 80 Dec 22, 2022
Log.c2 is based on rxi/log.c with MIT LICENSE which is inactive now. Log.c has a very flexible and scalable architecture

log.c2 A simple logging library. Log.c2 is based on rxi/log.c with MIT LICENSE which is inactive now. Log.c has a very flexible and scalable architect

Alliswell 2 Feb 13, 2022
C++Now 2013 PresentationsC++Now 2013 Presentations - Presentation materials presented at C++Now 2013.

C++Now 2013 Presentations Note: some of the presentations exceed GitHub's blob size limit of about 10MB. These presentations have been split into mult

null 191 Dec 17, 2022