Skip to content

Commit 09490e5

Browse files
Merge pull request #2219 from DataDog/maxep/RUM-8448/benchmarks-additional-telemetry
RUM-8448 Benchmarks Additional Metrics Co-authored-by: maxep <[email protected]>
2 parents 46a05d1 + b211cbd commit 09490e5

File tree

15 files changed

+129
-12
lines changed

15 files changed

+129
-12
lines changed

BenchmarkTests/Runner/BenchmarkMeter.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ internal final class Meter: DatadogInternal.BenchmarkMeter {
6868
func gauge(metric: @autoclosure () -> String) -> DatadogInternal.BenchmarkGauge {
6969
meter.createDoubleMeasure(name: metric())
7070
}
71+
72+
func observe(metric: @autoclosure () -> String, callback: @escaping (any DatadogInternal.BenchmarkGauge) -> Void) {
73+
_ = meter.createDoubleObserver(name: metric()) { callback(DoubleObserverWrapper(observer: $0)) }
74+
}
7175
}
7276

7377
extension AnyCounterMetric<Double>: DatadogInternal.BenchmarkCounter {
@@ -81,3 +85,11 @@ extension AnyMeasureMetric<Double>: DatadogInternal.BenchmarkGauge {
8185
record(value: value, labelset: LabelSet(labels: attributes()))
8286
}
8387
}
88+
89+
private struct DoubleObserverWrapper: DatadogInternal.BenchmarkGauge {
90+
let observer: DoubleObserverMetric
91+
92+
func record(value: Double, attributes: @autoclosure () -> [String: String]) {
93+
observer.observe(value: value, labelset: LabelSet(labels: attributes()))
94+
}
95+
}

