コンテンツにスキップ

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 が追加されます。
  • FTRumConfig.enableTraceUserResourceFTTraceConfig.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)
    }
}

フィードバック

このページは役に立ちましたか?