MONGOC_LOGGING(3)
π MONGOC_LOGGING(3) π
okay bestie, so this is the libmongoc logging page β the MongoDB C driver manual, section 3. and listen, it's giving two completely different logging systems in a trench coat, so let's get into it π«Ά
The MongoDB C driver has two different types of logging available:
- The original
mongoc_logfacility supports freeform string messages that originate from the driver itself or from application code. This has been retroactively termed "unstructured logging". - A new
mongoc_structured_logfacility reports messages from the driver itself using a BSON format defined across driver implementations by the MongoDB Logging Specification.
These two systems are configured and used independently. like they literally don't talk to each other, no cap.
β¨ UNSTRUCTURED LOGGING β¨
This is the original logging facility that supports freeform string messages originating from the driver itself or from application code. This has been retroactively termed "unstructured logging". See Structured Logging for the newer standardized logging facility. (yes, "retroactively termed" β the driver naming committee said slay and moved on π)
typedef enum {
MONGOC_LOG_LEVEL_ERROR,
MONGOC_LOG_LEVEL_CRITICAL,
MONGOC_LOG_LEVEL_WARNING,
MONGOC_LOG_LEVEL_MESSAGE,
MONGOC_LOG_LEVEL_INFO,
MONGOC_LOG_LEVEL_DEBUG,
MONGOC_LOG_LEVEL_TRACE,
} mongoc_log_level_t;
#define MONGOC_ERROR(...)
#define MONGOC_CRITICAL(...)
#define MONGOC_WARNING(...)
#define MONGOC_MESSAGE(...)
#define MONGOC_INFO(...)
#define MONGOC_DEBUG(...)
typedef void (*mongoc_log_func_t) (mongoc_log_level_t log_level,
const char *log_domain,
const char *message,
void *user_data);
void
mongoc_log_set_handler (mongoc_log_func_t log_func, void *user_data);
void
mongoc_log (mongoc_log_level_t log_level,
const char *log_domain,
const char *format,
...);
const char *
mongoc_log_level_str (mongoc_log_level_t log_level);
void
mongoc_log_default_handler (mongoc_log_level_t log_level,
const char *log_domain,
const char *message,
void *user_data);
void
mongoc_log_trace_enable (void);
void
mongoc_log_trace_disable (void);
This abstraction can be used for logging in your application, or you can integrate the driver with an existing logging system. your choice, your moment π«
π Macros
To make logging a little less painful, various helper macros are provided. See the following example β it's short, it ate:
#undef MONGOC_LOG_DOMAIN
#define MONGOC_LOG_DOMAIN "my-custom-domain"
MONGOC_WARNING ("An error occurred: %s", strerror (errno));
π¦ Custom Log Handlers
The default log handler prints a timestamp and the log message to stdout, or to stderr for warnings, critical messages, and errors. You can override the handler with mongoc_log_set_handler(). Your handler function is called in a mutex for thread safety. (yes, mutex β thread safety is the vibe check we all need π₯)
For example, you could register a custom handler to suppress messages at INFO level and below:
void
my_logger (mongoc_log_level_t log_level,
const char *log_domain,
const char *message,
void *user_data)
{
/* smaller values are more important */
if (log_level < MONGOC_LOG_LEVEL_INFO) {
mongoc_log_default_handler (log_level, log_domain, message, user_data);
}
}
int
main (int argc, char *argv[])
{
mongoc_log_set_handler (my_logger, NULL);
mongoc_init ();
/* ... your code ... */
mongoc_cleanup ();
return 0;
}
Note that in the example above mongoc_log_set_handler() is called before mongoc_init(). Otherwise, some log traces could not be processed by the log handler. order matters bestie, it's giving "sequencing is the whole plot" π
To restore the default handler:
mongoc_log_set_handler (mongoc_log_default_handler, NULL);
πΈ Disable logging
To disable all logging, including warnings, critical messages and errors, provide an empty log handler:
mongoc_log_set_handler (NULL, NULL);
like, everything. gone. silent. iconic but also maybe careful luv π
π§ Tracing
If compiling your own copy of the MongoDB C driver, consider configuring with -DENABLE_TRACING=ON to enable function tracing and hex dumps of network packets to STDERR and STDOUT during development and debugging.
This is especially useful when debugging what may be going on internally in the driver. (fr fr, this is the "what is happening inside the machine" button π΅οΈ)
Trace messages can be enabled and disabled by calling mongoc_log_trace_enable() and mongoc_log_trace_disable()
NOTE: Compiling the driver with-DENABLE_TRACING=ONwill affect its performance. Disabling tracing withmongoc_log_trace_disable()significantly reduces the overhead, but cannot remove it completely. so like, the tax is still there, sorry bestie πΈ
π STRUCTURED LOGGING π
This document describes a newer "structured" logging facility which reports messages from the driver itself using a BSON format defined across driver implementations by the MongoDB Logging Specification. See Unstructured Logging for the original freeform logging facility.
These two systems are configured and used independently.
Unstructured logging is global to the entire process, but structured logging is configured separately for each mongoc_client_t or mongoc_client_pool_t. See mongoc_client_set_structured_log_opts() and mongoc_client_pool_set_structured_log_opts(). per-client settings? main character energy, honestly π
β Options
Structured log settings are tracked explicitly by a mongoc_structured_log_opts_t instance.
Like other drivers supporting structured logging, we take default settings from environment variables and offer additional optional programmatic configuration. Environment variables are captured during mongoc_structured_log_opts_new(), refer there for a full list of the supported variables.
Normally environment variables provide defaults that can be overridden programmatically. To request the opposite behavior, where your programmatic defaults can be overridden by the environment, see mongoc_structured_log_opts_set_max_levels_from_env().
Structured log messages may be filtered in arbitrary ways by the handler, but as both a performance optimization and a convenience, a built-in filter limits the maximum log level of reported messages with a per-component setting. (performance and convenience? we love a dual-purpose icon β¨)
π mongoc_structured_log_opts_t
Synopsis
typedef struct mongoc_structured_log_opts_t mongoc_structured_log_opts_t;
mongoc_structured_log_opts_t is an opaque type that contains options for the structured logging subsystem: per-component log levels, a maximum logged document length, and a handler function.
Create a mongoc_structured_log_opts_t with mongoc_structured_log_opts_new(), set options and a callback on it, then pass it to mongoc_client_set_structured_log_opts() or mongoc_client_pool_set_structured_log_opts(). Must be destroyed by calling mongoc_structured_log_opts_destroy(). don't forget the destroy, bestie, that's the whole plot π¨
π Functions
mongoc_structured_log_opts_new()
Synopsis
mongoc_structured_log_opts_t *
mongoc_structured_log_opts_new (void);
Creates a new mongoc_structured_log_opts_t, filled with defaults captured from the current environment.
Sets a default log handler which would write a text representation of each log message to stderr, stdout, or another file configurable using MONGODB_LOG_PATH. This setting has no effect if the default handler is replaced using mongoc_structured_log_opts_set_handler().
Environment variable errors are non-fatal, and result in one-time warnings delivered as an unstructured log. like, the driver's gonna tell you once and then move on, she's not gonna nag π
Per-component maximum levels are initialized equivalently to:
mongoc_structured_log_opts_set_max_level_for_all_components(opts, MONGOC_STRUCTURED_LOG_LEVEL_WARNING);
mongoc_structured_log_opts_set_max_levels_from_env(opts);
π± Environment Variables
This is a full list of the captured environment variables.
MONGODB_LOG_MAX_DOCUMENT_LENGTH: Maximum length for JSON-serialized documents that appear within a log message. It may be a number, in bytes, orunlimited(case insensitive) to choose an implementation-specific value near the maximum representable length. By default, the limit is1000bytes. This limit affects interior documents like commands and replies, not the total length of a structured log message. (so yes, you can sayunlimitedand the driver will pick something near the biggest length it can represent β chaos, but sanctioned chaos π )MONGODB_LOG_PATH: A file path or one of the special stringsstderrorstdout(case insensitive) specifying the destination for structured logs seen by the default handler. By default, it writes tostderr. This path will be captured duringmongoc_structured_log_opts_new(), but it will not immediately be opened. If the file can't be opened, a warning is then written to the unstructured log and the handler writes structured logs tostderrinstead.
WARNING: When a file path is given forMONGODB_LOG_PATH, each log instance (one stand-alone client or pool) will separately open this file for append. The results are operating system specific. On UNIX-like platforms each instance's output will be interleaved, in most cases without splitting individual log messages. Notably on Windows the file will be opened in exclusive mode by the first instance and subsequent instances will fail, falling back on the default ofstderr. Applications that use multiple processes or multiple client pools will likely want to supply a log handler that annotates each message with information about its originating log instance. π multiple writers to one file is giving "group project energy", plan accordingly.
MONGODB_LOG_COMMAND: A log level name to set as the maximum forMONGOC_STRUCTURED_LOG_COMPONENT_COMMAND.MONGODB_LOG_TOPOLOGY: A log level name to set as the maximum forMONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY.MONGODB_LOG_SERVER_SELECTION: A log level name to set as the maximum forMONGOC_STRUCTURED_LOG_COMPONENT_SERVER_SELECTION.MONGODB_LOG_CONNECTION: A log level name to set as the maximum forMONGOC_STRUCTURED_LOG_COMPONENT_CONNECTION.MONGODB_LOG_ALL: A log level name applied to all components not otherwise specified. (the catch-all, the "everyone else" of the group chat π)
Note that log level names are always case insensitive. This is a full list of recognized names, including allowed aliases:
emergency,offalertcriticalerrorwarning,warnnoticeinformational,infodebugtrace
π Returns
A newly allocated mongoc_structured_log_opts_t.
mongoc_structured_log_opts_destroy()
Synopsis
void
mongoc_structured_log_opts_destroy (mongoc_structured_log_opts_t *opts);
Parameters
- opts: Pointer to a
mongoc_structured_log_opts_tallocated withmongoc_structured_log_opts_new(), orNULL.
Description
This function releases all resources associated with a mongoc_structured_log_opts_t. Does nothing if opts is NULL. (NULL-safe, we stan a considerate function π«Ά)
mongoc_structured_log_opts_set_handler()
Synopsis
void
mongoc_structured_log_opts_set_handler (mongoc_structured_log_opts_t *opts,
mongoc_structured_log_func_t log_func,
void *user_data);
Okay so this one is literally the whole point of the vibe π
β it sets the function that gets called to handle your structured log messages, as a mongoc_structured_log_func_t.
Your callback gets handed a mongoc_structured_log_entry_t, which is basically a little handle so you can pull extra info about the log message. Important though: that entry pointer is only valid during a callback, because β plot twist β it's just a low-cost reference to temporary data. It does not stick around. Do not be keeping it. π
Structured log handlers must be thread-safe if they're gonna be used with mongoc_client_pool_t. And handlers must avoid unbounded recursion β preferably by just not using any libmongoc client or pool that uses the same handler. Like, don't bite your own tail, bestie.
This function always replaces the default log handler from mongoc_structured_log_opts_new(), if that one was still set. And if log_func is NULL, structured logging gets disabled entirely. Poof. Gone. β¨
Parameters
- opts: structured log options, allocated with
mongoc_structured_log_opts_new(). - log_func: the handler to install, a
mongoc_structured_log_func_t, orNULLto disable structured logging. - user_data: optional user data, passed on to the handler.
SEE ALSO: Structured Logging
mongoc_structured_log_opts_set_max_level_for_component()
Synopsis
bool
mongoc_structured_log_opts_set_max_level_for_component (mongoc_structured_log_opts_t *opts,
mongoc_structured_log_component_t component,
mongoc_structured_log_level_t level);
Sets the maximum log level per-component. Only log messages at or below this severity level get passed to mongoc_structured_log_func_t. Think of it as a lil bouncer at the door of each component πͺβ¨
By default, each component's log level may come from environment variables β peep mongoc_structured_log_opts_set_max_levels_from_env().
Parameters
- opts: structured log options, allocated with
mongoc_structured_log_opts_new(). - component: the component to set a max log level for, as a
mongoc_structured_log_component_t. (Yes, the original says "for a max log level. for" β we're keeping that energy, typos and all. π) - level: the new max log level for this component, as a
mongoc_structured_log_level_t.
Returns
Returns true on success, or false if the supplied parameters were incorrect.
SEE ALSO: Structured Logging
mongoc_structured_log_opts_set_max_level_for_all_components()
Synopsis
bool
mongoc_structured_log_opts_set_max_level_for_all_components (mongoc_structured_log_opts_t *opts,
mongoc_structured_log_level_t level);
Sets all the per-component maximum log levels to the same value in one go. Iconic. Only log messages at or below this severity level get passed to mongoc_structured_log_func_t. And the slay part? It's effective even for logging components not known at compile-time. Future-proof queen π
Parameters
- opts: structured log options, allocated with
mongoc_structured_log_opts_new(). - level: the max log level for all components, as a
mongoc_structured_log_level_t.
Returns
Returns true on success, or false if the supplied parameters were incorrect.
SEE ALSO: Structured Logging
mongoc_structured_log_opts_set_max_levels_from_env()
Synopsis
bool
mongoc_structured_log_opts_set_max_levels_from_env (mongoc_structured_log_opts_t *opts);
Sets any maximum log levels that were requested by environment variables. In order: MONGODB_LOG_ALL for all components, followed by the per-component log levels MONGODB_LOG_COMMAND, MONGODB_LOG_CONNECTION, MONGODB_LOG_TOPOLOGY, and MONGODB_LOG_SERVER_SELECTION.
It expects the value to be recognizable by mongoc_structured_log_get_named_level(). Parse errors may cause a warning message, delivered via unstructured logging. lowkey warning energy β οΈ
Component levels with no valid environment variable setting will just be left unmodified. No touching. π
This happens automatically when mongoc_structured_log_opts_new() establishes defaults. Any subsequent programmatic modifications to the mongoc_structured_log_opts_t will override the environment variable settings. But for apps that want the opposite behavior β where env vars may override programmatic settings β they can call mongoc_structured_log_opts_set_max_levels_from_env() after calling mongoc_structured_log_opts_set_max_level_for_component() and mongoc_structured_log_opts_set_max_level_for_all_components(). That processes the environment a second time, letting it override your customized defaults. Sneaky but valid. π§
Returns
Returns true on success. If warnings are encountered in the environment, returns false and may log additional information to the unstructured logging facility. Note that, by design, these errors are by default non-fatal β so don't panic π When mongoc_structured_log_opts_new() internally calls this function, it ignores the return value.
SEE ALSO: Structured Logging
mongoc_structured_log_opts_get_max_level_for_component()
Synopsis
mongoc_structured_log_level_t
mongoc_structured_log_opts_get_max_level_for_component (const mongoc_structured_log_opts_t *opts,
mongoc_structured_log_component_t component);
Parameters
- opts: structured log options, allocated with
mongoc_structured_log_opts_new(). - component: log component as a
mongoc_structured_log_component_t.
Returns
Returns the configured maximum log level for a specific component, as a mongoc_structured_log_level_t. This may be the last value set with mongoc_structured_log_opts_set_max_level_for_component() or mongoc_structured_log_opts_set_max_level_for_all_components(), or it may be the default obtained from environment variables. And if you hand it an invalid or unknown component enum? It returns the lowest log level. Rude but consistent. π
SEE ALSO: Structured Logging
mongoc_structured_log_opts_set_max_document_length()
Synopsis
bool
mongoc_structured_log_opts_set_max_document_length (mongoc_structured_log_opts_t *opts,
size_t max_document_length);
Sets a max length for BSON documents that show up serialized in JSON form as part of a structured log message. Basically: your docs got a character limit now π
Serialized JSON gets truncated at this limit, interpreted as a count of UTF-8 encoded bytes. Truncation is indicated with a ... suffix β and the length of that suffix is not included in the max document length. Also, if truncating at the exact indicated length would split a valid UTF-8 sequence, it instead truncates the document earlier, at the nearest boundary between code points. So no mangled characters, we're classy here π
Parameters
- opts: structured log options, allocated with
mongoc_structured_log_opts_new(). - max_document_length: maximum length for each embedded JSON document, in bytes, not including an ellipsis (
...) added to indicate truncation. Values near or aboveINT_MAXwill be rejected.
Returns
Returns true on success, or false if the supplied maximum length is too large.
SEE ALSO: Structured Logging, mongoc_structured_log_opts_set_max_document_length_from_env()
mongoc_structured_log_opts_set_max_document_length_from_env()
Synopsis
bool
mongoc_structured_log_opts_set_max_document_length_from_env (mongoc_structured_log_opts_t *opts);
Sets a maximum document length from the MONGODB_LOG_MAX_DOCUMENT_LENGTH environment variable, if a valid setting is found. See mongoc_structured_log_opts_new() for a description of the supported environment variable formats. (Go read that one, bestie, it's got the deets π«Ά)
Parse errors may cause a warning message, delivered via unstructured logging.
This happens automatically when mongoc_structured_log_opts_new() establishes defaults. Any subsequent programmatic modifications to the mongoc_structured_log_opts_t will override the environment variable settings. For apps that desire the opposite behavior β env vars overriding programmatic settings β they may call mongoc_structured_log_opts_set_max_document_length_from_env() after calling mongoc_structured_log_opts_set_max_document_length(). That processes the environment a second time, letting it override your customized defaults. Same trick as before, different function π
Returns
Returns true on success: either a valid environment setting was found, or the value is unset and opts will not be modified. If warnings are encountered in the environment, returns false and may log additional information to the unstructured logging facility. Note that, by design, these errors are by default non-fatal. When mongoc_structured_log_opts_new() internally calls this function, it ignores the return value.
SEE ALSO: Structured Logging
mongoc_structured_log_opts_get_max_document_length()
Synopsis
size_t
mongoc_structured_log_opts_get_max_document_length (const mongoc_structured_log_opts_t *opts);
Parameters
- opts: structured log options, allocated with
mongoc_structured_log_opts_new().
Returns
Returns the current maximum document length set in opts, as a size_t.
SEE ALSO: Structured Logging
SEE ALSO: Structured Logging
yeah it says SEE ALSO twice in the original. we're not fixing it. it's canon now. π
π Levels and Components π
Log levels and components are defined as the mongoc_structured_log_level_t and mongoc_structured_log_component_t enumerations. Utilities are provided to convert between these values and their standard string representations. The string values are case-insensitive β¨
typedef enum {
MONGOC_STRUCTURED_LOG_LEVEL_EMERGENCY = 0, // "Emergency" ("off" also accepted)
MONGOC_STRUCTURED_LOG_LEVEL_ALERT = 1, // "Alert"
MONGOC_STRUCTURED_LOG_LEVEL_CRITICAL = 2, // "Critical"
MONGOC_STRUCTURED_LOG_LEVEL_ERROR = 3, // "Error"
MONGOC_STRUCTURED_LOG_LEVEL_WARNING = 4, // "Warning" ("warn" also accepted)
MONGOC_STRUCTURED_LOG_LEVEL_NOTICE = 5, // "Notice"
MONGOC_STRUCTURED_LOG_LEVEL_INFO = 6, // "Informational" ("info" also accepted)
MONGOC_STRUCTURED_LOG_LEVEL_DEBUG = 7, // "Debug"
MONGOC_STRUCTURED_LOG_LEVEL_TRACE = 8, // "Trace"
} mongoc_structured_log_level_t;
typedef enum {
MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND = 0, // "command"
MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY = 1, // "topology"
MONGOC_STRUCTURED_LOG_COMPONENT_SERVER_SELECTION = 2, // "serverSelection"
MONGOC_STRUCTURED_LOG_COMPONENT_CONNECTION = 3, // "connection"
} mongoc_structured_log_component_t;
π mongoc_structured_log_level_t
Synopsis
typedef enum {
MONGOC_STRUCTURED_LOG_LEVEL_EMERGENCY = 0,
MONGOC_STRUCTURED_LOG_LEVEL_ALERT = 1,
MONGOC_STRUCTURED_LOG_LEVEL_CRITICAL = 2,
MONGOC_STRUCTURED_LOG_LEVEL_ERROR = 3,
MONGOC_STRUCTURED_LOG_LEVEL_WARNING = 4,
MONGOC_STRUCTURED_LOG_LEVEL_NOTICE = 5,
MONGOC_STRUCTURED_LOG_LEVEL_INFO = 6,
MONGOC_STRUCTURED_LOG_LEVEL_DEBUG = 7,
MONGOC_STRUCTURED_LOG_LEVEL_TRACE = 8,
} mongoc_structured_log_level_t;
mongoc_structured_log_level_t is literally just the roster of log levels you can use with structured logging. That's it. That's the whole vibe check. π
π« mongoc_structured_log_get_level_name()
Synopsis
const char *
mongoc_structured_log_get_level_name (mongoc_structured_log_level_t level);
Parameters
levelβ the log level, as amongoc_structured_log_level_t. π
Returns
If the level is known, you get back a pointer to a constant string β and bestie, do not free it, it's not yours. If the level has no known name, you get NULL. π
SEE ALSO: Structured Logging
π« mongoc_structured_log_get_named_level()
Synopsis
bool
mongoc_structured_log_get_named_level (const char *name, mongoc_structured_log_level_t *out);
Look up a log level by name. Case insensitive, so go off with whatever capitalization you want, it does not care. β¨
Parameters
nameβ the name you're looking up as a log level.outβ on success, the matchingmongoc_structured_log_level_tgets written here. π«Ά
Returns
If the level name is known: returns true and writes the level enum to *out. If the level name is not known: returns false and does not write *out. No sneaky partial writes, we respect boundaries here. π
SEE ALSO: Structured Logging
SEE ALSO: Structured Logging
π§© mongoc_structured_log_component_t
Synopsis
typedef enum {
MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND = 0,
MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY = 1,
MONGOC_STRUCTURED_LOG_COMPONENT_SERVER_SELECTION = 2,
MONGOC_STRUCTURED_LOG_COMPONENT_CONNECTION = 3,
} mongoc_structured_log_component_t;
mongoc_structured_log_component_t enumerates the structured logging components β the little categories logs get sorted into. ποΈ
β οΈ Real talk: applications should never rely on having an exhaustive list of all log components. New ones can show up, and you'd be left looking silly. Instead, use mongoc_structured_log_opts_set_max_level_for_all_components() to set a default level if you need one. iykyk. π
π« mongoc_structured_log_get_component_name()
Synopsis
const char *
mongoc_structured_log_get_component_name (mongoc_structured_log_component_t component);
Parameters
componentβ the log component, as amongoc_structured_log_component_t.
Returns
If the component is known, you get a pointer to a constant string that should not be freed. If the component has no known name, you get NULL. π¦
SEE ALSO: Structured Logging
π« mongoc_structured_log_get_named_component()
Synopsis
bool
mongoc_structured_log_get_named_component (const char *name, mongoc_structured_log_component_t *out);
Look up a component by name. Case insensitive again, we're consistent like that. β
Parameters
nameβ a name to look up as a log component.outβ on success, the correspondingmongoc_structured_log_component_tis written here. π«Ά
Returns
If the component name is known, returns true and writes the component enum to *out. If the component name is not known, returns false and does not write *out. Same deal as the level version, no cap. π
SEE ALSO: Structured Logging
SEE ALSO: Structured Logging
SEE ALSO:
mongoc_structured_log_get_level_namemongoc_structured_log_get_named_levelmongoc_structured_log_get_component_namemongoc_structured_log_get_named_component
π¬ Log Handlers
Okay so here's the mental model, and it's actually iconic once it clicks. π
Each mongoc_client_pool_t or standalone mongoc_client_t has its own instance of the structured logging subsystem β its own settings, its own handler. Separate little universes. π
When you're using a mongoc_client_pool_t, all the pooled clients share one common logging instance. Which means: handlers must be thread-safe. Not optional, not a suggestion. Periodt. π
The handler gets called for each log entry whose level is no greater than its component's maximum. A mongoc_structured_log_entry_t pointer hands you access to the further details β but only during the handler. After that it's gone, so don't get attached. π
π¨ Handlers must take care not to re-enter libmongoc with the samemongoc_client_tormongoc_client_pool_tthat the handler was called by. Fr fr, don't do it.
π mongoc_structured_log_func_t
Synopsis
typedef void (*mongoc_structured_log_func_t)
(const mongoc_structured_log_entry_t *entry, void *user_data);
This is the callback function type for mongoc_structured_log_opts_set_handler(). Structured log handlers must be thread-safe if they're gonna be used with a mongoc_client_pool_t. And handlers must avoid unbounded recursion β preferably by avoiding the use of any libmongoc client or pool that uses the same handler. We said what we said. π
Parameters
entryβ amongoc_structured_log_entry_tpointer, only valid during the handler invocation. Blink and it's gone.user_dataβ optional user data frommongoc_structured_log_opts_set_handler(). π«Ά
SEE ALSO: Structured Logging
π¨ Log Entries
Each log entry shows up inside the handler as a short-lived mongoc_structured_log_entry_t pointer. While you're in the handler, that pointer is your bestie β it gets you the individual properties of the entry: its level, its component, and its message. π
Here's the cute part β¨: the message only gets assembled as a bson_t when you explicitly ask for it with a call to mongoc_structured_log_entry_message_as_bson(). What you get back is a standalone document that you can keep for as long as you like β and that you must explicitly destroy. Your document, your responsibility. π§
π―οΈ mongoc_structured_log_entry_t
Synopsis
typedef struct mongoc_structured_log_entry_t mongoc_structured_log_entry_t;
mongoc_structured_log_entry_t is an opaque structure representing the temporary state of an in-progress log entry. It can only be used during a mongoc_structured_log_func_t β it is not valid after the log handler returns. Use the functions below to query the individual aspects of the log entry. π
π§ Functions
π« mongoc_structured_log_entry_get_component()
Synopsis
mongoc_structured_log_component_t
mongoc_structured_log_entry_get_component (const mongoc_structured_log_entry_t *entry);
Parameters
entryβ amongoc_structured_log_entry_tpointer.
Returns
The mongoc_structured_log_component_t associated with this log entry. π§©
SEE ALSO: Structured Logging
π« mongoc_structured_log_entry_get_level()
Synopsis
mongoc_structured_log_level_t
mongoc_structured_log_entry_get_level (const mongoc_structured_log_entry_t *entry);
Parameters
entryβ amongoc_structured_log_entry_tpointer.
Returns
The mongoc_structured_log_level_t associated with this log entry. π
SEE ALSO: Structured Logging
π« mongoc_structured_log_entry_get_message_string()
Synopsis
const char *
mongoc_structured_log_entry_get_message_string (const mongoc_structured_log_entry_t *entry);
Parameters
entryβ amongoc_structured_log_entry_tpointer.
Returns
A string β and it's guaranteed valid only during the lifetime of the structured log handler. It should not be freed or modified. Hands off. π ββοΈ
It's identical to the value of the message key in the document returned by mongoc_structured_log_entry_message_as_bson(). πΈ
β οΈ Heads up: this is not a complete string representation of the structured log. It's a standardized identifier for a particular log event. So don't expect the whole story from it, bestie.
SEE ALSO: Structured Logging
π« mongoc_structured_log_entry_message_as_bson()
Synopsis
bson_t *
mongoc_structured_log_entry_message_as_bson (const mongoc_structured_log_entry_t *entry);
Makes a brand-new copy, as a bson_t, of the log entry's standardized BSON representation. When possible, a log handler should avoid serializing log messages that are just gonna get discarded β like, why do the work π. Each call allocates an independent copy of the message, and that copy must be freed. π
Parameters
entryβ amongoc_structured_log_entry_tpointer.
Returns
A new allocated bson_t that must be freed with a call to bson_destroy(). Don't forget, or it's a leak, and leaks are not the vibe. π«Ά
SEE ALSO: Structured Logging
SEE ALSO: Structured Logging
π Example
Behold: example-structured-log.c β the whole demo, and honestly it ate. π₯
/* gcc example-structured-log.c -o example-structured-log \
* $(pkg-config --cflags --libs libmongoc-1.0) */
#include <mongoc/mongoc.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
static pthread_mutex_t handler_mutex;
static void
example_handler(const mongoc_structured_log_entry_t *entry, void *user_data)
{
(void)user_data;
mongoc_structured_log_component_t component = mongoc_structured_log_entry_get_component(entry);
mongoc_structured_log_level_t level = mongoc_structured_log_entry_get_level(entry);
const char *message_string = mongoc_structured_log_entry_get_message_string(entry);
/*
* With a single-threaded mongoc_client_t, handlers will always be called
* by the thread that owns the client. On a mongoc_client_pool_t, handlers
* are shared by multiple threads and must be reentrant.
*
* Note that unstructured logging includes a global mutex in the API,
* but structured logging allows applications to avoid lock contention
* even when multiple threads are issuing commands simultaneously.
*
* Simple apps like this example can achieve thread safety by adding their
* own global mutex. For other apps, this would be a performance bottleneck
* and it would be more appropriate for handlers to process their log
* messages concurrently.
*
* In this example, our mutex protects access to a global log counter.
* In a real application, you may need to protect access to a shared stream
* or queue.
*/
pthread_mutex_lock(&handler_mutex);
static unsigned log_serial_number = 0;
printf("%u. Log entry with component=%s level=%s message_string='%s'\n",
++log_serial_number,
mongoc_structured_log_get_component_name(component),
mongoc_structured_log_get_level_name(level),
message_string);
/*
* At this point, the handler might make additional filtering decisions
* before asking for a bson_t. As an example, let's log the component and
* level for all messages but only show contents for command logs.
*/
if (component == MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND) {
bson_t *message = mongoc_structured_log_entry_message_as_bson(entry);
char *json = bson_as_relaxed_extended_json(message, NULL);
printf("Full log message, as json: %s\n", json);
bson_destroy(message);
bson_free(json);
}
pthread_mutex_unlock(&handler_mutex);
}
int
main(void)
{
const char *uri_string = "mongodb://localhost:27017";
int result = EXIT_FAILURE;
bson_error_t error;
mongoc_uri_t *uri = NULL;
mongoc_structured_log_opts_t *log_opts = NULL;
mongoc_client_t *client = NULL;
mongoc_client_pool_t *pool = NULL;
/*
* Note that structured logging only applies per-client or per-pool,
* and it won't be used during or before mongoc_init.
*/
mongoc_init();
/*
* Logging options are represented by a mongoc_structured_log_opts_t,
* which can be copied into a mongoc_client_t or mongoc_client_pool_t
* using mongoc_client_set_structured_log_opts() or
* mongoc_client_pool_set_structured_log_opts(), respectively.
*
* Default settings are captured from the environment into
* this structure when it's constructed.
*/
log_opts = mongoc_structured_log_opts_new();
/*
* For demonstration purposes, set up a handler that receives all possible log messages.
*/
pthread_mutex_init(&handler_mutex, NULL);
mongoc_structured_log_opts_set_max_level_for_all_components(log_opts, MONGOC_STRUCTURED_LOG_LEVEL_TRACE);
mongoc_structured_log_opts_set_handler(log_opts, example_handler, NULL);
/*
* By default libmongoc processes log options from the environment first,
* and then allows you to apply programmatic overrides. To request the
* opposite behavior, allowing the environment to override programmatic
* defaults, you can ask for the environment to be re-read after setting
* your own defaults.
*/
mongoc_structured_log_opts_set_max_levels_from_env(log_opts);
/*
* Create a MongoDB URI object. This example assumes a local server.
*/
uri = mongoc_uri_new_with_error(uri_string, &error);
if (!uri) {
fprintf(stderr, "URI parse error: %s\n", error.message);
goto done;
}
/*
* Create a new client pool.
*/
pool = mongoc_client_pool_new(uri);
if (!pool) {
goto done;
}
/*
* Set the client pool's log options.
* This must happen only once, and only before the first mongoc_client_pool_pop.
* There's no need to keep log_opts after this point.
*/
mongoc_client_pool_set_structured_log_opts(pool, log_opts);
/*
* Check out a client, and do some work that we'll see logs from.
* This example just sends a 'ping' command.
*/
client = mongoc_client_pool_pop(pool);
if (!client) {
goto done;
}
bson_t *command = BCON_NEW("ping", BCON_INT32(1));
bson_t reply;
bool command_ret = mongoc_client_command_simple(client, "admin", command, NULL, &reply, &error);
bson_destroy(command);
bson_destroy(&reply);
mongoc_client_pool_push(pool, client);
if (!command_ret) {
fprintf(stderr, "Command error: %s\n", error.message);
goto done;
}
result = EXIT_SUCCESS;
done:
mongoc_uri_destroy(uri);
mongoc_structured_log_opts_destroy(log_opts);
mongoc_client_pool_destroy(pool);
mongoc_cleanup();
return result;
}
Likeβ¦ that's the whole thing, bestie. π You made it through the entire example. Screenshot it, frame it, put it on your fridge. β¨
π SEE ALSO
If you wanna keep going down the rabbit hole (and honestly, who wouldn't), these are your girls:
mongoc_structured_log_entry_get_componentβ tells you which component a log entry came frommongoc_structured_log_entry_get_levelβ tells you the severity level of an entrymongoc_structured_log_entry_message_as_bsonβ hands you the message as a BSON doc
Lowkey the whole structured-logging squad. Go read 'em, iykyk. π
π AUTHOR
MongoDB, Inc β the icons who wrote all this, no cap. π
Β©οΈ COPYRIGHT
2009-present, MongoDB, Inc. fr fr, all rights reserved and all that. π
Okay that's a wrap on MONGOC_LOGGING(3), bestie!! π¦ This masterpiece is version 2.5.6, dated Oct 09, 2026 β the MONGOC_LOGGING(3) page from 2.5.6 / Oct 09, 2026. Go forth and log responsibly. Periodt. ππΈ
π¦ where this page comes from
- epel 10: mongo-c-driver-devel 2.5.6-1.el10_3 Β· Apache-2.0 AND ISC AND MIT AND Zlib
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms