URLSession カスタムネットワーク収集¶
URLSession Delegate の転送によるカスタムネットワーク収集の設定¶
SDK はクラス FTURLSessionDelegate を提供しており、このクラスを使用して特定の URLSession が開始するネットワークリクエストのカスタム RUM Resource 収集および分散型トレーシングを実行できます。
FTURLSessionDelegateは、traceInterceptorブロックを設定してURLResquestをインターセプトし、カスタムの分散型トレーシングを行うことをサポートしています(SDK 1.5.9 以降でサポート)。優先順位はFTTraceConfig.traceInterceptorより高くなります。FTURLSessionDelegateは、providerブロックを設定して RUM Resource に追加で収集する属性をカスタマイズすることをサポートしています。優先順位はFTRumConfig.resourcePropertyProviderより高くなります。FTURLSessionDelegateは、errorFilterブロックを設定して SessionTask Error をインターセプトするかどうかをカスタマイズすることをサポートしています(SDK 1.5.17 以降でサポート)。- return YES:インターセプトします。RUM-Error にこの
network_errorは追加されません。 - return NO:インターセプトしません。RUM-Error にこの
network_errorが追加されます。
- return YES:インターセプトします。RUM-Error にこの
FTRumConfig.enableTraceUserResource、FTTraceConfig.enableAutoTraceと一緒に使用する場合、優先順位は カスタム > 自動収集 となります。
以下に、さまざまなシナリオに対応する 3 つの方法を提供します。
方法一¶
URLSession の delegate オブジェクトを FTURLSessionDelegate のインスタンスに直接設定します。
id<NSURLSessionDelegate> delegate = [[FTURLSessionDelegate alloc]init];
// カスタム RUM リソース属性を追加します。タグ名にはプロジェクトの略語をプレフィックスとして付けることを推奨します(例:`df_tag_name`)。
delegate.provider = ^NSDictionary * _Nullable(NSURLRequest *request, NSURLResponse *response, NSData *data, NSError *error) {
NSString *body = [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding];
return @{@"df_requestbody":body};
};
// カスタム trace をサポートします。インターセプトする場合は TraceContext を返し、インターセプトしない場合は nil を返します。
delegate.traceInterceptor = ^FTTraceContext * _Nullable(NSURLRequest *request) {
FTTraceContext *context = [FTTraceContext new];
context.traceHeader = @{@"trace_key":@"trace_value"};
context.traceId = @"trace_id";
context.spanId = @"span_id";
return context;
};
// SessionTask Error をインターセプトするかどうかをカスタマイズします。return YES:インターセプトし、RUM-Error にこの `network_error` は追加されません。
delegate.errorFilter = ^BOOL(NSError * _Nonnull error) {
return error.code == NSURLErrorCancelled;
};
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:delegate delegateQueue:nil];
let delegate = FTURLSessionDelegate.init()
// カスタム RUM リソース属性を追加します。タグ名にはプロジェクトの略語をプレフィックスとして付けることを推奨します(例:`df_tag_name`)。
delegate.provider = { request,response,data,error in
var extraData:Dictionary<String, Any> = Dictionary()
if let data = data,let requestBody = String(data: data, encoding: .utf8) {
extraData["df_requestBody"] = requestBody
}
if let error = error {
extraData["df_error"] = error.localizedDescription
}
return extraData
}
// カスタム trace をサポートします。インターセプトする場合は TraceContext を返し、インターセプトしない場合は nil を返します。
delegate.traceInterceptor = { request in
let traceContext = FTTraceContext()
traceContext.traceHeader = ["trace_key":"trace_value"]
traceContext.spanId = "spanId"
traceContext.traceId = "traceId"
return traceContext
}
delegate.errorFilter = { error in
return (error as? URLError)?.code == .cancelled
}
let session = URLSession.init(configuration: URLSessionConfiguration.default, delegate:delegate
, delegateQueue: nil)
方法二¶
URLSession の delegate オブジェクトを FTURLSessionDelegate クラスから継承させます。
delegate オブジェクトが以下のメソッドを実装している場合は、メソッド内で親クラスの該当メソッドを必ず呼び出してください。
-URLSession:dataTask:didReceiveData:-URLSession:task:didCompleteWithError:-URLSession:task:didFinishCollectingMetrics:
@interface InstrumentationInheritClass:FTURLSessionDelegate
@property (nonatomic, strong) NSURLSession *session;
@end
@implementation InstrumentationInheritClass
-(instancetype)init{
self = [super init];
if(self){
_session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
// カスタム RUM リソース属性を追加します。タグ名にはプロジェクトの略語をプレフィックスとして付けることを推奨します(例:`df_tag_name`)。
self.provider = ^NSDictionary * _Nullable(NSURLRequest *request, NSURLResponse *response, NSData *data, NSError *error) {
NSString *body = [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding];
return @{@"df_requestbody":body};
};
// カスタム trace をサポートします。インターセプトする場合は TraceContext を返し、インターセプトしない場合は nil を返します。
self.traceInterceptor = ^FTTraceContext * _Nullable(NSURLRequest *request) {
FTTraceContext *context = [FTTraceContext new];
context.traceHeader = @{@"trace_key":@"trace_value"};
context.traceId = @"trace_id";
context.spanId = @"span_id";
return context;
};
// SessionTask Error をインターセプトするかどうかをカスタマイズします。return YES:インターセプトし、RUM-Error にこの `network_error` は追加されません。
self.errorFilter = ^BOOL(NSError * _Nonnull error) {
return error.code == NSURLErrorCancelled;
};
}
return self;
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics{
// 必ず親クラスのメソッドを呼び出してください
[super URLSession:session task:task didFinishCollectingMetrics:metrics];
// ご自身のロジック
// ......
}
@end
class InheritHttpEngine:FTURLSessionDelegate {
var session:URLSession?
override init(){
session = nil
super.init()
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = 30
session = URLSession.init(configuration: configuration, delegate:self, delegateQueue: nil)
override init() {
super.init()
// カスタム RUM リソース属性を追加します。タグ名にはプロジェクトの略語をプレフィックスとして付けることを推奨します(例:`df_tag_name`)。
provider = { request,response,data,error in
var extraData:Dictionary<String, Any> = Dictionary()
if let data = data,let requestBody = String(data: data, encoding: .utf8) {
extraData["df_requestBody"] = requestBody
}
if let error = error {
extraData["df_error"] = error.localizedDescription
}
return extraData
}
// カスタム trace をサポートします。インターセプトする場合は TraceContext を返し、インターセプトしない場合は nil を返します。
traceInterceptor = { request in
let traceContext = FTTraceContext()
traceContext.traceHeader = ["trace_key":"trace_value"]
traceContext.spanId = "spanId"
traceContext.traceId = "traceId"
return traceContext
}
errorFilter = { error in
return (error as? URLError)?.code == .cancelled
}
}
}
override func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
// 必ず親クラスのメソッドを呼び出してください
super.urlSession(session, task: task, didFinishCollecting: metrics)
// ユーザー自身のロジック
// ......
}
}
方法三¶
URLSession の delegate オブジェクトに FTURLSessionDelegateProviding プロトコルを準拠させます。
- プロトコル内の
ftURLSessionDelegateプロパティの get メソッドを実装します。 - 以下の URLSession の delegate メソッドを
ftURLSessionDelegateに転送し、SDK がデータ収集を行えるようにします。-URLSession:dataTask:didReceiveData:-URLSession:task:didCompleteWithError:-URLSession:task:didFinishCollectingMetrics:
@interface UserURLSessionDelegateClass:NSObject<NSURLSessionDataDelegate,FTURLSessionDelegateProviding>
@end
@implementation UserURLSessionDelegateClass
@synthesize ftURLSessionDelegate = _ftURLSessionDelegate;
- (nonnull FTURLSessionDelegate *)ftURLSessionDelegate {
if(!_ftURLSessionDelegate){
_ftURLSessionDelegate = [[FTURLSessionDelegate alloc]init];
// カスタム RUM リソース属性を追加します。タグ名にはプロジェクトの略語をプレフィックスとして付けることを推奨します(例:`df_tag_name`)。
_ftURLSessionDelegate.provider = ^NSDictionary * _Nullable(NSURLRequest *request, NSURLResponse *response, NSData *data, NSError *error) {
NSString *body = [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding];
return @{@"df_requestbody":body};
};
// カスタム trace をサポートします。インターセプトする場合は TraceContext を返し、インターセプトしない場合は nil を返します。
_ftURLSessionDelegate.requestInterceptor = ^NSURLRequest * _Nonnull(NSURLRequest * _Nonnull request) {
NSDictionary *traceHeader = [[FTExternalDataManager sharedManager] getTraceHeaderWithUrl:request.URL];
NSMutableURLRequest *newRequest = [request mutableCopy];
if(traceHeader){
for (NSString *key in traceHeader.allKeys) {
[newRequest setValue:traceHeader[key] forHTTPHeaderField:key];
}
}
return newRequest;
};
// SessionTask Error をインターセプトするかどうかをカスタマイズします。return YES:インターセプトし、RUM-Error にこの `network_error` は追加されません。
_ftURLSessionDelegate.errorFilter = ^BOOL(NSError * _Nonnull error) {
return error.code == NSURLErrorCancelled;
};
}
return _ftURLSessionDelegate;
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
[self.ftURLSessionDelegate URLSession:session dataTask:dataTask didReceiveData:data];
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
[self.ftURLSessionDelegate URLSession:session task:task didCompleteWithError:error];
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics{
[self.ftURLSessionDelegate URLSession:session task:task didFinishCollectingMetrics:metrics];
}
@end
class HttpEngine:NSObject,URLSessionDataDelegate,FTURLSessionDelegateProviding {
var ftURLSessionDelegate: FTURLSessionDelegate = FTURLSessionDelegate()
var session:URLSession?
override init(){
session = nil
super.init()
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = 30
session = URLSession.init(configuration: configuration, delegate:self, delegateQueue: nil)
// カスタム RUM リソース属性を追加します。タグ名にはプロジェクトの略語をプレフィックスとして付けることを推奨します(例:`df_tag_name`)。
ftURLSessionDelegate.provider = { request,response,data,error in
var extraData:Dictionary<String, Any> = Dictionary()
if let data = data,let requestBody = String(data: data, encoding: .utf8) {
extraData["df_requestBody"] = requestBody
}
if let error = error {
extraData["df_error"] = error.localizedDescription
}
return extraData
}
// カスタム trace をサポートします。インターセプトする場合は TraceContext を返し、インターセプトしない場合は nil を返します。
ftURLSessionDelegate.traceInterceptor = { request in
let traceContext = FTTraceContext()
traceContext.traceHeader = ["trace_key":"trace_value"]
traceContext.spanId = "spanId"
traceContext.traceId = "traceId"
return traceContext
}
ftURLSessionDelegate.errorFilter = { error in
return (error as? URLError)?.code == .cancelled
}
}
// 以下のメソッドは必ず実装してください
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
ftURLSessionDelegate.urlSession(session, dataTask: dataTask, didReceive: data)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
ftURLSessionDelegate.urlSession(session, task: task, didFinishCollecting: metrics)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
ftURLSessionDelegate.urlSession(session, task: task, didCompleteWithError: error)
}
}