CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
Log Serializers

Data Structures

struct  LogSerializer
 A record serializer, owned by whichever transport it was handed to. More...
 
struct  LogTextConfig
 
struct  LogNdjsonConfig
 Configuration for the NDJSON serializer. More...
 

Typedefs

typedef void(* LogSerializeFunc) (string *out, const LogRecord *rec, void *userdata)
 
typedef void(* LogSerializerClose) (void *userdata)
 Releases a serializer's private context.
 
typedef struct LogSerializer LogSerializer
 A record serializer, owned by whichever transport it was handed to.
 
typedef struct LogTextConfig LogTextConfig
 
typedef struct LogNdjsonConfig LogNdjsonConfig
 Configuration for the NDJSON serializer.
 

Enumerations

enum  LOG_DATE_FORMATS {
  LOG_DateISO , LOG_DateISOCompact , LOG_DateNCSA , LOG_DateSyslog ,
  LOG_DateISOCompactMsec , LOG_DateTimeOnly , LOG_DateTimeOnlyMsec
}
 Timestamp format options for log output. More...
 
enum  LOG_FLAGS {
  LOG_LocalTime = 0x0001 , LOG_OmitLevel = 0x0002 , LOG_ShortLevel = 0x0004 , LOG_BracketLevel = 0x0008 ,
  LOG_JustifyLevel = 0x0010 , LOG_IncludeChannel = 0x0020 , LOG_BracketChannel = 0x0040 , LOG_AddColon = 0x0080 ,
  LOG_ChannelFirst = 0x0100 , LOG_IncludeContext = 0x0200 , LOG_OmitDate = 0x0400
}
 Formatting flags for text log output. More...
 

Functions

LogSerializerlogSerializerCreate (LogSerializeFunc serialize, LogSerializerClose close, void *userdata)
 
void logSerializerDestroy (LogSerializer **ser)
 
void logSerialize (string *out, LogSerializer *ser, const LogRecord *rec)
 
LogSerializerlogTextSerializer (LogTextConfig *config)
 
LogSerializerlogNdjsonSerializer (LogNdjsonConfig *config)
 
void logVarText (string *out, const stvar *v)
 
void logFormatDate (string *out, int dateFormat, uint32 flags, int64 timestamp)
 
void logFormatLevel (string *out, int level, uint32 flags)
 
void logFormatChannel (string *out, LogChannel *chan, uint32 flags)
 

Detailed Description

A destination is two separable things: a serializer, which turns a LogRecord into bytes, and a transport, which puts those bytes somewhere. Splitting them is what lets one rendering feed several places and one place accept several renderings:

record ──> serializer ──> transport
text rotating file
NDJSON console (TTY-aware)

A rotating NDJSON log is therefore not a new kind of destination; it is the file transport with a different serializer:

