Skip to content

Commit 5410957

Browse files
committed
chore: Native logging bridge
1 parent 0a9f81e commit 5410957

File tree

3 files changed

+144
-0
lines changed

3 files changed

+144
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#import <React/RCTEventEmitter.h>
2+
3+
@interface RCT_EXTERN_REMAP_MODULE(CioLoggingEmitter, CioLoggingEmitter, RCTEventEmitter)
4+
@end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
2+
import React
3+
import CioInternalCommon
4+
5+
typealias CioLogger = CioInternalCommon.Logger
6+
7+
@objc(CioLoggingEmitter)
8+
class CioLoggingEmitter: RCTEventEmitter {
9+
10+
fileprivate static var eventName = "CioLogEvent"
11+
12+
fileprivate var hasObservers = false
13+
14+
override func startObserving() {
15+
hasObservers = true
16+
}
17+
18+
override func stopObserving() {
19+
hasObservers = false
20+
}
21+
22+
override func supportedEvents() -> [String] {
23+
[Self.eventName]
24+
}
25+
26+
override var methodQueue: dispatch_queue_t! {
27+
DispatchQueue(label: Self.moduleName())
28+
}
29+
}
30+
31+
32+
class CioLoggerWrapper: CioLogger {
33+
private(set) var logLevel: CioLogLevel
34+
private var moduleRegistry: RCTModuleRegistry
35+
36+
static func getInstance (moduleRegistry: RCTModuleRegistry, logLevel: CioLogLevel) -> CioLogger {
37+
if let wrapper = DIGraphShared.shared.logger as? Self {
38+
wrapper.logLevel = logLevel
39+
wrapper.moduleRegistry = moduleRegistry
40+
return wrapper
41+
}
42+
43+
let wrapper = CioLoggerWrapper(moduleRegistry: moduleRegistry, logLevel: logLevel)
44+
DIGraphShared.shared.override(value: wrapper, forType: CioLogger.self)
45+
return wrapper
46+
}
47+
48+
private init(moduleRegistry: RCTModuleRegistry, logLevel: CioLogLevel?) {
49+
self.logLevel = logLevel ?? .none
50+
self.moduleRegistry = moduleRegistry
51+
}
52+
53+
func setLogLevel(_ level: CioLogLevel) {
54+
logLevel = level
55+
}
56+
57+
func debug(_ message: String) {
58+
emit(message, level: .debug)
59+
}
60+
61+
func info(_ message: String) {
62+
emit(message, level: .info)
63+
}
64+
65+
func error(_ message: String) {
66+
emit(message, level: .error)
67+
}
68+
69+
private func emit(_ message: String, level: CioLogLevel) {
70+
if shouldEmit(level: level), let emitter, emitter.hasObservers {
71+
emitter.sendEvent(withName: CioLoggingEmitter.eventName, body: ["logLevel": level.rawValue, "message": message])
72+
}
73+
}
74+
75+
private func shouldEmit(level: CioLogLevel) -> Bool {
76+
switch self.logLevel {
77+
case .none: return false
78+
case .error:
79+
return level == .error
80+
case .info:
81+
return level == .error || level == .info
82+
case .debug:
83+
return true
84+
}
85+
}
86+
87+
private var emitter: CioLoggingEmitter? {
88+
moduleRegistry.module(forName: "CioLoggingEmitter") as? CioLoggingEmitter
89+
}
90+
91+
}

src/native-logger-listener.ts

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
2+
import { CioLogLevel } from './cio-config';
3+
4+
const LINKING_ERROR =
5+
`The package 'customerio-reactnative' doesn't seem to be linked. Make sure: ` +
6+
Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
7+
'- You rebuilt the app after installing the package\n' +
8+
'- You are not using Expo Go\n';
9+
10+
const CioLoggingEmitter = NativeModules.CioLoggingEmitter
11+
? NativeModules.CioLoggingEmitter
12+
: new Proxy(
13+
{},
14+
{
15+
get() {
16+
throw new Error(LINKING_ERROR);
17+
},
18+
}
19+
);
20+
21+
export class NativeLoggerListener {
22+
static initialize() {
23+
const bridge = new NativeEventEmitter(CioLoggingEmitter);
24+
bridge.addListener(
25+
'CioLogEvent',
26+
(event: { logLevel: CioLogLevel; message: string }) => {
27+
// if we just use console.log, it will log to the JS side but it will prevent RN default behavior of redirecting logs to the native side
28+
// doing it async allows to be logged to the JS side and then to the native side
29+
async function log() {
30+
switch (event.logLevel) {
31+
case CioLogLevel.Debug:
32+
console.debug(event.message);
33+
break;
34+
case CioLogLevel.Info:
35+
console.info(event.message);
36+
break;
37+
case CioLogLevel.Error:
38+
console.error(event.message);
39+
break;
40+
default:
41+
console.log(event);
42+
break;
43+
}
44+
}
45+
log();
46+
}
47+
);
48+
}
49+
}

0 commit comments

Comments
 (0)