diff --git a/packages/core/ios/RNEmbrace/EmbraceManager.m b/packages/core/ios/RNEmbrace/EmbraceManager.m index 6bc573ab..b67e3aa7 100755 --- a/packages/core/ios/RNEmbrace/EmbraceManager.m +++ b/packages/core/ios/RNEmbrace/EmbraceManager.m @@ -125,7 +125,7 @@ @interface RCT_EXTERN_MODULE(EmbraceManager, NSObject) endInMillis:(double)endInMillis bytesSent:(double)bytesSent bytesReceived:(double)bytesReceived - statusCode:(double)statusCode + statusCode:(int)statusCode error:(NSString *)error resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) @@ -135,7 +135,7 @@ @interface RCT_EXTERN_MODULE(EmbraceManager, NSObject) startInMillis:(double)startInMillis endInMillis:(double)endInMillis errorType:(NSString *)errorType - error:(NSString *)error + errorMessage:(NSString *)errorMessage resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) diff --git a/packages/core/ios/RNEmbrace/EmbraceManager.swift b/packages/core/ios/RNEmbrace/EmbraceManager.swift index ce189352..a6dd92cd 100644 --- a/packages/core/ios/RNEmbrace/EmbraceManager.swift +++ b/packages/core/ios/RNEmbrace/EmbraceManager.swift @@ -391,14 +391,14 @@ class EmbraceManager: NSObject { private func errorCodeFrom(str: String) -> ErrorCode? { switch str { - case "Failure": - return .failure - case "UserAbandon": - return .userAbandon - case "Unknown": - return .unknown - default: - return nil + case "Failure": + return .failure + case "UserAbandon": + return .userAbandon + case "Unknown": + return .unknown + default: + return nil } } @@ -603,30 +603,40 @@ class EmbraceManager: NSObject { endInMillis: Double, bytesSent: Double, bytesReceived: Double, - statusCode: Double, + statusCode: Int, error: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock ) { if Embrace.client == nil { - reject("RECORD_LOG_NETWORK_REQUEST_ERROR", "Error recording span, Embrace SDK may not be initialized", nil) + reject("RECORD_LOG_NETWORK_REQUEST_ERROR", "Error recording a network request, Embrace SDK may not be initialized", nil) return } - - let attributes = attributeStringsFrom(dict: [ - "http.response.status_code": String(Int(statusCode)), - "http.request.body.size": String(Int(bytesSent)), - "http.response.body.size": String(Int(bytesReceived)), + + var attributes = [ "http.request.method": httpMethod.uppercased(), "url.full": url, - ]); + ]; + + if statusCode >= 0 { + attributes["http.response.status_code"] = String(statusCode); + } + + if bytesSent >= 0 { + attributes["http.request.body.size"] = String(Int(bytesSent)); + } + + if bytesReceived >= 0 { + attributes["http.response.body.size"] = String(Int(bytesReceived)); + } Embrace.client?.recordCompletedSpan(name: createNetworkSpanName(url: url, httpMethod: httpMethod), type: SpanType.networkRequest, parent: nil, startTime: dateFrom(ms: startInMillis), endTime: dateFrom(ms: endInMillis), - attributes: attributes, + attributes: attributeStringsFrom(dict: attributes as NSDictionary), events: eventsFrom(array: []), - errorCode: errorCodeFrom(str: error)) + errorCode: errorCodeFrom(str: error) + ); resolve(true) } @@ -638,29 +648,33 @@ class EmbraceManager: NSObject { startInMillis: Double, endInMillis: Double, errorType: String, - error: String, + errorMessage: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock ) { if Embrace.client == nil { - reject("RECORD_LOG_NETWORK_CLIENT_ERROR_ERROR", "Error recording span, Embrace SDK may not be initialized", nil) + reject("RECORD_LOG_NETWORK_CLIENT_ERROR_ERROR", "Error recording a network client error, Embrace SDK may not be initialized", nil) return } - let attributes = attributeStringsFrom(dict: [ - "http.request.method": httpMethod.uppercased(), - "url.full": url, - "error.message": error, - "error.type": errorType, - ]); - Embrace.client?.recordCompletedSpan(name: createNetworkSpanName(url: url, httpMethod: httpMethod), type: SpanType.networkRequest, parent: nil, startTime: dateFrom(ms: startInMillis), endTime: dateFrom(ms: endInMillis), - attributes: attributes, + attributes: attributeStringsFrom(dict: [ + "http.request.method": httpMethod.uppercased(), + "url.full": url, + "error.message": errorMessage, + "error.type": errorType, + + // NOTE: this should be handled by iOS native sdk using `errorCode` value + // To remove from here when it's done. + "emb.error_code": "failure", + ]), events: eventsFrom(array: []), - errorCode: errorCodeFrom(str: error)) + // this should be used to calc `emb.error_code` + errorCode: ErrorCode.failure + ); resolve(true) } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 75702344..b763ff5e 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -297,84 +297,6 @@ export const recordNetworkRequest = ( statusCode?: number, error?: string, ): Promise => { - /** - * Android / Java - { - "trace_id" : "70da1fe78061e4491282ca56420c77aa", - "span_id" : "0999f87c9506795f", - "parent_span_id" : "0000000000000000", - "name" : "emb-GET /get", - "start_time_unix_nano" : 1723146380892000000, - "end_time_unix_nano" : 1723146390892000000, - "status" : "Unset", - "events" : [ ], - "attributes" : [ { - "key" : "http.response.body.size", - "value" : "222" - }, { - "key" : "http.request.method", - "value" : "GET" - }, { - "key" : "emb.private.sequence_id", - "value" : "11" - }, { - "key" : "http.request.body.size", - "value" : "111" - }, { - "key" : "emb.type", - "value" : "perf.network_request" - }, { - "key" : "emb.process_identifier", - "value" : "254ec58ba0931b64" - }, { - "key" : "url.full", - "value" : "https://httpbin.org/get" - }, { - "key" : "http.response.status_code", - "value" : "200" - } ] - } - */ - - /** - * iOS / Swift - { - "end_time_unix_nano" : 1723150350412000000, - "trace_id" : "4501f3bab412f48719997d9eac1f618e", - "status" : "ok", - "name" : "emb-GET /get", - "span_id" : "84e49684547d60b0", - "attributes" : [ { - "key" : "emb.private.sequence_id", - "value" : "?" - }, { - "key" : "http.response.body.size", - "value" : "222" - }, { - "key" : "http.request.method", - "value" : "GET" - }, { - "key" : "http.request.body.size", - "value" : "111" - }, { - "key" : "http.response.status_code", - "value" : "200" - }, { - "key" : "url.full", - "value" : "https://httpbin.org/get" - }, { - "key" : "emb.process_identifier", - "value" : "?" - }, { - "key" : "emb.type", - "value" : "perf.network_request" - } ], - "links" : [ ], - "start_time_unix_nano" : 1723150346412000000, - "events" : [ ] - } - */ - return NativeModules.EmbraceManager.logNetworkRequest( url, httpMethod, @@ -383,7 +305,7 @@ export const recordNetworkRequest = ( bytesSent || -1, bytesReceived || -1, statusCode || -1, - error, + error || "", ); }; @@ -395,71 +317,6 @@ export const logNetworkClientError = ( errorType: string, errorMessage: string, ): Promise => { - /** - * Android / Java - { - "trace_id" : "b95f3899f4dc45b861eb2c1ee32d91f4", - "span_id" : "5ebc025d9c88b256", - "parent_span_id" : "0000000000000000", - "name" : "emb-POST /error", - "start_time_unix_nano" : 1723151955086000000, - "end_time_unix_nano" : 1723151970086000000, - "status" : "Error", - "events" : [ ], - "attributes" : [ { - "key" : "error.type", - "value" : "ERROR" - }, { - "key" : "http.request.method", - "value" : "POST" - }, { - "key" : "emb.private.sequence_id", // from where does it come? - "value" : "13" - }, { - "key" : "error.message", - "value" : "error message" - }, { - "key" : "emb.type", - "value" : "perf.network_request" - }, { - "key" : "emb.error_code", - "value" : "failure" - }, { - "key" : "emb.process_identifier", // from where does it come? - "value" : "0e047c8bb522a0d8" - }, { - "key" : "url.full", - "value" : "https://httpbin.org/error" - } ] - } - */ - - /** - * iOS / Swift - { - "attributes" : [ { - "value" : "ERROR", - "key" : "http.response.status_code" - }, { - "key" : "url.full", - "value" : "https://httpbin.org/error" - }, { - "key" : "emb.type", - "value" : "perf.network_request" - }, { - "key" : "http.request.method", - "value" : "POST" - } ], - "events" : [ ], - "span_id" : "b60cb504564cccc5", - "name" : "emb-POST /POST", - "links" : [ ], - "start_time_unix_nano" : 1723152234916999936, - "trace_id" : "83230a439e1ce6b361ee189b1aa8f478", - "end_time_unix_nano" : 1723152210916999936, - "status" : "ok" - } - */ return NativeModules.EmbraceManager.logNetworkClientError( url, httpMethod, diff --git a/packages/core/test-project/ios/RNEmbraceTests/RNEmbraceTests.swift b/packages/core/test-project/ios/RNEmbraceTests/RNEmbraceTests.swift index faff62f2..1eb21d9c 100644 --- a/packages/core/test-project/ios/RNEmbraceTests/RNEmbraceTests.swift +++ b/packages/core/test-project/ios/RNEmbraceTests/RNEmbraceTests.swift @@ -519,16 +519,18 @@ class EmbraceSpansTests: XCTestCase { } func testLogNetworkRequest() async throws { - module.logNetworkRequest("https://otest.com/v1/products", httpMethod: "get", startInMillis: 1723221815889, endInMillis: 1723221815891, bytesSent: 1000, bytesReceived: 2000, statusCode: 200, error: "", resolver: promise.resolve, rejecter: promise.reject) + module.logNetworkRequest("https://otest.com/v1/products", httpMethod: "get", startInMillis: 1723221815889, endInMillis: 1723221815891, bytesSent: 1000, bytesReceived: 2000, statusCode: 200, error: "my error", resolver: promise.resolve, rejecter: promise.reject) XCTAssertEqual(promise.resolveCalls.count, 1) XCTAssertTrue((promise.resolveCalls[0] as? Bool)!) - module.logNetworkRequest("https://otest.com/", httpMethod: "POST", startInMillis: 1723221815889, endInMillis: 1723221815891, bytesSent: 1000, bytesReceived: 2000, statusCode: 200, error: "", resolver: promise.resolve, rejecter: promise.reject) + module.logNetworkRequest("https://otest.com/", httpMethod: "POST", startInMillis: 1723221815889, endInMillis: 1723221815891, bytesSent: -1, bytesReceived: -2, statusCode: -1, error: "", resolver: promise.resolve, rejecter: promise.reject) let exportedSpans = try await getExportedSpans() XCTAssertEqual(exportedSpans[0].name, "emb-GET /v1/products") + XCTAssertEqual(exportedSpans[0].startTime, Date(timeIntervalSince1970: 1723221815.889)) + XCTAssertEqual(exportedSpans[0].endTime, Date(timeIntervalSince1970: 1723221815.891)) XCTAssertEqual(exportedSpans[0].attributes["emb.type"]!.description, "perf.network_request") XCTAssertEqual(exportedSpans[0].attributes["url.full"]!.description, "https://otest.com/v1/products") XCTAssertEqual(exportedSpans[0].attributes["http.request.method"]!.description, "GET") @@ -537,11 +539,18 @@ class EmbraceSpansTests: XCTestCase { XCTAssertEqual(exportedSpans[0].attributes["http.response.status_code"]!.description, "200") XCTAssertEqual(exportedSpans[1].name, "emb-POST") + XCTAssertEqual(exportedSpans[1].startTime, Date(timeIntervalSince1970: 1723221815.889)) + XCTAssertEqual(exportedSpans[1].endTime, Date(timeIntervalSince1970: 1723221815.891)) XCTAssertEqual(exportedSpans[1].attributes["url.full"]!.description, "https://otest.com/") + + // negative values should not be added + XCTAssertNil(exportedSpans[1].attributes["http.response.body.size"]) + XCTAssertNil(exportedSpans[1].attributes["http.request.body.size"]) + XCTAssertNil(exportedSpans[1].attributes["http.response.status_code"]) } func testLogNetworkClientError() async throws { - module.logNetworkClientError("https://otest.com/v1/products", httpMethod: "get", startInMillis: 1723221815889, endInMillis: 1723221815891, errorType: "custom error", error: "this is my error", resolver: promise.resolve, rejecter: promise.reject) + module.logNetworkClientError("https://otest.com/v1/products", httpMethod: "get", startInMillis: 1723221815889, endInMillis: 1723221815891, errorType: "custom error", errorMessage: "this is my error", resolver: promise.resolve, rejecter: promise.reject) XCTAssertEqual(promise.resolveCalls.count, 1) XCTAssertTrue((promise.resolveCalls[0] as? Bool)!)