From 828351a8fb8d5ba38bfe60aa63d2317f473e2ae2 Mon Sep 17 00:00:00 2001 From: Fedor Korotkov Date: Thu, 15 Dec 2022 16:53:34 -0500 Subject: [PATCH] Report pull metrics to Sentry (#354) * Report GC events to Sentry * Formatting * Use transactions for measuring pull duration on cache miss * Fixed linting * Explicitly enable capturing of failed requests * Allow customizing tracesSampleRate * bindToScope * Measure compressed disk size * Don't capture GC events --- Sources/tart/Commands/Prune.swift | 3 +++ Sources/tart/Root.swift | 11 +++++++++++ Sources/tart/VMDirectory+OCI.swift | 2 ++ Sources/tart/VMStorageOCI.swift | 4 ++++ 4 files changed, 20 insertions(+) diff --git a/Sources/tart/Commands/Prune.swift b/Sources/tart/Commands/Prune.swift index ad4f7f1..cdcc6c5 100644 --- a/Sources/tart/Commands/Prune.swift +++ b/Sources/tart/Commands/Prune.swift @@ -1,5 +1,6 @@ import ArgumentParser import Dispatch +import Sentry import SwiftUI import SwiftDate @@ -103,5 +104,7 @@ struct Prune: AsyncParsableCommand { } puppy.info("reclaimed \(cacheReclaimedBytes) bytes") + + SentrySDK.span?.setMeasurement(name: "gc_disk_reclaimed", value: cacheReclaimedBytes as NSNumber, unit: MeasurementUnitInformation.byte); } } diff --git a/Sources/tart/Root.swift b/Sources/tart/Root.swift index c5af631..1df18bb 100644 --- a/Sources/tart/Root.swift +++ b/Sources/tart/Root.swift @@ -39,6 +39,17 @@ struct Root: AsyncParsableCommand { SentrySDK.start { options in options.dsn = dsn options.releaseName = CI.release + options.tracesSampleRate = Float( + ProcessInfo.processInfo.environment["SENTRY_TRACES_SAMPLE_RATE"] ?? "1.0" + ) as NSNumber? + + // By default only 5XX are captured + // Let's capture everything but 401 (unauthorized) + options.enableCaptureFailedRequests = true + options.failedRequestStatusCodes = [ + HttpStatusCodeRange(min: 400, max: 400), + HttpStatusCodeRange(min: 402, max: 599) + ] } } defer { SentrySDK.flush(timeout: 2.seconds.timeInterval) } diff --git a/Sources/tart/VMDirectory+OCI.swift b/Sources/tart/VMDirectory+OCI.swift index a29fc45..7401176 100644 --- a/Sources/tart/VMDirectory+OCI.swift +++ b/Sources/tart/VMDirectory+OCI.swift @@ -1,5 +1,6 @@ import Foundation import Compression +import Sentry enum OCIError: Error { case ShouldBeExactlyOneLayer @@ -77,6 +78,7 @@ extension VMDirectory { } try filter.finalize() try disk.close() + SentrySDK.span?.setMeasurement(name: "compressed_disk_size", value: diskCompressedSize as NSNumber, unit: MeasurementUnitInformation.byte); // Pull VM's NVRAM file layer and store it in an NVRAM file defaultLogger.appendNewLine("pulling NVRAM...") diff --git a/Sources/tart/VMStorageOCI.swift b/Sources/tart/VMStorageOCI.swift index be26ec2..0d89bf6 100644 --- a/Sources/tart/VMStorageOCI.swift +++ b/Sources/tart/VMStorageOCI.swift @@ -1,4 +1,5 @@ import Foundation +import Sentry class VMStorageOCI: PrunableStorage { let baseURL = try! Config().tartCacheDir.appendingPathComponent("OCIs", isDirectory: true) @@ -148,6 +149,7 @@ class VMStorageOCI: PrunableStorage { } if !exists(digestName) { + let transaction = SentrySDK.startTransaction(name: name.description, operation: "pull", bindToScope: true) let tmpVMDir = try VMDirectory.temporary() // Lock the temporary VM directory to prevent it's garbage collection @@ -182,7 +184,9 @@ class VMStorageOCI: PrunableStorage { try await withTaskCancellationHandler(operation: { try await tmpVMDir.pullFromRegistry(registry: registry, manifest: manifest) try move(digestName, from: tmpVMDir) + transaction.finish() }, onCancel: { + transaction.finish(status: SentrySpanStatus.cancelled) try? FileManager.default.removeItem(at: tmpVMDir.baseURL) }) } else {