Sources/OTSwift/ActivityContextManager.swift (65 lines of code) (raw):

/* * Copyright The OpenTelemetry Authors * SPDX-License-Identifier: Apache-2.0 */ import Foundation import os.activity // Bridging Obj-C variabled defined as c-macroses. See `activity.h` header. private let OS_ACTIVITY_CURRENT = unsafeBitCast(dlsym(UnsafeMutableRawPointer(bitPattern: -2), "_os_activity_current"), to: os_activity_t.self) @_silgen_name("_os_activity_create") private func _os_activity_create(_ dso: UnsafeRawPointer?, _ description: UnsafePointer<Int8>, _ parent: Unmanaged<AnyObject>?, _ flags: os_activity_flag_t) -> AnyObject! @objc public class ActivityContextManager: NSObject { static let instance = ActivityContextManager() let rlock = NSRecursiveLock() class ScopeElement { init(scope: os_activity_scope_state_s) { self.scope = scope } var scope: os_activity_scope_state_s } var objectScope = NSMapTable<AnyObject, ScopeElement>(keyOptions: .weakMemory, valueOptions: .strongMemory) var contextMap = [os_activity_id_t: [String: AnyObject]]() @objc public func getCurrentContextValue(forKey key: String) -> AnyObject? { var parentIdent: os_activity_id_t = 0 let activityIdent = os_activity_get_identifier(OS_ACTIVITY_CURRENT, &parentIdent) var contextValue: AnyObject? rlock.lock() guard let context = contextMap[activityIdent] ?? contextMap[parentIdent] else { rlock.unlock() return nil } contextValue = context[key] rlock.unlock() return contextValue } @objc public func setCurrentContextValue(forKey key: String, value: AnyObject) { var parentIdent: os_activity_id_t = 0 var activityIdent = os_activity_get_identifier(OS_ACTIVITY_CURRENT, &parentIdent) rlock.lock() if contextMap[activityIdent] == nil || contextMap[activityIdent]?[key] != nil { var scope: os_activity_scope_state_s (activityIdent, scope) = createActivityContext() contextMap[activityIdent] = [String: AnyObject]() objectScope.setObject(ScopeElement(scope: scope), forKey: value) } contextMap[activityIdent]?[key] = value rlock.unlock() } func createActivityContext() -> (os_activity_id_t, os_activity_scope_state_s) { let dso = UnsafeMutableRawPointer(mutating: #dsohandle) let activity = _os_activity_create(dso, "sls_activity_context", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT) let currentActivityId = os_activity_get_identifier(activity, nil) var activityState = os_activity_scope_state_s() os_activity_scope_enter(activity, &activityState) return (currentActivityId, activityState) } @objc public func removeContextValue(forKey key: String, value: AnyObject) { if let scope = objectScope.object(forKey: value) { var scope = scope.scope os_activity_scope_leave(&scope) objectScope.removeObject(forKey: value) } } }