From ca3cc5064861aa7e565110ba2d31debafcfa36a4 Mon Sep 17 00:00:00 2001 From: Damian Mussi Date: Tue, 30 Jul 2024 10:29:05 -0300 Subject: [PATCH 01/12] logRNAction --- packages/action-tracker/src/index.ts | 54 +++++++++++++++++++++------- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/packages/action-tracker/src/index.ts b/packages/action-tracker/src/index.ts index 59ec1fd0..37cc9f7b 100644 --- a/packages/action-tracker/src/index.ts +++ b/packages/action-tracker/src/index.ts @@ -15,7 +15,7 @@ import { export const buildEmbraceMiddleware = () => { return (store: IMiddleware) => (next: IDispatch) => - (action: IAnyAction) => { + async (action: IAnyAction) => { if (!next || typeof next !== "function") { console.warn( "[Embrace] The state managment middleware was not applied succesfully", @@ -23,6 +23,21 @@ export const buildEmbraceMiddleware = () => { return 0; } const startTime = new Date().getTime(); + const attributes = { + name: action.type.toString().toUpperCase(), + "emb.send_immediately": true, + payload_size: zip(action.payload || 0).length, + "emb.type": "sys.rn_action", + }; + const spanId = await NativeModules.EmbraceManager.startSpan( + "emb-rn-action", + startTime, + ); + const attributePromises: Promise[] = Object.entries( + attributes, + ).map(([key, value]) => + NativeModules.EmbraceManager.addSpanAttributeToSpan(spanId, key, value), + ); try { const result = next(action); @@ -32,13 +47,23 @@ export const buildEmbraceMiddleware = () => { ); } else { const endTime = new Date().getTime(); - NativeModules.EmbraceManager.logRNAction( - action.type.toString().toUpperCase(), + attributePromises.push( + NativeModules.EmbraceManager.addSpanAttributeToSpan( + spanId, + "outcome", + "SUCCESS", + ), + ); + + await Promise.all(attributePromises); + NativeModules.EmbraceManager.recordCompletedSpan( + "emb-rn-action", startTime, endTime, - {}, - zip(action.payload || 0).length, - "SUCCESS", + null, + null, + attributes, + [], ); } return result; @@ -49,14 +74,17 @@ export const buildEmbraceMiddleware = () => { ); } else { const endTime = new Date().getTime(); - NativeModules.EmbraceManager.logRNAction( - action.type.toString().toUpperCase(), - startTime, - endTime, - {}, - zip(action.payload || 0).length, - "FAIL", + + attributePromises.push( + NativeModules.EmbraceManager.addSpanAttributeToSpan( + spanId, + "outcome", + "FAIL", + ), ); + await Promise.all(attributePromises); + + NativeModules.EmbraceManager.stopSpan(spanId, "Failure", endTime); throw e; } } From 40ae48da6a97d638cab1d56ad925a852a74611a7 Mon Sep 17 00:00:00 2001 From: Damian Mussi Date: Tue, 30 Jul 2024 10:29:21 -0300 Subject: [PATCH 02/12] addBreadcrumb --- packages/core/ios/RNEmbrace/EmbraceManager.m | 24 +++++-- .../core/ios/RNEmbrace/EmbraceManager.swift | 65 ++++++++++++------- 2 files changed, 62 insertions(+), 27 deletions(-) diff --git a/packages/core/ios/RNEmbrace/EmbraceManager.m b/packages/core/ios/RNEmbrace/EmbraceManager.m index 84bfc4eb..150c39ed 100755 --- a/packages/core/ios/RNEmbrace/EmbraceManager.m +++ b/packages/core/ios/RNEmbrace/EmbraceManager.m @@ -16,6 +16,9 @@ @interface RCT_EXTERN_MODULE(EmbraceManager, NSObject) RCT_EXTERN_METHOD(getDeviceId:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(getLastRunEndState:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) + RCT_EXTERN_METHOD(setUserIdentifier:(NSString *)userIdentifier resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) @@ -54,7 +57,12 @@ @interface RCT_EXTERN_MODULE(EmbraceManager, NSObject) RCT_EXTERN_METHOD(checkAndSetCodePushBundleURL:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(clearAllUserPersonas:(RCTPromiseResolveBlock)resolve +RCT_EXTERN_METHOD(setUserAsPayer:(NSString *)payer + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(clearUserAsPayer:(NSString *)payer + resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(setReactNativeVersion:(NSString *)version @@ -75,9 +83,6 @@ @interface RCT_EXTERN_MODULE(EmbraceManager, NSObject) resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(clearUserPersona:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) - RCT_EXTERN_METHOD(logMessageWithSeverityAndProperties:(NSString *)message severity:(NSString *)severity properties:(NSDictionary *)properties @@ -119,6 +124,17 @@ @interface RCT_EXTERN_MODULE(EmbraceManager, NSObject) resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(addUserPersona:(NSString *)persona + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(clearUserPersona:(NSString *)persona + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(clearAllUserPersonas:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) + + (BOOL)requiresMainQueueSetup { return NO; diff --git a/packages/core/ios/RNEmbrace/EmbraceManager.swift b/packages/core/ios/RNEmbrace/EmbraceManager.swift index 1cdda64a..7cb1f944 100644 --- a/packages/core/ios/RNEmbrace/EmbraceManager.swift +++ b/packages/core/ios/RNEmbrace/EmbraceManager.swift @@ -98,13 +98,12 @@ class EmbraceManager: NSObject { @objc(addBreadcrumb:resolver:rejecter:) func addBreadcrumb(_ event: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { - //TODO Refactor SPAN - // do { - // try Embrace.client?.add(event: event) - // resolve(true) - // } catch { - // reject(false) - // } + // Add function returns empty if it sucess, so I specify true as return + if ((Embrace.client?.add(event: .breadcrumb(event))) != nil){ + resolve(true) + } else { + reject("ADD_BREADCRUMB", "Error adding breadcrumb", nil) + } } @objc @@ -210,6 +209,16 @@ class EmbraceManager: NSObject { reject("CLEAR_ALL_USER_PERSONAS", "Error clearing all User Personas", error) } } + + @objc(clearUserPersona:resolver:rejecter:) + func clearUserPersona(_ persona:String, resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { + do { + try Embrace.client?.metadata.remove(persona: PersonaTag(persona), lifespan: .session) + resolve(true) + }catch let error { + reject("CLEAR_USER_PERSONA", "Error removing User Persona", error) + } + } @objc(setReactNativeVersion:resolver:rejecter:) func setReactNativeVersion(_ version: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { @@ -256,17 +265,7 @@ class EmbraceManager: NSObject { } } - @objc(clearUserPersona:resolver:rejecter:) - func clearUserPersona(_ persona:String, resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { - do { - try Embrace.client?.metadata.remove(persona: PersonaTag(persona), lifespan: .session) - resolve(true) - }catch let error { - reject("CLEAR_USER_PERSONA", "Error removing User Persona", error) - } - } - - @objc(clearUserPersona:severity:properties:resolver:rejecter:) + @objc(logMessageWithSeverityAndProperties:severity:properties:resolver:rejecter:) func logMessageWithSeverityAndProperties( _ message: String, severity: String, @@ -288,6 +287,26 @@ class EmbraceManager: NSObject { resolve(true) } + + @objc(setUserAsPayer:resolver:rejecter:) + func setUserAsPayer(_ payer: String, resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { + do { + try Embrace.client?.metadata.add(persona: payer) + resolve(true) + } catch let error { + reject("SET_USER_PAYER", "Error adding User Payer", error) + } + } + + @objc(clearUserAsPayer:resolver:rejecter:) + func clearUserAsPayer(_ payer:String, resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { + do { + try Embrace.client?.metadata.remove(persona: PersonaTag(payer), lifespan:.session) + resolve(true) + }catch let error { + reject("CLEAR_USER_PAYER", "Error removing User Payer", error) + } + } private func severityFromString(from inputString: String) -> LogSeverity { switch inputString { @@ -393,7 +412,7 @@ class EmbraceManager: NSObject { return events } - @objc + @objc(startSpan:parentSpanId:startTimeMs:resolver:rejecter:) func startSpan( _ name: String, parentSpanId: String, @@ -433,7 +452,7 @@ class EmbraceManager: NSObject { } } - @objc + @objc(stopSpan:errorCodeString:endTimeMs:resolver:rejecter:) func stopSpan( _ spanId: String, errorCodeString: String, @@ -461,7 +480,7 @@ class EmbraceManager: NSObject { resolve(true) } - @objc + @objc(addSpanEventToSpan:name:time:attributes:resolver:rejecter:) func addSpanEventToSpan( _ spanId: String, name: String, @@ -486,7 +505,7 @@ class EmbraceManager: NSObject { resolve(true) } - @objc + @objc(addSpanAttributeToSpan:key:value:resolver:rejecter:) func addSpanAttributeToSpan( _ spanId: String, key: String, @@ -506,7 +525,7 @@ class EmbraceManager: NSObject { resolve(true) } - @objc + @objc(recordCompletedSpan:startTimeMs:endTimeMs:errorCodeString:parentSpanId:attributes:events:resolver:rejecter:) func recordCompletedSpan( _ name: String, startTimeMs: Double, From e9622e9fbd27b0a648688055c63078f4eaa2c3e7 Mon Sep 17 00:00:00 2001 From: Jonathan Munz Date: Tue, 30 Jul 2024 12:13:53 -0400 Subject: [PATCH 03/12] add test for duplicate span attributes --- .../ios/RNEmbraceTests/RNEmbraceTests.swift | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/packages/core/test-project/ios/RNEmbraceTests/RNEmbraceTests.swift b/packages/core/test-project/ios/RNEmbraceTests/RNEmbraceTests.swift index 79fbbe58..4a7a5f87 100644 --- a/packages/core/test-project/ios/RNEmbraceTests/RNEmbraceTests.swift +++ b/packages/core/test-project/ios/RNEmbraceTests/RNEmbraceTests.swift @@ -327,6 +327,31 @@ class EmbraceSpansTests: XCTestCase { XCTAssertEqual(exportedSpans[0].attributes["my-attr2"]!.description, "bar") } + func testAddSpanAttributeDuplicate() async throws { + module.startSpan("my-span", parentSpanId: "", startTimeMs: 0.0, + resolver: promise.resolve, rejecter: promise.reject) + XCTAssertEqual(promise.resolveCalls.count, 1) + let spanId = (promise.resolveCalls[0] as? String)! + + module.addSpanAttributeToSpan(spanId, key: "my-attr1", value: "foo", + resolver: promise.resolve, rejecter: promise.reject) + XCTAssertEqual(promise.resolveCalls.count, 2) + XCTAssertTrue((promise.resolveCalls[1] as? Bool)!) + // Add the same key again, the value should get overridden + module.addSpanAttributeToSpan(spanId, key: "my-attr1", value: "bar", + resolver: promise.resolve, rejecter: promise.reject) + module.stopSpan(spanId, errorCodeString: "", endTimeMs: 0.0, + resolver: promise.resolve, rejecter: promise.reject) + + let exportedSpans = try await getExportedSpans() + XCTAssertEqual(exportedSpans.count, 1) + XCTAssertEqual(exportedSpans[0].name, "my-span") + XCTAssertEqual(exportedSpans[0].attributes.count, 3) + XCTAssertEqual(exportedSpans[0].attributes["emb.type"]!.description, "perf") + XCTAssertEqual(exportedSpans[0].attributes["emb.key"]!.description, "true") + XCTAssertEqual(exportedSpans[0].attributes["my-attr1"]!.description, "bar") + } + func testAddSpanAttributeInvalidId() async throws { module.addSpanAttributeToSpan("invalid", key: "my-attr1", value: "foo", resolver: promise.resolve, rejecter: promise.reject) From fcb00e4c9de7f7f741c50bd2fa345d645e25d817 Mon Sep 17 00:00:00 2001 From: Damian Mussi Date: Tue, 30 Jul 2024 18:01:42 -0300 Subject: [PATCH 04/12] add incomplete + change record complete > stopSpa --- packages/action-tracker/src/index.ts | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/action-tracker/src/index.ts b/packages/action-tracker/src/index.ts index 37cc9f7b..8b252e77 100644 --- a/packages/action-tracker/src/index.ts +++ b/packages/action-tracker/src/index.ts @@ -28,6 +28,7 @@ export const buildEmbraceMiddleware = () => { "emb.send_immediately": true, payload_size: zip(action.payload || 0).length, "emb.type": "sys.rn_action", + outcome: "INCOMPLETE", }; const spanId = await NativeModules.EmbraceManager.startSpan( "emb-rn-action", @@ -56,15 +57,8 @@ export const buildEmbraceMiddleware = () => { ); await Promise.all(attributePromises); - NativeModules.EmbraceManager.recordCompletedSpan( - "emb-rn-action", - startTime, - endTime, - null, - null, - attributes, - [], - ); + + NativeModules.EmbraceManager.stopSpan(spanId, undefined, endTime); } return result; } catch (e) { From e29b97b590eed2c027737705865aa7630f8c064d Mon Sep 17 00:00:00 2001 From: Damian Mussi Date: Tue, 30 Jul 2024 18:07:24 -0300 Subject: [PATCH 05/12] Remove send_inmeddiate, its not longer needed --- packages/action-tracker/src/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/action-tracker/src/index.ts b/packages/action-tracker/src/index.ts index 8b252e77..dec71f34 100644 --- a/packages/action-tracker/src/index.ts +++ b/packages/action-tracker/src/index.ts @@ -25,7 +25,6 @@ export const buildEmbraceMiddleware = () => { const startTime = new Date().getTime(); const attributes = { name: action.type.toString().toUpperCase(), - "emb.send_immediately": true, payload_size: zip(action.payload || 0).length, "emb.type": "sys.rn_action", outcome: "INCOMPLETE", From 5808a29b93b7cf39e80e13635713cc2e07d387f6 Mon Sep 17 00:00:00 2001 From: Damian Mussi Date: Tue, 30 Jul 2024 18:53:15 -0300 Subject: [PATCH 06/12] Refactor payer to add literal, payer --- packages/core/ios/RNEmbrace/EmbraceManager.m | 6 ++---- packages/core/ios/RNEmbrace/EmbraceManager.swift | 12 ++++++------ packages/core/src/index.ts | 13 +++---------- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/packages/core/ios/RNEmbrace/EmbraceManager.m b/packages/core/ios/RNEmbrace/EmbraceManager.m index 150c39ed..59a56ec8 100755 --- a/packages/core/ios/RNEmbrace/EmbraceManager.m +++ b/packages/core/ios/RNEmbrace/EmbraceManager.m @@ -57,12 +57,10 @@ @interface RCT_EXTERN_MODULE(EmbraceManager, NSObject) RCT_EXTERN_METHOD(checkAndSetCodePushBundleURL:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(setUserAsPayer:(NSString *)payer - resolver:(RCTPromiseResolveBlock)resolve +RCT_EXTERN_METHOD(setUserAsPayer:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(clearUserAsPayer:(NSString *)payer - resolver:(RCTPromiseResolveBlock)resolve +RCT_EXTERN_METHOD(clearUserAsPayer:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(setReactNativeVersion:(NSString *)version diff --git a/packages/core/ios/RNEmbrace/EmbraceManager.swift b/packages/core/ios/RNEmbrace/EmbraceManager.swift index 7cb1f944..ee54227e 100644 --- a/packages/core/ios/RNEmbrace/EmbraceManager.swift +++ b/packages/core/ios/RNEmbrace/EmbraceManager.swift @@ -288,20 +288,20 @@ class EmbraceManager: NSObject { } - @objc(setUserAsPayer:resolver:rejecter:) - func setUserAsPayer(_ payer: String, resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { + @objc + func setUserAsPayer(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { do { - try Embrace.client?.metadata.add(persona: payer) + try Embrace.client?.metadata.add(persona: "payer") resolve(true) } catch let error { reject("SET_USER_PAYER", "Error adding User Payer", error) } } - @objc(clearUserAsPayer:resolver:rejecter:) - func clearUserAsPayer(_ payer:String, resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { + @objc + func clearUserAsPayer(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { do { - try Embrace.client?.metadata.remove(persona: PersonaTag(payer), lifespan:.session) + try Embrace.client?.metadata.remove(persona: "payer", lifespan:.session) resolve(true) }catch let error { reject("CLEAR_USER_PAYER", "Error removing User Payer", error) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 93b3b6b8..d1c67c4f 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -270,20 +270,13 @@ export const endSession = () => { }; export const setUserAsPayer = (): Promise => { - // TODO REFACTOR WHEN iOS IMPLEMENT THE METHOD - - // return NativeModules.EmbraceManager.setUserAsPayer(); - - return createFalsePromise(); + return NativeModules.EmbraceManager.setUserAsPayer(); }; export const clearUserAsPayer = (): Promise => { - // TODO REFACTOR WHEN iOS IMPLEMENT THE METHOD - - // return NativeModules.EmbraceManager.clearUserAsPayer(); - - return createFalsePromise(); + return NativeModules.EmbraceManager.clearUserAsPayer(); }; + export const recordNetworkRequest = ( url: string, httpMethod: MethodType, From 08854690e8059f7f0e6f2bd9fd729253e7abd424 Mon Sep 17 00:00:00 2001 From: TheMutsi <33431136+TheMutsi@users.noreply.github.com> Date: Fri, 9 Aug 2024 14:11:38 -0300 Subject: [PATCH 07/12] Update packages/core/ios/RNEmbrace/EmbraceManager.swift Co-authored-by: Jonathan Munz --- packages/core/ios/RNEmbrace/EmbraceManager.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/ios/RNEmbrace/EmbraceManager.swift b/packages/core/ios/RNEmbrace/EmbraceManager.swift index ee54227e..a68b434f 100644 --- a/packages/core/ios/RNEmbrace/EmbraceManager.swift +++ b/packages/core/ios/RNEmbrace/EmbraceManager.swift @@ -98,7 +98,7 @@ class EmbraceManager: NSObject { @objc(addBreadcrumb:resolver:rejecter:) func addBreadcrumb(_ event: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { - // Add function returns empty if it sucess, so I specify true as return + // Add function returns empty if it succeeds, so I specify true as return if ((Embrace.client?.add(event: .breadcrumb(event))) != nil){ resolve(true) } else { From 938ef2431dea3a3a5c8f586e984141c4fc016239 Mon Sep 17 00:00:00 2001 From: TheMutsi <33431136+TheMutsi@users.noreply.github.com> Date: Fri, 9 Aug 2024 14:12:29 -0300 Subject: [PATCH 08/12] Update packages/action-tracker/src/index.ts Co-authored-by: Jonathan Munz --- packages/action-tracker/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/action-tracker/src/index.ts b/packages/action-tracker/src/index.ts index dec71f34..afdb98fe 100644 --- a/packages/action-tracker/src/index.ts +++ b/packages/action-tracker/src/index.ts @@ -25,7 +25,7 @@ export const buildEmbraceMiddleware = () => { const startTime = new Date().getTime(); const attributes = { name: action.type.toString().toUpperCase(), - payload_size: zip(action.payload || 0).length, + payload_size: (zip(action.payload || 0).length).toString(), "emb.type": "sys.rn_action", outcome: "INCOMPLETE", }; From fb21422e8fa7502ae1806f6e6fe415cae0cd8ae1 Mon Sep 17 00:00:00 2001 From: TheMutsi <33431136+TheMutsi@users.noreply.github.com> Date: Fri, 9 Aug 2024 14:13:08 -0300 Subject: [PATCH 09/12] Update packages/action-tracker/src/index.ts Co-authored-by: Jonathan Munz --- packages/action-tracker/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/action-tracker/src/index.ts b/packages/action-tracker/src/index.ts index afdb98fe..f62b6070 100644 --- a/packages/action-tracker/src/index.ts +++ b/packages/action-tracker/src/index.ts @@ -57,7 +57,7 @@ export const buildEmbraceMiddleware = () => { await Promise.all(attributePromises); - NativeModules.EmbraceManager.stopSpan(spanId, undefined, endTime); + NativeModules.EmbraceManager.stopSpan(spanId, "None", endTime); } return result; } catch (e) { From a3f6fe4e6e7329a78300fa077495b05501862042 Mon Sep 17 00:00:00 2001 From: Damian Mussi Date: Fri, 9 Aug 2024 14:13:57 -0300 Subject: [PATCH 10/12] Comments --- packages/action-tracker/src/index.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/action-tracker/src/index.ts b/packages/action-tracker/src/index.ts index f62b6070..5a5de867 100644 --- a/packages/action-tracker/src/index.ts +++ b/packages/action-tracker/src/index.ts @@ -25,12 +25,13 @@ export const buildEmbraceMiddleware = () => { const startTime = new Date().getTime(); const attributes = { name: action.type.toString().toUpperCase(), - payload_size: (zip(action.payload || 0).length).toString(), + payload_size: zip(action.payload || 0).length.toString(), "emb.type": "sys.rn_action", outcome: "INCOMPLETE", }; const spanId = await NativeModules.EmbraceManager.startSpan( "emb-rn-action", + undefined, startTime, ); const attributePromises: Promise[] = Object.entries( @@ -55,8 +56,6 @@ export const buildEmbraceMiddleware = () => { ), ); - await Promise.all(attributePromises); - NativeModules.EmbraceManager.stopSpan(spanId, "None", endTime); } return result; @@ -75,7 +74,6 @@ export const buildEmbraceMiddleware = () => { "FAIL", ), ); - await Promise.all(attributePromises); NativeModules.EmbraceManager.stopSpan(spanId, "Failure", endTime); throw e; From 5a8ad95afc5ffb0c8b348b909ae658d0d8b3575d Mon Sep 17 00:00:00 2001 From: Damian Mussi Date: Mon, 12 Aug 2024 21:04:52 -0300 Subject: [PATCH 11/12] Remove attributePromises --- packages/action-tracker/src/index.ts | 34 +++++++++++----------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/packages/action-tracker/src/index.ts b/packages/action-tracker/src/index.ts index 5a5de867..f40bd8a5 100644 --- a/packages/action-tracker/src/index.ts +++ b/packages/action-tracker/src/index.ts @@ -34,9 +34,7 @@ export const buildEmbraceMiddleware = () => { undefined, startTime, ); - const attributePromises: Promise[] = Object.entries( - attributes, - ).map(([key, value]) => + Object.entries(attributes).forEach(([key, value]) => NativeModules.EmbraceManager.addSpanAttributeToSpan(spanId, key, value), ); @@ -48,15 +46,12 @@ export const buildEmbraceMiddleware = () => { ); } else { const endTime = new Date().getTime(); - attributePromises.push( - NativeModules.EmbraceManager.addSpanAttributeToSpan( - spanId, - "outcome", - "SUCCESS", - ), - ); - - NativeModules.EmbraceManager.stopSpan(spanId, "None", endTime); + NativeModules.EmbraceManager.addSpanAttributeToSpan( + spanId, + "outcome", + "SUCCESS", + ), + NativeModules.EmbraceManager.stopSpan(spanId, "None", endTime); } return result; } catch (e) { @@ -67,15 +62,12 @@ export const buildEmbraceMiddleware = () => { } else { const endTime = new Date().getTime(); - attributePromises.push( - NativeModules.EmbraceManager.addSpanAttributeToSpan( - spanId, - "outcome", - "FAIL", - ), - ); - - NativeModules.EmbraceManager.stopSpan(spanId, "Failure", endTime); + NativeModules.EmbraceManager.addSpanAttributeToSpan( + spanId, + "outcome", + "FAIL", + ), + NativeModules.EmbraceManager.stopSpan(spanId, "Failure", endTime); throw e; } } From a32062a4de8f4aa2778649a2541a97964488d106 Mon Sep 17 00:00:00 2001 From: Damian Mussi Date: Mon, 12 Aug 2024 21:27:41 -0300 Subject: [PATCH 12/12] Fix test + add validations --- .../__tests__/state-tracker.test.ts | 108 ++++++++++++------ packages/action-tracker/src/index.ts | 13 +++ packages/core/src/__tests__/embrace.test.ts | 20 ++-- 3 files changed, 98 insertions(+), 43 deletions(-) diff --git a/packages/action-tracker/__tests__/state-tracker.test.ts b/packages/action-tracker/__tests__/state-tracker.test.ts index 5a49bad8..cf9b11bd 100644 --- a/packages/action-tracker/__tests__/state-tracker.test.ts +++ b/packages/action-tracker/__tests__/state-tracker.test.ts @@ -7,13 +7,16 @@ beforeEach(() => { }); describe("Test State Managment", () => { - test("Applying middleware - With Name", () => { - const mockLogBreadcrumb = jest.fn(); - + test("Applying middleware - With Name", async () => { + const mockStartSpan = jest.fn(); + const mockStopSpan = jest.fn(); + const mockAddSpanAttributeToSpan = jest.fn(); jest.mock("react-native", () => ({ NativeModules: { EmbraceManager: { - logRNAction: mockLogBreadcrumb, + startSpan: mockStartSpan, + stopSpan: mockStopSpan, + addSpanAttributeToSpan: mockAddSpanAttributeToSpan, }, }, })); @@ -25,17 +28,22 @@ describe("Test State Managment", () => { return d; }; const action = {type: "CREATE_USER"}; - - expect(store(dispatch)(action)).toEqual(action); - expect(mockLogBreadcrumb).toHaveBeenCalled(); + const response = await store(dispatch)(action); + expect(response).toEqual(action); + expect(mockStartSpan).toHaveBeenCalled(); + expect(mockStopSpan).toHaveBeenCalled(); + expect(mockAddSpanAttributeToSpan).toHaveBeenCalled(); }); - test("Applying middleware - Without Name", () => { - const mockLogBreadcrumb = jest.fn(); - + test("Applying middleware - Without Name", async () => { + const mockStartSpan = jest.fn(); + const mockStopSpan = jest.fn(); + const mockAddSpanAttributeToSpan = jest.fn(); jest.mock("react-native", () => ({ NativeModules: { EmbraceManager: { - logRNAction: mockLogBreadcrumb, + startSpan: mockStartSpan, + stopSpan: mockStopSpan, + addSpanAttributeToSpan: mockAddSpanAttributeToSpan, }, }, })); @@ -48,16 +56,22 @@ describe("Test State Managment", () => { }; const action = {type: undefined}; - expect(store(dispatch)(action)).toEqual(action); - expect(mockLogBreadcrumb).toHaveBeenCalledTimes(0); + const response = await store(dispatch)(action); + expect(response).toEqual(0); + expect(mockStartSpan).toBeCalledTimes(0); + expect(mockStopSpan).toBeCalledTimes(0); + expect(mockAddSpanAttributeToSpan).toBeCalledTimes(0); }); - test("Dispatch not provided", () => { - const mockLogBreadcrumb = jest.fn(); - + test("Dispatch not provided", async () => { + const mockStartSpan = jest.fn(); + const mockStopSpan = jest.fn(); + const mockAddSpanAttributeToSpan = jest.fn(); jest.mock("react-native", () => ({ NativeModules: { EmbraceManager: { - logRNAction: mockLogBreadcrumb, + startSpan: mockStartSpan, + stopSpan: mockStopSpan, + addSpanAttributeToSpan: mockAddSpanAttributeToSpan, }, }, })); @@ -68,15 +82,22 @@ describe("Test State Managment", () => { const action = {type: "CREATE_USER"}; - expect(store()(action)).toEqual(0); + const response = await store()(action); + expect(response).toEqual(0); + expect(mockStartSpan).toBeCalledTimes(0); + expect(mockStopSpan).toBeCalledTimes(0); + expect(mockAddSpanAttributeToSpan).toBeCalledTimes(0); }); - test("Dispatch is not a function", () => { - const mockLogBreadcrumb = jest.fn(); - + test("Dispatch is not a function", async () => { + const mockStartSpan = jest.fn(); + const mockStopSpan = jest.fn(); + const mockAddSpanAttributeToSpan = jest.fn(); jest.mock("react-native", () => ({ NativeModules: { EmbraceManager: { - logRNAction: mockLogBreadcrumb, + startSpan: mockStartSpan, + stopSpan: mockStopSpan, + addSpanAttributeToSpan: mockAddSpanAttributeToSpan, }, }, })); @@ -87,15 +108,22 @@ describe("Test State Managment", () => { const action = {type: "CREATE_USER"}; - expect(store({})(action)).toEqual(0); + const response = await store({})(action); + expect(response).toEqual(0); + expect(mockStartSpan).toHaveBeenCalledTimes(0); + expect(mockStopSpan).toHaveBeenCalledTimes(0); + expect(mockAddSpanAttributeToSpan).toHaveBeenCalledTimes(0); }); - test("Action not provided", () => { - const mockLogBreadcrumb = jest.fn(); - + test("Action not provided", async () => { + const mockStartSpan = jest.fn(); + const mockStopSpan = jest.fn(); + const mockAddSpanAttributeToSpan = jest.fn(); jest.mock("react-native", () => ({ NativeModules: { EmbraceManager: { - logRNAction: mockLogBreadcrumb, + startSpan: mockStartSpan, + stopSpan: mockStopSpan, + addSpanAttributeToSpan: mockAddSpanAttributeToSpan, }, }, })); @@ -107,16 +135,23 @@ describe("Test State Managment", () => { const dispatch = (d: IAnyAction) => { return d; }; - expect(store(dispatch)()).toEqual(undefined); - expect(mockLogBreadcrumb).toHaveBeenCalledTimes(0); - }); - test("Action provided is not a String", () => { - const mockLogBreadcrumb = jest.fn(); + const response = await store(dispatch)(); + expect(response).toEqual(0); + expect(mockStartSpan).toBeCalledTimes(0); + expect(mockStopSpan).toBeCalledTimes(0); + expect(mockAddSpanAttributeToSpan).toBeCalledTimes(0); + }); + test("Action provided is not a String", async () => { + const mockStartSpan = jest.fn(); + const mockStopSpan = jest.fn(); + const mockAddSpanAttributeToSpan = jest.fn(); jest.mock("react-native", () => ({ NativeModules: { EmbraceManager: { - logRNAction: mockLogBreadcrumb, + startSpan: mockStartSpan, + stopSpan: mockStopSpan, + addSpanAttributeToSpan: mockAddSpanAttributeToSpan, }, }, })); @@ -129,8 +164,11 @@ describe("Test State Managment", () => { }; const action = {type: 1}; - expect(store(dispatch)(action)).toEqual(action); - expect(mockLogBreadcrumb).toHaveBeenCalled(); + const response = await store(dispatch)(action); + expect(response).toEqual(action); + expect(mockStartSpan).toHaveBeenCalled(); + expect(mockStopSpan).toHaveBeenCalled(); + expect(mockAddSpanAttributeToSpan).toHaveBeenCalled(); }); test("Error occurred", () => { diff --git a/packages/action-tracker/src/index.ts b/packages/action-tracker/src/index.ts index f40bd8a5..f10eccca 100644 --- a/packages/action-tracker/src/index.ts +++ b/packages/action-tracker/src/index.ts @@ -22,6 +22,19 @@ export const buildEmbraceMiddleware = () => { ); return 0; } + + if (!action) { + console.warn( + "[Embrace] You have to provide an action in order to track actions", + ); + return 0; + } + if (!action.type) { + console.warn( + "[Embrace] You have to provide an action type in order to track actions", + ); + return 0; + } const startTime = new Date().getTime(); const attributes = { name: action.type.toString().toUpperCase(), diff --git a/packages/core/src/__tests__/embrace.test.ts b/packages/core/src/__tests__/embrace.test.ts index 5f659e24..01516d6e 100644 --- a/packages/core/src/__tests__/embrace.test.ts +++ b/packages/core/src/__tests__/embrace.test.ts @@ -486,7 +486,10 @@ describe("Payers Test", () => { () => ({ NativeModules: { EmbraceManager: { - setUserAsPayer: mock, + setUserAsPayer: () => { + mock(); + return false; + }, }, }, }), @@ -494,11 +497,10 @@ describe("Payers Test", () => { ); const {setUserAsPayer} = require("../index"); const promiseToResolve = setUserAsPayer(); - // expect(mock).toHaveBeenCalled(); jest.runAllTimers(); const result = await promiseToResolve; - // TODO uncomment the expect once the method is imeplemented - // expect(mock).toHaveBeenCalled(); + + expect(mock).toHaveBeenCalled(); expect(result).toBe(false); }); test("clearUserAsPayer", async () => { @@ -508,7 +510,10 @@ describe("Payers Test", () => { () => ({ NativeModules: { EmbraceManager: { - clearUserAsPayer: mock, + clearUserAsPayer: () => { + mock(); + return false; + }, }, }, }), @@ -516,12 +521,11 @@ describe("Payers Test", () => { ); const {clearUserAsPayer} = require("../index"); const promiseToResolve = clearUserAsPayer(); - // expect(mock).toHaveBeenCalled(); jest.runAllTimers(); const result = await promiseToResolve; - // TODO uncomment the expect once the method is imeplemented - // expect(mock).toHaveBeenCalled(); + + expect(mock).toHaveBeenCalled(); expect(result).toBe(false); }); });