Skip to content
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

chore: Native logging bridge #278

Draft
wants to merge 1 commit into
base: feature/cdp/project-setup
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ios/wrappers/logging/CioLoggingEmitter.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#import <React/RCTEventEmitter.h>

@interface RCT_EXTERN_REMAP_MODULE(CioLoggingEmitter, CioLoggingEmitter, RCTEventEmitter)
@end
91 changes: 91 additions & 0 deletions ios/wrappers/logging/CioLoggingEmitter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@

import React
import CioInternalCommon

typealias CioLogger = CioInternalCommon.Logger

@objc(CioLoggingEmitter)
class CioLoggingEmitter: RCTEventEmitter {

fileprivate static var eventName = "CioLogEvent"

fileprivate var hasObservers = false

override func startObserving() {
hasObservers = true
}

override func stopObserving() {
hasObservers = false
}

override func supportedEvents() -> [String] {
[Self.eventName]
}

override var methodQueue: dispatch_queue_t! {
DispatchQueue(label: Self.moduleName())
}
}


class CioLoggerWrapper: CioLogger {
private(set) var logLevel: CioLogLevel
private var moduleRegistry: RCTModuleRegistry

static func getInstance (moduleRegistry: RCTModuleRegistry, logLevel: CioLogLevel) -> CioLogger {
if let wrapper = DIGraphShared.shared.logger as? Self {
wrapper.logLevel = logLevel
wrapper.moduleRegistry = moduleRegistry
return wrapper
}

let wrapper = CioLoggerWrapper(moduleRegistry: moduleRegistry, logLevel: logLevel)
DIGraphShared.shared.override(value: wrapper, forType: CioLogger.self)
return wrapper
}

private init(moduleRegistry: RCTModuleRegistry, logLevel: CioLogLevel?) {
self.logLevel = logLevel ?? .none
self.moduleRegistry = moduleRegistry
}

func setLogLevel(_ level: CioLogLevel) {
logLevel = level
}

func debug(_ message: String) {
emit(message, level: .debug)
}

func info(_ message: String) {
emit(message, level: .info)
}

func error(_ message: String) {
emit(message, level: .error)
}

private func emit(_ message: String, level: CioLogLevel) {
if shouldEmit(level: level), let emitter, emitter.hasObservers {
emitter.sendEvent(withName: CioLoggingEmitter.eventName, body: ["logLevel": level.rawValue, "message": message])
}
}

private func shouldEmit(level: CioLogLevel) -> Bool {
switch self.logLevel {
case .none: return false
case .error:
return level == .error
case .info:
return level == .error || level == .info
case .debug:
return true
}
}

private var emitter: CioLoggingEmitter? {
moduleRegistry.module(forName: "CioLoggingEmitter") as? CioLoggingEmitter
}

}
49 changes: 49 additions & 0 deletions src/native-logger-listener.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
import { CioLogLevel } from './cio-config';

const LINKING_ERROR =
`The package 'customerio-reactnative' doesn't seem to be linked. Make sure: ` +
Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
'- You rebuilt the app after installing the package\n' +
'- You are not using Expo Go\n';

const CioLoggingEmitter = NativeModules.CioLoggingEmitter
? NativeModules.CioLoggingEmitter
: new Proxy(
{},
{
get() {
throw new Error(LINKING_ERROR);
},
}
);

export class NativeLoggerListener {
static initialize() {
const bridge = new NativeEventEmitter(CioLoggingEmitter);
bridge.addListener(
'CioLogEvent',
(event: { logLevel: CioLogLevel; message: string }) => {
// 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
// doing it async allows to be logged to the JS side and then to the native side
async function log() {
switch (event.logLevel) {
case CioLogLevel.Debug:
console.debug(event.message);
break;
case CioLogLevel.Info:
console.info(event.message);
break;
case CioLogLevel.Error:
console.error(event.message);
break;
default:
console.log(event);
break;
}
}
log();
}
);
}
}
Loading