Skip to content

Commit 5089ff9

Browse files
committed
feat(logging): add public log listener methods
* Adds the following new public methods: - OneSignal.Debug.addLogListener - OneSignal.Debug.removeLogListener * These new methods provide a way to capture all SDK log entires at runtime, allowing the app developer to store these and/or send them to their server. * The log listener is independent of logLevel, all message are always sent to listeners. * Use the new `OSCopyOnWriteSet`: it is possible for someone to add or remove a log listener within the `onLogEvent` callback, thus modifying the set of listeners as the set is being enumerated. @synchronized is a recursive lock, so it would not be sufficient. Locking the entire set of listeners would result in deadlock. * This mimics the Android implementation which uses the built-in `CopyOnWriteArraySet`
1 parent 256f957 commit 5089ff9

File tree

4 files changed

+85
-1
lines changed

4 files changed

+85
-1
lines changed

iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2619,9 +2619,9 @@
26192619
4529DF0B1FA932AC00CEAB1D /* OneSignalTrackFirebaseAnalytics.m */,
26202620
DE7D1831270279D9002D3A5D /* OSNotificationClasses.h */,
26212621
DE7D183527027AA0002D3A5D /* OneSignalLog.h */,
2622+
DE7D183327027A73002D3A5D /* OneSignalLog.m */,
26222623
3CCF44BC299B17290021964D /* OneSignalWrapper.h */,
26232624
3CCF44BD299B17290021964D /* OneSignalWrapper.m */,
2624-
DE7D183327027A73002D3A5D /* OneSignalLog.m */,
26252625
DE7D187627037A16002D3A5D /* OneSignalCoreHelper.h */,
26262626
DE7D187827037A26002D3A5D /* OneSignalCoreHelper.m */,
26272627
7AE28B8725B8ADF400529100 /* OSMacros.h */,

iOS_SDK/OneSignalSDK/OneSignalCore/Source/OneSignalLog.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,40 @@ 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;
61+
/**
62+
Add a listener to receive all logging messages the SDK produces.
63+
Useful to capture and send logs to your server.
64+
65+
NOTE: All log messages are always passed, LogLevel has no effect on this.
66+
*/
67+
+ (void)addLogListener:(NSObject<OSLogListener>*_Nonnull)listener NS_REFINED_FOR_SWIFT;
68+
/**
69+
Removes a listener added by addLogListener
70+
*/
71+
+ (void)removeLogListener:(NSObject<OSLogListener>*_Nonnull)listener NS_REFINED_FOR_SWIFT;
72+
4273
@end
4374

4475
@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
@implementation OneSignalLog
3342

@@ -38,6 +47,15 @@ @implementation OneSignalLog
3847
return self;
3948
}
4049

50+
+ (OSCopyOnWriteSet<NSObject<OSLogListener> *>*)logListeners {
51+
static OSCopyOnWriteSet<NSObject<OSLogListener> *> *_logListeners;
52+
static dispatch_once_t onceToken;
53+
dispatch_once(&onceToken, ^{
54+
_logListeners = [OSCopyOnWriteSet new];
55+
});
56+
return _logListeners;
57+
}
58+
4159
+ (void)setLogLevel:(ONE_S_LOG_LEVEL)nsLogLevel {
4260
_nsLogLevel = nsLogLevel;
4361
}
@@ -46,6 +64,14 @@ + (void)setAlertLevel:(ONE_S_LOG_LEVEL)logLevel {
4664
_alertLogLevel = logLevel;
4765
}
4866

67+
+ (void)addLogListener:(NSObject<OSLogListener>*_Nonnull)listener {
68+
[self.logListeners addObject:listener];
69+
}
70+
71+
+ (void)removeLogListener:(NSObject<OSLogListener>*_Nonnull)listener {
72+
[self.logListeners removeObject:listener];
73+
}
74+
4975
+ (void)onesignalLog:(ONE_S_LOG_LEVEL)logLevel message:(NSString* _Nonnull)message {
5076
onesignal_Log(logLevel, message);
5177
}
@@ -86,6 +112,13 @@ void onesignal_Log(ONE_S_LOG_LEVEL logLevel, NSString* message) {
86112
if (logLevel <= _alertLogLevel) {
87113
[[OSDialogInstanceManager sharedInstance] presentDialogWithTitle:levelString withMessage:message withActions:nil cancelTitle:NSLocalizedString(@"Close", @"Close button") withActionCompletion:nil];
88114
}
115+
116+
for (NSObject<OSLogListener> *listener in OneSignalLog.logListeners.allObjects) {
117+
if ([listener respondsToSelector:@selector(onLogEvent:)]) {
118+
OneSignalLogEvent *event = [[OneSignalLogEvent alloc] initWithLevel:logLevel entry:[levelString stringByAppendingString:message]];
119+
[listener onLogEvent:event];
120+
}
121+
}
89122
}
90123

91124
@end

iOS_SDK/OneSignalSDK/Source/OneSignalSwiftInterface.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,29 @@ public extension OneSignal {
6363
}
6464

6565
public extension OSDebug {
66+
/**
67+
The log level the OneSignal SDK should be showing as a modal. Defaults to [LogLevel.NONE].
68+
69+
WARNING: This should not be used in a production setting.
70+
*/
6671
static func setAlertLevel(_ logLevel: ONE_S_LOG_LEVEL) {
6772
__setAlert(logLevel)
6873
}
74+
/**
75+
Add a listener to receive all logging messages the SDK produces.
76+
Useful to capture and send logs to your server.
77+
78+
NOTE: All log messages are always passed, LogLevel has no effect on this.
79+
*/
80+
static func addLogListener(_ listener: OSLogListener) {
81+
__add(listener)
82+
}
83+
/**
84+
Removes a listener added by addLogListener
85+
*/
86+
static func removeLogListener(_ listener: OSLogListener) {
87+
__remove(listener)
88+
}
6989
}
7090

7191
public extension OSInAppMessages {

0 commit comments

Comments
 (0)