|
CX Framework
Cross-platform C utility framework
|
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) |
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.
What the log system has been doing
Counters are cumulative since startup or the last logResetStats(); depths are instantaneous.
| 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.
| chan | Channel to sample, or NULL for the default channel |
| n | Keep one record in N; 0 or 1 turns sampling off 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 |
| void logGetStats | ( | LogStats * | out | ) |
Read the log system's counters
| out | Receives the current statistics LogStats st;
logGetStats(&st);
if (st.dropped)
reportLogLoss(st.dropped);
void logGetStats(LogStats *out) Definition logvolume.h:32 uint64 dropped Entries lost because a queue and its overflow list were both full. Definition logvolume.h:34 |
| 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.
| 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.
| window | Length of the counting window, or 0 to turn deduplication off (the default) |
| threshold | Records per site per window delivered before suppression starts void logSetDedup(int64 window, uint32 threshold) |
| 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()).
| interval | Time between records, or 0 to stop (the default) logSetStatsInterval(timeS(60));
LogDest * logfileRegister(int maxlevel, strref chanfilter, VFS *vfs, strref filename, const LogFileConfig *config, LogSerializer *ser) void logSetStatsInterval(int64 interval) |
| 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.
| level | Log 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) void logSetSyncLevel(int level) |