-
Notifications
You must be signed in to change notification settings - Fork 265
feat: [SDK-5156] wire named events into the log pipeline on iOS #1732
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
nan-li
wants to merge
8
commits into
nan/bump-kmp-submodule
Choose a base branch
from
nan/sdk-5156
base: nan/bump-kmp-submodule
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
784fe44
feat: [SDK-5156] wire named events into the log pipeline on iOS
nan-li c6e2a70
chore: [SDK-5156] tighten the event recorder comments and say remote …
nan-li 88d0e28
fix: [SDK-5156] detach only what this logger attached, and harden the…
nan-li b2884e1
refactor: [SDK-5156] rename the event recorder types to Observability…
nan-li 07da474
chore: [SDK-5156] pin the KMP submodule to the flag key without _enabled
nan-li 2158c40
refactor: [SDK-5156] answer flag lookups instead of gating events
nan-li f95e74a
chore: [SDK-5156] pin the KMP submodule to the reset fix
nan-li d1e9989
refactor: [SDK-5156] name the console logger for what it does
nan-li File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Submodule OneSignal-KMP-SDK
updated
12 files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Logging/OSObservabilityEventRecorder.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| /* | ||
| Modified MIT License | ||
|
|
||
| Copyright 2026 OneSignal | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
|
|
||
| 1. The above copyright notice and this permission notice shall be included in | ||
| all copies or substantial portions of the Software. | ||
|
|
||
| 2. All copies of substantial portions of the Software may only be used in connection | ||
| with services provided by OneSignal. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| THE SOFTWARE. | ||
| */ | ||
|
|
||
| import Foundation | ||
| import OneSignalCore | ||
| @_implementationOnly import OneSignalKMP | ||
|
|
||
| /// Mirrors the KMP `ObservabilityEvent` catalog so a call site can name an event without seeing KMP | ||
| /// types, which this module imports implementation-only. | ||
| @_spi(OneSignalInternal) | ||
| public enum OSObservabilityEvent: CaseIterable { | ||
| /// Temporary: comes out once its usage question is answered. | ||
| case deviceGesture | ||
|
|
||
| /// The `event.name` of the KMP entry, so a test can check the mirror against the catalog. | ||
| var eventName: String { | ||
| kmpEvent.eventName | ||
| } | ||
| } | ||
|
|
||
| /// The producer-facing contract, so a call site can take a spy in tests. | ||
| @_spi(OneSignalInternal) | ||
| public protocol OSObservabilityEventRecorderProtocol: AnyObject { | ||
| /// Never throws or blocks. Drops when the event's flag is off or the per-process cap is | ||
| /// reached; queues, bounded, until remote telemetry is attached. | ||
| func record(event: OSObservabilityEvent, attributes: [String: String]) | ||
| } | ||
|
|
||
| /// The attach side, driven by `OSRemoteLogger`. Internal because the telemetry is a KMP type. | ||
| protocol OSObservabilityEventRecorderAttaching: AnyObject { | ||
| func attach(_ telemetry: ILogTelemetry) | ||
|
|
||
| /// Ignored unless `telemetry` is the attached one, so a logger that lost the install race | ||
| /// cannot detach the winner. | ||
| func detach(_ telemetry: ILogTelemetry) | ||
| } | ||
|
|
||
| /// Wraps the shared KMP recorder, which owns the flag check, the pre-attach queue and the | ||
| /// per-process cap. Events ride the remote logger's telemetry, so they share the crash gate | ||
| /// rather than the severity filter. | ||
| @_spi(OneSignalInternal) | ||
| public final class OSObservabilityEventRecorder: OSObservabilityEventRecorderProtocol, OSObservabilityEventRecorderAttaching { | ||
| public static let shared = OSObservabilityEventRecorder(isFeatureEnabled: featureIsEnabledIfInitialized) | ||
|
|
||
| private let recorder: IObservabilityEventRecorder | ||
|
|
||
| /// - Parameter isFeatureEnabled: the feature-manager read for a catalog flag key. | ||
| init(isFeatureEnabled: @escaping (String) -> Bool) { | ||
| // Console-only logger: `attach` runs under the remote logger's lifecycle lock, and | ||
| // `OneSignalLog` reaches app listeners synchronously, so a listener that re-enters the | ||
| // SDK would deadlock on that lock. | ||
| recorder = LoggerFactory.shared.createObservabilityEventRecorder( | ||
| flags: OSFeatureFlagReader(isFeatureEnabled: isFeatureEnabled), | ||
| logger: OSConsoleLogger() | ||
| ) | ||
| } | ||
|
|
||
| /// Never constructs the feature manager: first touch latches every APP_STARTUP flag from | ||
| /// whatever storage returns, and a record can arrive from any thread at any time. Off until | ||
| /// the manager exists, which is also the documented state before the first flags fetch. | ||
| static func featureIsEnabledIfInitialized(_ key: String) -> Bool { | ||
| OSFeatureManager.enabledFeatureKeysIfInitialized().contains(key) | ||
| } | ||
|
|
||
| public func record(event: OSObservabilityEvent, attributes: [String: String]) { | ||
| recorder.record(event: event.kmpEvent, attributes: attributes) | ||
| } | ||
|
|
||
| /// Drops whatever an earlier app id queued; called beside the other app-id-change resets. | ||
| public func reset() { | ||
| recorder.reset() | ||
| } | ||
|
|
||
| func attach(_ telemetry: ILogTelemetry) { | ||
| recorder.attach(telemetry: telemetry) | ||
| } | ||
|
|
||
| func detach(_ telemetry: ILogTelemetry) { | ||
| recorder.detach(telemetry: telemetry) | ||
| } | ||
| } | ||
|
|
||
| /// Answers the KMP recorder's flag lookups; each event's own gate decides which flag to ask about. | ||
| private final class OSFeatureFlagReader: IFeatureFlagReader { | ||
| private let isFeatureEnabled: (String) -> Bool | ||
|
|
||
| init(isFeatureEnabled: @escaping (String) -> Bool) { | ||
| self.isFeatureEnabled = isFeatureEnabled | ||
| } | ||
|
|
||
| func isEnabled(flag: FeatureFlag) -> Bool { | ||
| isFeatureEnabled(flag.key) | ||
| } | ||
| } | ||
|
|
||
| private extension OSObservabilityEvent { | ||
| var kmpEvent: ObservabilityEvent { | ||
| switch self { | ||
| case .deviceGesture: | ||
| return .deviceGesture | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.