@perfbitapp/rn-sdk 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -0
- package/dist/core/EventQueue.d.ts +29 -0
- package/dist/core/EventQueue.d.ts.map +1 -0
- package/dist/core/EventQueue.js +69 -0
- package/dist/core/EventQueue.js.map +1 -0
- package/dist/core/HttpClient.d.ts +18 -0
- package/dist/core/HttpClient.d.ts.map +1 -0
- package/dist/core/HttpClient.js +41 -0
- package/dist/core/HttpClient.js.map +1 -0
- package/dist/core/PerfSDK.d.ts +19 -0
- package/dist/core/PerfSDK.d.ts.map +1 -0
- package/dist/core/PerfSDK.js +69 -0
- package/dist/core/PerfSDK.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/instrumentation/FrameTracker.d.ts +15 -0
- package/dist/instrumentation/FrameTracker.d.ts.map +1 -0
- package/dist/instrumentation/FrameTracker.js +76 -0
- package/dist/instrumentation/FrameTracker.js.map +1 -0
- package/dist/instrumentation/NavigationTracker.d.ts +8 -0
- package/dist/instrumentation/NavigationTracker.d.ts.map +1 -0
- package/dist/instrumentation/NavigationTracker.js +52 -0
- package/dist/instrumentation/NavigationTracker.js.map +1 -0
- package/dist/instrumentation/NetworkTracker.d.ts +11 -0
- package/dist/instrumentation/NetworkTracker.d.ts.map +1 -0
- package/dist/instrumentation/NetworkTracker.js +101 -0
- package/dist/instrumentation/NetworkTracker.js.map +1 -0
- package/dist/instrumentation/SessionTracker.d.ts +11 -0
- package/dist/instrumentation/SessionTracker.d.ts.map +1 -0
- package/dist/instrumentation/SessionTracker.js +55 -0
- package/dist/instrumentation/SessionTracker.js.map +1 -0
- package/dist/instrumentation/StartupTracker.d.ts +9 -0
- package/dist/instrumentation/StartupTracker.d.ts.map +1 -0
- package/dist/instrumentation/StartupTracker.js +49 -0
- package/dist/instrumentation/StartupTracker.js.map +1 -0
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +21 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/storage.d.ts +6 -0
- package/dist/utils/storage.d.ts.map +1 -0
- package/dist/utils/storage.js +41 -0
- package/dist/utils/storage.js.map +1 -0
- package/dist/utils/uuid.d.ts +2 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/dist/utils/uuid.js +11 -0
- package/dist/utils/uuid.js.map +1 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# @perfbitapp/rn-sdk
|
|
2
|
+
|
|
3
|
+
React Native performance monitoring. Drop it in, see your app vitals in minutes.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @perfbitapp/rn-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
In your app entry point (`App.tsx` or `index.ts`), before your NavigationContainer:
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { PerfSDK } from '@perfbitapp/rn-sdk';
|
|
17
|
+
|
|
18
|
+
PerfSDK.init({
|
|
19
|
+
apiKey: 'YOUR_API_KEY', // from perfbit.com dashboard
|
|
20
|
+
appVersion: '1.0.0', // use your actual app version
|
|
21
|
+
environment: 'production', // 'development' | 'staging' | 'production'
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
For screen tracking, pass your navigation ref:
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { NavigationContainer, createNavigationContainerRef } from '@react-navigation/native';
|
|
29
|
+
import { PerfSDK } from '@perfbitapp/rn-sdk';
|
|
30
|
+
|
|
31
|
+
const navigationRef = createNavigationContainerRef();
|
|
32
|
+
|
|
33
|
+
PerfSDK.init({
|
|
34
|
+
apiKey: 'YOUR_API_KEY',
|
|
35
|
+
appVersion: '1.0.0',
|
|
36
|
+
navigationRef,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export default function App() {
|
|
40
|
+
return (
|
|
41
|
+
<NavigationContainer ref={navigationRef}>
|
|
42
|
+
{/* your app */}
|
|
43
|
+
</NavigationContainer>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## What's tracked automatically
|
|
49
|
+
|
|
50
|
+
- Screen load time (per screen)
|
|
51
|
+
- App cold start and warm start
|
|
52
|
+
- Slow and frozen frames
|
|
53
|
+
- Crash-free session rate
|
|
54
|
+
- Network request latency
|
|
55
|
+
|
|
56
|
+
No manual instrumentation needed.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface QueuedEvent {
|
|
2
|
+
type: string;
|
|
3
|
+
timestamp: number;
|
|
4
|
+
session_id: string;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
}
|
|
7
|
+
interface EnvelopeConfig {
|
|
8
|
+
api_key: string;
|
|
9
|
+
app_version: string;
|
|
10
|
+
environment: string;
|
|
11
|
+
platform: string;
|
|
12
|
+
sdk_version: string;
|
|
13
|
+
}
|
|
14
|
+
declare class EventQueue {
|
|
15
|
+
private queue;
|
|
16
|
+
private flushTimer;
|
|
17
|
+
private envelope;
|
|
18
|
+
private isFlushing;
|
|
19
|
+
private retryCount;
|
|
20
|
+
configure(envelope: EnvelopeConfig): void;
|
|
21
|
+
push(event: QueuedEvent): void;
|
|
22
|
+
startAutoFlush(): void;
|
|
23
|
+
stopAutoFlush(): void;
|
|
24
|
+
flush(): Promise<void>;
|
|
25
|
+
getSize(): number;
|
|
26
|
+
}
|
|
27
|
+
export declare const eventQueue: EventQueue;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=EventQueue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventQueue.d.ts","sourceRoot":"","sources":["../../src/core/EventQueue.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAMD,cAAM,UAAU;IACd,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAK;IAEvB,SAAS,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAIzC,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAQ9B,cAAc,IAAI,IAAI;IAOtB,aAAa,IAAI,IAAI;IAOf,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA8B5B,OAAO,IAAI,MAAM;CAGlB;AAED,eAAO,MAAM,UAAU,YAAmB,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.eventQueue = void 0;
|
|
4
|
+
const logger_1 = require("../utils/logger");
|
|
5
|
+
const HttpClient_1 = require("./HttpClient");
|
|
6
|
+
const MAX_QUEUE_SIZE = 50;
|
|
7
|
+
const FLUSH_INTERVAL_MS = 30000;
|
|
8
|
+
const MAX_RETRIES = 3;
|
|
9
|
+
class EventQueue {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.queue = [];
|
|
12
|
+
this.flushTimer = null;
|
|
13
|
+
this.envelope = null;
|
|
14
|
+
this.isFlushing = false;
|
|
15
|
+
this.retryCount = 0;
|
|
16
|
+
}
|
|
17
|
+
configure(envelope) {
|
|
18
|
+
this.envelope = envelope;
|
|
19
|
+
}
|
|
20
|
+
push(event) {
|
|
21
|
+
this.queue.push(event);
|
|
22
|
+
logger_1.Logger.log('EventQueue: pushed event', event.type);
|
|
23
|
+
if (this.queue.length >= MAX_QUEUE_SIZE) {
|
|
24
|
+
void this.flush();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
startAutoFlush() {
|
|
28
|
+
if (this.flushTimer !== null)
|
|
29
|
+
return;
|
|
30
|
+
this.flushTimer = setInterval(() => {
|
|
31
|
+
void this.flush();
|
|
32
|
+
}, FLUSH_INTERVAL_MS);
|
|
33
|
+
}
|
|
34
|
+
stopAutoFlush() {
|
|
35
|
+
if (this.flushTimer !== null) {
|
|
36
|
+
clearInterval(this.flushTimer);
|
|
37
|
+
this.flushTimer = null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async flush() {
|
|
41
|
+
if (this.isFlushing || this.queue.length === 0 || !this.envelope)
|
|
42
|
+
return;
|
|
43
|
+
this.isFlushing = true;
|
|
44
|
+
const batch = this.queue.splice(0, this.queue.length);
|
|
45
|
+
const payload = Object.assign(Object.assign({}, this.envelope), { events: batch });
|
|
46
|
+
const result = await HttpClient_1.httpClient.post(payload);
|
|
47
|
+
if (result.ok) {
|
|
48
|
+
logger_1.Logger.log('EventQueue: flushed', batch.length + ' events');
|
|
49
|
+
this.retryCount = 0;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
this.retryCount++;
|
|
53
|
+
if (this.retryCount <= MAX_RETRIES) {
|
|
54
|
+
logger_1.Logger.warn('EventQueue: flush failed, re-queuing', `attempt ${this.retryCount}`);
|
|
55
|
+
this.queue.unshift(...batch);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
logger_1.Logger.error('EventQueue: dropping batch after max retries', batch.length);
|
|
59
|
+
this.retryCount = 0;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
this.isFlushing = false;
|
|
63
|
+
}
|
|
64
|
+
getSize() {
|
|
65
|
+
return this.queue.length;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.eventQueue = new EventQueue();
|
|
69
|
+
//# sourceMappingURL=EventQueue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventQueue.js","sourceRoot":"","sources":["../../src/core/EventQueue.ts"],"names":[],"mappings":";;;AAAA,4CAAyC;AACzC,6CAAwD;AAiBxD,MAAM,cAAc,GAAG,EAAE,CAAC;AAC1B,MAAM,iBAAiB,GAAG,KAAM,CAAC;AACjC,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB,MAAM,UAAU;IAAhB;QACU,UAAK,GAAkB,EAAE,CAAC;QAC1B,eAAU,GAA0C,IAAI,CAAC;QACzD,aAAQ,GAA0B,IAAI,CAAC;QACvC,eAAU,GAAG,KAAK,CAAC;QACnB,eAAU,GAAG,CAAC,CAAC;IA6DzB,CAAC;IA3DC,SAAS,CAAC,QAAwB;QAChC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,IAAI,CAAC,KAAkB;QACrB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,eAAM,CAAC,GAAG,CAAC,0BAA0B,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACnD,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,cAAc,EAAE,CAAC;YACxC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAED,cAAc;QACZ,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI;YAAE,OAAO;QACrC,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;YACjC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC,EAAE,iBAAiB,CAAC,CAAC;IACxB,CAAC;IAED,aAAa;QACX,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YAC7B,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEzE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAEtD,MAAM,OAAO,mCACR,IAAI,CAAC,QAAQ,KAChB,MAAM,EAAE,KAAK,GACd,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,uBAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE9C,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACd,eAAM,CAAC,GAAG,CAAC,qBAAqB,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;YAC5D,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,EAAE,CAAC;YAClB,IAAI,IAAI,CAAC,UAAU,IAAI,WAAW,EAAE,CAAC;gBACnC,eAAM,CAAC,IAAI,CAAC,sCAAsC,EAAE,WAAW,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;gBAClF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,eAAM,CAAC,KAAK,CAAC,8CAA8C,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC3E,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;CACF;AAEY,QAAA,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface FlushPayload {
|
|
2
|
+
api_key: string;
|
|
3
|
+
app_version: string;
|
|
4
|
+
environment: string;
|
|
5
|
+
platform: string;
|
|
6
|
+
sdk_version: string;
|
|
7
|
+
events: unknown[];
|
|
8
|
+
}
|
|
9
|
+
declare class HttpClient {
|
|
10
|
+
private endpoint;
|
|
11
|
+
setEndpoint(url: string): void;
|
|
12
|
+
post(payload: FlushPayload): Promise<{
|
|
13
|
+
ok: boolean;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
export declare const httpClient: HttpClient;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=HttpClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpClient.d.ts","sourceRoot":"","sources":["../../src/core/HttpClient.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB;AAED,cAAM,UAAU;IACd,OAAO,CAAC,QAAQ,CAAM;IAEtB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIxB,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAA;KAAE,CAAC;CA6B5D;AAED,eAAO,MAAM,UAAU,YAAmB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.httpClient = void 0;
|
|
4
|
+
const logger_1 = require("../utils/logger");
|
|
5
|
+
class HttpClient {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.endpoint = '';
|
|
8
|
+
}
|
|
9
|
+
setEndpoint(url) {
|
|
10
|
+
this.endpoint = url;
|
|
11
|
+
}
|
|
12
|
+
async post(payload) {
|
|
13
|
+
if (!this.endpoint) {
|
|
14
|
+
logger_1.Logger.error('HttpClient: endpoint not set');
|
|
15
|
+
return { ok: false };
|
|
16
|
+
}
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
19
|
+
try {
|
|
20
|
+
const response = await fetch(this.endpoint, {
|
|
21
|
+
method: 'POST',
|
|
22
|
+
headers: { 'Content-Type': 'application/json' },
|
|
23
|
+
body: JSON.stringify(payload),
|
|
24
|
+
signal: controller.signal,
|
|
25
|
+
});
|
|
26
|
+
clearTimeout(timeoutId);
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
logger_1.Logger.error('HttpClient: non-2xx response', response.status);
|
|
29
|
+
return { ok: false };
|
|
30
|
+
}
|
|
31
|
+
return { ok: true };
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
clearTimeout(timeoutId);
|
|
35
|
+
logger_1.Logger.error('HttpClient: request failed', err);
|
|
36
|
+
return { ok: false };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.httpClient = new HttpClient();
|
|
41
|
+
//# sourceMappingURL=HttpClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpClient.js","sourceRoot":"","sources":["../../src/core/HttpClient.ts"],"names":[],"mappings":";;;AAAA,4CAAyC;AAWzC,MAAM,UAAU;IAAhB;QACU,aAAQ,GAAG,EAAE,CAAC;IAmCxB,CAAC;IAjCC,WAAW,CAAC,GAAW;QACrB,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAqB;QAC9B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,eAAM,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;YAC7C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;QACvB,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,KAAM,CAAC,CAAC;QAE/D,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;gBAC1C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;gBAC7B,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YACH,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,eAAM,CAAC,KAAK,CAAC,8BAA8B,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAC9D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;YACvB,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,eAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAC;YAChD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;CACF;AAEY,QAAA,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface PerfSDKConfig {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
appVersion: string;
|
|
4
|
+
environment?: 'development' | 'staging' | 'production';
|
|
5
|
+
debug?: boolean;
|
|
6
|
+
endpoint?: string;
|
|
7
|
+
navigationRef?: React.RefObject<unknown>;
|
|
8
|
+
}
|
|
9
|
+
declare class PerfSDKClass {
|
|
10
|
+
private config;
|
|
11
|
+
private initialized;
|
|
12
|
+
init(config: PerfSDKConfig): void;
|
|
13
|
+
flush(): Promise<void>;
|
|
14
|
+
getConfig(): PerfSDKConfig | null;
|
|
15
|
+
isInitialized(): boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare const PerfSDK: PerfSDKClass;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=PerfSDK.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PerfSDK.d.ts","sourceRoot":"","sources":["../../src/core/PerfSDK.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,aAAa,GAAG,SAAS,GAAG,YAAY,CAAC;IACvD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;CAC1C;AAKD,cAAM,YAAY;IAChB,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,WAAW,CAAS;IAE5B,IAAI,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IA+C3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,SAAS,IAAI,aAAa,GAAG,IAAI;IAIjC,aAAa,IAAI,OAAO;CAGzB;AAED,eAAO,MAAM,OAAO,cAAqB,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PerfSDK = void 0;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
const logger_1 = require("../utils/logger");
|
|
6
|
+
const HttpClient_1 = require("./HttpClient");
|
|
7
|
+
const EventQueue_1 = require("./EventQueue");
|
|
8
|
+
const SessionTracker_1 = require("../instrumentation/SessionTracker");
|
|
9
|
+
const StartupTracker_1 = require("../instrumentation/StartupTracker");
|
|
10
|
+
const NavigationTracker_1 = require("../instrumentation/NavigationTracker");
|
|
11
|
+
const FrameTracker_1 = require("../instrumentation/FrameTracker");
|
|
12
|
+
const NetworkTracker_1 = require("../instrumentation/NetworkTracker");
|
|
13
|
+
const SDK_VERSION = '0.1.0';
|
|
14
|
+
const DEFAULT_ENDPOINT = 'https://perfbit.com/api/ingest';
|
|
15
|
+
class PerfSDKClass {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.config = null;
|
|
18
|
+
this.initialized = false;
|
|
19
|
+
}
|
|
20
|
+
init(config) {
|
|
21
|
+
var _a, _b;
|
|
22
|
+
if (this.initialized) {
|
|
23
|
+
logger_1.Logger.warn('PerfSDK.init() called more than once — ignoring');
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const env = (_a = config.environment) !== null && _a !== void 0 ? _a : 'production';
|
|
27
|
+
if (env === 'development' && !config.debug) {
|
|
28
|
+
console.warn('[PerfSDK] Tracking disabled in development mode. Pass debug: true to enable.');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
this.config = config;
|
|
32
|
+
if (config.debug) {
|
|
33
|
+
logger_1.Logger.enable();
|
|
34
|
+
}
|
|
35
|
+
HttpClient_1.httpClient.setEndpoint((_b = config.endpoint) !== null && _b !== void 0 ? _b : DEFAULT_ENDPOINT);
|
|
36
|
+
EventQueue_1.eventQueue.configure({
|
|
37
|
+
api_key: config.apiKey,
|
|
38
|
+
app_version: config.appVersion,
|
|
39
|
+
environment: env,
|
|
40
|
+
platform: react_native_1.Platform.OS,
|
|
41
|
+
sdk_version: SDK_VERSION,
|
|
42
|
+
});
|
|
43
|
+
const sessionId = SessionTracker_1.SessionTracker.start();
|
|
44
|
+
StartupTracker_1.StartupTracker.start(sessionId);
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
|
+
NavigationTracker_1.NavigationTracker.start(config.navigationRef, sessionId);
|
|
47
|
+
FrameTracker_1.FrameTracker.start(sessionId);
|
|
48
|
+
NetworkTracker_1.NetworkTracker.start(sessionId);
|
|
49
|
+
EventQueue_1.eventQueue.startAutoFlush();
|
|
50
|
+
react_native_1.AppState.addEventListener('change', (nextState) => {
|
|
51
|
+
if (nextState === 'background') {
|
|
52
|
+
void EventQueue_1.eventQueue.flush();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
this.initialized = true;
|
|
56
|
+
logger_1.Logger.log('PerfSDK: initialized', { appVersion: config.appVersion, env, platform: react_native_1.Platform.OS });
|
|
57
|
+
}
|
|
58
|
+
async flush() {
|
|
59
|
+
return EventQueue_1.eventQueue.flush();
|
|
60
|
+
}
|
|
61
|
+
getConfig() {
|
|
62
|
+
return this.config;
|
|
63
|
+
}
|
|
64
|
+
isInitialized() {
|
|
65
|
+
return this.initialized;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.PerfSDK = new PerfSDKClass();
|
|
69
|
+
//# sourceMappingURL=PerfSDK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PerfSDK.js","sourceRoot":"","sources":["../../src/core/PerfSDK.ts"],"names":[],"mappings":";;;AAAA,+CAAkD;AAClD,4CAAyC;AACzC,6CAA0C;AAC1C,6CAA0C;AAC1C,sEAAmE;AACnE,sEAAmE;AACnE,4EAAyE;AACzE,kEAA+D;AAC/D,sEAAmE;AAWnE,MAAM,WAAW,GAAG,OAAO,CAAC;AAC5B,MAAM,gBAAgB,GAAG,gCAAgC,CAAC;AAE1D,MAAM,YAAY;IAAlB;QACU,WAAM,GAAyB,IAAI,CAAC;QACpC,gBAAW,GAAG,KAAK,CAAC;IA4D9B,CAAC;IA1DC,IAAI,CAAC,MAAqB;;QACxB,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,eAAM,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;YAC/D,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,MAAA,MAAM,CAAC,WAAW,mCAAI,YAAY,CAAC;QAC/C,IAAI,GAAG,KAAK,aAAa,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAC3C,OAAO,CAAC,IAAI,CAAC,8EAA8E,CAAC,CAAC;YAC7F,OAAO;QACT,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,eAAM,CAAC,MAAM,EAAE,CAAC;QAClB,CAAC;QAED,uBAAU,CAAC,WAAW,CAAC,MAAA,MAAM,CAAC,QAAQ,mCAAI,gBAAgB,CAAC,CAAC;QAE5D,uBAAU,CAAC,SAAS,CAAC;YACnB,OAAO,EAAE,MAAM,CAAC,MAAM;YACtB,WAAW,EAAE,MAAM,CAAC,UAAU;YAC9B,WAAW,EAAE,GAAG;YAChB,QAAQ,EAAE,uBAAQ,CAAC,EAAE;YACrB,WAAW,EAAE,WAAW;SACzB,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,+BAAc,CAAC,KAAK,EAAE,CAAC;QACzC,+BAAc,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAChC,8DAA8D;QAC9D,qCAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,aAAiD,EAAE,SAAS,CAAC,CAAC;QAC7F,2BAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC9B,+BAAc,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAEhC,uBAAU,CAAC,cAAc,EAAE,CAAC;QAE5B,uBAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,EAAE;YAChD,IAAI,SAAS,KAAK,YAAY,EAAE,CAAC;gBAC/B,KAAK,uBAAU,CAAC,KAAK,EAAE,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,eAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,QAAQ,EAAE,uBAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;IACpG,CAAC;IAED,KAAK,CAAC,KAAK;QACT,OAAO,uBAAU,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF;AAEY,QAAA,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PerfSDK = void 0;
|
|
4
|
+
var PerfSDK_1 = require("./core/PerfSDK");
|
|
5
|
+
Object.defineProperty(exports, "PerfSDK", { enumerable: true, get: function () { return PerfSDK_1.PerfSDK; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,0CAAyC;AAAhC,kGAAA,OAAO,OAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare class FrameTrackerClass {
|
|
2
|
+
private running;
|
|
3
|
+
private lastFrameTime;
|
|
4
|
+
private windowStart;
|
|
5
|
+
private totalFrames;
|
|
6
|
+
private slowFrames;
|
|
7
|
+
private frozenFrames;
|
|
8
|
+
private sessionId;
|
|
9
|
+
start(sessionId: string): void;
|
|
10
|
+
stop(): void;
|
|
11
|
+
private scheduleFrame;
|
|
12
|
+
}
|
|
13
|
+
export declare const FrameTracker: FrameTrackerClass;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=FrameTracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FrameTracker.d.ts","sourceRoot":"","sources":["../../src/instrumentation/FrameTracker.ts"],"names":[],"mappings":"AAOA,cAAM,iBAAiB;IACrB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,SAAS,CAAM;IAEvB,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAY9B,IAAI,IAAI,IAAI;IAIZ,OAAO,CAAC,aAAa;CA2CtB;AAED,eAAO,MAAM,YAAY,mBAA0B,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FrameTracker = void 0;
|
|
4
|
+
const logger_1 = require("../utils/logger");
|
|
5
|
+
const EventQueue_1 = require("../core/EventQueue");
|
|
6
|
+
const SLOW_FRAME_THRESHOLD_MS = 16.67;
|
|
7
|
+
const FROZEN_FRAME_THRESHOLD_MS = 700;
|
|
8
|
+
const REPORTING_WINDOW_MS = 10000;
|
|
9
|
+
class FrameTrackerClass {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.running = false;
|
|
12
|
+
this.lastFrameTime = null;
|
|
13
|
+
this.windowStart = 0;
|
|
14
|
+
this.totalFrames = 0;
|
|
15
|
+
this.slowFrames = 0;
|
|
16
|
+
this.frozenFrames = 0;
|
|
17
|
+
this.sessionId = '';
|
|
18
|
+
}
|
|
19
|
+
start(sessionId) {
|
|
20
|
+
this.sessionId = sessionId;
|
|
21
|
+
this.running = true;
|
|
22
|
+
this.lastFrameTime = Date.now();
|
|
23
|
+
this.windowStart = Date.now();
|
|
24
|
+
this.totalFrames = 0;
|
|
25
|
+
this.slowFrames = 0;
|
|
26
|
+
this.frozenFrames = 0;
|
|
27
|
+
this.scheduleFrame();
|
|
28
|
+
logger_1.Logger.log('FrameTracker: started');
|
|
29
|
+
}
|
|
30
|
+
stop() {
|
|
31
|
+
this.running = false;
|
|
32
|
+
}
|
|
33
|
+
scheduleFrame() {
|
|
34
|
+
if (!this.running)
|
|
35
|
+
return;
|
|
36
|
+
requestAnimationFrame(() => {
|
|
37
|
+
if (!this.running)
|
|
38
|
+
return;
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
if (this.lastFrameTime !== null) {
|
|
41
|
+
const frameDuration = now - this.lastFrameTime;
|
|
42
|
+
this.totalFrames++;
|
|
43
|
+
if (frameDuration > FROZEN_FRAME_THRESHOLD_MS) {
|
|
44
|
+
this.frozenFrames++;
|
|
45
|
+
}
|
|
46
|
+
else if (frameDuration > SLOW_FRAME_THRESHOLD_MS) {
|
|
47
|
+
this.slowFrames++;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
this.lastFrameTime = now;
|
|
51
|
+
if (now - this.windowStart >= REPORTING_WINDOW_MS) {
|
|
52
|
+
EventQueue_1.eventQueue.push({
|
|
53
|
+
type: 'frame_metrics',
|
|
54
|
+
timestamp: this.windowStart,
|
|
55
|
+
session_id: this.sessionId,
|
|
56
|
+
window_duration_ms: now - this.windowStart,
|
|
57
|
+
total_frames: this.totalFrames,
|
|
58
|
+
slow_frames: this.slowFrames,
|
|
59
|
+
frozen_frames: this.frozenFrames,
|
|
60
|
+
});
|
|
61
|
+
logger_1.Logger.log('FrameTracker: frame_metrics', {
|
|
62
|
+
total: this.totalFrames,
|
|
63
|
+
slow: this.slowFrames,
|
|
64
|
+
frozen: this.frozenFrames,
|
|
65
|
+
});
|
|
66
|
+
this.windowStart = now;
|
|
67
|
+
this.totalFrames = 0;
|
|
68
|
+
this.slowFrames = 0;
|
|
69
|
+
this.frozenFrames = 0;
|
|
70
|
+
}
|
|
71
|
+
this.scheduleFrame();
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.FrameTracker = new FrameTrackerClass();
|
|
76
|
+
//# sourceMappingURL=FrameTracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FrameTracker.js","sourceRoot":"","sources":["../../src/instrumentation/FrameTracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
declare class NavigationTrackerClass {
|
|
2
|
+
private currentScreen;
|
|
3
|
+
private sessionId;
|
|
4
|
+
start(navigationRef: React.RefObject<any> | undefined, sessionId: string): void;
|
|
5
|
+
}
|
|
6
|
+
export declare const NavigationTracker: NavigationTrackerClass;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=NavigationTracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NavigationTracker.d.ts","sourceRoot":"","sources":["../../src/instrumentation/NavigationTracker.ts"],"names":[],"mappings":"AAiBA,cAAM,sBAAsB;IAC1B,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,SAAS,CAAM;IAGvB,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;CAiChF;AAED,eAAO,MAAM,iBAAiB,wBAA+B,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NavigationTracker = void 0;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
const logger_1 = require("../utils/logger");
|
|
6
|
+
const EventQueue_1 = require("../core/EventQueue");
|
|
7
|
+
function getActiveRouteName(state) {
|
|
8
|
+
const route = state.routes[state.index];
|
|
9
|
+
if (route.state) {
|
|
10
|
+
return getActiveRouteName(route.state);
|
|
11
|
+
}
|
|
12
|
+
return route.name;
|
|
13
|
+
}
|
|
14
|
+
class NavigationTrackerClass {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.currentScreen = null;
|
|
17
|
+
this.sessionId = '';
|
|
18
|
+
}
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
start(navigationRef, sessionId) {
|
|
21
|
+
this.sessionId = sessionId;
|
|
22
|
+
if (!(navigationRef === null || navigationRef === void 0 ? void 0 : navigationRef.current)) {
|
|
23
|
+
logger_1.Logger.warn('NavigationTracker: no navigationRef provided, screen tracking disabled');
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
navigationRef.current.addListener('state', () => {
|
|
27
|
+
var _a;
|
|
28
|
+
const state = (_a = navigationRef.current) === null || _a === void 0 ? void 0 : _a.getRootState();
|
|
29
|
+
if (!state)
|
|
30
|
+
return;
|
|
31
|
+
const screenName = getActiveRouteName(state);
|
|
32
|
+
if (screenName === this.currentScreen)
|
|
33
|
+
return;
|
|
34
|
+
const navStartTime = Date.now();
|
|
35
|
+
this.currentScreen = screenName;
|
|
36
|
+
react_native_1.InteractionManager.runAfterInteractions(() => {
|
|
37
|
+
const load_duration_ms = Date.now() - navStartTime;
|
|
38
|
+
EventQueue_1.eventQueue.push({
|
|
39
|
+
type: 'screen_load',
|
|
40
|
+
timestamp: navStartTime,
|
|
41
|
+
session_id: this.sessionId,
|
|
42
|
+
screen_name: screenName,
|
|
43
|
+
load_duration_ms,
|
|
44
|
+
});
|
|
45
|
+
logger_1.Logger.log('NavigationTracker: screen_load', screenName + ' ' + load_duration_ms + 'ms');
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
logger_1.Logger.log('NavigationTracker: started');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.NavigationTracker = new NavigationTrackerClass();
|
|
52
|
+
//# sourceMappingURL=NavigationTracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NavigationTracker.js","sourceRoot":"","sources":["../../src/instrumentation/NavigationTracker.ts"],"names":[],"mappings":";;;AAAA,+CAAkD;AAClD,4CAAyC;AACzC,mDAAgD;AAOhD,SAAS,kBAAkB,CAAC,KAAe;IACzC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACxC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC;AACpB,CAAC;AAED,MAAM,sBAAsB;IAA5B;QACU,kBAAa,GAAkB,IAAI,CAAC;QACpC,cAAS,GAAG,EAAE,CAAC;IAoCzB,CAAC;IAlCC,8DAA8D;IAC9D,KAAK,CAAC,aAA+C,EAAE,SAAiB;QACtE,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAE3B,IAAI,CAAC,CAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,OAAO,CAAA,EAAE,CAAC;YAC5B,eAAM,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC;YACtF,OAAO;QACT,CAAC;QAED,aAAa,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE;;YAC9C,MAAM,KAAK,GAAG,MAAA,aAAa,CAAC,OAAO,0CAAE,YAAY,EAAE,CAAC;YACpD,IAAI,CAAC,KAAK;gBAAE,OAAO;YAEnB,MAAM,UAAU,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;YAC7C,IAAI,UAAU,KAAK,IAAI,CAAC,aAAa;gBAAE,OAAO;YAE9C,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAChC,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC;YAEhC,iCAAkB,CAAC,oBAAoB,CAAC,GAAG,EAAE;gBAC3C,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC;gBACnD,uBAAU,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,aAAa;oBACnB,SAAS,EAAE,YAAY;oBACvB,UAAU,EAAE,IAAI,CAAC,SAAS;oBAC1B,WAAW,EAAE,UAAU;oBACvB,gBAAgB;iBACjB,CAAC,CAAC;gBACH,eAAM,CAAC,GAAG,CAAC,gCAAgC,EAAE,UAAU,GAAG,GAAG,GAAG,gBAAgB,GAAG,IAAI,CAAC,CAAC;YAC3F,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,eAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC3C,CAAC;CACF;AAEY,QAAA,iBAAiB,GAAG,IAAI,sBAAsB,EAAE,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
declare class NetworkTrackerClass {
|
|
2
|
+
private patched;
|
|
3
|
+
private sessionId;
|
|
4
|
+
start(sessionId: string): void;
|
|
5
|
+
private patchFetch;
|
|
6
|
+
private patchXHR;
|
|
7
|
+
private sanitizeUrl;
|
|
8
|
+
}
|
|
9
|
+
export declare const NetworkTracker: NetworkTrackerClass;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=NetworkTracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NetworkTracker.d.ts","sourceRoot":"","sources":["../../src/instrumentation/NetworkTracker.ts"],"names":[],"mappings":"AAGA,cAAM,mBAAmB;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAM;IAEvB,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAS9B,OAAO,CAAC,UAAU;IAuClB,OAAO,CAAC,QAAQ;IAuDhB,OAAO,CAAC,WAAW;CAQpB;AAED,eAAO,MAAM,cAAc,qBAA4B,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NetworkTracker = void 0;
|
|
4
|
+
const logger_1 = require("../utils/logger");
|
|
5
|
+
const EventQueue_1 = require("../core/EventQueue");
|
|
6
|
+
class NetworkTrackerClass {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.patched = false;
|
|
9
|
+
this.sessionId = '';
|
|
10
|
+
}
|
|
11
|
+
start(sessionId) {
|
|
12
|
+
if (this.patched)
|
|
13
|
+
return;
|
|
14
|
+
this.sessionId = sessionId;
|
|
15
|
+
this.patchFetch();
|
|
16
|
+
this.patchXHR();
|
|
17
|
+
this.patched = true;
|
|
18
|
+
logger_1.Logger.log('NetworkTracker: started');
|
|
19
|
+
}
|
|
20
|
+
patchFetch() {
|
|
21
|
+
const originalFetch = global.fetch;
|
|
22
|
+
const self = this;
|
|
23
|
+
global.fetch = async function (input, init) {
|
|
24
|
+
var _a;
|
|
25
|
+
const startTime = Date.now();
|
|
26
|
+
const url = self.sanitizeUrl(input.toString());
|
|
27
|
+
const method = ((_a = (init === null || init === void 0 ? void 0 : init.method)) !== null && _a !== void 0 ? _a : 'GET').toUpperCase();
|
|
28
|
+
try {
|
|
29
|
+
const response = await originalFetch(input, init);
|
|
30
|
+
EventQueue_1.eventQueue.push({
|
|
31
|
+
type: 'network_request',
|
|
32
|
+
timestamp: startTime,
|
|
33
|
+
session_id: self.sessionId,
|
|
34
|
+
url,
|
|
35
|
+
method,
|
|
36
|
+
status_code: response.status,
|
|
37
|
+
duration_ms: Date.now() - startTime,
|
|
38
|
+
request_size_bytes: 0,
|
|
39
|
+
response_size_bytes: 0,
|
|
40
|
+
});
|
|
41
|
+
return response;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
EventQueue_1.eventQueue.push({
|
|
45
|
+
type: 'network_request',
|
|
46
|
+
timestamp: startTime,
|
|
47
|
+
session_id: self.sessionId,
|
|
48
|
+
url,
|
|
49
|
+
method,
|
|
50
|
+
duration_ms: Date.now() - startTime,
|
|
51
|
+
request_size_bytes: 0,
|
|
52
|
+
response_size_bytes: 0,
|
|
53
|
+
});
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
patchXHR() {
|
|
59
|
+
const self = this;
|
|
60
|
+
const OriginalXHR = global.XMLHttpRequest;
|
|
61
|
+
if (!OriginalXHR)
|
|
62
|
+
return;
|
|
63
|
+
const originalOpen = OriginalXHR.prototype.open;
|
|
64
|
+
const originalSend = OriginalXHR.prototype.send;
|
|
65
|
+
OriginalXHR.prototype.open = function (method, url, ...args) {
|
|
66
|
+
this.__perfbit_method = method.toUpperCase();
|
|
67
|
+
this.__perfbit_url = self.sanitizeUrl(url);
|
|
68
|
+
this.__perfbit_start = Date.now();
|
|
69
|
+
return originalOpen.apply(this, [method, url, ...args]);
|
|
70
|
+
};
|
|
71
|
+
OriginalXHR.prototype.send = function (body) {
|
|
72
|
+
var _a, _b, _c;
|
|
73
|
+
const meta = this;
|
|
74
|
+
const startTime = (_a = meta.__perfbit_start) !== null && _a !== void 0 ? _a : Date.now();
|
|
75
|
+
const url = (_b = meta.__perfbit_url) !== null && _b !== void 0 ? _b : '';
|
|
76
|
+
const method = (_c = meta.__perfbit_method) !== null && _c !== void 0 ? _c : 'GET';
|
|
77
|
+
const pushEvent = (statusCode) => {
|
|
78
|
+
EventQueue_1.eventQueue.push(Object.assign(Object.assign({ type: 'network_request', timestamp: startTime, session_id: self.sessionId, url,
|
|
79
|
+
method }, (statusCode !== undefined ? { status_code: statusCode } : {})), { duration_ms: Date.now() - startTime, request_size_bytes: 0, response_size_bytes: 0 }));
|
|
80
|
+
};
|
|
81
|
+
this.addEventListener('load', function () {
|
|
82
|
+
pushEvent(this.status);
|
|
83
|
+
});
|
|
84
|
+
this.addEventListener('error', function () {
|
|
85
|
+
pushEvent();
|
|
86
|
+
});
|
|
87
|
+
return originalSend.apply(this, [body]);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
sanitizeUrl(url) {
|
|
91
|
+
try {
|
|
92
|
+
const parsed = new URL(url);
|
|
93
|
+
return `${parsed.origin}${parsed.pathname}`;
|
|
94
|
+
}
|
|
95
|
+
catch (_a) {
|
|
96
|
+
return url;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.NetworkTracker = new NetworkTrackerClass();
|
|
101
|
+
//# sourceMappingURL=NetworkTracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NetworkTracker.js","sourceRoot":"","sources":["../../src/instrumentation/NetworkTracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
declare class SessionTrackerClass {
|
|
2
|
+
private sessionId;
|
|
3
|
+
private startedAt;
|
|
4
|
+
start(): string;
|
|
5
|
+
end(): void;
|
|
6
|
+
private recordCrash;
|
|
7
|
+
getSessionId(): string;
|
|
8
|
+
}
|
|
9
|
+
export declare const SessionTracker: SessionTrackerClass;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=SessionTracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionTracker.d.ts","sourceRoot":"","sources":["../../src/instrumentation/SessionTracker.ts"],"names":[],"mappings":"AAKA,cAAM,mBAAmB;IACvB,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,SAAS,CAAK;IAEtB,KAAK,IAAI,MAAM;IAoBf,GAAG,IAAI,IAAI;IAUX,OAAO,CAAC,WAAW;IAWnB,YAAY,IAAI,MAAM;CAGvB;AAED,eAAO,MAAM,cAAc,qBAA4B,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SessionTracker = void 0;
|
|
4
|
+
const uuid_1 = require("../utils/uuid");
|
|
5
|
+
const logger_1 = require("../utils/logger");
|
|
6
|
+
const EventQueue_1 = require("../core/EventQueue");
|
|
7
|
+
class SessionTrackerClass {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.sessionId = '';
|
|
10
|
+
this.startedAt = 0;
|
|
11
|
+
}
|
|
12
|
+
start() {
|
|
13
|
+
this.sessionId = (0, uuid_1.generateUUID)();
|
|
14
|
+
this.startedAt = Date.now();
|
|
15
|
+
EventQueue_1.eventQueue.push({
|
|
16
|
+
type: 'session_start',
|
|
17
|
+
timestamp: this.startedAt,
|
|
18
|
+
session_id: this.sessionId,
|
|
19
|
+
});
|
|
20
|
+
const prevHandler = ErrorUtils.getGlobalHandler();
|
|
21
|
+
ErrorUtils.setGlobalHandler((error, isFatal) => {
|
|
22
|
+
this.recordCrash(error);
|
|
23
|
+
if (prevHandler)
|
|
24
|
+
prevHandler(error, isFatal);
|
|
25
|
+
});
|
|
26
|
+
logger_1.Logger.log('SessionTracker: started', this.sessionId);
|
|
27
|
+
return this.sessionId;
|
|
28
|
+
}
|
|
29
|
+
end() {
|
|
30
|
+
if (!this.sessionId)
|
|
31
|
+
return;
|
|
32
|
+
EventQueue_1.eventQueue.push({
|
|
33
|
+
type: 'session_end',
|
|
34
|
+
timestamp: Date.now(),
|
|
35
|
+
session_id: this.sessionId,
|
|
36
|
+
duration_ms: Date.now() - this.startedAt,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
recordCrash(error) {
|
|
40
|
+
var _a, _b;
|
|
41
|
+
EventQueue_1.eventQueue.push({
|
|
42
|
+
type: 'session_crash',
|
|
43
|
+
timestamp: Date.now(),
|
|
44
|
+
session_id: this.sessionId,
|
|
45
|
+
error_message: (_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : 'unknown error',
|
|
46
|
+
error_stack: (_b = error === null || error === void 0 ? void 0 : error.stack) !== null && _b !== void 0 ? _b : '',
|
|
47
|
+
});
|
|
48
|
+
void EventQueue_1.eventQueue.flush();
|
|
49
|
+
}
|
|
50
|
+
getSessionId() {
|
|
51
|
+
return this.sessionId;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.SessionTracker = new SessionTrackerClass();
|
|
55
|
+
//# sourceMappingURL=SessionTracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionTracker.js","sourceRoot":"","sources":["../../src/instrumentation/SessionTracker.ts"],"names":[],"mappings":";;;AACA,wCAA6C;AAC7C,4CAAyC;AACzC,mDAAgD;AAEhD,MAAM,mBAAmB;IAAzB;QACU,cAAS,GAAG,EAAE,CAAC;QACf,cAAS,GAAG,CAAC,CAAC;IA8CxB,CAAC;IA5CC,KAAK;QACH,IAAI,CAAC,SAAS,GAAG,IAAA,mBAAY,GAAE,CAAC;QAChC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE5B,uBAAU,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,eAAe;YACrB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,UAAU,EAAE,IAAI,CAAC,SAAS;SAC3B,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,UAAU,CAAC,gBAAgB,EAAE,CAAC;QAClD,UAAU,CAAC,gBAAgB,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC7C,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACxB,IAAI,WAAW;gBAAE,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,eAAM,CAAC,GAAG,CAAC,yBAAyB,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,GAAG;QACD,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO;QAC5B,uBAAU,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,aAAa;YACnB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,UAAU,EAAE,IAAI,CAAC,SAAS;YAC1B,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS;SACzC,CAAC,CAAC;IACL,CAAC;IAEO,WAAW,CAAC,KAAY;;QAC9B,uBAAU,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,eAAe;YACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,UAAU,EAAE,IAAI,CAAC,SAAS;YAC1B,aAAa,EAAE,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,mCAAI,eAAe;YAChD,WAAW,EAAE,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,KAAK,mCAAI,EAAE;SAChC,CAAC,CAAC;QACH,KAAK,uBAAU,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;CACF;AAEY,QAAA,cAAc,GAAG,IAAI,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare class StartupTrackerClass {
|
|
2
|
+
private coldStartRecorded;
|
|
3
|
+
private lastBackgroundTime;
|
|
4
|
+
private sessionId;
|
|
5
|
+
start(sessionId: string): void;
|
|
6
|
+
}
|
|
7
|
+
export declare const StartupTracker: StartupTrackerClass;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=StartupTracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StartupTracker.d.ts","sourceRoot":"","sources":["../../src/instrumentation/StartupTracker.ts"],"names":[],"mappings":"AAOA,cAAM,mBAAmB;IACvB,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,SAAS,CAAM;IAEvB,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CA+B/B;AAED,eAAO,MAAM,cAAc,qBAA4B,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StartupTracker = void 0;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
const logger_1 = require("../utils/logger");
|
|
6
|
+
const EventQueue_1 = require("../core/EventQueue");
|
|
7
|
+
// Captured at module load — this is the earliest point we can record
|
|
8
|
+
const MODULE_INIT_TIME = Date.now();
|
|
9
|
+
class StartupTrackerClass {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.coldStartRecorded = false;
|
|
12
|
+
this.lastBackgroundTime = null;
|
|
13
|
+
this.sessionId = '';
|
|
14
|
+
}
|
|
15
|
+
start(sessionId) {
|
|
16
|
+
this.sessionId = sessionId;
|
|
17
|
+
react_native_1.AppState.addEventListener('change', (nextState) => {
|
|
18
|
+
if (nextState === 'active') {
|
|
19
|
+
if (!this.coldStartRecorded) {
|
|
20
|
+
const duration_ms = Date.now() - MODULE_INIT_TIME;
|
|
21
|
+
EventQueue_1.eventQueue.push({
|
|
22
|
+
type: 'cold_start',
|
|
23
|
+
timestamp: Date.now(),
|
|
24
|
+
session_id: this.sessionId,
|
|
25
|
+
duration_ms,
|
|
26
|
+
});
|
|
27
|
+
this.coldStartRecorded = true;
|
|
28
|
+
logger_1.Logger.log('StartupTracker: cold start', duration_ms + 'ms');
|
|
29
|
+
}
|
|
30
|
+
else if (this.lastBackgroundTime !== null) {
|
|
31
|
+
const duration_ms = Date.now() - this.lastBackgroundTime;
|
|
32
|
+
EventQueue_1.eventQueue.push({
|
|
33
|
+
type: 'warm_start',
|
|
34
|
+
timestamp: Date.now(),
|
|
35
|
+
session_id: this.sessionId,
|
|
36
|
+
duration_ms,
|
|
37
|
+
});
|
|
38
|
+
this.lastBackgroundTime = null;
|
|
39
|
+
logger_1.Logger.log('StartupTracker: warm start', duration_ms + 'ms');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else if (nextState === 'background') {
|
|
43
|
+
this.lastBackgroundTime = Date.now();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.StartupTracker = new StartupTrackerClass();
|
|
49
|
+
//# sourceMappingURL=StartupTracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StartupTracker.js","sourceRoot":"","sources":["../../src/instrumentation/StartupTracker.ts"],"names":[],"mappings":";;;AAAA,+CAAwD;AACxD,4CAAyC;AACzC,mDAAgD;AAEhD,qEAAqE;AACrE,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AAEpC,MAAM,mBAAmB;IAAzB;QACU,sBAAiB,GAAG,KAAK,CAAC;QAC1B,uBAAkB,GAAkB,IAAI,CAAC;QACzC,cAAS,GAAG,EAAE,CAAC;IAiCzB,CAAC;IA/BC,KAAK,CAAC,SAAiB;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAE3B,uBAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,SAAyB,EAAE,EAAE;YAChE,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;gBAC3B,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,gBAAgB,CAAC;oBAClD,uBAAU,CAAC,IAAI,CAAC;wBACd,IAAI,EAAE,YAAY;wBAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;wBACrB,UAAU,EAAE,IAAI,CAAC,SAAS;wBAC1B,WAAW;qBACZ,CAAC,CAAC;oBACH,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;oBAC9B,eAAM,CAAC,GAAG,CAAC,4BAA4B,EAAE,WAAW,GAAG,IAAI,CAAC,CAAC;gBAC/D,CAAC;qBAAM,IAAI,IAAI,CAAC,kBAAkB,KAAK,IAAI,EAAE,CAAC;oBAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,kBAAkB,CAAC;oBACzD,uBAAU,CAAC,IAAI,CAAC;wBACd,IAAI,EAAE,YAAY;wBAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;wBACrB,UAAU,EAAE,IAAI,CAAC,SAAS;wBAC1B,WAAW;qBACZ,CAAC,CAAC;oBACH,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;oBAC/B,eAAM,CAAC,GAAG,CAAC,4BAA4B,EAAE,WAAW,GAAG,IAAI,CAAC,CAAC;gBAC/D,CAAC;YACH,CAAC;iBAAM,IAAI,SAAS,KAAK,YAAY,EAAE,CAAC;gBACtC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAEY,QAAA,cAAc,GAAG,IAAI,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM;;iBAIJ,MAAM,SAAS,OAAO;kBAGrB,MAAM,SAAS,OAAO;mBAGrB,MAAM,SAAS,OAAO;CAGtC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Logger = void 0;
|
|
4
|
+
let debugEnabled = false;
|
|
5
|
+
exports.Logger = {
|
|
6
|
+
enable() {
|
|
7
|
+
debugEnabled = true;
|
|
8
|
+
},
|
|
9
|
+
log(message, data) {
|
|
10
|
+
if (debugEnabled)
|
|
11
|
+
console.log('[perfbit]', message, data !== null && data !== void 0 ? data : '');
|
|
12
|
+
},
|
|
13
|
+
warn(message, data) {
|
|
14
|
+
if (debugEnabled)
|
|
15
|
+
console.warn('[perfbit]', message, data !== null && data !== void 0 ? data : '');
|
|
16
|
+
},
|
|
17
|
+
error(message, data) {
|
|
18
|
+
console.error('[perfbit]', message, data !== null && data !== void 0 ? data : '');
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":";;;AAAA,IAAI,YAAY,GAAG,KAAK,CAAC;AAEZ,QAAA,MAAM,GAAG;IACpB,MAAM;QACJ,YAAY,GAAG,IAAI,CAAC;IACtB,CAAC;IACD,GAAG,CAAC,OAAe,EAAE,IAAc;QACjC,IAAI,YAAY;YAAE,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,CAAC,OAAe,EAAE,IAAc;QAClC,IAAI,YAAY;YAAE,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,KAAK,CAAC,OAAe,EAAE,IAAc;QACnC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,EAAE,CAAC,CAAC;IAClD,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/utils/storage.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,OAAO;aACT,MAAM,SAAS,MAAM,GAAG,IAAI;aAO5B,MAAM,GAAG,MAAM,GAAG,IAAI;gBAMnB,MAAM,GAAG,IAAI;CAO1B,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Storage = void 0;
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
|
+
let mmkv = null;
|
|
6
|
+
const memoryStore = new Map();
|
|
7
|
+
try {
|
|
8
|
+
// MMKV is an optional peer dependency — if not installed, fall back to memory
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
10
|
+
const { MMKV } = require('react-native-mmkv');
|
|
11
|
+
mmkv = new MMKV({ id: 'perfbit-sdk' });
|
|
12
|
+
}
|
|
13
|
+
catch (_a) {
|
|
14
|
+
// fall through to memory fallback
|
|
15
|
+
}
|
|
16
|
+
exports.Storage = {
|
|
17
|
+
set(key, value) {
|
|
18
|
+
if (mmkv) {
|
|
19
|
+
mmkv.set(key, value);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
memoryStore.set(key, value);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
get(key) {
|
|
26
|
+
var _a, _b;
|
|
27
|
+
if (mmkv) {
|
|
28
|
+
return (_a = mmkv.getString(key)) !== null && _a !== void 0 ? _a : null;
|
|
29
|
+
}
|
|
30
|
+
return (_b = memoryStore.get(key)) !== null && _b !== void 0 ? _b : null;
|
|
31
|
+
},
|
|
32
|
+
delete(key) {
|
|
33
|
+
if (mmkv) {
|
|
34
|
+
mmkv.delete(key);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
memoryStore.delete(key);
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/utils/storage.ts"],"names":[],"mappings":";;;AAAA,8DAA8D;AAC9D,IAAI,IAAI,GAAQ,IAAI,CAAC;AACrB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;AAE9C,IAAI,CAAC;IACH,8EAA8E;IAC9E,8DAA8D;IAC9D,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9C,IAAI,GAAG,IAAI,IAAI,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;AACzC,CAAC;AAAC,WAAM,CAAC;IACP,kCAAkC;AACpC,CAAC;AAEY,QAAA,OAAO,GAAG;IACrB,GAAG,CAAC,GAAW,EAAE,KAAa;QAC5B,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACvB,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,GAAG,CAAC,GAAW;;QACb,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,MAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,mCAAI,IAAI,CAAC;QACrC,CAAC;QACD,OAAO,MAAA,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,mCAAI,IAAI,CAAC;IACtC,CAAC;IACD,MAAM,CAAC,GAAW;QAChB,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../../src/utils/uuid.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,IAAI,MAAM,CAMrC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateUUID = generateUUID;
|
|
4
|
+
function generateUUID() {
|
|
5
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
6
|
+
const r = (Math.random() * 16) | 0;
|
|
7
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
8
|
+
return v.toString(16);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=uuid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuid.js","sourceRoot":"","sources":["../../src/utils/uuid.ts"],"names":[],"mappings":";;AAAA,oCAMC;AAND,SAAgB,YAAY;IAC1B,OAAO,sCAAsC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;QACnE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;QACnC,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;QAC1C,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@perfbitapp/rn-sdk",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "React Native performance monitoring SDK",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"require": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"react-native": ">=0.70.0",
|
|
21
|
+
"@react-navigation/native": ">=6.0.0"
|
|
22
|
+
},
|
|
23
|
+
"peerDependenciesMeta": {
|
|
24
|
+
"@react-navigation/native": {
|
|
25
|
+
"optional": true
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"typescript": "^5.0.0",
|
|
30
|
+
"@types/react-native": "^0.72.0"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsc",
|
|
34
|
+
"dev": "tsc --watch",
|
|
35
|
+
"release": "pnpm build && npm version minor && pnpm publish"
|
|
36
|
+
}
|
|
37
|
+
}
|