-
Notifications
You must be signed in to change notification settings - Fork 155
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
Fix thread safety issue in HTTP exporters #481
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,8 @@ public func defaultOltpHttpLoggingEndpoint() -> URL { | |
public class OtlpHttpLogExporter : OtlpHttpExporterBase, LogRecordExporter { | ||
|
||
var pendingLogRecords: [ReadableLogRecord] = [] | ||
|
||
let dispatchQueue = DispatchQueue(label: "OtlpHttpLogExporter Queue") | ||
|
||
override public init(endpoint: URL = defaultOltpHttpLoggingEndpoint(), | ||
config: OtlpConfiguration = OtlpConfiguration(), | ||
useSession: URLSession? = nil, | ||
|
@@ -23,22 +24,28 @@ public class OtlpHttpLogExporter : OtlpHttpExporterBase, LogRecordExporter { | |
} | ||
|
||
public func export(logRecords: [OpenTelemetrySdk.ReadableLogRecord], explicitTimeout: TimeInterval? = nil) -> OpenTelemetrySdk.ExportResult { | ||
pendingLogRecords.append(contentsOf: logRecords) | ||
let sendingLogRecords = pendingLogRecords | ||
pendingLogRecords = [] | ||
|
||
var sendingLogRecords: [ReadableLogRecord]! | ||
dispatchQueue.sync { | ||
pendingLogRecords.append(contentsOf: logRecords) | ||
sendingLogRecords = pendingLogRecords | ||
pendingLogRecords = [] | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. instead of this you can use:
|
||
|
||
let body = Opentelemetry_Proto_Collector_Logs_V1_ExportLogsServiceRequest.with { request in | ||
request.resourceLogs = LogRecordAdapter.toProtoResourceRecordLog(logRecordList: sendingLogRecords) | ||
} | ||
|
||
var request = createRequest(body: body, endpoint: endpoint) | ||
request.timeoutInterval = min(explicitTimeout ?? TimeInterval.greatestFiniteMagnitude , config.timeout) | ||
httpClient.send(request: request) { [weak self] result in | ||
guard let self = self else { return } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is wrong, we would ideally like to know if there was an error, which now is not printing anymore |
||
switch result { | ||
case .success(_): | ||
break | ||
case .failure(let error): | ||
self?.pendingLogRecords.append(contentsOf: sendingLogRecords) | ||
self.dispatchQueue.sync { [weak self] in | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same with the |
||
self?.pendingLogRecords.append(contentsOf: sendingLogRecords) | ||
} | ||
print(error) | ||
} | ||
} | ||
|
@@ -52,7 +59,10 @@ public class OtlpHttpLogExporter : OtlpHttpExporterBase, LogRecordExporter { | |
|
||
public func flush(explicitTimeout: TimeInterval? = nil) -> ExportResult { | ||
var exporterResult: ExportResult = .success | ||
|
||
var pendingLogRecords: [ReadableLogRecord]! | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same with the |
||
dispatchQueue.sync { | ||
pendingLogRecords = self.pendingLogRecords | ||
} | ||
if !pendingLogRecords.isEmpty { | ||
let body = Opentelemetry_Proto_Collector_Logs_V1_ExportLogsServiceRequest.with { request in | ||
request.resourceLogs = LogRecordAdapter.toProtoResourceRecordLog(logRecordList: pendingLogRecords) | ||
|
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 would prefer if you imported Locks.swift file which is in other parts of the project (e.g in the sdk, but its methods are internal) and you used it instead of GCD queues like:
private let exporterLock = Lock()
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.
It appears that Lock is internal to OpenTelemetrySdk. Would you like me to make it public, or copy it to OpenTelemetryProtocolHttp?
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.
Copy in the exporter folder. Thanks.
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.
Updated.