This repository has been archived by the owner on Apr 23, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from ktoso/wip-holders
WIP #7: on holding baggage in framework protocols
- Loading branch information
Showing
9 changed files
with
779 additions
and
8 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"object": { | ||
"pins": [ | ||
{ | ||
"package": "swift-log", | ||
"repositoryURL": "https://github.com/apple/swift-log.git", | ||
"state": { | ||
"branch": null, | ||
"revision": "57c6bd04256ba47590ee2285e208f731210c5c10", | ||
"version": "1.3.0" | ||
} | ||
} | ||
] | ||
}, | ||
"version": 1 | ||
} |
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the Swift Baggage Context open source project | ||
// | ||
// Copyright (c) 2020 Moritz Lang and the Swift Baggage Context project authors | ||
// Licensed under Apache License v2.0 | ||
// | ||
// See LICENSE.txt for license information | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// ==== ---------------------------------------------------------------------------------------------------------------- | ||
// MARK: Framework Context Protocols | ||
|
||
/// Framework context protocols may conform to this protocol if they are used to carry a baggage object. | ||
/// | ||
/// Notice that the baggage context property is spelled as `baggage`, this is purposefully designed in order to read well | ||
/// with framework context's which often will be passed as `context: FrameworkContext` and used as `context.baggage`. | ||
/// | ||
/// Such carrier protocol also conforms to `BaggageContextProtocol` meaning that it has the same convenient accessors | ||
/// as the actual baggage type. Users should be able to use the `context.myValue` the same way if a raw baggage context, | ||
/// or a framework context was passed around as `context` parameter, allowing for easier migrations between those two when needed. | ||
public protocol BaggageContextCarrier: BaggageContextProtocol { | ||
/// The underlying `BaggageContext`. | ||
var baggage: BaggageContext { get set } | ||
} | ||
|
||
extension BaggageContextCarrier { | ||
public subscript<Key: BaggageContextKey>(baggageKey: Key.Type) -> Key.Value? { | ||
get { | ||
self.baggage[baggageKey] | ||
} set { | ||
self.baggage[baggageKey] = newValue | ||
} | ||
} | ||
|
||
public func forEach(_ callback: (AnyBaggageContextKey, Any) -> Void) { | ||
self.baggage.forEach(callback) | ||
} | ||
} | ||
|
||
/// A baggage itself also is a carrier of _itself_. | ||
extension BaggageContext: BaggageContextCarrier { | ||
public var baggage: BaggageContext { | ||
get { | ||
self | ||
} | ||
set { | ||
self = newValue | ||
} | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the Swift Baggage Context open source project | ||
// | ||
// Copyright (c) 2020 Moritz Lang and the Swift Baggage Context project authors | ||
// Licensed under Apache License v2.0 | ||
// | ||
// See LICENSE.txt for license information | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import Baggage | ||
import Logging | ||
|
||
// ==== ---------------------------------------------------------------------------------------------------------------- | ||
// MARK: BaggageContext (as additional Logger.Metadata) LogHandler | ||
|
||
/// Proxying log handler which adds `BaggageContext` as metadata when log events are to be emitted. | ||
public struct BaggageMetadataLogHandler: LogHandler { | ||
var underlying: Logger | ||
let context: BaggageContext | ||
|
||
public init(logger underlying: Logger, context: BaggageContext) { | ||
self.underlying = underlying | ||
self.context = context | ||
} | ||
|
||
public var logLevel: Logger.Level { | ||
get { | ||
self.underlying.logLevel | ||
} | ||
set { | ||
self.underlying.logLevel = newValue | ||
} | ||
} | ||
|
||
public func log( | ||
level: Logger.Level, | ||
message: Logger.Message, | ||
metadata: Logger.Metadata?, | ||
source: String, | ||
file: String, | ||
function: String, | ||
line: UInt | ||
) { | ||
guard self.underlying.logLevel <= level else { | ||
return | ||
} | ||
|
||
var effectiveMetadata = self.baggageAsMetadata() | ||
if let metadata = metadata { | ||
effectiveMetadata.merge(metadata, uniquingKeysWith: { _, r in r }) | ||
} | ||
self.underlying.log(level: level, message, metadata: effectiveMetadata, source: source, file: file, function: function, line: line) | ||
} | ||
|
||
public var metadata: Logger.Metadata { | ||
get { | ||
[:] | ||
} | ||
set { | ||
newValue.forEach { k, v in | ||
self.underlying[metadataKey: k] = v | ||
} | ||
} | ||
} | ||
|
||
/// Note that this does NOT look up inside the baggage. | ||
/// | ||
/// This is because a context lookup either has to use the specific type key, or iterate over all keys to locate one by name, | ||
/// which may be incorrect still, thus rather than making an potentially slightly incorrect lookup, we do not implement peeking | ||
/// into a baggage with String keys through this handler (as that is not a capability `BaggageContext` offers in any case. | ||
public subscript(metadataKey metadataKey: Logger.Metadata.Key) -> Logger.Metadata.Value? { | ||
get { | ||
self.underlying[metadataKey: metadataKey] | ||
} | ||
set { | ||
self.underlying[metadataKey: metadataKey] = newValue | ||
} | ||
} | ||
|
||
private func baggageAsMetadata() -> Logger.Metadata { | ||
var effectiveMetadata: Logger.Metadata = [:] | ||
self.context.forEach { key, value in | ||
if let convertible = value as? String { | ||
effectiveMetadata[key.name] = .string(convertible) | ||
} else if let convertible = value as? CustomStringConvertible { | ||
effectiveMetadata[key.name] = .stringConvertible(convertible) | ||
} else { | ||
effectiveMetadata[key.name] = .stringConvertible(BaggageValueCustomStringConvertible(value)) | ||
} | ||
} | ||
|
||
return effectiveMetadata | ||
} | ||
|
||
struct BaggageValueCustomStringConvertible: CustomStringConvertible { | ||
let value: Any | ||
|
||
init(_ value: Any) { | ||
self.value = value | ||
} | ||
|
||
var description: String { | ||
"\(self.value)" | ||
} | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the Swift Baggage Context open source project | ||
// | ||
// Copyright (c) 2020 Moritz Lang and the Swift Baggage Context project authors | ||
// Licensed under Apache License v2.0 | ||
// | ||
// See LICENSE.txt for license information | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import Baggage | ||
import Logging | ||
|
||
extension Logger { | ||
/// Returns a logger that in addition to any explicit metadata passed to log statements, | ||
/// also includes the `BaggageContext` adapted into metadata values. | ||
/// | ||
/// The rendering of baggage values into metadata values is performed on demand, | ||
/// whenever a log statement is effective (i.e. will be logged, according to active `logLevel`). | ||
public func with(context: BaggageContext) -> Logger { | ||
Logger( | ||
label: self.label, | ||
factory: { _ in BaggageMetadataLogHandler(logger: self, context: context) } | ||
) | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the Swift Baggage Context open source project | ||
// | ||
// Copyright (c) 2020 Moritz Lang and the Swift Baggage Context project authors | ||
// Licensed under Apache License v2.0 | ||
// | ||
// See LICENSE.txt for license information | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import Baggage | ||
import Logging | ||
|
||
/// A `BaggageContextLogging` purpose is to be adopted by frameworks which already provide a "FrameworkContext", | ||
/// and to such frameworks to pass their context as `BaggageContextCarrier`. | ||
public protocol LoggingBaggageContextCarrier: BaggageContextCarrier { | ||
/// The logger associated with this carrier context. | ||
/// | ||
/// It should automatically populate the loggers metadata based on the `BaggageContext` associated with this context object. | ||
/// | ||
/// ### Implementation note | ||
/// | ||
/// Libraries and/or frameworks which conform to this protocol with their "Framework Context" types, | ||
/// SHOULD implement this logger by wrapping the "raw" logger associated with this context with the `logger.with(BaggageContext:)` function, | ||
/// which efficiently handles the bridging of baggage to logging metadata values. | ||
/// | ||
/// Writes to the `logger` metadata SHOULD NOT be reflected in the `baggage`, | ||
/// however writes to the underlying `baggage` SHOULD be reflected in the `logger`. | ||
var logger: Logger { get set } | ||
} |
Oops, something went wrong.