Skip to content

Commit f8d47fa

Browse files
lemnikyousif-bugsnag
authored andcommitted
fix(react-native): replaced all the clock.toUnixNanoseconds with toUnixTimestampNanoseconds to avoid representing Unix nanoTime as a number
1 parent d903836 commit f8d47fa

File tree

13 files changed

+159
-73
lines changed

13 files changed

+159
-73
lines changed

packages/platforms/react-native/android/src/main/java/com/bugsnag/android/performance/NativeBugsnagPerformanceImpl.java

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ public NativeBugsnagPerformanceImpl(ReactApplicationContext reactContext) {
7676
try {
7777
BugsnagPerformanceImpl.INSTANCE.getInstrumentedAppState().getConfig$internal();
7878
isNativePerformanceAvailable = true;
79-
}
80-
catch (LinkageError e) {
79+
} catch (LinkageError e) {
8180
// do nothing, Android Performance SDK is not installed or is incompatible
8281
}
8382
}
@@ -117,12 +116,12 @@ String requestEntropy() {
117116
random.nextBytes(bytes);
118117

119118
StringBuilder hex = new StringBuilder(bytes.length * 2);
120-
for(byte b : bytes) {
121-
int byteValue = ((int)b & 0xff);
122-
if(byteValue < 16) {
123-
hex.append('0');
124-
}
125-
hex.append(Integer.toHexString(byteValue));
119+
for (byte b : bytes) {
120+
int byteValue = ((int) b & 0xff);
121+
if (byteValue < 16) {
122+
hex.append('0');
123+
}
124+
hex.append(Integer.toHexString(byteValue));
126125
}
127126
return hex.toString();
128127
}
@@ -204,23 +203,23 @@ WritableMap startNativeSpan(String name, ReadableMap options) {
204203
return nativeSpanToJsSpan(nativeSpan);
205204
}
206205

207-
void markNativeSpanEndTime(String spanId, String traceId, double endTime) {
206+
void markNativeSpanEndTime(String spanId, String traceId, String endTime) {
208207
SpanImpl nativeSpan = openSpans.get(spanId + traceId);
209208
if (nativeSpan != null) {
210-
long nativeEndTime = BugsnagClock.INSTANCE.unixNanoTimeToElapsedRealtime((long)endTime);
209+
long nativeEndTime = BugsnagClock.INSTANCE.unixNanoTimeToElapsedRealtime(Long.parseLong(endTime));
211210
nativeSpan.markEndTime$internal(nativeEndTime);
212211
}
213212
}
214213

215-
void endNativeSpan(String spanId, String traceId, double endTime, ReadableMap jsAttributes, Promise promise) {
214+
void endNativeSpan(String spanId, String traceId, String endTime, ReadableMap jsAttributes, Promise promise) {
216215
SpanImpl nativeSpan = openSpans.remove(spanId + traceId);
217216
if (nativeSpan == null) {
218217
promise.resolve(null);
219218
return;
220219
}
221220

222221
ReactNativeSpanAttributes.setAttributesFromReadableMap(nativeSpan.getAttributes(), jsAttributes);
223-
long nativeEndTime = BugsnagClock.INSTANCE.unixNanoTimeToElapsedRealtime((long)endTime);
222+
long nativeEndTime = BugsnagClock.INSTANCE.unixNanoTimeToElapsedRealtime(Long.parseLong(endTime));
224223
if (nativeEndTime > nativeSpan.getEndTime$internal()) {
225224
nativeSpan.markEndTime$internal(nativeEndTime);
226225
}
@@ -245,7 +244,7 @@ private WritableMap nativeSpanToJsSpan(SpanImpl nativeSpan) {
245244
span.putString("traceId", EncodingUtils.toHexString(nativeSpan.getTraceId()));
246245

247246
long unixNanoStartTime = BugsnagClock.INSTANCE.elapsedNanosToUnixTime(nativeSpan.getStartTime$internal());
248-
span.putDouble("startTime", (double)unixNanoStartTime);
247+
span.putString("startTime", Long.toString(unixNanoStartTime));
249248

250249
long parentSpanId = nativeSpan.getParentSpanId();
251250
if (parentSpanId != 0L) {
@@ -262,8 +261,8 @@ private SpanOptions readableMapToSpanOptions(ReadableMap jsOptions) {
262261
.within(null);
263262

264263
if (jsOptions.hasKey("startTime")) {
265-
double startTime = jsOptions.getDouble("startTime");
266-
long nativeStartTime = BugsnagClock.INSTANCE.unixNanoTimeToElapsedRealtime((long)startTime);
264+
String startTime = jsOptions.getString("startTime");
265+
long nativeStartTime = BugsnagClock.INSTANCE.unixNanoTimeToElapsedRealtime(Long.parseLong(startTime));
267266
spanOptions = spanOptions.startTime(nativeStartTime);
268267
}
269268

@@ -305,7 +304,7 @@ void exists(String path, Promise promise) {
305304
try {
306305
boolean result = new File(path).exists();
307306
promise.resolve(result);
308-
} catch(Exception e) {
307+
} catch (Exception e) {
309308
promise.reject(e);
310309
}
311310
}
@@ -314,7 +313,7 @@ void isDir(String path, Promise promise) {
314313
try {
315314
boolean result = new File(path).isDirectory();
316315
promise.resolve(result);
317-
} catch(Exception e) {
316+
} catch (Exception e) {
318317
promise.reject(e);
319318
}
320319
}
@@ -328,7 +327,7 @@ void ls(String path, Promise promise) {
328327
}
329328

330329
promise.resolve(resultArray);
331-
} catch(Exception e) {
330+
} catch (Exception e) {
332331
promise.reject(e);
333332
}
334333
}
@@ -347,15 +346,15 @@ void mkdir(String path, Promise promise) {
347346
} else {
348347
promise.reject("EPERM", new Exception("Failed to create directory"));
349348
}
350-
} catch(Exception e) {
349+
} catch (Exception e) {
351350
promise.reject(e);
352351
}
353352
}
354353

355354
void readFile(String path, String encoding, Promise promise) {
356355
File file = new File(path);
357356
StringBuilder fileContent = new StringBuilder((int) file.length());
358-
try(
357+
try (
359358
FileInputStream fin = new FileInputStream(file);
360359
InputStreamReader isr = new InputStreamReader(fin, encoding);
361360
) {
@@ -378,13 +377,13 @@ void unlink(String path, Promise promise) {
378377
} else {
379378
promise.reject(new Exception("Failed to delete file/directory"));
380379
}
381-
} catch(Exception e) {
380+
} catch (Exception e) {
382381
promise.reject(e);
383382
}
384383
}
385384

386385
void writeFile(String path, String data, String encoding, Promise promise) {
387-
try(
386+
try (
388387
FileOutputStream fout = new FileOutputStream(path);
389388
Writer w = new OutputStreamWriter(fout, encoding);
390389
) {

packages/platforms/react-native/android/src/newarch/java/com/bugsnag/android/performance/BugsnagReactNativePerformance.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,18 @@ public WritableMap attachToNativeSDK() {
8686
return impl.attachToNativeSDK();
8787
}
8888

89-
@Override
89+
@Override
9090
public WritableMap startNativeSpan(String name, ReadableMap options) {
9191
return impl.startNativeSpan(name, options);
9292
}
9393

9494
@Override
95-
public void endNativeSpan(String spanId, String traceId, double endTime, ReadableMap attributes, Promise promise) {
95+
public void endNativeSpan(String spanId, String traceId, String endTime, ReadableMap attributes, Promise promise) {
9696
impl.endNativeSpan(spanId, traceId, endTime, attributes, promise);
9797
}
9898

99-
@Override
100-
public void markNativeSpanEndTime(String spanId, String traceId, double endTime) {
99+
@Override
100+
public void markNativeSpanEndTime(String spanId, String traceId, String endTime) {
101101
impl.markNativeSpanEndTime(spanId, traceId, endTime);
102102
}
103103

packages/platforms/react-native/android/src/oldarch/java/com/bugsnag/android/performance/BugsnagReactNativePerformance.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import java.util.Map;
1111

1212
public class BugsnagReactNativePerformance extends ReactContextBaseJavaModule {
13-
13+
1414
private final NativeBugsnagPerformanceImpl impl;
1515

1616
public BugsnagReactNativePerformance(ReactApplicationContext reactContext) {
@@ -94,12 +94,12 @@ public WritableMap startNativeSpan(String name, ReadableMap options) {
9494
}
9595

9696
@ReactMethod
97-
public void endNativeSpan(String spanId, String traceId, double endTime, ReadableMap attributes, Promise promise) {
98-
impl.endNativeSpan(spanId, traceId, endTime, attributes, promise);
97+
public void endNativeSpan(String spanId, String traceId, String endTime, ReadableMap attributes, Promise promise) {
98+
impl.endNativeSpan(spanId, traceId, endTime, attributes, promise);
9999
}
100100

101101
@ReactMethod(isBlockingSynchronousMethod = true)
102-
public void markNativeSpanEndTime(String spanId, String traceId, double endTime) {
102+
public void markNativeSpanEndTime(String spanId, String traceId, String endTime) {
103103
impl.markNativeSpanEndTime(spanId, traceId, endTime);
104104
}
105105

packages/platforms/react-native/ios/BugsnagReactNativePerformance.mm

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ @implementation BugsnagReactNativePerformance
1616
/**
1717
* A dictionary of open native spans, keyed by the span ID and trace ID,
1818
* so that they can be retrieved and closed/discarded from JS.
19-
*
19+
*
2020
* Since native spans are only ever started and ended from the JS thread,
2121
* no thread synchronization is required when accessing.
2222
*/
@@ -91,7 +91,7 @@ static uint64_t hexStringToUInt64(NSString *hexString) {
9191
[hexStr appendFormat:@"%02x", bytes[i]];
9292
}
9393
}
94-
94+
9595
return hexStr;
9696
}
9797

@@ -298,11 +298,11 @@ static uint64_t hexStringToUInt64(NSString *hexString) {
298298
spanOptions.makeCurrentContext = NO;
299299
spanOptions.instrumentRendering = BSGInstrumentRenderingYes;
300300
spanOptions.parentContext = nil;
301-
301+
302302
// Start times are passsed from JS as unix nanosecond timestamps
303303
NSNumber *startTime = options[@"startTime"];
304304
spanOptions.startTime = [NSDate dateWithTimeIntervalSince1970:([startTime doubleValue] / NSEC_PER_SEC)];
305-
305+
306306
NSDictionary *parentContext = options[@"parentContext"];
307307
if (parentContext != nil) {
308308
NSString *parentSpanId = parentContext[@"id"];
@@ -314,10 +314,10 @@ static uint64_t hexStringToUInt64(NSString *hexString) {
314314

315315
spanOptions.parentContext = [BugsnagReactNativePerformanceCrossTalkAPIClient.sharedInstance newSpanContext:traceIdHi traceIdLo:traceIdLo spanId:spanId];
316316
}
317-
317+
318318
BugsnagPerformanceSpan *nativeSpan = [BugsnagReactNativePerformanceCrossTalkAPIClient.sharedInstance startSpan:name options:spanOptions];
319319
[nativeSpan.attributes removeAllObjects];
320-
320+
321321
NSString *spanId = [NSString stringWithFormat:@"%llx", nativeSpan.spanId];
322322
NSString *traceId = [NSString stringWithFormat:@"%llx%llx", nativeSpan.traceIdHi, nativeSpan.traceIdLo];
323323

@@ -329,17 +329,17 @@ static uint64_t hexStringToUInt64(NSString *hexString) {
329329
span[@"name"] = nativeSpan.name;
330330
span[@"id"] = spanId;
331331
span[@"traceId"] = traceId;
332-
span[@"startTime"] = [NSNumber numberWithDouble: [nativeSpan.startTime timeIntervalSince1970] * NSEC_PER_SEC];
332+
span[@"startTime"] = [NSString stringWithFormat:@"%.0f", [nativeSpan.startTime timeIntervalSince1970] * NSEC_PER_SEC];
333333
if (nativeSpan.parentId > 0) {
334334
span[@"parentSpanId"] = [NSString stringWithFormat:@"%llx", nativeSpan.parentId];
335335
}
336-
336+
337337
return span;
338338
}
339339

340340
RCT_EXPORT_METHOD(endNativeSpan:(NSString *)spanId
341341
traceId:(NSString *)traceId
342-
endTime:(double)endTime
342+
endTime:(NSString *)endTime
343343
attributes:(NSDictionary *)attributes
344344
resolve:(RCTPromiseResolveBlock)resolve
345345
reject:(RCTPromiseRejectBlock)reject) {
@@ -359,28 +359,35 @@ static uint64_t hexStringToUInt64(NSString *hexString) {
359359

360360
// We need to reinstate the bugsnag.sampling.p attribute here as it might not be re-populated on span end
361361
nativeSpan.attributes[@"bugsnag.sampling.p"] = @(nativeSpan.samplingProbability);
362-
363-
// If the end time is later than the current end time, update it
364-
NSDate *nativeEndTime = [NSDate dateWithTimeIntervalSince1970: endTime / NSEC_PER_SEC];
362+
363+
NSDecimalNumber *endTimeDecimal = [NSDecimalNumber decimalNumberWithString:endTime];
364+
NSDecimalNumber *nsecPerSecDecimal = [NSDecimalNumber decimalNumberWithMantissa:1 exponent:9 isNegative:NO];
365+
NSDecimalNumber *endTimeSecondsDecimal = [endTimeDecimal decimalNumberByDividingBy:nsecPerSecDecimal];
366+
NSTimeInterval endTimeInterval = [endTimeSecondsDecimal doubleValue];
367+
NSDate *nativeEndTime = [NSDate dateWithTimeIntervalSince1970:endTimeInterval];
365368
if ([nativeEndTime timeIntervalSinceDate:nativeSpan.endTime] > 0) {
366369
[nativeSpan markEndTime:nativeEndTime];
367370
}
368-
371+
369372
[nativeSpan sendForProcessing];
370373
}
371374

372375
resolve(nil);
373376
}
374377

375-
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(markNativeSpanEndTime:(NSString *)spanId traceId:(NSString *)traceId endTime:(double)endTime) {
378+
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(markNativeSpanEndTime:(NSString *)spanId traceId:(NSString *)traceId endTime:(NSString *)endTime) {
376379
@synchronized (openSpans) {
377380
BugsnagPerformanceSpan *nativeSpan = openSpans[[spanId stringByAppendingString:traceId]];
378381
if (nativeSpan != nil) {
379-
NSDate *nativeEndTime = [NSDate dateWithTimeIntervalSince1970: endTime / NSEC_PER_SEC];
382+
NSDecimalNumber *endTimeDecimal = [NSDecimalNumber decimalNumberWithString:endTime];
383+
NSDecimalNumber *nsecPerSecDecimal = [NSDecimalNumber decimalNumberWithMantissa:1 exponent:9 isNegative:NO];
384+
NSDecimalNumber *endTimeSecondsDecimal = [endTimeDecimal decimalNumberByDividingBy:nsecPerSecDecimal];
385+
NSTimeInterval endTimeInterval = [endTimeSecondsDecimal doubleValue];
386+
NSDate *nativeEndTime = [NSDate dateWithTimeIntervalSince1970:endTimeInterval];
380387
[nativeSpan markEndTime:nativeEndTime];
381388
}
382389
}
383-
390+
384391
return nil;
385392
}
386393

@@ -390,7 +397,7 @@ static uint64_t hexStringToUInt64(NSString *hexString) {
390397
reject:(RCTPromiseRejectBlock)reject) {
391398
NSString *spanKey = [spanId stringByAppendingString:traceId];
392399
@synchronized (openSpans) {
393-
BugsnagPerformanceSpan *nativeSpan = openSpans[spanKey];
400+
BugsnagPerformanceSpan *nativeSpan = openSpans[spanKey];
394401
if (nativeSpan != nil) {
395402
[openSpans removeObjectForKey:spanKey];
396403
[nativeSpan abortUnconditionally];
@@ -403,15 +410,15 @@ static uint64_t hexStringToUInt64(NSString *hexString) {
403410
- (void)discardLongRunningSpans {
404411
NSDate *oneHourAgo = [NSDate dateWithTimeIntervalSinceNow:-hourInSeconds];
405412
NSMutableArray *keysToRemove = [NSMutableArray new];
406-
413+
407414
@synchronized (openSpans) {
408415
for (NSString *key in openSpans) {
409416
BugsnagPerformanceSpan *span = openSpans[key];
410417
if ([span.startTime compare:oneHourAgo] == NSOrderedAscending) {
411418
[keysToRemove addObject:key];
412419
}
413420
}
414-
421+
415422
[openSpans removeObjectsForKeys:keysToRemove];
416423
}
417424
}

packages/platforms/react-native/lib/NativeBugsnagPerformance.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ export interface Spec extends TurboModule {
5757
isNativePerformanceAvailable: () => boolean
5858
attachToNativeSDK: () => NativeConfiguration | null
5959
startNativeSpan: (name: string, options: UnsafeObject) => NativeSpan
60-
endNativeSpan: (spanId: string, traceId: string, endTime: number, attributes: UnsafeObject) => Promise<void>
61-
markNativeSpanEndTime: (spanId: string, traceId: string, endTime: number) => void
60+
endNativeSpan: (spanId: string, traceId: string, endTime: string, attributes: UnsafeObject) => Promise<void>
61+
markNativeSpanEndTime: (spanId: string, traceId: string, endTime: string) => void
6262
discardNativeSpan: (spanId: string, traceId: string) => Promise<void>
6363
}
6464

0 commit comments

Comments
 (0)