1
1
//
2
2
// Copyright The OpenTelemetry Authors
3
3
// SPDX-License-Identifier: Apache-2.0
4
- //
4
+ //
5
5
6
6
import Foundation
7
7
import OpenTelemetryApi
8
8
9
9
public class BatchLogRecordProcessor : LogRecordProcessor {
10
-
11
-
10
+
12
11
fileprivate var worker : BatchWorker
13
-
12
+
14
13
public init ( logRecordExporter: LogRecordExporter , scheduleDelay: TimeInterval = 5 , exportTimeout: TimeInterval = 30 , maxQueueSize: Int = 2048 , maxExportBatchSize: Int = 512 , willExportCallback: ( ( inout [ ReadableLogRecord ] ) -> Void ) ? = nil ) {
15
14
worker = BatchWorker ( logRecordExporter: logRecordExporter, scheduleDelay: scheduleDelay, exportTimeout: exportTimeout, maxQueueSize: maxQueueSize, maxExportBatchSize: maxExportBatchSize, willExportCallback: willExportCallback)
16
-
15
+
17
16
worker. start ( )
18
17
}
19
-
18
+
20
19
public func onEmit( logRecord: ReadableLogRecord ) {
21
20
worker. emit ( logRecord: logRecord)
22
21
}
23
-
22
+
24
23
public func forceFlush( explicitTimeout: TimeInterval ? ) -> ExportResult {
25
24
forceFlush ( timeout: explicitTimeout)
26
25
return . success
27
26
}
28
-
27
+
29
28
public func forceFlush( timeout: TimeInterval ? = nil ) {
30
29
worker. forceFlush ( explicitTimeout: timeout)
31
30
}
32
-
33
-
31
+
32
+
34
33
public func shutdown( explicitTimeout: TimeInterval ? = nil ) -> ExportResult {
35
34
worker. cancel ( )
36
35
worker. shutdown ( explicitTimeout: explicitTimeout)
37
36
return . success
38
37
}
39
38
}
40
39
41
- private class BatchWorker : Thread {
40
+ private class BatchWorker {
41
+ var thread : Thread !
42
42
let logRecordExporter : LogRecordExporter
43
43
let scheduleDelay : TimeInterval
44
44
let maxQueueSize : Int
@@ -49,14 +49,14 @@ private class BatchWorker : Thread {
49
49
private let cond = NSCondition ( )
50
50
var logRecordList = [ ReadableLogRecord] ( )
51
51
var queue : OperationQueue
52
-
52
+
53
53
init ( logRecordExporter: LogRecordExporter ,
54
54
scheduleDelay: TimeInterval ,
55
55
exportTimeout: TimeInterval ,
56
56
maxQueueSize: Int ,
57
57
maxExportBatchSize: Int ,
58
58
willExportCallback: ( ( inout [ ReadableLogRecord ] ) -> Void ) ? ) {
59
-
59
+
60
60
self . logRecordExporter = logRecordExporter
61
61
self . scheduleDelay = scheduleDelay
62
62
self . exportTimeout = exportTimeout
@@ -67,58 +67,69 @@ private class BatchWorker : Thread {
67
67
queue = OperationQueue ( )
68
68
queue. name = " BatchWorker Queue "
69
69
queue. maxConcurrentOperationCount = 1
70
+ self . thread = Thread ( block: { [ weak self] in
71
+ self ? . main ( )
72
+ } )
73
+ }
74
+
75
+ func start( ) {
76
+ self . thread. start ( )
77
+ }
78
+
79
+ func cancel( ) {
80
+ self . thread. cancel ( )
70
81
}
71
-
82
+
72
83
func emit( logRecord: ReadableLogRecord ) {
73
84
cond. lock ( )
74
- defer { cond. unlock ( ) }
85
+ defer { cond. unlock ( ) }
75
86
if logRecordList. count == maxQueueSize {
76
87
// TODO: record a counter for dropped logs
77
88
return
78
89
}
79
-
90
+
80
91
// TODO: record a gauge for referenced logs
81
92
logRecordList. append ( logRecord)
82
93
if logRecordList. count >= halfMaxQueueSize {
83
94
cond. broadcast ( )
84
95
}
85
96
}
86
-
87
- override func main( ) {
97
+
98
+ func main( ) {
88
99
repeat {
89
100
autoreleasepool {
90
101
var logRecordsCopy : [ ReadableLogRecord ]
91
102
cond. lock ( )
92
103
if logRecordList. count < maxExportBatchSize {
93
104
repeat {
94
105
cond. wait ( until: Date ( ) . addingTimeInterval ( scheduleDelay) )
95
- } while logRecordList. isEmpty && !self . isCancelled
106
+ } while logRecordList. isEmpty && !thread . isCancelled
96
107
}
97
108
logRecordsCopy = logRecordList
98
109
logRecordList. removeAll ( )
99
110
cond. unlock ( )
100
111
self . exportBatch ( logRecordList: logRecordsCopy, explicitTimeout: exportTimeout)
101
112
}
102
- } while !self . isCancelled
113
+ } while !thread . isCancelled
103
114
}
104
-
115
+
105
116
public func forceFlush( explicitTimeout: TimeInterval ? = nil ) {
106
117
var logRecordsCopy : [ ReadableLogRecord ]
107
118
cond. lock ( )
108
119
logRecordsCopy = logRecordList
109
120
logRecordList. removeAll ( )
110
121
cond. unlock ( )
111
-
122
+
112
123
exportBatch ( logRecordList: logRecordsCopy, explicitTimeout: explicitTimeout)
113
124
}
114
-
115
-
125
+
126
+
116
127
public func shutdown( explicitTimeout: TimeInterval ? ) {
117
128
let timeout = min ( explicitTimeout ?? TimeInterval . greatestFiniteMagnitude, exportTimeout)
118
129
forceFlush ( explicitTimeout: timeout)
119
130
_ = logRecordExporter. shutdown ( explicitTimeout: timeout)
120
131
}
121
-
132
+
122
133
private func exportBatch( logRecordList: [ ReadableLogRecord ] , explicitTimeout: TimeInterval ? = nil ) {
123
134
let exportOperation = BlockOperation { [ weak self] in
124
135
self ? . exportAction ( logRecordList : logRecordList, explicitTimeout: explicitTimeout)
@@ -132,7 +143,7 @@ private class BatchWorker : Thread {
132
143
queue. waitUntilAllOperationsAreFinished ( )
133
144
timeoutTimer. cancel ( )
134
145
}
135
-
146
+
136
147
private func exportAction( logRecordList: [ ReadableLogRecord ] , explicitTimeout: TimeInterval ? = nil ) {
137
148
stride ( from: 0 , to: logRecordList. endIndex, by: maxExportBatchSize) . forEach {
138
149
var logRecordToExport = logRecordList [ $0 ..< min ( $0 + maxExportBatchSize, logRecordList. count) ] . map { $0}
0 commit comments