Skip to content

Commit 8e0a9df

Browse files
authored
Merge pull request #1576 from OneSignal/jwt/add_log_listener
jwt(feat): add public log listener methods
2 parents 7b2a899 + 8102b71 commit 8e0a9df

File tree

11 files changed

+373
-5
lines changed

11 files changed

+373
-5
lines changed

iOS_SDK/OneSignalDevApp/OneSignalDevApp/AppDelegate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#import <UIKit/UIKit.h>
3232
#import <OneSignalFramework/OneSignalFramework.h>
3333

34-
@interface AppDelegate : UIResponder <UIApplicationDelegate, OSNotificationPermissionObserver, OSInAppMessageLifecycleListener, OSPushSubscriptionObserver, OSNotificationLifecycleListener, OSInAppMessageClickListener, OSNotificationClickListener, OSUserStateObserver, OSUserJwtInvalidatedListener>
34+
@interface AppDelegate : UIResponder <UIApplicationDelegate, OSNotificationPermissionObserver, OSInAppMessageLifecycleListener, OSPushSubscriptionObserver, OSNotificationLifecycleListener, OSInAppMessageClickListener, OSNotificationClickListener, OSUserStateObserver, OSUserJwtInvalidatedListener, OSLogListener>
3535

3636
@property (strong, nonatomic) UIWindow *window;
3737

iOS_SDK/OneSignalDevApp/OneSignalDevApp/AppDelegate.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
5555
// [FIRApp configure];
5656

5757
NSLog(@"Bundle URL: %@", [[NSBundle mainBundle] bundleURL]);
58+
// Uncomment to test LogListener
59+
// [OneSignal.Debug addLogListener:self];
5860
[OneSignal.Debug setLogLevel:ONE_S_LL_VERBOSE];
5961
[OneSignal.Debug setAlertLevel:ONE_S_LL_NONE];
6062

@@ -203,4 +205,8 @@ - (void)application:(UIApplication *)application
203205
completionHandler(UIBackgroundFetchResultNoData);
204206
}
205207

208+
- (void)onLogEvent:(OneSignalLogEvent * _Nonnull)event {
209+
NSLog(@"Dev App onLogEvent: %@", event.entry);
210+
}
211+
206212
@end

iOS_SDK/OneSignalDevApp/OneSignalDevApp/SwiftTest.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@
2828
import Foundation
2929
import OneSignalFramework
3030

