CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
Volume Control and Backpressure

Data Structures

struct  LogStats
 

Typedefs

typedef struct LogStats LogStats
 

Functions

void logGetStats (LogStats *out)
 
void logResetStats (void)
 Zero the cumulative counters and the queue high-water mark.
 
void logSetStatsInterval (int64 interval)
 
void logChanSetSampling (LogChannel *chan, uint32 n)
 
void logSetDedup (int64 window, uint32 threshold)
 
void logSetSyncLevel (int level)
 
void logPanicFlush (void)
 

Detailed Description

Everything that decides how much actually gets logged, and what happens to the rest. Four separate mechanisms, none of them on by default except the last:

Sampling and deduplication are complementary to the per-call-site gating in Rate-Limited Log Macros, not replacements for it: that gates one site before an entry exists, this works across every site and can report on what it dropped.

Typedef Documentation

◆ LogStats

typedef struct LogStats LogStats

What the log system has been doing

Counters are cumulative since startup or the last logResetStats(); depths are instantaneous.

Function Documentation

◆ logChanSetSampling()

void logChanSetSampling ( LogChannel chan,
uint32  n 
)

Keep only one record in N on a channel

Applied at the call site, before an entry exists, so a sampled-away record costs a counter increment and nothing else. Fatal and Error are never sampled, whatever the rate: losing an error to a sampling rate set for debug traffic is not a trade anyone intends to make.

The surviving record carries the rate it survived at (LogRecord.sample), so a structured destination can scale the counts back up. Sampling is per channel, not inherited by children.

Parameters
chanChannel to sample, or NULL for the default channel
nKeep one record in N; 0 or 1 turns sampling off
logChanSetSampling(logChan(_SL("net/http/request")), 100);
LogChannel * logChan(strref path)
void logChanSetSampling(LogChannel *chan, uint32 n)
#define _SL(s)
Inline ASCII string literal with compile-time embedded length (STR_LEN8). Content must be < 200 bytes...
Definition strliteral.h:207

◆ logGetStats()

void logGetStats ( LogStats out)

Read the log system's counters

Parameters
outReceives the current statistics
if (st.dropped)
reportLogLoss(st.dropped);
void logGetStats(LogStats *out)
uint64 dropped
Entries lost because a queue and its overflow list were both full.
Definition logvolume.h:34

◆ logPanicFlush()

void logPanicFlush ( void  )

Write everything queued, from this thread, without waiting for the drain threads

For a crashing process. Unlike logFlush(), it does not depend on any drain thread being alive or responsive: it takes over the queues itself, waiting only briefly for an in-flight dispatch to finish before proceeding regardless. That makes it unsafe to call concurrently with normal operation in the general case, and correct in the one case it exists for.

static void onFatalSignal(int sig) {
logStr(Fatal, _SL("caught a fatal signal"));
}
#define logStr(level, str)
Definition log.h:612
void logPanicFlush(void)

◆ logSetDedup()

void logSetDedup ( int64  window,
uint32  threshold 
)

Collapse repeats from the same call site on the drain thread

Within each window, the first threshold records from a call site are delivered normally and the rest are counted. When the window closes, one summary record goes out in their place – the text of the first suppressed record, plus how many followed it.

Keyed by the address of the call site's LogSite (Rate-Limited Log Macros), which is stable, discloses nothing, and is a better key than hashing the message: two sites that happen to log the same sentence keep separate budgets, and one site whose message varies per record still shares one. Records logged without a call site – anything generated dynamically – are never deduplicated.

Parameters
windowLength of the counting window, or 0 to turn deduplication off (the default)
thresholdRecords per site per window delivered before suppression starts
logSetDedup(timeS(10), 5); // 5 per site per 10s, then a summary
void logSetDedup(int64 window, uint32 threshold)
#define timeS(s)
Definition time.h:20

◆ logSetStatsInterval()

void logSetStatsInterval ( int64  interval)

Log the statistics periodically to the restricted cx/log/stats channel

The record is emitted by a drain thread when it next goes idle and the interval has passed, so there is no timer and no thread of its own, and a process logging nothing produces nothing. The channel is declared LOG_Restricted, so a destination has to name it: metrics do not appear in a general-purpose log by accident (see logDeclareChan()).

Parameters
intervalTime between records, or 0 to stop (the default)
logfileRegister(LOG_Notice, _SL("cx/log/stats"), vfs, _SL("stats.log"), &cfg, NULL);
@ LOG_Notice
Normal but significant conditions.
Definition log.h:102
LogDest * logfileRegister(int maxlevel, strref chanfilter, VFS *vfs, strref filename, const LogFileConfig *config, LogSerializer *ser)
void logSetStatsInterval(int64 interval)

◆ logSetSyncLevel()

void logSetSyncLevel ( int  level)

Severity at or above which a record is never dropped for lack of queue space

When a drain queue and its per-thread overflow list are both full, records less severe than this are dropped; records this severe or worse are written from the logging thread instead, which is slow and blocks the caller but does not lose the message. Silently dropping a Fatal is the worst failure mode this system has, so the default is LOG_Error.

Parameters
levelLog level, e.g. LOG_Error; pass -1 to disable synchronous writes entirely, or LOG_Count to make every write synchronous (but really, don't do that)
logSetSyncLevel(LOG_Warn); // warnings survive a full queue too
@ LOG_Warn
Warning conditions that may indicate problems.
Definition log.h:101
void logSetSyncLevel(int level)