Skip to content

Commit 93fd1d3

Browse files
author
Ignacio Bonafonte
authored
Merge pull request #347 from bryce-b/LoggingSDK
2 parents 444d981 + a7224bf commit 93fd1d3

File tree

51 files changed

+2277
-8
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2277
-8
lines changed

Examples/OTLP Exporter/main.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ let spanExporter = MultiSpanExporter(spanExporters: [otlpTraceExporter, stdoutEx
4040
let spanProcessor = SimpleSpanProcessor(spanExporter: spanExporter)
4141
OpenTelemetrySDK.instance.tracerProvider.addSpanProcessor(spanProcessor)
4242

43-
if #available(macOS 10.14, *) {
43+
if #available(macOS 10.14, *), #available(iOS 12.0, *) {
4444
OpenTelemetrySDK.instance.tracerProvider.addSpanProcessor(SignPostIntegration())
4545
}
4646

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import Foundation
7+
import OpenTelemetryApi
8+
import OpenTelemetrySdk
9+
public class LogRecordAdapter {
10+
public static func toProtoResourceRecordLog(logRecordList: [ReadableLogRecord]) -> [Opentelemetry_Proto_Logs_V1_ResourceLogs] {
11+
let resourceAndScopeMap = groupByResourceAndScope(logRecordList: logRecordList)
12+
var resourceLogs = [Opentelemetry_Proto_Logs_V1_ResourceLogs]()
13+
resourceAndScopeMap.forEach { resMap in
14+
var scopeLogs = [Opentelemetry_Proto_Logs_V1_ScopeLogs]()
15+
resMap.value.forEach { scopeInfo, logRecords in
16+
var protoScopeLogs = Opentelemetry_Proto_Logs_V1_ScopeLogs()
17+
protoScopeLogs.scope = CommonAdapter.toProtoInstrumentationScope(instrumentationScopeInfo: scopeInfo)
18+
logRecords.forEach { record in
19+
protoScopeLogs.logRecords.append(record)
20+
}
21+
scopeLogs.append(protoScopeLogs)
22+
}
23+
var resourceLog = Opentelemetry_Proto_Logs_V1_ResourceLogs()
24+
resourceLog.resource = ResourceAdapter.toProtoResource(resource: resMap.key)
25+
resourceLog.scopeLogs.append(contentsOf: scopeLogs)
26+
resourceLogs.append(resourceLog)
27+
}
28+
return resourceLogs
29+
}
30+
31+
public static func groupByResourceAndScope(logRecordList: [ReadableLogRecord]) -> [Resource:[InstrumentationScopeInfo:[Opentelemetry_Proto_Logs_V1_LogRecord]]] {
32+
var result = [Resource:[InstrumentationScopeInfo: [Opentelemetry_Proto_Logs_V1_LogRecord]]]()
33+
logRecordList.forEach { logRecord in
34+
result[logRecord.resource, default:[InstrumentationScopeInfo: [Opentelemetry_Proto_Logs_V1_LogRecord]]()][logRecord.instrumentationScopeInfo,default:[Opentelemetry_Proto_Logs_V1_LogRecord]()].append(toProtoLogRecord(logRecord: logRecord))
35+
}
36+
return result
37+
}
38+
39+
public static func toProtoLogRecord(logRecord: ReadableLogRecord) -> Opentelemetry_Proto_Logs_V1_LogRecord {
40+
var protoLogRecord = Opentelemetry_Proto_Logs_V1_LogRecord()
41+
42+
if let observedTimestamp = logRecord.observedTimestamp {
43+
protoLogRecord.observedTimeUnixNano = observedTimestamp.timeIntervalSince1970.toNanoseconds
44+
}
45+
46+
protoLogRecord.timeUnixNano = logRecord.timestamp.timeIntervalSince1970.toNanoseconds
47+
48+
if let body = logRecord.body, !body.isEmpty {
49+
var protoBody = Opentelemetry_Proto_Common_V1_AnyValue()
50+
protoBody.stringValue = body
51+
protoLogRecord.body = protoBody
52+
}
53+
54+
55+
if let severity = logRecord.severity {
56+
protoLogRecord.severityText = severity.description
57+
if let protoSeverity = Opentelemetry_Proto_Logs_V1_SeverityNumber(rawValue: severity.rawValue) {
58+
protoLogRecord.severityNumber = protoSeverity
59+
}
60+
}
61+
62+
if let context = logRecord.spanContext {
63+
protoLogRecord.spanID = TraceProtoUtils.toProtoSpanId(spanId: context.spanId)
64+
protoLogRecord.traceID = TraceProtoUtils.toProtoTraceId(traceId: context.traceId)
65+
protoLogRecord.flags = UInt32(context.traceFlags.byte)
66+
}
67+
68+
var protoAttributes = [Opentelemetry_Proto_Common_V1_KeyValue]()
69+
logRecord.attributes.forEach { key, value in
70+
protoAttributes.append(CommonAdapter.toProtoAttribute(key: key, attributeValue: value))
71+
}
72+
protoLogRecord.attributes = protoAttributes
73+
return protoLogRecord
74+
}
75+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import Foundation
7+
import Logging
8+
import GRPC
9+
import NIO
10+
import NIOHPACK
11+
import OpenTelemetryApi
12+
import OpenTelemetrySdk
13+
14+
public class OtlpLogExporter : LogRecordExporter {
15+
let channel : GRPCChannel
16+
var logClient : Opentelemetry_Proto_Collector_Logs_V1_LogsServiceNIOClient
17+
let config : OtlpConfiguration
18+
var callOptions : CallOptions? = nil
19+
20+
public init(channel: GRPCChannel,
21+
config: OtlpConfiguration = OtlpConfiguration(),
22+
logger: Logging.Logger = Logging.Logger(label: "io.grpc", factory: { _ in SwiftLogNoOpLogHandler() }),
23+
envVarHeaders: [(String, String)]? = EnvVarHeaders.attributes){
24+
self.channel = channel
25+
logClient = Opentelemetry_Proto_Collector_Logs_V1_LogsServiceNIOClient(channel: channel)
26+
self.config = config
27+
if let headers = envVarHeaders {
28+
callOptions = CallOptions(customMetadata: HPACKHeaders(headers), logger: logger)
29+
} else if let headers = config.headers {
30+
callOptions = CallOptions(customMetadata: HPACKHeaders(headers), logger: logger)
31+
}
32+
else {
33+
callOptions = CallOptions(logger: logger)
34+
}
35+
}
36+
37+
public func export(logRecords: [ReadableLogRecord]) -> ExportResult {
38+
let logRequest = Opentelemetry_Proto_Collector_Logs_V1_ExportLogsServiceRequest.with { request in
39+
request.resourceLogs = LogRecordAdapter.toProtoResourceRecordLog(logRecordList: logRecords)
40+
}
41+
let export = logClient.export(logRequest, callOptions: callOptions)
42+
do {
43+
_ = try export.response.wait()
44+
return .success
45+
} catch {
46+
return .failure
47+
}
48+
}
49+
50+
public func shutdown() {
51+
_ = channel.close()
52+
}
53+
54+
public func forceFlush() -> ExportResult {
55+
.success
56+
}
57+
}

Sources/Exporters/OpenTelemetryProtocol/metric/OtlpMetricExporter.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public class OtlpMetricExporter: MetricExporter {
1919

2020

2121

22-
public init(channel: GRPCChannel, config: OtlpConfiguration = OtlpConfiguration(), logger: Logger = Logger(label: "io.grpc", factory: { _ in SwiftLogNoOpLogHandler() }), envVarHeaders: [(String,String)]? = EnvVarHeaders.attributes) {
22+
public init(channel: GRPCChannel, config: OtlpConfiguration = OtlpConfiguration(), logger: Logging.Logger = Logging.Logger(label: "io.grpc", factory: { _ in SwiftLogNoOpLogHandler() }), envVarHeaders: [(String,String)]? = EnvVarHeaders.attributes) {
2323
self.channel = channel
2424
self.config = config
2525
self.metricClient = Opentelemetry_Proto_Collector_Metrics_V1_MetricsServiceNIOClient(channel: self.channel)

Sources/Exporters/OpenTelemetryProtocol/trace/OtlpTraceExporter.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class OtlpTraceExporter: SpanExporter {
1717
let config : OtlpConfiguration
1818
var callOptions : CallOptions? = nil
1919

20-
public init(channel: GRPCChannel, config: OtlpConfiguration = OtlpConfiguration(), logger: Logger = Logger(label: "io.grpc", factory: { _ in SwiftLogNoOpLogHandler() }), envVarHeaders: [(String,String)]? = EnvVarHeaders.attributes) {
20+
public init(channel: GRPCChannel, config: OtlpConfiguration = OtlpConfiguration(), logger: Logging.Logger = Logging.Logger(label: "io.grpc", factory: { _ in SwiftLogNoOpLogHandler() }), envVarHeaders: [(String,String)]? = EnvVarHeaders.attributes) {
2121
self.channel = channel
2222
traceClient = Opentelemetry_Proto_Collector_Trace_V1_TraceServiceNIOClient(channel: channel)
2323
self.config = config

Sources/Instrumentation/URLSession/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,6 @@ This behaviour can be modified or augmented by using the optional callbacks defi
2525

2626
`receivedResponse: ((URLResponse, DataOrFile?, Span) -> Void)?`- Called after response is received, it allows to add extra information to the Span
2727

28-
`receivedError: ((Error, DataOrFile?, HTTPStatus, Span) -> Void)?` - Called after an errror is received, it allows to add extra information to the Span
28+
`receivedError: ((Error, DataOrFile?, HTTPStatus, Span) -> Void)?` - Called after an error is received, it allows to add extra information to the Span
2929

3030

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import Foundation
7+
8+
public class DefaultLogger : Logger {
9+
10+
private static let instanceWithDomain = DefaultLogger(true)
11+
private static let instanceNoDomain = DefaultLogger(false)
12+
private static let noopLogRecordBuilder = NoopLogRecordBuilder()
13+
14+
private var hasDomain : Bool
15+
16+
private init(_ hasDomain : Bool) {
17+
self.hasDomain = hasDomain
18+
}
19+
20+
static func getInstance(_ hasDomain: Bool) -> Logger {
21+
if hasDomain {
22+
return Self.instanceWithDomain
23+
} else {
24+
return Self.instanceNoDomain
25+
}
26+
}
27+
28+
public func eventBuilder(name: String) -> EventBuilder {
29+
if !hasDomain {
30+
/// log error
31+
}
32+
return Self.noopLogRecordBuilder
33+
}
34+
35+
public func logRecordBuilder() -> LogRecordBuilder {
36+
return Self.noopLogRecordBuilder
37+
}
38+
39+
private class NoopLogRecordBuilder : EventBuilder {
40+
41+
func setObservedTimestamp(_ observed: Date) -> Self {
42+
return self
43+
}
44+
45+
func setSpanContext(_ context: SpanContext) -> Self {
46+
return self
47+
}
48+
49+
func setSeverity(_ severity: Severity) -> Self {
50+
return self
51+
}
52+
53+
func setBody(_ body: String) -> Self {
54+
return self
55+
}
56+
57+
func setAttributes(_ attributes: [String: AttributeValue]) -> Self {
58+
return self
59+
}
60+
61+
func emit() {
62+
63+
}
64+
65+
}
66+
67+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import Foundation
7+
8+
public class DefaultLoggerProvider : LoggerProvider {
9+
public static let instance: LoggerProvider = DefaultLoggerProvider()
10+
fileprivate static let noopBuilderWithDomain = NoopLoggerBuilder(true)
11+
fileprivate static let noopBuilderNoDomain = NoopLoggerBuilder(false)
12+
13+
public func get(instrumentationScopeName: String) -> Logger {
14+
return loggerBuilder(instrumentationScopeName: instrumentationScopeName).build()
15+
}
16+
17+
public func loggerBuilder(instrumentationScopeName: String) -> LoggerBuilder {
18+
return Self.noopBuilderNoDomain
19+
}
20+
}
21+
22+
fileprivate class NoopLoggerBuilder: LoggerBuilder {
23+
private let hasDomain : Bool
24+
25+
fileprivate init(_ hasDomain: Bool) {
26+
self.hasDomain = hasDomain
27+
}
28+
29+
public func setEventDomain(_ eventDomain: String) -> Self {
30+
if eventDomain.isEmpty {
31+
return DefaultLoggerProvider.noopBuilderNoDomain as! Self
32+
}
33+
return DefaultLoggerProvider.noopBuilderWithDomain as! Self
34+
}
35+
36+
public func setSchemaUrl(_ schemaUrl: String) -> Self {
37+
return self
38+
}
39+
40+
public func setInstrumentationVersion(_ instrumentationVersion: String) -> Self {
41+
return self
42+
}
43+
44+
public func setIncludeTraceContext(_ includeTraceContext: Bool) -> Self {
45+
return self
46+
}
47+
48+
public func setAttributes(_ attributes: [String: AttributeValue]) -> Self {
49+
return self
50+
}
51+
52+
public func build() -> Logger {
53+
return DefaultLogger.getInstance(hasDomain)
54+
}
55+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import Foundation
7+
8+
/// Used to construct and emit events from a Logger.
9+
///
10+
/// An event is a LogRecord with attributes for `event.domain` and `event.name`.
11+
///
12+
/// Obtain an Logger.eventBuilder(name: String), add properties using the stters, and emit
13+
/// the LogRecord by calling `emit()`
14+
public protocol EventBuilder : LogRecordBuilder {
15+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import Foundation
7+
8+
public protocol LogRecordBuilder {
9+
10+
/// set the timestamp that the log was observed
11+
///
12+
/// - Parameter observed: the Date object
13+
/// - Returns: self
14+
func setObservedTimestamp (_ observed: Date) -> Self
15+
16+
/// set the span context associated with the log.
17+
///
18+
/// - Parameter context: the associated span context
19+
/// - Returns: self
20+
func setSpanContext(_ context: SpanContext) -> Self
21+
22+
/// set the severity of the log.
23+
///
24+
/// - Parameter severity: the severity level
25+
/// - Returns: self
26+
func setSeverity(_ severity: Severity) -> Self
27+
28+
/// set the body string.
29+
///
30+
/// - Parameter body: string value of the log
31+
/// - Returns: self
32+
func setBody(_ body: String) -> Self
33+
34+
/// set attributes assoicated with the log.
35+
///
36+
/// - Parameter attributes: Array of [String: AttributeValue]
37+
/// - Returns:
38+
func setAttributes(_ attributes: [String: AttributeValue]) -> Self
39+
40+
/// emits the log record.
41+
func emit()
42+
}
43+
44+

0 commit comments

Comments
 (0)