apple_kit

Apple-native services for Radroots iOS and macOS apps
git clone https://radroots.dev/git/apple_kit.git
Log | Files | Refs | README

RadrootsAppleLoggerTelemetryTests.swift (4220B)


      1 import Foundation
      2 import Testing
      3 @testable import RadrootsKit
      4 
      5 @Test func appleLoggerTelemetryEmitsRedactedBoundedRecords() async throws {
      6     let probe = RadrootsAppleLoggerTelemetryProbe()
      7     let telemetry = RadrootsAppleLoggerTelemetry(
      8         subsystem: " org.radroots.field ios ",
      9         adapters: RadrootsAppleLoggerTelemetryAdapters(emit: probe.emit),
     10         maximumRenderedMessageLength: 220
     11     )
     12     let event = try RadrootsTelemetryEvent(
     13         name: "field_ios.identity.import",
     14         category: "field_ios",
     15         level: .error,
     16         message: "imported nsec1secret",
     17         fields: [
     18             try .string("relay_light", "red"),
     19             try .string("selected_secret_key_name", "field identity")
     20         ],
     21         occurredAt: Date(timeIntervalSince1970: 10)
     22     )
     23 
     24     await telemetry.record(event)
     25 
     26     let record = try #require(probe.records.first)
     27     #expect(record.subsystem == "org.radroots.field_ios")
     28     #expect(record.category == "field_ios")
     29     #expect(record.level == .error)
     30     #expect(record.renderedMessage.contains("\"event\":\"field_ios.identity.import\""))
     31     #expect(record.renderedMessage.contains("\"message\":\"[redacted]\""))
     32     #expect(record.renderedMessage.contains("\"selected_secret_key_name\":\"[redacted]\""))
     33     #expect(!record.renderedMessage.contains("nsec1secret"))
     34     #expect(!record.renderedMessage.contains("field identity"))
     35     #expect(record.renderedMessage.count <= 220)
     36 }
     37 
     38 @Test func appleLoggerTelemetrySanitizesSubsystemAndCategory() async throws {
     39     #expect(RadrootsAppleLoggerTelemetry.normalizedSubsystem(" Field iOS / Local ") == "Field_iOS_Local")
     40     #expect(RadrootsAppleLoggerTelemetry.normalizedSubsystem("    ") == "org.radroots.apple_kit")
     41     #expect(RadrootsAppleLoggerTelemetry.normalizedCategory(" relay/status ") == "relay_status")
     42     #expect(RadrootsAppleLoggerTelemetry.normalizedCategory(" -- ") == "app")
     43 }
     44 
     45 @Test func appleLoggerTelemetryMapsLevelsToOsLogTypes() {
     46     #expect(RadrootsAppleTelemetryLogRecord(
     47         subsystem: "org.radroots.tests",
     48         category: "tests",
     49         level: .trace,
     50         renderedMessage: "{}"
     51     ).osLogType == .debug)
     52     #expect(RadrootsAppleTelemetryLogRecord(
     53         subsystem: "org.radroots.tests",
     54         category: "tests",
     55         level: .info,
     56         renderedMessage: "{}"
     57     ).osLogType == .info)
     58     #expect(RadrootsAppleTelemetryLogRecord(
     59         subsystem: "org.radroots.tests",
     60         category: "tests",
     61         level: .warning,
     62         renderedMessage: "{}"
     63     ).osLogType == .default)
     64     #expect(RadrootsAppleTelemetryLogRecord(
     65         subsystem: "org.radroots.tests",
     66         category: "tests",
     67         level: .error,
     68         renderedMessage: "{}"
     69     ).osLogType == .error)
     70     #expect(RadrootsAppleTelemetryLogRecord(
     71         subsystem: "org.radroots.tests",
     72         category: "tests",
     73         level: .critical,
     74         renderedMessage: "{}"
     75     ).osLogType == .fault)
     76 }
     77 
     78 @Test func appleLoggerTelemetryRendersSortedPayloads() throws {
     79     let event = try RadrootsTelemetryEvent(
     80         name: "field_ios.relay.status",
     81         category: "field_ios",
     82         level: .notice,
     83         fields: [
     84             try .integer("connecting_count", 1),
     85             try .integer("connected_count", 2)
     86         ],
     87         occurredAt: Date(timeIntervalSince1970: 1)
     88     )
     89 
     90     let rendered = RadrootsAppleLoggerTelemetry.renderedMessage(for: event)
     91 
     92     #expect(rendered.contains("\"category\":\"field_ios\""))
     93     #expect(rendered.contains("\"connected_count\":\"2\""))
     94     #expect(rendered.contains("\"connecting_count\":\"1\""))
     95     #expect(rendered.contains("\"event\":\"field_ios.relay.status\""))
     96     #expect(rendered.contains("\"level\":\"notice\""))
     97     #expect(rendered.contains("\"occurred_at_unix_ms\":1000"))
     98 }
     99 
    100 private final class RadrootsAppleLoggerTelemetryProbe: @unchecked Sendable {
    101     private let lock = NSLock()
    102     private var recordsValue: [RadrootsAppleTelemetryLogRecord] = []
    103 
    104     func emit(_ record: RadrootsAppleTelemetryLogRecord) {
    105         lock.withLock {
    106             recordsValue.append(record)
    107         }
    108     }
    109 
    110     var records: [RadrootsAppleTelemetryLogRecord] {
    111         lock.withLock {
    112             recordsValue
    113         }
    114     }
    115 }