31-
class SwiftTest: NSObject, OSUserJwtInvalidatedListener {
31+
class SwiftTest: NSObject, OSUserJwtInvalidatedListener, OSLogListener {
32+
func onLogEvent(_ event: OneSignalLogEvent) {
33+
print("Dev App onLogEvent: \(event.level) - \(event.entry)")
34+
}
35+
3236
func onUserJwtInvalidated(event: OSUserJwtInvalidatedEvent) {
3337
print("event: \(event.jsonRepresentation())")
3438
print("externalId: \(event.externalId)")
@@ -42,5 +46,7 @@ class SwiftTest: NSObject, OSUserJwtInvalidatedListener {
4246
OneSignal.updateUserJwt(externalId: "euid", token: "token")
4347
OneSignal.addUserJwtInvalidatedListener(self)
4448
OneSignal.removeUserJwtInvalidatedListener(self)
49+
OneSignal.Debug.addLogListener(self)
50+
OneSignal.Debug.removeLogListener(self)
4551
}
4652
}

iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@
9090
3C47A975292642B100312125 /* OneSignalConfigManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C47A973292642B100312125 /* OneSignalConfigManager.m */; };
9191
3C4F9E4428A4466C009F453A /* OSOperationRepo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C4F9E4328A4466C009F453A /* OSOperationRepo.swift */; };
9292
3C5117172B15C31E00563465 /* OSUserState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C5117162B15C31E00563465 /* OSUserState.swift */; };
93+
3C5501402E09CF0100E77DF7 /* OSCopyOnWriteSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C55013E2E09CF0100E77DF7 /* OSCopyOnWriteSet.h */; };
94+
3C5501412E09CF0100E77DF7 /* OSCopyOnWriteSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C55013F2E09CF0100E77DF7 /* OSCopyOnWriteSet.m */; };
95+
3C5501432E09F3D900E77DF7 /* LoggingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C5501422E09F3D900E77DF7 /* LoggingTests.swift */; };
9396
3C5929E32CAD9EC50020D6FF /* OneSignalUserManagerImpl+OSLoggable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C5929E22CAD9EC50020D6FF /* OneSignalUserManagerImpl+OSLoggable.swift */; };
9497
3C5929E52CAE523E0020D6FF /* MockUserJwtInvalidatedListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C5929E42CAE523E0020D6FF /* MockUserJwtInvalidatedListener.swift */; };
9598
3C62999F2BEEA34800649187 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3C62999E2BEEA34800649187 /* PrivacyInfo.xcprivacy */; };
@@ -1279,6 +1282,9 @@
12791282
3C47A973292642B100312125 /* OneSignalConfigManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OneSignalConfigManager.m; sourceTree = "<group>"; };
12801283
3C4F9E4328A4466C009F453A /* OSOperationRepo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSOperationRepo.swift; sourceTree = "<group>"; };
12811284
3C5117162B15C31E00563465 /* OSUserState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSUserState.swift; sourceTree = "<group>"; };
1285+
3C55013E2E09CF0100E77DF7 /* OSCopyOnWriteSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSCopyOnWriteSet.h; sourceTree = "<group>"; };
1286+
3C55013F2E09CF0100E77DF7 /* OSCopyOnWriteSet.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OSCopyOnWriteSet.m; sourceTree = "<group>"; };
1287+
3C5501422E09F3D900E77DF7 /* LoggingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggingTests.swift; sourceTree = "<group>"; };
12821288
3C5929E22CAD9EC50020D6FF /* OneSignalUserManagerImpl+OSLoggable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OneSignalUserManagerImpl+OSLoggable.swift"; sourceTree = "<group>"; };
12831289
3C5929E42CAE523E0020D6FF /* MockUserJwtInvalidatedListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockUserJwtInvalidatedListener.swift; sourceTree = "<group>"; };
12841290
3C62999E2BEEA34800649187 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
@@ -2247,6 +2253,7 @@
22472253
isa = PBXGroup;
22482254
children = (
22492255
3CC063A62B6D7A8E002BB07F /* OneSignalCoreTests.swift */,
2256+
3C5501422E09F3D900E77DF7 /* LoggingTests.swift */,
22502257
3C24B0EB2BD09D7A0052E771 /* OneSignalCoreObjCTests.m */,
22512258
3C24B0EA2BD09D790052E771 /* OneSignalCoreTests-Bridging-Header.h */,
22522259
);
@@ -2678,9 +2685,9 @@
26782685
4529DF0B1FA932AC00CEAB1D /* OneSignalTrackFirebaseAnalytics.m */,
26792686
DE7D1831270279D9002D3A5D /* OSNotificationClasses.h */,
26802687
DE7D183527027AA0002D3A5D /* OneSignalLog.h */,
2688+
DE7D183327027A73002D3A5D /* OneSignalLog.m */,
26812689
3CCF44BC299B17290021964D /* OneSignalWrapper.h */,
26822690
3CCF44BD299B17290021964D /* OneSignalWrapper.m */,
2683-
DE7D183327027A73002D3A5D /* OneSignalLog.m */,
26842691
DE7D187627037A16002D3A5D /* OneSignalCoreHelper.h */,
26852692
DE7D187827037A26002D3A5D /* OneSignalCoreHelper.m */,
26862693
7AE28B8725B8ADF400529100 /* OSMacros.h */,
@@ -2695,6 +2702,8 @@
26952702
DEBAAEB42A436D5D00BF2C1C /* OSStubLocation.m */,
26962703
DEBA2A272C24D0ED00E234DB /* OSBundleUtils.h */,
26972704
DEBA2A252C20E9AA00E234DB /* OSBundleUtils.m */,
2705+
3C55013E2E09CF0100E77DF7 /* OSCopyOnWriteSet.h */,
2706+
3C55013F2E09CF0100E77DF7 /* OSCopyOnWriteSet.m */,
26982707
);
26992708
path = Source;
27002709
sourceTree = "<group>";
@@ -3220,6 +3229,7 @@
32203229
DE7D182A270271A9002D3A5D /* OneSignalCommonDefines.h in Headers */,
32213230
3CE8CC522911AE90000DB0D3 /* OSNetworkingUtils.h in Headers */,
32223231
DEBAAEB02A435B4D00BF2C1C /* OSLocation.h in Headers */,
3232+
3C5501402E09CF0100E77DF7 /* OSCopyOnWriteSet.h in Headers */,
32233233
DE971754274C48CF00FC409E /* OSPrivacyConsentController.h in Headers */,
32243234
3CE8CC4E2911ADD1000DB0D3 /* OSDeviceUtils.h in Headers */,
32253235
3C47A974292642B100312125 /* OneSignalConfigManager.h in Headers */,
@@ -4281,6 +4291,7 @@
42814291
files = (
42824292
3CC063A72B6D7A8E002BB07F /* OneSignalCoreTests.swift in Sources */,
42834293
3C24B0EC2BD09D7A0052E771 /* OneSignalCoreObjCTests.m in Sources */,
4294+
3C5501432E09F3D900E77DF7 /* LoggingTests.swift in Sources */,
42844295
);
42854296
runOnlyForDeploymentPostprocessing = 0;
42864297
};
@@ -4531,6 +4542,7 @@
45314542
DE7D182E270275FA002D3A5D /* OneSignalTrackFirebaseAnalytics.m in Sources */,
45324543
DE51DDE5294262AB0073D5C4 /* OSRemoteParamController.m in Sources */,
45334544
DE7D182827026F86002D3A5D /* OneSignalUserDefaults.m in Sources */,
4545+
3C5501412E09CF0100E77DF7 /* OSCopyOnWriteSet.m in Sources */,
45344546
3CC063942B6D6B6B002BB07F /* OneSignalCore.m in Sources */,
45354547
);
45364548
runOnlyForDeploymentPostprocessing = 0;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* Modified MIT License
3+
*
4+
* Copyright 2025 OneSignal
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* 1. The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* 2. All copies of substantial portions of the Software may only be used in connection
17+
* with services provided by OneSignal.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
#import <Foundation/Foundation.h>
29+
30+
/**
31+
Usage of this class should be limited to cases where modification is rare but reads are frequent.
32+
*/
33+
@interface OSCopyOnWriteSet<__covariant ObjectType> : NSObject {
34+
NSMutableSet *_set;
35+
NSLock *_lock;
36+
}
37+
38+
- (instancetype)init;
39+
- (void)addObject:(ObjectType)object;
40+
- (void)removeObject:(ObjectType)object;
41+
- (NSSet *)allObjects;
42+
43+
@end
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* Modified MIT License
3+
*
4+
* Copyright 2025 OneSignal
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* 1. The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* 2. All copies of substantial portions of the Software may only be used in connection
17+
* with services provided by OneSignal.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
#import "OSCopyOnWriteSet.h"
29+
30+
@implementation OSCopyOnWriteSet
31+
32+
- (instancetype)init {
33+
if (self = [super init]) {
34+
_set = [[NSMutableSet alloc] init];
35+
_lock = [[NSLock alloc] init];
36+
}
37+
return self;
38+
}
39+
40+
- (void)addObject:(id)object {
41+
[_lock lock];
42+
43+
// Create a new copy and modify it
44+
NSMutableSet *newSet = [_set mutableCopy];
45+
[newSet addObject:object];
46+
47+
// Update the internal set
48+
_set = newSet;
49+
50+
[_lock unlock];
51+
}
52+
53+
- (void)removeObject:(id)object {
54+
[_lock lock];
55+
56+
// Create a new copy and modify it
57+
NSMutableSet *newSet = [_set mutableCopy];
58+
[newSet removeObject:object];
59+
60+
// Update the internal set
61+
_set = newSet;
62+
63+
[_lock unlock];
64+
}
65+
66+
- (NSSet *)allObjects {
67+
// Read operation - no lock needed
68+
return _set;
69+
}
70+
71+
@end

