-
Notifications
You must be signed in to change notification settings - Fork 299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add withMetadata() convenience function for adding multiple metadata k/v pairs to a Logger #322
base: main
Are you sure you want to change the base?
Conversation
@swift-server-bot test this please |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty good convenience func, I like it. Thanks for the PR
4e2911c
to
e98a4aa
Compare
@swift-server-bot test this please |
1 similar comment
@swift-server-bot test this please |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @gabbifish – this looks handy! I've proposed a slightly different name but otherwise this looks great.
Sources/Logging/Logging.swift
Outdated
/// - note: Logging metadata behaves as a value that means a change to the logging metadata will only affect the | ||
/// very `Logger` it was changed on. | ||
@inlinable | ||
public mutating func withMetadata(metadata: Logger.Metadata) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can I propose we spell this slightly differently?
with
is typically used in names that provide scoped access to something (withUnsafePointer
, withCheckedContinuation
, withTaskGroup
etc.) so doesn't feel quite right here (although I appreciate it is the spelling used for loggers in other languages).
How about addMetadata
? Could we also drop the metadata:
label to avoid the repetition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, fully agree. Also from "other languages" you would expect a "withMetadata" method to be "not mutable" but return a new logger with the metadata replaced with the new value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if merging
is the right term here since we merge the new values over the old values if keys are in both metadata "bags". Could we also add a doc comment for the parameter that we pass here please
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think merging
should not be mutable and return a new Logger
.
merge
would be the mutable
counterpart.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think
merging
should not be mutable and return a newLogger
.merge
would be themutable
counterpart.
Agreed. merge
is the correct spelling for this context. If we do this we should allow the caller to specify how to handle non-unique keys too. Dictionary
has a spelling for this: https://developer.apple.com/documentation/swift/dictionary/merge(_:uniquingkeyswith:)-m2ub
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since Metadata
is actually a Dictionary
, this is already available as logger.metadata.merge(_:uniquingKeysWith:)
🤷♂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have to go via the handler
(logger.handler.metadata.merge(...)
) which is non-obvious so adding API directly on the logger
is valuable (especially as you can already set individual values via the subscript
s)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do think mergeMetadata
, paired with the dropping a required metadata
argument label, is the clearest option here--will proceed with that.
Sources/Logging/Logging.swift
Outdated
/// - note: Logging metadata behaves as a value that means a change to the logging metadata will only affect the | ||
/// very `Logger` it was changed on. | ||
@inlinable | ||
public mutating func withMetadata(metadata: Logger.Metadata) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if merging
is the right term here since we merge the new values over the old values if keys are in both metadata "bags". Could we also add a doc comment for the parameter that we pass here please
Tests/LoggingTests/LoggingTest.swift
Outdated
@@ -357,6 +357,25 @@ class LoggingTest: XCTestCase { | |||
"nested-list": ["l1str", ["l2str1", "l2str2"]]]) | |||
} | |||
|
|||
func testWithMetadata() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add three more test cases:
- Where the logger has some existing metadata and we add new metadata without any overlapping keys
- Same as above but with overlapping keys
- Adding more than once with overlapping keys
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added to existing testMergeMetadata
function.
e98a4aa
to
24cb3e1
Compare
24cb3e1
to
6bb92fb
Compare
… k/v pairs to a Logger
6bb92fb
to
1bc7650
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this might open up a larger question since @t089 rightly pointed out that Metadata
really is just a type alias for Dictionary<String: MetadataValue>
what if we expose the metadata that a logger has via a var
so that users could just call metadata.merge
via the standard method on dictionary.
@weissi @ktoso do you know if there is historical reasons why we don't expose the metadata on the logger? LogHandler
has it as a get/set
requirement on the protocol so it seems very easy to wire through safely.
I would anticipate there are some concerns about exposing the logger handler's internal state so directly? Having simple functions for getting/setting logger metadata provides a simple, easier-to-secure abstraction. |
I am personally not concerned about exposing the underlying metadata of the log hander directly on the logger. Specifically because the next feature request will be "Can I access the metadata of the logger?" which we would then have to add a getter on the Logger. That's why I think we should have this discussion before we add this specialised method here. |
One more thought: Exposing I guess this already exists today, though? With |
Yes, that's a performance reason. The |
Yes, this was also a reason we do not offer |
So yes, please keep not exposing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@swift-server-bot test this please |
/// - note: Logging metadata behaves as a value that means a change to the logging metadata will only affect the | ||
/// very `Logger` it was changed on. | ||
@inlinable | ||
public mutating func mergeMetadata(_ metadata: Logger.Metadata) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add the uniquingKeysWith
parameter as well à la Dictionary?
metadata.forEach { (key, value) in | ||
self.handler[metadataKey: key] = value | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect in many (all?) handler implementations this will acquire and release a lock for each value we update. Can we call merge
directly on the handler.metadata
to avoid this? i.e. self.handler.metadata.merge(metadata)
Adds withMetadata() convenience function for adding multiple metadata k/v pairs to a Logger.
Motivation:
Addresses #321
Modifications:
Note that in the spirit of the
Logger[metadataKey: key] = value
subscript mutating a logger, this PR also mutates the logger in-place.Result:
Provides users a convenience function to add or modify multiple Logger.Metadata values in a Logger in place.