refactor!: introduce LoggerProvider and record Metadata - #241
Draft
tisonkun wants to merge 1 commit into
Draft
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is a stacked design PR on top of #239. Its purpose is to make the proposed native API concrete before either layer is stabilized.
Summary
LoggerBuilderwithLoggerProviderBuilderLoggerProviderown and share the configuredDispatchgraphLoggera lightweight, cloneable handle obtained withprovider.logger()orprovider.named_logger(name)FilterCriteriawith a completeMetadatavalueMetadatain the resultingRecord, so prefiltering and record construction cannot driftlogbridge andRustLogFilterdirectly to the Logforth metadata modelDispatch,Append,Filter,Diagnostic,Layout, and the existing native macro grammarProposed final API
LoggerProvideris deliberately not called a runtime. It has one concrete responsibility: own shared dispatch configuration and create logger handles.Loggerremains the object passed to native macros and used to emit records.Named and unnamed loggers remain explicit variants of the existing target behavior:
provider.logger()uses the call-site module path as the native targetprovider.named_logger("metering")uses the stable logger name as the native targetA dedicated dispatch graph still uses a dedicated provider. Multiple logger handles from one provider intentionally share its dispatches.
Metadata
The macro constructs
Metadatabefore evaluating payload/KV expressions, asksLogger::enabled(&metadata), and then moves the same value intoRecord::builder().metadata(metadata).This is different from the older Logforth type that was renamed from
MetadatatoFilterCriteria: that type contained only level and target and was not part ofRecord. This PR makes metadata the actual record header and includes all information already present in Logforth records; it does not introduce a parallel event schema.There is deliberately no public
Emittrait orInteresttype in this proposal. The native macros continue to depend on the concreteLogger; an abstraction can be added later if a real second implementation requires it.Event model boundaries
This PR does not add
channel,delivery, or a requiredevent_name.CloudEvents requires
id,source, andtypebecause it defines an interoperable event envelope. That requirement does not imply that every diagnostic log call should fill those fields: https://github.com/cloudevents/spec/blob/main/cloudevents/spec.mdOpenTelemetry Logs treats body, attributes, and event name as optional. A non-empty event name identifies a structured Event, while ordinary LogRecords need not have one: https://opentelemetry.io/docs/specs/otel/logs/data-model/
If Logforth later adds an optional event name, it can be evaluated independently without being coupled to this provider/metadata split.
Compatibility
logforth-bridge-logmapslog::Metadataandlog::Recorddirectly into LogforthMetadataandRecord. The core model has no dependency onlogtypes.A future tracing integration should likewise be a direct adapter into this model; this PR does not add tracing dependencies or route tracing through
log.Breaking changes
builder().build()now returnsLoggerProvider; call.logger()to obtain an unnamed loggerLoggerBuilderbecomesLoggerProviderBuilderLoggerBuilder::namebecomesLoggerProvider::named_loggerFilter::enabledandLogger::enabledreceiveMetadatainstead ofFilterCriteriaLoggerProviderfrombuild()Validation
cargo x testcargo +nightly clippy --tests --all-features --all-targets --workspace -- -D warningscargo +nightly fmt --all --checktyposhawkeye check