iOS_SDK/OneSignalSDK/OneSignalCore/Source/OneSignalLog.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,41 @@ typedef NS_ENUM(NSUInteger, ONE_S_LOG_LEVEL) {
3636
ONE_S_LL_VERBOSE
3737
};
3838

39+
@interface OneSignalLogEvent : NSObject
40+
@property(readonly)ONE_S_LOG_LEVEL level;
41+
@property(readonly, nonnull)NSString *entry;
42+
@end
43+
44+
@protocol OSLogListener <NSObject>
45+
- (void)onLogEvent:(OneSignalLogEvent *_Nonnull)event;
46+
@end
47+
3948
@protocol OSDebug <NSObject>
49+
/**
50+
The log level the OneSignal SDK should be writing to the Xcode log. Defaults to [LogLevel.WARN].
51+
52+
WARNING: This should not be set higher than LogLevel.WARN in a production setting.
53+
*/
4054
+ (void)setLogLevel:(ONE_S_LOG_LEVEL)logLevel;
55+
/**
56+
The log level the OneSignal SDK should be showing as a modal. Defaults to [LogLevel.NONE].
57+
58+
WARNING: This should not be used in a production setting.
59+
*/
4160
+ (void)setAlertLevel:(ONE_S_LOG_LEVEL)logLevel NS_REFINED_FOR_SWIFT;
4261
+ (void)_dump;
62+
/**
63+
Add a listener to receive all logging messages the SDK produces.
64+
Useful to capture and send logs to your server.
65+
66+
NOTE: All log messages are always passed, LogLevel has no effect on this.
67+
*/
68+
+ (void)addLogListener:(NSObject<OSLogListener>*_Nonnull)listener NS_REFINED_FOR_SWIFT;
69+
/**
70+
Removes a listener added by addLogListener
71+
*/
72+
+ (void)removeLogListener:(NSObject<OSLogListener>*_Nonnull)listener NS_REFINED_FOR_SWIFT;
73+
4374
@end
4475

