sfio_tracing_ffi/
lib.rs

1//! [oo_bindgen](https://github.com/stepfunc/oo_bindgen/) model for FFI bindings to [tracing](https://docs.rs/tracing/latest/tracing/).w
2use oo_bindgen::model::*;
3
4/// Retrieve the implementation file for this schema
5pub const fn get_impl_file() -> &'static str {
6    include_str!("../implementation.rs")
7}
8
9/// Adds required types for logging to an `oo_bindgen` model
10///
11/// * `lib` - Builder for library
12/// * `error_type` - Error type that will be used if logging configuration fails
13pub fn define(lib: &mut LibraryBuilder, error_type: ErrorTypeHandle) -> BackTraced<()> {
14    let log_level_enum = define_log_level_enum(lib)?;
15
16    let logging_config_struct = define_logging_config_struct(lib, log_level_enum.clone())?;
17
18    let log_callback_interface = lib
19        .define_interface(
20            "logger",
21            "Logging interface that receives the log messages and writes them somewhere.",
22        )?
23        .begin_callback(
24            "on_message",
25            "Called when a log message was received and should be logged",
26        )?
27        .param("level", log_level_enum, "Level of the message")?
28        .param("message", StringType, "Actual formatted message")?
29        .end_callback()?
30        .build_async()?;
31
32    let configure_logging_fn = lib
33        .define_function("configure_logging")?
34        .param(
35            "config",
36            logging_config_struct,
37            "Configuration options for logging"
38        )?
39        .param(
40            "logger",
41            log_callback_interface,
42            "Logger that will receive each logged message",
43        )?
44        .fails_with(error_type)?
45        .doc(
46            doc("Set the callback that will receive all the log messages")
47                .details("There is only a single globally allocated logger. Calling this method a second time will return an error.")
48                .details("If this method is never called, no logging will be performed.")
49        )?
50        .build_static("configure")?;
51
52    let _ = lib
53        .define_static_class("logging")?
54        .static_method(configure_logging_fn)?
55        .doc("Provides a static method for configuring logging")?
56        .build()?;
57
58    Ok(())
59}
60fn define_log_level_enum(lib: &mut LibraryBuilder) -> BackTraced<EnumHandle> {
61    let definition = lib
62        .define_enum("log_level")?
63        .push("error", "Error log level")?
64        .push("warn", "Warning log level")?
65        .push("info", "Information log level")?
66        .push("debug", "Debugging log level")?
67        .push("trace", "Trace log level")?
68        .doc(
69            doc("Log level")
70                .details("Used in {interface:logger.on_message()} callback to identify the log level of a message.")
71        )?
72        .build()?;
73
74    Ok(definition)
75}
76
77fn define_time_format_enum(lib: &mut LibraryBuilder) -> BackTraced<EnumHandle> {
78    let definition = lib
79        .define_enum("time_format")?
80        .push("none", "Don't format the timestamp as part of the message")?
81        .push("rfc_3339", "Format the time using RFC 3339")?
82        .push(
83            "system",
84            "Format the time in a human readable format e.g. 'Jun 25 14:27:12.955'",
85        )?
86        .doc("Describes if and how the time will be formatted in log messages")?
87        .build()?;
88
89    Ok(definition)
90}
91
92fn define_log_output_format_enum(lib: &mut LibraryBuilder) -> BackTraced<EnumHandle> {
93    let definition = lib
94        .define_enum("log_output_format")?
95        .push("text", "A simple text-based format")?
96        .push("json", "Output formatted as JSON")?
97        .doc("Describes how each log event is formatted")?
98        .build()?;
99
100    Ok(definition)
101}
102
103fn define_logging_config_struct(
104    lib: &mut LibraryBuilder,
105    log_level_enum: EnumHandle,
106) -> BackTraced<FunctionArgStructHandle> {
107    let logging_config_struct = lib.declare_function_argument_struct("logging_config")?;
108
109    let log_output_format_enum = define_log_output_format_enum(lib)?;
110    let time_format_enum = define_time_format_enum(lib)?;
111
112    let level = Name::create("level")?;
113    let output_format = Name::create("output_format")?;
114    let time_format = Name::create("time_format")?;
115    let print_level = Name::create("print_level")?;
116    let print_module_info = Name::create("print_module_info")?;
117
118    let logging_config_struct = lib
119        .define_function_argument_struct(logging_config_struct)?
120        .add(&level, log_level_enum, "logging level")?
121        .add(
122            &output_format,
123            log_output_format_enum,
124            "output formatting options",
125        )?
126        .add(&time_format, time_format_enum, "optional time format")?
127        .add(
128            &print_level,
129            Primitive::Bool,
130            "optionally print the log level as part to the message string",
131        )?
132        .add(
133            &print_module_info,
134            Primitive::Bool,
135            "optionally print the underlying Rust module information to the message string",
136        )?
137        .doc("Logging configuration options")?
138        .end_fields()?
139        .begin_initializer(
140            "init",
141            InitializerType::Normal,
142            "Initialize the configuration to default values",
143        )?
144        .default(&level, "info".default_variant())?
145        .default(&output_format, "text".default_variant())?
146        .default(&time_format, "system".default_variant())?
147        .default(&print_level, true)?
148        .default(&print_module_info, false)?
149        .end_initializer()?
150        .build()?;
151
152    Ok(logging_config_struct)
153}