macOS Application Access¶
Overview¶
Guance Real User Monitoring can analyze the performance of each macOS application in a visual way by collecting the metrics data of each macOS application.
Precondition¶
- Installing DataKit (DataKit Installation Documentation)
macOS Application Access¶
Login to Guance Console, enter "Real User Monitoring" page, click "New Application" in the upper right corner, enter "Application Name" and customize "Application ID" in the new window, and click "Create" to select the application type to get access.
- Application Name (required): The name of the application used to identify the current implementation of user access monitoring.
- Application ID (required): The unique identification of the application in the current workspace, which is used for SDK data collection and upload matching, and corresponds to the field: app_id after data entry. This field only supports English, numeric, underscore input, up to 48 characters.
Installation¶
Source Code Address:https://github.com/GuanceCloud/datakit-macos
Demo:https://github.com/GuanceCloud/datakit-macos/Example
1.Configure the Podfile
file.
2.Run pod install
in the Podfile
directory to install the SDK.
1.Select PROJECT
-> Package Dependency
,Click + under 'Packages'.
2.Enter https://github.com/GuanceCloud/datakit-macos
in the search box on the page that pops up.
3.After Xcode successfully obtains the package, the SDK configuration page is displayed.
Dependency Rule
:suggest you to choose Up to Next Major Version
.
Add To Project
:Select a supported project.
Click the 'Add Package' button and wait for the load to complete.
4.In the pop-up window Choose Package Products for datakit-macos
,select the Target that needs to Add the SDK and click the' Add Package 'button. At this time, the SDK has been added successfully.
If your project is managed by SPM, add the SDK as a dependency and add 'dependencies' to 'Package.swift'.
Add Header File¶
SDK Initialization¶
Basic Configuration¶
The -viewDidLoad
method of NSViewController
and -windowDidLoad
method of NSWindowController
are called earlier than AppDelegate -applicationDidFinishLaunching
.To avoid life cycle collection exceptions for the first view, it is recommended to initialize the SDK in the main.m file.
// main.m
#import "FTMacOSSDK.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Setup code that might create autoreleased objects goes here.
FTSDKConfig *config = [[FTSDKConfig alloc]initWithMetricsUrl:@"YOUR_ACCESS_SERVER_URL"];
config.enableSDKDebugLog = YES;
[FTSDKAgent startWithConfigOptions:config];
}
return NSApplicationMain(argc, argv);
}
create mian.swift file,deleate @main
or @NSApplicationMain
in AppDelegate.swift
file.
import Cocoa
import FTMacOSSDK
let delegate = AppDelegate()
NSApplication.shared.delegate = delegate
// Installation SDK
let config = FTSDKConfig.init(metricsUrl: "YOUR_ACCESS_SERVER_URL")
config.enableSDKDebugLog = true
FTSDKAgent.start(withConfigOptions: config)
_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)
Fields | Type | Required | Meaning | Attention |
---|---|---|---|---|
metricsUrl | NSString | Yes | Datakit installation address | The url of the datakit installation address, example: http://10.0.0.1:9529, port 9529. Datakit url address needs to be accessible by the device where the SDK is installed |
enableSDKDebugLog | BOOL | No | Whether to turn on debug mode | Default is NO , enable to print SDK run log |
env | NSString | No | Set the acquisition environment | Default prod , support for custom. It can also be set using the -setEnvWithType: method based on the 'FTEnv' enumeration.FTEnv FTEnvGray : grayFTEnvPre :pre FTEnvCommon :common FTEnvLocal : local |
service | NSString | No | Set Service Name | Impact the service field data in Log and RUM, which is set to df_rum_macos by default. |
globalContext | NSDictionary | No | Add SDK global properties | Adding rules can be found here |
RUM Configuration¶
FTRumConfig *rumConfig = [[FTRumConfig alloc]initWithAppid:appid];
rumConfig.enableTrackAppCrash = YES;
rumConfig.enableTrackAppANR = YES;
rumConfig.enableTrackAppFreeze = YES;
rumConfig.enableTraceUserAction = YES;
rumConfig.enableTraceUserVIew = YES;
rumConfig.enableTraceUserResource = YES;
rumConfig.errorMonitorType = FTErrorMonitorAll;
rumConfig.deviceMetricsMonitorType = FTDeviceMetricsMonitorAll;
[[FTSDKAgent sharedInstance] startRumWithConfigOptions:rumConfig];
let rumConfig = FTRumConfig(appid: appid)
rumConfig.enableTraceUserAction = true
rumConfig.enableTrackAppANR = true
rumConfig.enableTraceUserView = true
rumConfig.enableTraceUserResource = true
rumConfig.enableTrackAppCrash = true
rumConfig.enableTrackAppFreeze = true
rumConfig.errorMonitorType = .all
rumConfig.deviceMetricsMonitorType = .all
rumConfig.monitorFrequency = .rare
FTSDKAgent.sharedInstance().startRum(withConfigOptions: rumConfig)
Fields | Type | Required | Meaning | Attention |
---|---|---|---|---|
appid | NSString | Yes | Set Rum AppId |
Corresponding to setting RUM appid to enable RUM collection, get appid method |
sampleRate | int | No | Set acquisition rate | The collection rate ranges from >= 0 to <= 100. The default value is 100 |
enableTrackAppCrash | BOOL | No | Set whether crash need to be collected | Default NO |
enableTrackAppANR | BOOL | No | Collect ANR stuck unresponsive events | Default NO |
enableTrackAppFreeze | BOOL | No | Collect UI jamming events | Default NO |
enableTraceUserView | BOOL | No | Set whether to track user View actions | Default NO |
enableTraceUserAction | BOOL | No | Set whether to track user Action actions | Default NO |
enableTraceUserResource | BOOL | No | Set whether to track user network requests | Default NO |
errorMonitorType | FTErrorMonitorType | No | Error Event Monitoring Supplementary Type | Add monitoring information to the collected crash data.FTErrorMonitorType FTErrorMonitorAll :allFTErrorMonitorBattery :battery powerFTErrorMonitorMemory :total memory, memory usageFTErrorMonitorCpu :CPU usage |
monitorFrequency | FTMonitorFrequency | No | View's Performance Monitoring Sampling Period | Configure 'monitorFrequency' to set the sampling period for View monitor information.FTMonitorFrequency FTMonitorFrequencyDefault :500ms (default)FTMonitorFrequencyFrequent :100msFTMonitorFrequencyRare :1000m |
deviceMetricsMonitorType | FTDeviceMetricsMonitorType | No | The performance monitoring type of the view | Add the monitoring item information to the collected View data。FTDeviceMetricsMonitorType FTDeviceMetricsMonitorAll :allFTDeviceMetricsMonitorMemory :average memory, maximum memoryFTDeviceMetricsMonitorCpu :The maximum and average number of CPU ticks |
globalContext | NSDictionary | No | Add Rum global properties | Adding rules can be found here |
Log Configuration¶
FTLoggerConfig *loggerConfig = [[FTLoggerConfig alloc]init];
loggerConfig.enableCustomLog = YES;
loggerConfig.printCustomLogToConsole = YES;
loggerConfig.enableLinkRumData = YES;
loggerConfig.logLevelFilter = @[@(FTStatusError),@(FTStatusCritical)];
loggerConfig.discardType = FTDiscardOldest;
[[FTSDKAgent sharedInstance] startLoggerWithConfigOptions:loggerConfig];
let loggerConfig = FTLoggerConfig()
loggerConfig.enableCustomLog = true
loggerConfig.enableLinkRumData = true
loggerConfig.printCustomLogToConsole = true
loggerConfig.logLevelFilter = [NSNumber(value: FTLogStatus.statusError.rawValue),NSNumber(value: FTLogStatus.statusCritical.rawValue)] // loggerConfig.logLevelFilter = [2,3]
loggerConfig.discardType = .discardOldest
FTSDKAgent.sharedInstance().startLogger(withConfigOptions: loggerConfig)
Fields | Type | Required | Meaning | Attention |
---|---|---|---|---|
samplerate | int | No | Set acquisition rate | The collection rate ranges from >= 0 to <= 100. The default value is 100 |
enableCustomLog | BOOL | No | Whether to upload custom logs | Default NO |
printCustomLogToConsole | BOOL | No | Sets whether to output custom logs to the console | Default NO Custom log print format |
logLevelFilter | NSArray | No | Set the state array of the custom logs to be collected | Default full collection |
enableLinkRumData | BOOL | No | Whether to associate logger data with rum | Default NO |
discardType | FTLogCacheDiscard | No (the latest data is discarded by default) | Setting the log deprecation policy | Default FTDiscard FTLogCacheDiscard :FTDiscard :Default,When the number of log data exceeds the maximum value (5000), the appended data is discardedFTDiscardOldest :When the log data exceeds the maximum value, the old data is discarded |
globalContext | NSDictionary | No | Add log global properties | Adding rules can be found here |
Trace Configuration¶
Fields | Type | Required | Meaning | Attention |
---|---|---|---|---|
samplerate | int | No | Set acquisition rate | The collection rate ranges from >= 0 to <= 100. The default value is 100 |
enableCustomLog | BOOL | No | Whether to upload custom logs | Default NO |
printCustomLogToConsole | BOOL | No | Sets whether to output custom logs to the console | Default NO Custom log print format |
logLevelFilter | NSArray | No | Set the state array of the custom logs to be collected | Default full collection |
enableLinkRumData | BOOL | No | Whether to associate logger data with rum | Default NO |
discardType | FTLogCacheDiscard | No (the latest data is discarded by default) | Setting the log deprecation policy | Default FTDiscard FTLogCacheDiscard :FTDiscard :Default,When the number of log data exceeds the maximum value (5000), the appended data is discardedFTDiscardOldest :When the log data exceeds the maximum value, the old data is discarded |
globalContext | NSDictionary | No | Add log global properties | Adding rules can be found here |
RUM¶
You can configure FTRUMConfig
to enable automatic mode or add it manually. Rum related data can be passed in through the FTGlobalRumManager
singleton with the following API.
View¶
If you set enableTraceUserView = YES
to enable automatic collection, the SDK will automatically collect the life cycle of the Window. The life cycle of the window -becomeKeyWindow
defines the beginning of View, and -resignKeyWindow
defines the end of View.
The view name is set in the order of NSStringFromClass(window.contentViewController.class)
> NSStringFromClass(window.windowController.class)
> NSStringFromClass(window)
.
If the views inside the window is complex, you can use the following API to customize the capture。
Method¶
/// Create View
///
/// Called before the '-startViewWithName' method, which is used to record the loading time of the page. If the loading time cannot be obtained, this method may not be called.
/// - Parameters:
/// - viewName: Current View Name
/// - loadTime: The loading time of this view(ns)
-(void)onCreateView:(NSString *)viewName loadTime:(NSNumber *)loadTime;
/// view start
///
/// - Parameters:
/// - viewName: Current View Name
-(void)startViewWithName:(NSString *)viewName;
/// view start
/// - Parameters:
/// - viewName: Current View Name
/// - property: Extra Property (optional)
-(void)startViewWithName:(NSString *)viewName property:(nullable NSDictionary *)property;
/// view stop
-(void)stopView;
/// view stop
/// - Parameter property: Extra Property (optional)
-(void)stopViewWithProperty:(nullable NSDictionary *)property;
/// Create View
///
/// Called before the '-startViewWithName' method, which is used to record the loading time of the page. If the loading time cannot be obtained, this method may not be called.
/// - Parameters:
/// - viewName: Current View Name
/// - loadTime: The loading time of this view (ns)
open func onCreateView(_ viewName: String, loadTime: NSNumber)
/// view start
///
/// - Parameters:
/// - viewName: Current View Name
open func startView(withName viewName: String)
/// view start
/// - Parameters:
/// - viewName: Current View Name
/// - property: Extra Property (optional)
open func startView(withName viewName: String, property: [AnyHashable : Any]?)
/// view stop
open func stopView()
/// view stop
/// - Parameter property: Extra Property (optional)
open func stopView(withProperty property: [AnyHashable : Any]?)
Code Example¶
- (void)viewDidAppear{
[super viewDidAppear];
// Scene 1:
[[FTGlobalRumManager sharedManager] startViewWithName:@"TestVC"];
// Secne 2: extra property
[[FTGlobalRumManager sharedManager] startViewWithName:@"TestVC" property:@{@"custom_key":@"custom_value"}];
}
-(void)viewDidDisappear{
[super viewDidDisappear];
// Scene 1:
[[FTGlobalRumManager sharedManager] stopView];
// Secne 2: extra property
[[FTGlobalRumManager sharedManager] stopViewWithProperty:@{@"custom_key":@"custom_value"}];
}
override func viewDidAppear() {
super.viewDidAppear()
// Scene 1:
FTExternalDataManager.shared().startView(withName: "TestVC")
// Secne 2: extra property
FTExternalDataManager.shared().startView(withName: "TestVC",property: ["custom_key":"custom_value"])
}
override func viewDidDisappear() {
super.viewDidDisappear()
// Scene 1:
FTGlobalRumManager.shared().stopView()
// Secne 2: extra property
FTGlobalRumManager.shared().stopView(withProperty: ["custom_key":"custom_value"])
}
Action¶
Method¶
/// add action
///
/// - Parameters:
/// - actionName: action name
/// - actionType: action type
- (void)addActionName:(NSString *)actionName actionType:(NSString *)actionType;
/// add action
/// - Parameters:
/// - actionName: action name
/// - actionType: action type
/// - property: extra property (optional)
- (void)addActionName:(NSString *)actionName actionType:(NSString *)actionType property:(nullable NSDictionary *)property;
/// add action
///
/// - Parameters:
/// - actionName: action name
/// - actionType: action type
func addActionName(String, actionType: String)
/// add action
/// - Parameters:
/// - actionName: action name
/// - actionType: action type
/// - property: extra property (optional)
func addActionName(String, actionType: String, property: [AnyHashable : Any]?)
Code Example¶
Error¶
Method¶
/// add error data
///
/// - Parameters:
/// - type: error type
/// - message: error message detail
/// - stack: error log content
- (void)addErrorWithType:(NSString *)type message:(NSString *)message stack:(NSString *)stack;
/// add error data
/// - Parameters:
/// - type: error type
/// - message: error message detail
/// - stack: error log content
/// - property: extra property (optional)
- (void)addErrorWithType:(NSString *)type message:(NSString *)message stack:(NSString *)stack property:(nullable NSDictionary *)property;
/// add error data
/// - Parameters:
/// - type: error type
/// - state: application running state
/// - message: error message detail
/// - stack: error log content
/// - property: extra property (optional)
- (void)addErrorWithType:(NSString *)type state:(FTAppState)state message:(NSString *)message stack:(NSString *)stack property:(nullable NSDictionary *)property;
/// add error data
///
/// - Parameters:
/// - type: error type
/// - message: error message detail
/// - stack: error log content
func addError(withType: String, message: String, stack: String)
/// add error data
/// - Parameters:
/// - type: error type
/// - message: error message detail
/// - stack: error log content
/// - property: extra property (optional)
func addError(withType: String, message: String, stack: String, property: [AnyHashable : Any]?)
/// add error data
/// - Parameters:
/// - type: error type
/// - state: application running state
/// - message: error message detail
/// - stack: error log content
/// - property: extra property (optional)
open func addError(withType type: String, state: FTAppState, message: String, stack: String, property: [AnyHashable : Any]?)
Code Example¶
// Scene 1:
[[FTGlobalRumManager sharedManager] addErrorWithType:@"type" message:@"message" stack:@"stack"];
// Secne 2: extra property
[[FTGlobalRumManager sharedManager] addErrorWithType:@"ios_crash" message:@"crash_message" stack:@"crash_stack" property:@{@"custom_key":@"custom_value"}];
// Secne 3: extra property
[[FTGlobalRumManager sharedManager] addErrorWithType:@"ios_crash" state:FTAppStateUnknown message:@"crash_message" stack:@"crash_stack" property:@{@"custom_key":@"custom_value"}];
// Scene 1:
FTGlobalRumManager.shared().addError(withType: "custom_type", message: "custom_message", stack: "custom_stack")
// Secne 2: extra property
FTGlobalRumManager.shared().addError(withType: "custom_type", message: "custom_message", stack: "custom_stack",property: ["custom_key":"custom_value"])
// Secne 3: extra property
FTGlobalRumManager.shared().addError(withType: "custom_type", state: .unknown, message: "custom_message", stack: "custom_stack", property: ["custom_key":"custom_value"])
LongTask¶
Method¶
/// add long task data
///
/// - Parameters:
/// - stack: stack or log content
/// - duration: Duration, in nanoseconds.
- (void)addLongTaskWithStack:(NSString *)stack duration:(NSNumber *)duration;
/// add long task data
/// - Parameters:
/// - stack: stack or log content
/// - duration: Duration, in nanoseconds.
/// - property: extra property (optional)
- (void)addLongTaskWithStack:(NSString *)stack duration:(NSNumber *)duration property:(nullable NSDictionary *)property;
/// add long task data
///
/// - Parameters:
/// - stack: stack or log content
/// - duration: Duration, in nanoseconds.
func addLongTask(withStack: String, duration: NSNumber)
/// add long task data
/// - Parameters:
/// - stack: stack or log content
/// - duration: Duration, in nanoseconds.
/// - property: extra property (optional)
func addLongTask(withStack: String, duration: NSNumber, property: [AnyHashable : Any]?)
Code Example¶
Resource¶
Method¶
/// resource start
///
/// - Parameters:
/// - key: resource Id ,unique every request
- (void)startResourceWithKey:(NSString *)key;
/// resource start
/// - Parameters:
/// - key: resource Id ,unique every request
/// - property: extra property
- (void)startResourceWithKey:(NSString *)key property:(nullable NSDictionary *)property;
/// resource stop
///
/// - Parameters:
/// - key: resource Id ,unique every request
- (void)stopResourceWithKey:(NSString *)key;
/// resource stop
/// - Parameters:
/// - key: resource Id ,unique every request
/// - property: extra property
- (void)stopResourceWithKey:(NSString *)key property:(nullable NSDictionary *)property;
/// append network metrics and content data
///
/// - Parameters:
/// - key: resource Id ,unique every request
/// - metrics: request performance attributes
/// - content: request data
- (void)addResourceWithKey:(NSString *)key metrics:(nullable FTResourceMetricsModel *)metrics content:(FTResourceContentModel *)content;
/// resource start
///
/// - Parameters:
/// - key: resource Id ,unique every request
open func startResource(withKey key: String)
/// resource start
/// - Parameters:
/// - key: resource Id ,unique every request
/// - property: extra property
open func startResource(withKey key: String, property: [AnyHashable : Any]?)
/// resource stop
///
/// - Parameters:
/// - key: resource Id ,unique every request
open func stopResource(withKey key: String)
/// resource stop
/// - Parameters:
/// - key: resource Id ,unique every request
/// - property: extra property
open func stopResource(withKey key: String, property: [AnyHashable : Any]?)
/// append network metrics and content data
///
/// - Parameters:
/// - key: resource Id ,unique every request
/// - metrics: request performance attributes
/// - content: request data
open func addResource(withKey key: String, metrics: FTResourceMetricsModel?, content: FTResourceContentModel)
Code Example¶
#import "FTMacOSSDK.h"
//step 1: Before the network request starts
[[FTGlobalRumManager sharedManager] startResourceWithKey:key];
//step 2:Request completed
[[FTGlobalRumManager sharedManager] stopResourceWithKey:key];
//step 3:① Add resource data
//FTResourceContentModel
FTResourceContentModel *content = [[FTResourceContentModel alloc]init];
content.httpMethod = request.HTTPMethod;
content.requestHeader = request.allHTTPHeaderFields;
content.responseHeader = httpResponse.allHeaderFields;
content.httpStatusCode = httpResponse.statusCode;
content.responseBody = responseBody;
//ios native
content.error = error;
//② If the performance data of the network request can be obtained
//FTResourceMetricsModel
//ios native. Get NSURLSessionTaskMetrics data, directly use the initialization method of FTResourceMetricsModel
FTResourceMetricsModel *metricsModel = [[FTResourceMetricsModel alloc]initWithTaskMetrics:metrics];
//other platforms. All time data in nanoseconds
FTResourceMetricsModel *metricsModel = [[FTResourceMetricsModel alloc]init];
// step 4:add resource: If there is no performance data, the metrics parameter is set to nil
[[FTGlobalRumManager sharedManager] addResourceWithKey:key metrics:metricsModel content:content];
import FTMacOSSDK
//step 1: Before the network request starts
FTGlobalRumManager.shared().startResource(withKey: key)
//step 2:Request completed
FTGlobalRumManager.shared().stopResource(withKey: resource.key)
//step 3:① Add resource data
let contentModel = FTResourceContentModel(request: task.currentRequest!, response: task.response as? HTTPURLResponse, data: resource.data, error: error)
//② If the performance data of the network request can be obtained
//FTResourceMetricsModel
//ios native. Get NSURLSessionTaskMetrics data, directly use the initialization method of FTResourceMetricsModel
var metricsModel:FTResourceMetricsModel?
if let metrics = resource.metrics {
metricsModel = FTResourceMetricsModel(taskMetrics:metrics)
}
//other platforms. All time data in nanoseconds
metricsModel = FTResourceMetricsModel()
...
// step 4:add resource: If there is no performance data, the metrics parameter is set to nil
FTGlobalRumManager.shared().addResource(withKey: resource.key, metrics: metricsModel, content: contentModel)
Resource url filter¶
When the automatic collection is enabled, the internal processing will not collect the data reporting address of the SDK. You can also set filter conditions through the Open API to collect the network addresses you need.
Method¶
Code Example¶
Logging¶
Method¶
// FTSDKAgent.h
// FTMacOSSDK
/// add log
/// @param content Log content, which can be a json string
/// @param status Log Level (info、warning、error、critical、ok).
-(void)logging:(NSString *)content status:(FTStatus)status;
/// add log
/// @param content Log content, which can be a json string
/// @param status Log Level (info、warning、error、critical、ok).
/// @param property Extra Property (optional)
-(void)logging:(NSString *)content status:(FTLogStatus)status property:(nullable NSDictionary *)property;
//
// FTLogger.h
// FTMacOSSDK
/// add info type log
/// - Parameters:
/// - content: Log content, which can be a json string
/// - property: Extra Property (optional)
-(void)info:(NSString *)content property:(nullable NSDictionary *)property;
/// add warning type log
/// - Parameters:
/// - content: Log content, which can be a json string
/// - property: Extra Property (optional)
-(void)warning:(NSString *)content property:(nullable NSDictionary *)property;
/// add error type log
/// - Parameters:
/// - content: Log content, which can be a json string
/// - property: Extra Property (optional)
-(void)error:(NSString *)content property:(nullable NSDictionary *)property;
/// add critical type log
/// - Parameters:
/// - content: Log content, which can be a json string
/// - property: Extra Property (optional)
-(void)critical:(NSString *)content property:(nullable NSDictionary *)property;
/// add ok type log
/// - Parameters:
/// - content: Log content, which can be a json string
/// - property: Extra Property (optional)
-(void)ok:(NSString *)content property:(nullable NSDictionary *)property;
open class FTSDKAgent : NSObject {
/// add log
///
/// - Parameters:
/// - content: Log content, can be a json string
/// - status: Log Level (info、warning、error、critical、ok).
open func logging(_ content: String, status: FTLogStatus)
/// add log
/// - Parameters:
/// - content: Log content, can be a json string
/// - status: Log Level (info、warning、error、critical、ok).
/// - property: Extra Property (optional)
open func logging(_ content: String, status: FTLogStatus, property: [AnyHashable : Any]?)
}
open class FTLogger : NSObject, FTLoggerProtocol {}
public protocol FTLoggerProtocol : NSObjectProtocol {
/// add info type log
/// - Parameters:
/// - content: Log content, can be a json string
/// - property: Extra Property (optional)
optional func info(_ content: String, property: [AnyHashable : Any]?)
/// add warning type log
/// - Parameters:
/// - content: Log content, can be a json string
/// - property: Extra Property (optional)
optional func warning(_ content: String, property: [AnyHashable : Any]?)
/// add error type log
/// - Parameters:
/// - content: Log content, can be a json string
/// - property: Extra Property (optional)
optional func error(_ content: String, property: [AnyHashable : Any]?)
/// add critical type log
/// - Parameters:
/// - content: Log content, can be a json string
/// - property: Extra Property (optional)
optional func critical(_ content: String, property: [AnyHashable : Any]?)
/// add ok type log
/// - Parameters:
/// - content: Log content, can be a json string
/// - property: Extra Property (optional)
optional func ok(_ content: String, property: [AnyHashable : Any]?)
}
Log level¶
Code Example¶
// Method 1:Use FTSDKAgent
// Note: Ensure that the SDK has been successfully initialized at the time of use, otherwise failure will be asserted in the test environment resulting in a crash.
[[FTSDKAgent sharedInstance] logging:@"test_custom" status:FTStatusInfo];
// Method 2:Use FTLogger (recommend)
// If the SDK is not initialized successfully, calling the methods in FTLogger to add custom logs will fail, but there will be no assertion failure crash.
[[FTLogger sharedInstance] info:@"test" property:@{@"custom_key":@"custom_value"}];
// Method 1:Use FTSDKAgent
// Note: Ensure that the SDK has been successfully initialized at the time of use, otherwise failure will be asserted in the test environment resulting in a crash.
FTSDKAgent.sharedInstance().logging("contentStr", status: .statusInfo, property:["custom_key":"custom_value"])
// Method 2:Use FTLogger (recommend)
// If the SDK is not initialized successfully, calling the methods in FTLogger to add custom logs will fail, but there will be no assertion failure crash.
FTLogger.shared().info("contentStr", property: ["custom_key":"custom_value"])
Print Custom Log To Console¶
Set 'printCustomLogToConsole = YES' to enable the output of custom logs to the console. You will see logs in the following format in the xcode debug console:
2023-06-29 13:47:56.960021+0800 App[64731:44595791]
:os_log Specifies the standard prefix of log output (< xcode 15);
[MACOS APP]
:The prefix is used to distinguish the custom log output by the SDK;
[INFO]
:Customize the log level;
content
:Customize log content;
{K=V,...,Kn=Vn}
:Extra Property 。
Network Link Tracing¶
You can FTTraceConfig
configuration to turn on automatic mode, or manually add. Trace related data, through the FTTraceManager
singleton, to pass in, the relevant API as follows.
Method¶
Code Example¶
NSString *key = [[NSUUID UUID]UUIDString];
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
//manual operation required: Get trace header before the request and add it to the request header
NSDictionary *traceHeader = [[FTTraceManager sharedInstance] getTraceHeaderWithKey:key url:url];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
if (traceHeader && traceHeader.allKeys.count>0) {
[traceHeader enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
[request setValue:value forHTTPHeaderField:field];
}];
}
NSURLSession *session=[NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//your code
}];
[task resume];
let url:URL = NSURL.init(string: "https://www.baidu.com")! as URL
if let traceHeader = FTTraceManager.sharedInstance().getTraceHeader(withKey: NSUUID().uuidString, url: url) {
let request = NSMutableURLRequest(url: url)
//manual operation required: Get trace header before the request and add it to the request header
for (a,b) in traceHeader {
request.setValue(b as? String, forHTTPHeaderField: a as! String)
}
let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
//your code
}
task.resume()
}
User Information Binding and Unbinding¶
Method¶
/// Bind user information
///
/// - Parameters:
/// - Id: user id
- (void)bindUserWithUserID:(NSString *)userId;
/// Bind user information
///
/// - Parameters:
/// - Id: user id
/// - userName: user name
/// - userEmailL: user email
- (void)bindUserWithUserID:(NSString *)Id userName:(nullable NSString *)userName userEmail:(nullable NSString *)userEmail;
/// Bind user information
///
/// - Parameters:
/// - Id: user id
/// - userName: user name
/// - userEmail: user email
/// - extra: extar infomation
- (void)bindUserWithUserID:(NSString *)Id userName:(nullable NSString *)userName userEmail:(nullable NSString *)userEmail extra:(nullable NSDictionary *)extra;
/// Unbind user information
- (void)unbindUser;
/// Bind user information
///
/// - Parameters:
/// - Id: user id
open func bindUser(withUserID userId: String)
/// Bind user information
///
/// - Parameters:
/// - Id: user id
/// - userName: user name
/// - userEmailL: user email
open func bindUser(withUserID Id: String, userName: String?, userEmail: String?)
/// Bind user information
///
/// - Parameters:
/// - Id: user id
/// - userName: user name
/// - userEmail: user email
/// - extra: extar infomation
open func bindUser(withUserID Id: String, userName: String?, userEmail: String?, extra: [AnyHashable : Any]?)
/// Unbind user information
open func unbindUser()
Code Example¶
// bind user info after log in
[[FTSDKAgent sharedInstance] bindUserWithUserID:USERID];
// or
[[FTSDKAgent sharedInstance] bindUserWithUserID:USERID userName:USERNAME userEmail:USEREMAIL];
// or
[[FTSDKAgent sharedInstance] bindUserWithUserID:USERID userName:USERNAME userEmail:USEREMAIL extra:@{EXTRA_KEY:EXTRA_VALUE}];
// clear user data after log out
[[FTSDKAgent sharedInstance] unbindUser];
// bind user info after log in
FTSDKAgent.sharedInstance().bindUser(withUserID: USERID)
// or
FTSDKAgent.sharedInstance().bindUser(withUserID: USERID, userName: USERNAME, userEmail: USEREMAIL)
// or
FTSDKAgent.sharedInstance().bindUser(withUserID: USERID, userName: USERNAME, userEmail: USEREMAIL,extra:[EXTRA_KEY:EXTRA_VALUE])
// clear user data after log out
FTSDKAgent.sharedInstance().unbindUser()
Close SDK¶
Using FTSDKAgent
to close SDK
Method¶
Code Example¶
Add Custom Tags¶
Static Use¶
You can create multiple Configurations to set values using pre-compiled instructions
- Create multiple configurations.
- Set preset properties to distinguish between Configurations.
- Use the pre-compile command.
//Target -> Build Settings -> GCC_PREPROCESSOR_DEFINITIONS
#if PRE
#define Track_id @"0000000001"
#define STATIC_TAG @"preprod"
#elif DEVELOP
#define Track_id @"0000000002"
#define STATIC_TAG @"common"
#else
#define Track_id @"0000000003"
#define STATIC_TAG @"prod"
#endif
FTRumConfig *rumConfig = [[FTRumConfig alloc]init];
rumConfig.globalContext = @{@"track_id":Track_id,@"static_tag":STATIC_TAG};
... //other set
[[FTSDKAgent sharedInstance] startRumWithConfigOptions:rumConfig];
Dynamic Use¶
Since the globalContext set after RUM is started will not take effect, users can save it locally and set it to take effect the next time the application is started.
- Save it locally by saving a file, e.g.
NSUserDefaults
, configure it usingSDK
and add the code to get the tag data in the configuration.
NSString *dynamicTag = [[NSUserDefaults standardUserDefaults] valueForKey:@"DYNAMIC_TAG"]?:@"NO_VALUE";
FTRumConfig *rumConfig = [[FTRumConfig alloc]init];
rumConfig.globalContext = @{@"dynamic_tag":dynamicTag};
... //other set
[[FTSDKAgent sharedInstance] startRumWithConfigOptions:rumConfig];
- Add a way to change the file data anywhere.
- Finally restart the application to take effect.
Attention¶
-
Special key : track_id (configured in RUM for tracking function)
-
When the user adds a custom tag through globalContext and the SDK has the same tag, the SDK tag will override the user's settings, it is recommended that the tag name add the prefix of the project abbreviation, such as
df_tag_name
. -
Set the globalContext before calling the -startRumWithConfigOptions method to start RUM to take effect.
-
Custom tags configured in
FTSDKConfig
will be added to all types of data.
For more details, please see SDK Demo。
Frequently Asked Questions¶
About crash log analysis¶
An Include of non-modular header inside framework module
occurred¶
Because the SDK's .h file introduces a library-dependent .h file, it needs to be set
Target
-> Build Settings
-> CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES
set YES.