4576
@interface OneSignalLog : NSObject <OSDebug>

iOS_SDK/OneSignalSDK/OneSignalCore/Source/OneSignalLog.m

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@
2828
#import <Foundation/Foundation.h>
2929
#import "OneSignalLog.h"
3030
#import "OSDialogInstanceManager.h"
31+
#import "OSCopyOnWriteSet.h"
32+
33+
@implementation OneSignalLogEvent
34+
- (instancetype)initWithLevel:(ONE_S_LOG_LEVEL)level entry:(NSString*)entry {
35+
_level = level;
36+
_entry = entry;
37+
return self;
38+
}
39+
@end
3140

3241
/**
3342
Implements the Log Level methods of protocol `OSDebug`.
@@ -42,6 +51,15 @@ @implementation OneSignalLog
4251
return self;
4352
}
4453

54+
+ (OSCopyOnWriteSet<NSObject<OSLogListener> *>*)logListeners {
55+
static OSCopyOnWriteSet<NSObject<OSLogListener> *> *_logListeners;
56+
static dispatch_once_t onceToken;
57+
dispatch_once(&onceToken, ^{
58+
_logListeners = [OSCopyOnWriteSet new];
59+
});
60+
return _logListeners;
61+
}
62+
4563
+ (void)setLogLevel:(ONE_S_LOG_LEVEL)nsLogLevel {
4664
_nsLogLevel = nsLogLevel;
4765
}
@@ -50,6 +68,14 @@ + (void)setAlertLevel:(ONE_S_LOG_LEVEL)logLevel {
5068
_alertLogLevel = logLevel;
5169
}
5270

71+
+ (void)addLogListener:(NSObject<OSLogListener>*_Nonnull)listener {
72+
[self.logListeners addObject:listener];
73+
}
74+
75+
+ (void)removeLogListener:(NSObject<OSLogListener>*_Nonnull)listener {
76+
[self.logListeners removeObject:listener];
77+
}
78+
5379
+ (void)_dump {}
5480

5581
+ (void)onesignalLog:(ONE_S_LOG_LEVEL)logLevel message:(NSString* _Nonnull)message {
@@ -92,6 +118,13 @@ void onesignal_Log(ONE_S_LOG_LEVEL logLevel, NSString* message) {
92118
if (logLevel <= _alertLogLevel) {
93119
[[OSDialogInstanceManager sharedInstance] presentDialogWithTitle:levelString withMessage:message withActions:nil cancelTitle:NSLocalizedString(@"Close", @"Close button") withActionCompletion:nil];
94120
}
121+
122+
for (NSObject<OSLogListener> *listener in OneSignalLog.logListeners.allObjects) {
123+
if ([listener respondsToSelector:@selector(onLogEvent:)]) {
124+
OneSignalLogEvent *event = [[OneSignalLogEvent alloc] initWithLevel:logLevel entry:[levelString stringByAppendingString:message]];
125+
[listener onLogEvent:event];
126+
}
127+
}
95128
}
96129

97130
@end

0 commit comments

Comments
 (0)