Skip to content

Commit a6907e6

Browse files
committed
Revert "Report endpoint_payload.dropped when the orchestrator removes a stored payload"
This reverts commit 5441bb5.
1 parent 5441bb5 commit a6907e6

5 files changed

Lines changed: 31 additions & 109 deletions

File tree

Sources/DatadogSDKTesting/Telemetry/ARCHITECTURE.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,10 @@ methods are the protocol requirements; no-observer convenience methods are
144144

145145
### Gathered (3776)
146146
- **`endpoint_payload.*`**`requests`, `requests_ms`, `bytes` (request size),
147-
`requests_errors`, `events_count`, `events_serialization_ms`, `dropped`, tagged
147+
`requests_errors`, `events_count`, `events_serialization_ms`, tagged
148148
`test_cycle` (spans) / `code_coverage` (coverage). Wired in
149149
`DDTracer.endpointPayloadObservers(...)`. This family has **no feature call
150-
site** — the observers are its only home. `dropped` is reported from
151-
`FilesOrchestrator` (via its `onDrop` callback → `UploadObserver.uploadDropped`)
152-
when a stored batch is removed without being uploaded: too old
153-
(`maxFileAgeForRead`) or purged to keep the directory under `maxDirectorySize`.
154-
Successful upload deletions (`delete(readableFile:)`) are **not** drops.
150+
site** — the observers are its only home.
155151
- **API request families**`git_requests.{settings,search_commits,objects_pack}`
156152
(+ `_ms`, `_errors`, and `objects_pack_bytes`), `itr_skippable_tests.{request,
157153
request_ms,request_errors,response_bytes}`, `known_tests.{request,request_ms,
@@ -168,7 +164,12 @@ methods are the protocol requirements; no-observer convenience methods are
168164
- `itr_skippable_tests.response_tests` / `response_suites`
169165
- `known_tests.response_tests`
170166
- `test_management_tests.response_tests`
171-
2. **Local feature metrics** — emitted directly via `SessionConfig.telemetry` /
167+
2. **`endpoint_payload.dropped`** — the `UploadObserver.uploadDropped` hook exists
168+
but the worker has no retry-exhaustion drop today; failed batches stay on disk
169+
and are age-purged by `FilesOrchestrator`. Wire `dropped` from the purge path
170+
(or add an explicit drop) — see `DDTracer.endpointPayloadObservers` where
171+
`onDropped` is already mapped to `endpointPayload.dropped`.
172+
3. **Local feature metrics** — emitted directly via `SessionConfig.telemetry` /
172173
the feature's injected `Telemetry`, at the feature instrumentation sites:
173174
- `events.created` / `events.finished` (+ all their tags: `event_type`,
174175
`test_framework`, `is_new`, `is_modified`, `is_retry`, `retry_reason`,
@@ -181,9 +182,9 @@ methods are the protocol requirements; no-observer convenience methods are
181182
- `git.commit_sha_match` / `git.commit_sha_discrepancy` — git info providers.
182183
- `itr.skipped` / `itr.unskippable` / `itr.forced_run``TestImpactAnalysis`.
183184
- `code_coverage.{started,finished,is_empty,errors,files}` — coverage feature.
184-
3. **`impacted_tests_detection.*`** — no feature/API exists yet; instruments are
185+
4. **`impacted_tests_detection.*`** — no feature/API exists yet; instruments are
185186
defined but unused.
186-
4. **`error_type` granularity**`Telemetry.errorType(statusCode:)` maps `nil`
187+
5. **`error_type` granularity**`Telemetry.errorType(statusCode:)` maps `nil`
187188
status to `.network`; it cannot distinguish `timeout` from `network` without
188189
the underlying `URLError`. Refine if needed.
189190

Sources/EventsExporter/CoverageExporter/CoverageExporter.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,10 @@ internal final class CoverageExporter: CoverageExporterType {
4040
observers: ExporterObservers.Feature = .init()) throws {
4141
self.configuration = config
4242

43-
let uploadObserver = observers.upload
4443
let filesOrchestrator = FilesOrchestrator(
4544
directory: try storage.createSubdirectory(path: "v1"),
4645
performance: PerformancePreset.instantDataDelivery,
47-
dateProvider: SystemDateProvider(),
48-
onDrop: uploadObserver.map { obs in { obs.uploadDropped(payloadBytes: $0) } }
46+
dateProvider: SystemDateProvider()
4947
)
5048

5149
let encoder = api.encoder

Sources/EventsExporter/Persistence/FilesOrchestrator.swift

Lines changed: 19 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -148,55 +148,47 @@ internal final class FilesOrchestrator: FilesOrchestratorType {
148148

149149
// MARK: - Reader
150150

151-
/// Reader results paired with the byte sizes of any files dropped
152-
/// (deleted for exceeding `maxFileAgeForRead`) during the scan. The
153-
/// caller reports the drops *outside* the state lock.
154151
func oldestReadableFile(directory: borrowing Directory,
155152
performance: borrowing StoragePerformancePreset,
156-
dateProvider: borrowing DateProvider) throws -> (file: ReadableFile?, droppedBytes: [Int])
153+
dateProvider: borrowing DateProvider) throws -> ReadableFile?
157154
{
158-
let (infos, droppedBytes) = try fileInfos(directory: directory,
159-
performance: performance,
160-
dateProvider: dateProvider)
161-
guard let oldest = infos.first else { return (nil, droppedBytes) }
155+
guard let oldest = try fileInfos(directory: directory,
156+
performance: performance,
157+
dateProvider: dateProvider).first
158+
else { return nil }
162159
let age = dateProvider.currentDate().timeIntervalSince(oldest.creationDate)
163-
return (age >= performance.minFileAgeForRead ? oldest.file : nil, droppedBytes)
160+
return age >= performance.minFileAgeForRead ? oldest.file : nil
164161
}
165162

166163
func allReadableFiles(directory: borrowing Directory,
167164
performance: borrowing StoragePerformancePreset,
168-
dateProvider: borrowing DateProvider) throws -> (files: [ReadableFile], droppedBytes: [Int])
165+
dateProvider: borrowing DateProvider) throws -> [ReadableFile]
169166
{
170-
let (infos, droppedBytes) = try fileInfos(directory: directory,
171-
performance: performance,
172-
dateProvider: dateProvider)
173-
return (infos.map { $0.file }, droppedBytes)
167+
try fileInfos(directory: directory,
168+
performance: performance,
169+
dateProvider: dateProvider).map { $0.file }
174170
}
175171

176172
private func fileInfos(directory: borrowing Directory,
177173
performance: borrowing StoragePerformancePreset,
178-
dateProvider: borrowing DateProvider) throws -> (files: [FileInfo], droppedBytes: [Int])
174+
dateProvider: borrowing DateProvider) throws -> [FileInfo]
179175
{
180176
let allFiles = try directory.files()
181177
.filter { !activeWrites.contains($0.name) }
182178
.map { FileInfo(file: $0) }
183179

184180
var readableFiles: [FileInfo] = []
185181
readableFiles.reserveCapacity(allFiles.count)
186-
var droppedBytes: [Int] = []
187182
for info in allFiles {
188183
let fileAge = dateProvider.currentDate().timeIntervalSince(info.creationDate)
189184
if fileAge > performance.maxFileAgeForRead {
190-
// Too old to ever upload — count it as a dropped payload.
191-
let size = (try? info.file.size()).map(Int.init) ?? 0
192185
try info.file.delete()
193-
droppedBytes.append(size)
194186
} else {
195187
readableFiles.append(info)
196188
}
197189
}
198190

199-
return (readableFiles.sorted(), droppedBytes)
191+
return readableFiles.sorted()
200192
}
201193
}
202194

@@ -208,20 +200,14 @@ internal final class FilesOrchestrator: FilesOrchestratorType {
208200
private let directory: Directory
209201
private let dateProvider: DateProvider
210202
private let performance: StoragePerformancePreset
211-
/// Invoked (outside the state lock) with the byte size of each file removed
212-
/// without being uploaded — too old (`maxFileAgeForRead`) or purged to keep
213-
/// the directory under `maxDirectorySize`. Wired to `endpoint_payload.dropped`.
214-
private let onDrop: (@Sendable (Int) -> Void)?
215203

216204
init(directory: Directory,
217205
performance: StoragePerformancePreset,
218-
dateProvider: DateProvider,
219-
onDrop: (@Sendable (Int) -> Void)? = nil)
206+
dateProvider: DateProvider)
220207
{
221208
self.directory = directory
222209
self.dateProvider = dateProvider
223210
self.performance = performance
224-
self.onDrop = onDrop
225211
self.state = Synced(.init())
226212
}
227213

@@ -259,30 +245,15 @@ internal final class FilesOrchestrator: FilesOrchestratorType {
259245
// MARK: - `ReadableFile` orchestration
260246

261247
func getReadableFile() throws -> ReadableFile? {
262-
let (file, droppedBytes) = try state.use {
263-
try $0.oldestReadableFile(directory: directory,
264-
performance: performance,
265-
dateProvider: dateProvider)
266-
}
267-
reportDrops(droppedBytes)
268-
return file
248+
try state.use { try $0.oldestReadableFile(directory: directory,
249+
performance: performance,
250+
dateProvider: dateProvider) }
269251
}
270252

271253
func getAllReadableFiles() throws -> [ReadableFile] {
272-
let (files, droppedBytes) = try state.use {
273-
try $0.allReadableFiles(directory: directory,
274-
performance: performance,
275-
dateProvider: dateProvider)
276-
}
277-
reportDrops(droppedBytes)
278-
return files
279-
}
280-
281-
/// Report dropped-payload sizes. Called outside the state lock so the
282-
/// observer (which may touch its own locks) can't contend with file ops.
283-
private func reportDrops(_ droppedBytes: [Int]) {
284-
guard let onDrop else { return }
285-
droppedBytes.forEach(onDrop)
254+
try state.use { try $0.allReadableFiles(directory: directory,
255+
performance: performance,
256+
dateProvider: dateProvider) }
286257
}
287258

288259
func delete(readableFile: ReadableFile) throws {
@@ -301,10 +272,7 @@ internal final class FilesOrchestrator: FilesOrchestratorType {
301272
.compactMap { (info) -> FileInfo? in
302273
let fileAge = dateProvider.currentDate().timeIntervalSince(info.creationDate)
303274
if fileAge > performance.maxFileAgeForRead {
304-
// Too old to ever upload — count it as a dropped payload.
305-
let size = (try? info.file.size()).map(Int.init) ?? 0
306275
try info.file.delete()
307-
onDrop?(size)
308276
return nil
309277
}
310278
return info
@@ -318,8 +286,6 @@ internal final class FilesOrchestrator: FilesOrchestratorType {
318286
let fileWithSize = filesWithSize.removeFirst()
319287
try fileWithSize.file.delete()
320288
sizeFreed += fileWithSize.size
321-
// Purged to stay under the directory size limit — also a drop.
322-
onDrop?(Int(fileWithSize.size))
323289
}
324290
}
325291
}

Sources/EventsExporter/Spans/SpansExporter.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,10 @@ internal final class SpansExporter: SpanExporter {
1717
observers: ExporterObservers.Feature = .init()) throws {
1818
self.configuration = config
1919

20-
let uploadObserver = observers.upload
2120
let filesOrchestrator = FilesOrchestrator(
2221
directory: try storage.createSubdirectory(path: "v1"),
2322
performance: configuration.performancePreset,
24-
dateProvider: SystemDateProvider(),
25-
onDrop: uploadObserver.map { obs in { obs.uploadDropped(payloadBytes: $0) } }
23+
dateProvider: SystemDateProvider()
2624
)
2725

2826
var metadata = SpanSanitizer().sanitize(metadata: config.metadata)

Tests/EventsExporter/Persistence/FilesOrchestratorTests.swift

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -223,47 +223,6 @@ class FilesOrchestratorTests: XCTestCase {
223223
XCTAssertEqual(try temporaryDirectory.files().count, 0)
224224
}
225225

226-
func testGivenFileTooOld_whenScanned_itReportsDropWithSize() throws {
227-
final class Box: @unchecked Sendable { var sizes: [Int] = [] }
228-
let box = Box()
229-
let dateProvider = RelativeDateProvider()
230-
let orchestrator = FilesOrchestrator(
231-
directory: temporaryDirectory,
232-
performance: performance,
233-
dateProvider: dateProvider,
234-
onDrop: { box.sizes.append($0) }
235-
)
236-
let file = try temporaryDirectory.createFile(named: dateProvider.currentDate().toFileName)
237-
try file.append(data: Data("hello".utf8)) // 5 bytes
238-
239-
dateProvider.advance(bySeconds: 2 * performance.maxFileAgeForRead)
240-
241-
// Scanning for a readable file finds it too old, deletes it, and reports
242-
// the drop with the file's size.
243-
XCTAssertNil(try orchestrator.getReadableFile())
244-
XCTAssertEqual(try temporaryDirectory.files().count, 0)
245-
XCTAssertEqual(box.sizes, [5])
246-
}
247-
248-
func testGivenSuccessfulRead_whenDeleted_itDoesNotReportDrop() throws {
249-
final class Box: @unchecked Sendable { var sizes: [Int] = [] }
250-
let box = Box()
251-
let dateProvider = RelativeDateProvider()
252-
let orchestrator = FilesOrchestrator(
253-
directory: temporaryDirectory,
254-
performance: performance,
255-
dateProvider: dateProvider,
256-
onDrop: { box.sizes.append($0) }
257-
)
258-
_ = try temporaryDirectory.createFile(named: dateProvider.currentDate().toFileName)
259-
dateProvider.advance(bySeconds: 1 + performance.minFileAgeForRead)
260-
261-
let readableFile = try orchestrator.getReadableFile().unwrapOrThrow()
262-
try orchestrator.delete(readableFile: readableFile) // marked-as-read, not a drop
263-
264-
XCTAssertEqual(box.sizes, [], "Successful upload deletion must not be reported as a drop")
265-
}
266-
267226
func testItDeletesReadableFile() throws {
268227
let dateProvider = RelativeDateProvider()
269228
let orchestrator = configureOrchestrator(using: dateProvider)

0 commit comments

Comments
 (0)