Skip to main content

Overview

WLog provides a hierarchy of named loggers that can be configured independently. Every logger has a dotted-path name (e.g. com.freerdp.core.channel). Child loggers inherit their level from the parent unless explicitly overridden, so you can silence everything at the root and selectively enable one subsystem. The header is winpr/include/winpr/wlog.h. Include it with:
#include <winpr/wlog.h>

Log levels

Levels are ordered from most-verbose to least-verbose. Setting a level enables that level and all levels above it (i.e., less verbose).
ConstantValueDescription
WLOG_TRACE0Everything, including raw packet/data dumps
WLOG_DEBUG1Debug messages
WLOG_INFO2General informational messages
WLOG_WARN3Warnings about unexpected but recoverable conditions
WLOG_ERROR4Errors that affect functionality
WLOG_FATAL5Fatal problems — the application cannot continue
WLOG_OFF6Completely disables all output for this logger
WLOG_LEVEL_INHERIT0xFFFFInherit the level from the parent logger (default)

Quick start

1

Get a logger

Call WLog_Get with a dotted tag name. The returned pointer is cached and reused for the lifetime of the process — it is safe to store in a static variable.
#include <winpr/wlog.h>

static wLog* log = NULL;

void mylib_init(void)
{
    log = WLog_Get("com.example.mylib");
}
2

Log messages

Use the WLog_Print macro (checks the active level before formatting) or the convenience tag-based macros WLog_DBG, WLog_INFO, WLog_WARN, WLog_ERR, WLog_FATAL.
WLog_Print(log, WLOG_INFO,  "connection established to %s:%d", host, port);
WLog_Print(log, WLOG_WARN,  "retrying after %d ms", delay);
WLog_Print(log, WLOG_ERROR, "failed to allocate buffer: %s", strerror(errno));
Or using the tag macros (logger is looked up once and cached internally):
#define TAG "com.example.mylib"

WLog_DBG(TAG,   "entering function %s", __func__);
WLog_INFO(TAG,  "version %d.%d", major, minor);
WLog_WARN(TAG,  "deprecated API called");
WLog_ERR(TAG,   "write failed: %s", strerror(errno));
WLog_FATAL(TAG, "out of memory — aborting");
3

Configure via environment (optional)

# Show INFO and above for everything
export WLOG_LEVEL=INFO

# Show TRACE only for one subsystem, WARN for everything else
export WLOG_FILTER="com.example.mylib:TRACE"
export WLOG_LEVEL=WARN

# Custom prefix format
export WLOG_PREFIX="pid=%pid:tid=%tid:%fn -"

Full API reference

Logger lifecycle

/* Get (or create) a named logger. Never returns NULL. */
wLog* WLog_Get(LPCSTR name);

/* Get the root logger (parent of all loggers). */
wLog* WLog_GetRoot(void);
WLog_Get and WLog_GetRoot return loggers that are owned by WinPR’s internal registry and must not be freed by the caller.

Level control

/* Get the effective log level for a logger. */
DWORD WLog_GetLogLevel(wLog* log);

/* Returns TRUE if the given level would produce output on this logger. */
BOOL  WLog_IsLevelActive(wLog* log, DWORD level);

/* Set the level using a WLOG_* constant. */
BOOL  WLog_SetLogLevel(wLog* log, DWORD logLevel);

/* Set the level using a string ("TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "OFF"). */
BOOL  WLog_SetStringLogLevel(wLog* log, LPCSTR level);

/* Add a comma-separated filter string, e.g. "core.channel:DEBUG,net:TRACE". */
BOOL  WLog_AddStringLogFilters(LPCSTR filter);

Printing messages

/*
 * Print a text message. Format string is validated at compile time.
 * Prefer the WLog_Print macro which short-circuits when the level is inactive.
 */
BOOL WLog_PrintTextMessage(
    wLog*       log,
    DWORD       level,
    size_t      line,      /* __LINE__ */
    const char* file,      /* __FILE__ */
    const char* function,  /* __func__ */
    const char* fmt,
    ...    /* printf-style arguments */);

/* va_list variant of WLog_PrintTextMessage. */
BOOL WLog_PrintTextMessageVA(
    wLog*       log,
    DWORD       level,
    size_t      line,
    const char* file,
    const char* function,
    const char* fmt,
    va_list     args);

/*
 * Generic message printer — supports TEXT, DATA, IMAGE, and PACKET types.
 * For text messages, prefer WLog_PrintTextMessage (compile-time format checks).
 */
BOOL WLog_PrintMessage(
    wLog*       log,
    DWORD       type,      /* WLOG_MESSAGE_TEXT | DATA | IMAGE | PACKET */
    DWORD       level,
    size_t      line,
    const char* file,
    const char* function,
    ...);

BOOL WLog_PrintMessageVA(
    wLog*       log,
    DWORD       type,
    DWORD       level,
    size_t      line,
    const char* file,
    const char* function,
    va_list     args);

Convenience macros