Datadog/Datadog.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,6 +1710,8 @@
17101710
D2DC4BF727F484AA00E4FB96 /* DataEncryption.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2DC4BF527F484AA00E4FB96 /* DataEncryption.swift */; };
17111711
D2DE63532A30A7CA00441A54 /* CoreRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2DE63522A30A7CA00441A54 /* CoreRegistry.swift */; };
17121712
D2DE63542A30A7CA00441A54 /* CoreRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2DE63522A30A7CA00441A54 /* CoreRegistry.swift */; };
1713+
D2E6E8FB2D8039BB00FF1398 /* BenchmarkURLSessionTaskDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E6E8FA2D8039B200FF1398 /* BenchmarkURLSessionTaskDelegate.swift */; };
1714+
D2E6E8FC2D8039BB00FF1398 /* BenchmarkURLSessionTaskDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E6E8FA2D8039B200FF1398 /* BenchmarkURLSessionTaskDelegate.swift */; };
17131715
D2EA0F462C0E1AE300CB20F8 /* SessionReplayConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EA0F452C0E1AE200CB20F8 /* SessionReplayConfiguration.swift */; };
17141716
D2EBEE1F29BA160F00B15732 /* HTTPHeadersReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 618E13A92524B8700098C6B0 /* HTTPHeadersReader.swift */; };
17151717
D2EBEE2029BA160F00B15732 /* TracePropagationHeadersWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EBEDCF29B8A02100B15732 /* TracePropagationHeadersWriter.swift */; };
@@ -3114,6 +3116,7 @@
31143116
D2DA23C9298D5C1300C6C7E6 /* UIKitMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitMocks.swift; sourceTree = "<group>"; };
31153117
D2DC4BF527F484AA00E4FB96 /* DataEncryption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataEncryption.swift; sourceTree = "<group>"; };
31163118
D2DE63522A30A7CA00441A54 /* CoreRegistry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreRegistry.swift; sourceTree = "<group>"; };
3119+
D2E6E8FA2D8039B200FF1398 /* BenchmarkURLSessionTaskDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BenchmarkURLSessionTaskDelegate.swift; sourceTree = "<group>"; };
31173120
D2E8D59728C7AB90007E5DE1 /* ContextMessageReceiverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMessageReceiverTests.swift; sourceTree = "<group>"; };
31183121
D2EA0F452C0E1AE200CB20F8 /* SessionReplayConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionReplayConfiguration.swift; sourceTree = "<group>"; };
31193122
D2EBEDCC29B893D800B15732 /* TraceID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TraceID.swift; sourceTree = "<group>"; };
@@ -5026,6 +5029,7 @@
50265029
6174D6082BFDDD1E00EC7469 /* SDKMetrics */ = {
50275030
isa = PBXGroup;
50285031
children = (
5032+
D2E6E8FA2D8039B200FF1398 /* BenchmarkURLSessionTaskDelegate.swift */,
50295033
614396712A67D74F00197326 /* BatchMetrics.swift */,
50305034
);
50315035
path = SDKMetrics;
@@ -8002,6 +8006,7 @@
80028006
D2FB1254292E0E96005B13F8 /* TrackingConsentPublisher.swift in Sources */,
80038007
61D3E0D6277B23F1008BE766 /* KronosClock.swift in Sources */,
80048008
D2A7841129A53B2F003B03BB /* File.swift in Sources */,
8009+
D2E6E8FB2D8039BB00FF1398 /* BenchmarkURLSessionTaskDelegate.swift in Sources */,
80058010
D286626E2A43487500852CE3 /* Datadog.swift in Sources */,
80068011
61F930C22BA1C41A005F0EE2 /* TLVBlockReader.swift in Sources */,
80078012
613E793B2577B6EE00DFCC17 /* DataReader.swift in Sources */,
@@ -9335,6 +9340,7 @@
93359340
D2CB6E5527C50EAE00A62B57 /* KronosNSTimer+ClosureKit.swift in Sources */,
93369341
D2CB6E6627C50EAE00A62B57 /* Reader.swift in Sources */,
93379342
D2CB6E6927C50EAE00A62B57 /* KronosDNSResolver.swift in Sources */,
9343+
D2E6E8FC2D8039BB00FF1398 /* BenchmarkURLSessionTaskDelegate.swift in Sources */,
93389344
D286626F2A43487500852CE3 /* Datadog.swift in Sources */,
93399345
61F930C32BA1C41A005F0EE2 /* TLVBlockReader.swift in Sources */,
93409346
D2A7841229A53B2F003B03BB /* File.swift in Sources */,

DatadogCore/Sources/Core/Storage/Files/File.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ internal protocol ReadableFile {
3535
/// Name of this file.
3636
var name: String { get }
3737

38+
/// Current size of this file.
39+
func size() throws -> UInt64
40+
3841
/// Creates InputStream for reading the available data from this file.
3942
func stream() throws -> InputStream
4043

DatadogCore/Sources/Core/Storage/FilesOrchestrator.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,15 @@ internal class FilesOrchestrator: FilesOrchestratorType {
8080
self.dateProvider = dateProvider
8181
self.telemetry = telemetry
8282
self.metricsData = metricsData
83+
84+
#if DD_BENCHMARK
85+
bench.meter.observe(metric: "ios.benchmark.batch_count") {[weak self] gauge in
86+
if let self {
87+
let files = try? directory.files()
88+
files.map { gauge.record($0.count, attributes: ["track": self.trackName]) }
89+
}
90+
}
91+
#endif
8392
}
8493

8594
// MARK: - `WritableFile` orchestration
@@ -211,6 +220,12 @@ internal class FilesOrchestrator: FilesOrchestratorType {
211220

212221
func delete(readableFile: ReadableFile, deletionReason: BatchDeletedMetric.RemovalReason) {
213222
do {
223+
#if DD_BENCHMARK
224+
if case .intakeCode = deletionReason {
225+
try bench.meter.counter(metric: "ios.benchmark.bytes_deleted")
226+
.increment(by: readableFile.size(), attributes: ["track": trackName])
227+
}
228+
#endif
214229
try readableFile.delete()
215230
// Decrement pending batches at each batch deletion
216231
_pendingBatches.mutate { $0 -= 1 }

DatadogCore/Sources/Core/Upload/DataUploadWorker.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ internal class DataUploadWorker: DataUploadWorkerType {
139139
batch,
140140
reason: .intakeCode(responseCode: uploadStatus.responseCode)
141141
)
142+
#if DD_BENCHMARK
143+
bench.meter.counter(metric: "ios.benchmark.upload_count")
144+
.increment(attributes: ["track": self.featureName])
145+
#endif
142146

143147
previousUploadStatus = nil
144148

DatadogCore/Sources/Core/Upload/DataUploader.swift

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,17 @@ internal final class DataUploader: DataUploaderType {
2626

2727
private let httpClient: HTTPClient
2828
private let requestBuilder: FeatureRequestBuilder
29+
/// Name of the feature this worker is performing uploads for.
30+
private let featureName: String
2931

30-
init(httpClient: HTTPClient, requestBuilder: FeatureRequestBuilder) {
32+
init(
33+
httpClient: HTTPClient,
34+
requestBuilder: FeatureRequestBuilder,
35+
featureName: String
36+
) {
3137
self.httpClient = httpClient
3238
self.requestBuilder = requestBuilder
39+
self.featureName = featureName
3340
}
3441

3542
/// Uploads data synchronously (will block current thread) and returns the upload status.
@@ -51,7 +58,13 @@ internal final class DataUploader: DataUploaderType {
5158

5259
let semaphore = DispatchSemaphore(value: 0)
5360

54-
httpClient.send(request: request) { result in
61+
#if DD_BENCHMARK
62+
let delegate: URLSessionTaskDelegate = BenchmarkURLSessionTaskDelegate(track: featureName)
63+
#else
64+
let delegate: URLSessionTaskDelegate? = nil
65+
#endif
66+
67+
httpClient.send(request: request, delegate: delegate) { result in
5568
switch result {
5669
case .success(let httpResponse):
5770
uploadStatus = DataUploadStatus(
@@ -71,6 +84,11 @@ internal final class DataUploader: DataUploaderType {
7184

7285
_ = semaphore.wait(timeout: .distantFuture)
7386

87+
#if DD_BENCHMARK
88+
bench.meter.counter(metric: "ios.benchmark.bytes_uploaded")
89+
.increment(by: request.httpBody?.count ?? 0, attributes: ["track": featureName])
90+
#endif
91+
7492
return uploadStatus ?? DataUploader.unreachableUploadStatus
7593
}
7694
}

DatadogCore/Sources/Core/Upload/FeatureUpload.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ internal struct FeatureUpload {
3030

3131
let dataUploader = DataUploader(
3232
httpClient: httpClient,
33-
requestBuilder: requestBuilder
33+
requestBuilder: requestBuilder,
34+
featureName: featureName
3435
)
3536

3637
#if canImport(UIKit)

DatadogCore/Sources/Core/Upload/HTTPClient.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ internal protocol HTTPClient {
1111
/// Sends the provided request using HTTP.
1212
/// - Parameters:
1313
/// - request: The request to be sent.
14+
/// - delegate: The task-specific delegate.
1415
/// - completion: A closure that receives a Result containing either an HTTPURLResponse or an Error.
15-
func send(request: URLRequest, completion: @escaping (Result<HTTPURLResponse, Error>) -> Void)
16+
func send(request: URLRequest, delegate: URLSessionTaskDelegate?, completion: @escaping (Result<HTTPURLResponse, Error>) -> Void)
17+
}
18+
19+
extension HTTPClient {
20+
/// Sends the provided request using HTTP.
21+
/// - Parameters:
22+
/// - request: The request to be sent.
23+
/// - completion: A closure that receives a Result containing either an HTTPURLResponse or an Error.
24+
func send(request: URLRequest, completion: @escaping (Result<HTTPURLResponse, Error>) -> Void) {
25+
self.send(request: request, delegate: nil, completion: completion)
26+
}
1627
}

DatadogCore/Sources/Core/Upload/URLSessionClient.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,13 @@ internal class URLSessionClient: HTTPClient {
3535
self.session = session
3636
}
3737

38-
func send(request: URLRequest, completion: @escaping (Result<HTTPURLResponse, Error>) -> Void) {
38+
func send(request: URLRequest, delegate: URLSessionTaskDelegate?, completion: @escaping (Result<HTTPURLResponse, Error>) -> Void) {
3939
let task = session.dataTask(with: request) { data, response, error in
4040
completion(httpClientResult(for: (data, response, error)))
4141
}
42+
if #available(iOS 15.0, tvOS 15.0, watchOS 8.0, *) {
43+
task.delegate = delegate
44+
}
4245
task.resume()
4346
}
4447
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
* Copyright 2019-Present Datadog, Inc.
5+
*/
6+
7+
#if DD_BENCHMARK
8+
9+
import Foundation
10+
import DatadogInternal
11+
12+
/// `URLSessionTaskDelegate` implementation to collect network request metrics during benchmark execution.
13+
internal final class BenchmarkURLSessionTaskDelegate: NSObject, URLSessionTaskDelegate {
14+
let track: String
15+
16+
init(track: String) {
17+
self.track = track
18+
}
19+
20+
func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
21+
bench.meter.gauge(metric: "ios.benchmark.reponse_latency")
22+
.record(metrics.taskInterval.duration, attributes: ["track": track])
23+
}
24+
}
25+
26+
#endif

0 commit comments

Comments
 (0)