콘텐츠로 이동

URLSession 커스텀 네트워크 수집

URLSession Delegate를 통한 커스텀 네트워크 수집

SDK는 FTURLSessionDelegate 클래스를 제공합니다. 이 클래스를 사용하여 특정 URLSession이 시작한 네트워크 요청에 대해 커스텀 RUM Resource 수집분산 추적을 수행할 수 있습니다.

  • FTURLSessionDelegatetraceInterceptor 블록을 설정하여 URLResquest를 가로채고 커스텀 분산 추적을 지원합니다 (SDK 1.5.9 이상 버전에서 지원). 우선순위는 FTTraceConfig.traceInterceptor보다 높습니다.
  • FTURLSessionDelegateprovider 블록을 설정하여 RUM Resource에 추가로 수집할 속성을 커스텀할 수 있습니다. 우선순위는 FTRumConfig.resourcePropertyProvider보다 높습니다.
  • FTURLSessionDelegateerrorFilter 블록을 설정하여 SessionTask Error 가로채기 여부를 커스텀할 수 있습니다 (SDK 1.5.17 이상 버전에서 지원).
    • return YES: 가로챔, RUM-Error에 해당 network_error가 추가되지 않습니다.
    • return NO: 가로채지 않음, RUM-Error에 해당 network_error가 추가됩니다.
  • FTRumConfig.enableTraceUserResource, FTTraceConfig.enableAutoTrace와 함께 사용할 경우 우선순위는 커스텀 > 자동 수집입니다.

다양한 시나리오를 충족하기 위해 세 가지 방법을 제공합니다.

방법 1

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)

방법 2

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)
        // 사용자 정의 로직
        // ......
    }
}

방법 3

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)
    }
}

문서 평가

이 페이지가 도움이 되었나요?