LogFileConfig cfg = { .rotateMode = LOG_RotateSize, .rotateSize = 10 * 1024 * 1024 };
LogDest *dest = logfileRegister(LOG_Info, NULL, vfs, _SL("app.ndjson"), &cfg,
struct LogDest LogDest
Opaque handle to a registered log destination.
Definition log.h:187
@ LOG_Info
Informational messages.
Definition log.h:103
LogDest * logfileRegister(int maxlevel, strref chanfilter, VFS *vfs, strref filename, const LogFileConfig *config, LogSerializer *ser)
@ LOG_RotateSize
Rotate when file exceeds rotateSize bytes.
Definition logfile.h:45
LogSerializer * logNdjsonSerializer(LogNdjsonConfig *config)
#define _SL(s)
Inline ASCII string literal with compile-time embedded length (STR_LEN8). Content must be < 200 bytes...
Definition strliteral.h:207
int rotateMode
Rotation mode from LOG_ROTATE_MODE enum.
Definition logfile.h:54

Ownership: a transport takes ownership of the serializer it is created with and destroys it when the destination is closed. Passing NULL gets a default text serializer, which is what every transport did before serializers existed.

Serializers do not write line terminators. Whether records are separated by "\n", "\r\n", or nothing at all is a property of the transport.

Typedef Documentation

◆ LogSerializeFunc

typedef void(* LogSerializeFunc) (string *out, const LogRecord *rec, void *userdata)

Turns a record into bytes

Parameters
outReceives the serialized record; any existing value is destroyed first
recRecord to serialize
userdataSerializer-private context

Definition at line 69 of file logserializer.h.

◆ LogTextConfig

typedef struct LogTextConfig LogTextConfig

Configuration for the text serializer

Produces the one-line human-readable form: timestamp, level, channel, message.

Enumeration Type Documentation

◆ LOG_DATE_FORMATS

Timestamp format options for log output.

Enumerator
LOG_DateISO 

ISO 8601: "2026-01-02T15:04:05Z", or with a zone offset.

LOG_DateISOCompact 

Compact ISO: "2026-01-02 15:04:05".

LOG_DateNCSA 

NCSA Common Log format: "02/Jan/2026:15:04:05 +00 00".

LOG_DateSyslog 

Syslog format: "Jan 2 15:04:05".

LOG_DateISOCompactMsec 

Compact ISO with milliseconds: "2026-01-02 15:04:05.123".

LOG_DateTimeOnly 

Time of day only, no calendar date: "15:04:05".

LOG_DateTimeOnlyMsec 

Time of day only, with milliseconds: "15:04:05.123".

Definition at line 39 of file logserializer.h.

◆ LOG_FLAGS

enum LOG_FLAGS

Formatting flags for text log output.

Enumerator
LOG_LocalTime 

Use local time instead of UTC.

LOG_OmitLevel 

Do not include severity level.

LOG_ShortLevel 

Use single-character level abbreviations.

LOG_BracketLevel 

Enclose log level in brackets [INFO].

LOG_JustifyLevel 

Make level a fixed-width column.

LOG_IncludeChannel 

Include channel path in output.

LOG_BracketChannel 

Enclose channel in brackets [net/http].

LOG_AddColon 

Add colon after the prefix.

LOG_ChannelFirst 

Channel between date and level instead of at end.

LOG_IncludeContext 

Append the log context's fields as [key:value ...].

LOG_OmitDate 

Do not include a timestamp at all.

Definition at line 50 of file logserializer.h.

Function Documentation

◆ logFormatChannel()

void logFormatChannel ( string *  out,
LogChannel chan,
uint32  flags 
)

Formats a channel prefix per flags (LOG_IncludeChannel, LOG_BracketChannel). Produces an empty string when the channel is omitted, NULL, or unnamed.

Parameters
outReceives the formatted channel prefix; any existing value is destroyed first
chanChannel, or NULL for default
flagsBitwise OR of LOG_FLAGS values

◆ logFormatDate()

void logFormatDate ( string *  out,
int  dateFormat,
uint32  flags,
int64  timestamp 
)

Formats a timestamp per dateFormat/flags.

Produces an empty string when LOG_OmitDate is set. Unlike the level and channel prefixes, the date does not carry a leading space – it is the first thing on the line – so a serializer that omits it has to drop the space belonging to whatever now comes first.

Parameters
outReceives the formatted date; any existing value is destroyed first
dateFormatOne of the LOG_DATE_FORMATS values
flagsBitwise OR of LOG_FLAGS values (LOG_LocalTime and LOG_OmitDate are consulted)
timestampWall clock timestamp to format

◆ logFormatLevel()

void logFormatLevel ( string *  out,
int  level,
uint32  flags 
)

Formats a level prefix per flags (LOG_OmitLevel, LOG_ShortLevel, LOG_BracketLevel, LOG_JustifyLevel). Produces an empty string when LOG_OmitLevel is set.

Parameters
outReceives the formatted level prefix; any existing value is destroyed first
levelLog severity level
flagsBitwise OR of LOG_FLAGS values

◆ logNdjsonSerializer()

LogSerializer * logNdjsonSerializer ( LogNdjsonConfig config)

Create an NDJSON serializer

Emits one JSON object per record: time, level, seq, chan (when the record has one) and msg, followed by one field per keyed argument. Unkeyed arguments are not emitted separately – they belong to the message template and are already in msg.

Parameters
configConfiguration, or NULL for the default (UTC timestamps)
Returns
Serializer, ready to be handed to a transport
logFmt(Info, _SL("request from ${string}"), stvar(string, host),
stvark(status, int32, 200));
// {"time":"2026-08-08T12:00:00Z","level":"Info","seq":7,"msg":"request from web01",
// "status":200}
#define logFmt(level, fmt,...)
Definition log.h:643
#define stvark(key, typen, val)
Definition stvar.h:204
#define stvar(typen, val)
Definition stvar.h:162

◆ logSerialize()

void logSerialize ( string *  out,
LogSerializer ser,
const LogRecord rec 
)

Serialize one record

Parameters
outReceives the serialized record; any existing value is destroyed first
serSerializer to use; NULL produces the record's plain rendered text
recRecord to serialize

◆ logSerializerCreate()

LogSerializer * logSerializerCreate ( LogSerializeFunc  serialize,
LogSerializerClose  close,
void *  userdata 
)

Assemble a serializer from callbacks

Only needed to write a serializer of your own; the built-in ones have their own factories.

Parameters
serializeCalled once per record
closeOptional cleanup for userdata
userdataSerializer-private context
Returns
Serializer, ready to be handed to a transport

◆ logSerializerDestroy()

void logSerializerDestroy ( LogSerializer **  ser)

Destroy a serializer

Transports call this on the serializer they own; a caller only needs it for a serializer that was never handed to one.

Parameters
serSerializer to destroy; set to NULL

◆ logTextSerializer()

LogSerializer * logTextSerializer ( LogTextConfig config)

Create a text serializer

Parameters
configFormatting configuration, or NULL for the zero-initialized default
Returns
Serializer, ready to be handed to a transport
LogDest *dest = logconsoleRegister(LOG_Info, NULL, NULL, NULL, &ccfg,
LogDest * logconsoleRegister(int maxlevel, strref chanfilter, ConStream *out, ConStream *err, const LogConsoleConfig *config, LogSerializer *ser)
LogSerializer * logTextSerializer(LogTextConfig *config)
@ LOG_BracketLevel
Enclose log level in brackets [INFO].
@ LOG_DateISO
ISO 8601: "2026-01-02T15:04:05Z", or with a zone offset.
int dateFormat
Date format from LOG_DATE_FORMATS; ignored under LOG_OmitDate.

◆ logVarText()

void logVarText ( string *  out,
const stvar v 
)

Renders any variant as plain text

What a serializer needs to emit a field value without knowing the field's type: numbers, strings and anything with a conversion to string come out as themselves, and objects go through the formatter. A value with no text form produces an empty string.

Parameters
outReceives the rendered value; any existing value is destroyed first
vVariant to render