These macros inject __LINE__, __FILE__, and __func__ automatically.
MacroDescription
WLog_Print(log, level, ...)Check level, then log a text message via a wLog*
WLog_Print_unchecked(log, level, ...)Log without checking level first
WLog_PrintVA(log, level, fmt, args)va_list variant of WLog_Print
WLog_Data(log, level, ...)Log a raw data buffer (WLOG_MESSAGE_DATA)
WLog_Image(log, level, ...)Log image data (WLOG_MESSAGE_IMAGE)
WLog_Packet(log, level, ...)Log a network packet (WLOG_MESSAGE_PACKET)
WLog_LVL(tag, lvl, ...)Log at an arbitrary level by tag name
WLog_VRB(tag, ...)WLOG_TRACE by tag
WLog_DBG(tag, ...)WLOG_DEBUG by tag
WLog_INFO(tag, ...)WLOG_INFO by tag
WLog_WARN(tag, ...)WLOG_WARN by tag
WLog_ERR(tag, ...)WLOG_ERROR by tag
WLog_FATAL(tag, ...)WLOG_FATAL by tag
WLog_Print_tag(tag, level, ...)Log by tag with explicit level (caches logger internally)

Context and prefix

/*
 * Attach a dynamic prefix callback to a logger.
 * fkt is called on every log event to produce the prefix string.
 * context is passed to fkt; the caller must keep it alive as long as log is used.
 */
BOOL WLog_SetContext(wLog* log, const char* (*fkt)(void*), void* context);

/*
 * Set a process-wide global prefix prepended to every log entry.
 * Call this once near the start of main() before threads are created.
 * Pass NULL to disable.
 */
BOOL WLog_SetGlobalContext(const char* globalprefix);

Appender management

/* Set appender type using a WLOG_APPENDER_* constant. */
BOOL          WLog_SetLogAppenderType(wLog* log, DWORD logAppenderType);

/* Get the current appender for a logger. */
wLogAppender* WLog_GetLogAppender(wLog* log);

/* Open / close the appender (allocates/releases resources). */
BOOL          WLog_OpenAppender(wLog* log);
BOOL          WLog_CloseAppender(wLog* log);

/* Configure an appender option by key/value. */
BOOL          WLog_ConfigureAppender(wLogAppender* appender, const char* setting, void* value);

Layout

/* Get the layout for a logger. */
wLogLayout* WLog_GetLogLayout(wLog* log);

/* Set the prefix format string programmatically (same syntax as WLOG_PREFIX). */
BOOL WLog_Layout_SetPrefixFormat(wLog* log, wLogLayout* layout, const char* format);

Logging code examples

#include <winpr/wlog.h>

#define TAG "com.example.network"

void connect_to_server(const char* host, int port)
{
    WLog_DBG(TAG, "connecting to %s:%d", host, port);

    /* ... connection logic ... */

    if (connected)
        WLog_INFO(TAG, "connected to %s:%d", host, port);
    else
        WLog_ERR(TAG, "connection to %s:%d failed: %s", host, port, strerror(errno));
}

Environment variables

VariableDescription
WLOG_LEVELDefault log level for the root logger. Accepted values: TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF.
WLOG_FILTERComma-separated <logger>:<level> pairs. Only matching loggers are shown. Overrides WLOG_LEVEL for matched loggers.
WLOG_PREFIXFormat string for the log prefix. See Format specifiers.
WLOG_APPENDERAppender type. Accepted values: CONSOLE, FILE, BINARY, SYSLOG, JOURNALD, UDP.
WLOG_FILEAPPENDER_OUTPUT_FILE_PATHDirectory for the file appender output.
WLOG_FILEAPPENDER_OUTPUT_FILE_NAMEFilename for the file appender output.
WLOG_JOURNALD_IDIdentifier used with the systemd journal (defaults to the executable name).
WLOG_UDP_TARGETTarget for the UDP appender in host:port format (default: 127.0.0.1:20000).

Filter syntax

WLOG_FILTER accepts a comma-separated list of <logger-name>:<level> pairs:
# Enable DEBUG for one logger, TRACE for another
export WLOG_FILTER="core.channel:DEBUG,com.freerdp.codec:TRACE"

# Combined with a global floor
export WLOG_LEVEL=ERROR
export WLOG_FILTER="com.example.mylib:TRACE"
WLOG_FILTER enables only the listed loggers at the specified levels. Loggers not matched by the filter are unaffected — they continue to use the level set by WLOG_LEVEL (or their programmatic level).

Format specifiers

The WLOG_PREFIX environment variable (and WLog_Layout_SetPrefixFormat) uses %-prefixed tokens. Up to 16 tokens may appear in a single format string.
TokenExpands to
%lvLog level (e.g. INFO, WARN)
%mnModule (logger) name
%flSource file name
%fnFunction name
%lnLine number
%pidProcess ID
%tidThread ID
%yrYear
%moMonth
%dwDay of week
%hrHour
%miMinute
%seSecond
%mlMillisecond
Example:
export WLOG_PREFIX="pid=%pid:tid=%tid:fn=%fn -"
xfreerdp /v:rdp.example.com
This produces lines like:
pid=12345:tid=12345:fn=rdp_recv_callback - Connected to rdp.example.com

