odygrd / quill

Asynchronous Low Latency C++ Logging Library
MIT License
1.53k stars 157 forks source link

How to forward timestamps to systemd journal #481

Open TillAlex opened 3 months ago

TillAlex commented 3 months ago

I am implementing a sink logging to the systemd journal using sd_journal_send(). In general this works, but not surprisingly the timestamps between quill and systemd journal differ. Does anyone have experience with this and knows how to pass the quill timestamp to the systemd journal, so that it's displayed when printing the logs using journalctl?

odygrd commented 3 months ago

Do you mean that sd_journal_send records the timestamp when the log is written async and not the real timestamp of the log statement and you wish to overwrite that?

TillAlex commented 3 months ago

Exactly, that's my problem. I really need the exact timestamps from quill for debugging and optimizing.

odygrd commented 3 months ago

I don't know how you overwrite it in systemd, as i haven't used systemd much. I want to add a systemd sink in the future. If you find a solution to this please let me know.

odygrd commented 3 months ago

Does something like this work ? I haven't tested the code

#include <systemd/sd-journal.h>
#include <time.h>
#include <stdio.h>
#include <sys/uio.h>
#include <inttypes.h>

int main() {
    // Set up the custom timestamp (in microseconds since the UNIX epoch)
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts); // Get the current time
    uint64_t custom_timestamp = ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000;

    // Format the custom timestamp as a string
    char timestamp_str[32];
    snprintf(timestamp_str, sizeof(timestamp_str), "%" PRIu64, custom_timestamp);

    // Define the log message and other fields
    const char *message = "MESSAGE=This is a test log message with a custom timestamp";
    const char *priority = "PRIORITY=6"; // LOG_INFO

    // Use a struct iovec array to specify the fields
    struct iovec iov[3];
    iov[0].iov_base = (void*)message;
    iov[0].iov_len = strlen(message);
    iov[1].iov_base = (void*)"_SOURCE_REALTIME_TIMESTAMP=";
    iov[1].iov_len = strlen("_SOURCE_REALTIME_TIMESTAMP=");
    iov[2].iov_base = (void*)timestamp_str;
    iov[2].iov_len = strlen(timestamp_str);

    // Send the log message with the custom timestamp
    sd_journal_sendv(iov, 3);

    return 0;
}
TillAlex commented 3 months ago

I already tried setting _SOURCE_REALTIME_TIMESTAMP, but unfortunately it can not be set by client code, because it belongs to the "trusted fields".

odygrd commented 3 months ago

I read somewhere while searching that it might be able to overpass that restriction with sd_journal_sendv but i haven’t tried it

TillAlex commented 3 months ago

I was using sd_journal_send and it did not work.

odygrd commented 3 months ago

This seems related by the way

https://github.com/systemd/systemd/issues/10301

TillAlex commented 3 months ago

For whatever reason I did not find that issue while searching for a solution and opened an issue myself:

https://github.com/systemd/systemd/issues/33446