Sources/AlibabaCloudRUM/AlibabaCloudRUM.swift (282 lines of code) (raw):
//
// Copyright 2023 aliyun-sls Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import OpenRUM
@objc(AlibabaCloudEnv)
public enum Env: Int {
case NONE
case PROD
case GRAY
case PRE
case DAILY
case LOCAL
}
@objc(AlibabaCloudFramework)
public enum Framework: Int {
case FLUTTER
case REACT_NATIVE
case UNITY
}
@objc
public class AlibabaCloudRUM : NSObject {
private static let CUSTOM_ATTRIBUTES_PREFIX = "_attr_"
private static let SDK_VERSION_PREFIX = "_sv_"
private static let SDK_FRAMEWORK = "_frmk_"
// private static let S_RUM_SDK_VERSION = Bundle(for: AlibabaCloudRUM.self).infoDictionary?["CFBundleShortVersionString"] as? String
private static let RUM_SDK_VERSION = "0.3.7"
private static var env: String?
private static let shared: AlibabaCloudRUM = AlibabaCloudRUM()
private override init() {
// default disable battery monitor
OpenRUM.updateLocalConfigWithBattery(on: false)
}
private static var cachedExtraInfo: [String: AnyObject] = {
var info = [String: AnyObject]()
info[SDK_VERSION_PREFIX] = RUM_SDK_VERSION as AnyObject
return info
}()
private static func envToString(_ env: Env) -> String {
switch env {
case .NONE: return "none"
case .PROD: return "prod"
case .GRAY: return "gray"
case .PRE: return "pre"
case .DAILY: return "daily"
case .LOCAL: return "local"
default: return "prod"
}
}
/// 禁止swizzle类中的某个方法
///
/// 可以传递普通类和元类。禁止传入动态注册的类
///
/// @note 需在探针启动前调用。**请谨慎使用**
@objc
public static func disableSwizzleMethod(_ selector: Selector, clazz: AnyClass) {
OpenRUM.disableSwizzleMethod(selector, in: clazz)
}
/// 禁止检查某个类
/// @note 需在探针启动前调用。**请谨慎使用**
@objc(disableInspectClass:)
public static func disableInspectClass(_ className: String) {
OpenRUM.disableInspectClass(className)
}
/// 开启/关闭电量模块。
/// 默认为关闭,需要在start方法调用之前设置
/// - Parameters:
/// - enable: 是否开启
@objc(enableBattery:)
public static func enableBattery(_ enable: Bool) {
OpenRUM.updateLocalConfigWithBattery(on: enable)
}
/// 开启/关闭 webview 模块。
/// 默认为开启,在需要时调用即可
/// - Parameters:
/// - enable: 是否开启
@objc(enableTrackingWebView:)
public static func enableTrackingWebView(_ enable: Bool) {
if enable {
OpenRUM.enableWebAgentInjection()
} else {
OpenRUM.disableWebAgentInjection()
}
}
/// 启动SDK
/// - Parameters:
/// - appID: 应用ID, 必填
@objc(startWithAppID:)
public static func start(_ appID: String) {
if nil == self.env {
self.setEnvironment(.PROD)
}
OpenRUM.start(withAppID: appID)
OpenRUM.setExtraInfo(cachedExtraInfo)
}
/// 配置config地址
/// - Parameters:
/// - configAddress: config 地址
@objc
public static func setConfigAddress(_ configAddress: String) {
OpenRUM.setConfigAddress(configAddress)
}
@objc
public static func setEnvironment(_ env: Env) {
self.env = envToString(env)
OpenRUM.setAppEnvironment(self.env!)
}
@objc
public static func setCustomEnvironment(_ env: String?) {
guard let env = env else {
return
}
self.env = env
OpenRUM.setAppEnvironment(env)
}
@objc
public static func setAppVersion(_ appVersion: String) {
OpenRUM.setAppVersion(appVersion)
}
@objc
public static func setChannelID(_ channelID: String) {
OpenRUM.setChannelID(channelID)
}
@objc
public static func setDeviceID(_ deviceID: String) {
OpenRUM.setDeviceID(deviceID)
}
@objc
public static var deviceID : String {
get {
return OpenRUM.deviceID()
}
}
@objc
public static func setUserName(_ userID: String) {
OpenRUM.setUserID(userID)
}
@objc(setExtraInfo:)
public static func setExtraInfo(_ extraInfo: [String: AnyObject]) {
internalSetExtraInfo(extraInfo, false, false)
}
@objc(addExtraInfo:)
public static func addExtraInfo(_ extraInfo: [String: AnyObject]) {
internalSetExtraInfo(extraInfo, false, true)
}
@objc(setUserExtraInfo:)
public static func setUserExtraInfo(_ extraInfo: [String: AnyObject]) {
internalSetExtraInfo(extraInfo, true, false)
}
@objc(addUserExtraInfo:)
public static func addUserExtraInfo(_ extraInfo: [String: AnyObject]) {
internalSetExtraInfo(extraInfo, true, true)
}
@objc(setAppFramework:)
public static func setAppFramework(_ framework: Framework) {
let frmkName = frameworkDescription(framework)
cachedExtraInfo[SDK_FRAMEWORK] = frmkName as AnyObject
}
private static func internalSetExtraInfo(_ extraInfo: [String: AnyObject]?, _ user: Bool, _ append: Bool) {
guard let info = extraInfo else {
return
}
var global: [String: AnyObject] = cachedExtraInfo[CUSTOM_ATTRIBUTES_PREFIX] as? [String : AnyObject] ?? [String: AnyObject]()
if !append {
var removedKeys = [String]()
for (key, _) in cachedExtraInfo {
// keep SDK_VERSION_PREFIX
if SDK_VERSION_PREFIX == key {
continue
}
// keep SDK_FRAMEWORK
if SDK_FRAMEWORK == key {
continue
}
if user {
// in user attributes mode
// remove kv if is not global attributes
if CUSTOM_ATTRIBUTES_PREFIX != key {
removedKeys.append(key)
}
} else {
// not in user attributes mode
// remove kv if is global attributes
if CUSTOM_ATTRIBUTES_PREFIX == key {
global.removeAll()
removedKeys.append(key)
}
}
}
for key in removedKeys {
cachedExtraInfo.removeValue(forKey: key)
}
}
if user {
// put user extra info to root node
cachedExtraInfo.merge(info, uniquingKeysWith: { current, _ in current })
} else {
// put global attributes to CUSTOM_ATTRIBUTES_PREFIX node
global.merge(info, uniquingKeysWith: { current, _ in current })
}
if !global.isEmpty {
cachedExtraInfo[CUSTOM_ATTRIBUTES_PREFIX] = global as AnyObject
}
OpenRUM.setExtraInfo(cachedExtraInfo)
}
@objc
public static func setLogFlag(_ flag: NSNumber) {
OpenRUM.setLogFlag(flag)
}
@objc
public static func stopSDK() {
OpenRUM.stopSDK()
}
// MARK: ===== exception =====
@objc(setCustomException:causeBy:errorDump:)
public static func setCustomException(_ exceptionType: String, causeBy: String, errorDump: String) {
OpenRUM.setCustomExceptionWithType(exceptionType, causeBy: causeBy, errorDump: errorDump)
}
// MARK: ===== metric =====
@objc(setCustomMetric:value:param:)
public static func setCustomMetric(_ metricName: String, value: Int, snapshots: String?) {
OpenRUM.setCustomMetricWithName(metricName, value: value, param: snapshots)
}
// MARK: ===== event =====
@objc(setCustomEvent:)
public static func setCustomEvent(_ name: String) {
self.setCustomEvent(name, group: nil)
}
@objc(setCustomEvent:group:)
public static func setCustomEvent(_ name: String, group: String? = nil) {
self.setCustomEvent(name, group: group, snapshots: nil)
}
@objc(setCustomEvent:group:snapshots:)
public static func setCustomEvent(_ name: String, group: String? = nil, snapshots: String? = nil) {
self.setCustomEvent(name, group: group, snapshots: snapshots, value: 0)
}
@objc(setCustomEvent:group:value:)
public static func setCustomEvent(_ name: String, group: String? = nil, value: Double = 0) {
self.setCustomEvent(name, group: group, snapshots: nil, value: value)
}
@objc(setCustomEvent:group:info:)
public static func setCustomEvent(_ name: String, group: String? = nil, info: [String: String]? = nil) {
self.setCustomEvent(name, group: group, snapshots: nil, info: info)
}
@objc(setCustomEvent:group:snapshots:value:)
public static func setCustomEvent(_ name: String, group: String? = nil, snapshots: String? = nil, value: Double = 0) {
self.setCustomEvent(name, group: group, snapshots: snapshots, value: value, info: nil)
}
@objc(setCustomEvent:group:snapshots:info:)
public static func setCustomEvent(_ name: String, group: String? = nil, snapshots: String? = nil, info: [String: String]? = nil) {
self.setCustomEvent(name, group: group, snapshots: snapshots, value: 0, info: info)
}
@objc(setCustomEvent:group:value:info:)
public static func setCustomEvent(_ name: String, group: String? = nil, value: Double = 0, info: [String: String]? = nil) {
self.setCustomEvent(name, group: group, snapshots: nil, value: value, info: info)
}
@objc(setCustomEvent:group:snapshots:value:info:)
public static func setCustomEvent(_ name: String, group: String? = nil, snapshots: String? = nil, value: Double = 0, info: [String: String]? = nil) {
var extra: [String: String]
if let _ = info {
extra = info!
} else {
extra = [String: String]()
}
extra["_orcv"] = String(value)
OpenRUM.setCustomEventWithID(UUID().uuidString, name: name, label: group, param: snapshots, info: extra)
}
// MARK: ===== log =====
@objc(setCustomLog:)
public static func setCustomLog(_ logInfo: String) {
setCustomLog(logInfo, name: nil)
}
@objc(setCustomLog:name:)
public static func setCustomLog(_ logInfo: String, name: String? = nil) {
setCustomLog(logInfo, name: name, snapshots: "")
}
@objc(setCustomLog:name:snapshots:)
public static func setCustomLog(_ logInfo: String, name: String? = nil, snapshots: String? = "") {
setCustomLog(logInfo, name: name, snapshots: snapshots, info: nil)
}
@objc(setCustomLog:name:snapshots:level:info:)
public static func setCustomLog(_ logInfo: String, name: String? = nil, snapshots: String? = "", level: String? = "INFO", info: [String: String]? = nil) {
var extra : [String: String]
if let _ = info {
extra = info!
} else {
extra = [String: String]()
}
if let _ = level {
extra["_ll"] = level
} else {
extra["_ll"] = "INFO"
}
if let _ = name {
extra["_ln"] = name
}
extra["_lc"] = logInfo
do {
let info = try JSONSerialization.data(withJSONObject: extra, options: [])
OpenRUM.setCustomLog(String(data: info, encoding: .utf8)!, param: snapshots)
} catch {
return
}
}
@objc(getDeviceId)
public static func getDeviceId() -> String {
return OpenRUM.deviceID()
}
private static func frameworkDescription(_ framework: Framework) -> String {
switch framework {
case .FLUTTER:
return "Flutter"
case .REACT_NATIVE:
return "ReactNative"
case .UNITY:
return "Unity"
default:
return ""
}
}
}