Appenders

Writes to the terminal. On Android, redirects to __android_log_print. Output stream routing:
outputstream valueBehavior
stdoutAll levels → stdout
stderrAll levels → stderr
defaultERROR/FATAL → stderr; others → stdout
debugWindows: OutputDebugString; elsewhere: same as default
Configuration key: outputstream, value: const char*
export WLOG_APPENDER=CONSOLE
Writes formatted text to a file.
Configuration keyTypeDescription
outputfilenameconst char*Output filename
outputfilepathconst char*Output directory path
export WLOG_APPENDER=FILE
export WLOG_FILEAPPENDER_OUTPUT_FILE_PATH=/var/log/myapp
export WLOG_FILEAPPENDER_OUTPUT_FILE_NAME=freerdp.log
Writes log data in a binary format file — useful for post-processing or tooling that parses structured log records.
Configuration keyTypeDescription
outputfilenameconst char*Output filename
outputfilepathconst char*Output directory path
export WLOG_APPENDER=BINARY
Sends log messages over UDP to a remote host. Suitable for centralised log aggregation without writing to disk.
Configuration keyTypeDescription
targetconst char*Destination in host:port format
Default target: 127.0.0.1:20000.
export WLOG_APPENDER=UDP
export WLOG_UDP_TARGET=loghost.internal:20000
Receive with netcat:
nc -u 127.0.0.1 -p 20000 -l
Routes log messages to the system logger via the POSIX syslog(3) API. WLog levels are mapped to syslog priorities. No additional options.
export WLOG_APPENDER=SYSLOG
Requires WinPR to have been built with syslog support (enabled automatically when <syslog.h> is detected at build time).
Sends structured log entries to the systemd journal via sd_journal_send.
Configuration keyTypeDescription
identifierconst char*Journal identifier (default: winpr)
export WLOG_APPENDER=JOURNALD
export WLOG_JOURNALD_ID=myapp
View output:
journalctl -t myapp -f
Requires WinPR to be built with WITH_SYSTEMD=ON and libsystemd installed.
Delivers all log messages to application-provided function pointers. Use this to integrate WLog into an existing logging framework.
typedef BOOL (*wLogCallbackMessage_t)(const wLogMessage* msg);
typedef BOOL (*wLogCallbackData_t)(const wLogMessage* msg);
typedef BOOL (*wLogCallbackImage_t)(const wLogMessage* msg);
typedef BOOL (*wLogCallbackPackage_t)(const wLogMessage* msg);

typedef struct {
    wLogCallbackData_t    data;
    wLogCallbackImage_t   image;
    wLogCallbackMessage_t message;
    wLogCallbackPackage_t package;
} wLogCallbacks;
Configuration keyTypeDescription
callbackswLogCallbacks*Pointer to callback struct
Set unused callbacks to NULL; WLog will skip them.

Message types

Beyond plain text, WLog can carry structured payloads. Pass the type constant as the first argument to WLog_PrintMessage.
ConstantValueDescription
WLOG_MESSAGE_TEXT0Plain formatted text (use WLog_Print or WLog_PrintTextMessage)
WLOG_MESSAGE_DATA1Raw binary buffer (use WLog_Data macro)
WLOG_MESSAGE_IMAGE2Image data with width/height/bpp metadata (use WLog_Image macro)
WLOG_MESSAGE_PACKET3Network packet with direction flag (use WLog_Packet macro)
Packet direction constants:
ConstantValue
WLOG_PACKET_INBOUND1
WLOG_PACKET_OUTBOUND2

wLogMessage structure

All appender callbacks receive a const wLogMessage*. Fields of interest:
typedef struct {
    DWORD   Type;           /* WLOG_MESSAGE_TEXT, DATA, IMAGE, or PACKET */
    DWORD   Level;          /* WLOG_TRACE ... WLOG_FATAL */
    LPSTR   PrefixString;   /* formatted prefix string */
    LPCSTR  FormatString;   /* original printf format string */
    LPCSTR  TextString;     /* formatted message text */
    size_t  LineNumber;     /* __LINE__ */
    LPCSTR  FileName;       /* __FILE__ */
    LPCSTR  FunctionName;   /* __func__ */

    /* DATA message fields */
    void*   Data;
    size_t  Length;

    /* IMAGE message fields */
    void*   ImageData;
    size_t  ImageWidth;
    size_t  ImageHeight;
    size_t  ImageBpp;

    /* PACKET message fields */
    void*   PacketData;
    size_t  PacketLength;
    DWORD   PacketFlags;    /* WLOG_PACKET_INBOUND or WLOG_PACKET_OUTBOUND */
} wLogMessage;