@goliapkg/sentori-react-native 5.6.0 → 5.6.1

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 CHANGED
@@ -5,11 +5,24 @@ self-hosted crash + warning monitor for mobile apps. JS layer +
5
5
  iOS Swift + Android Kotlin native, distributed as an Expo module
6
6
  (works on bare RN too).
7
7
 
8
- Eight verbs are the whole API. Every one is synchronous, returns
9
- immediately, and can never throw into your app.
8
+ Eight verbs are the whole API.
10
9
 
11
10
  Upgrading from 4.x? See [MIGRATION.md](./MIGRATION.md).
12
11
 
12
+ ## The zero-cost contract
13
+
14
+ Sentori must only ever be a free upgrade for your app:
15
+
16
+ - **Every call is synchronous, O(1), and can never throw.** Not on
17
+ garbage input, not when the network is down, not when the server
18
+ is gone. You never need a try/catch around a Sentori call.
19
+ - `init()` failure (bad token, missing URL) degrades every verb to
20
+ a no-op with one console.warn — never a crash, never a red box.
21
+ - Nothing leaves the device until an error/warn actually fires;
22
+ then one batched request carries the event with its context.
23
+ - Buffers (signal ring, replay rings, offline queue) are all
24
+ hard-bounded.
25
+
13
26
  ## Install
14
27
 
15
28
  ```sh
@@ -26,11 +39,15 @@ sentori.init({
26
39
  token: 'st_…', // ingest token, Settings → Tokens
27
40
  ingestUrl: 'https://sentori.example.com',
28
41
  release: 'my-app@1.2.3',
29
- environment: 'prod',
42
+ environment: 'production', // the DEPLOYMENT environment
43
+ replayScreens: true, // opt-in visual replay (v5.1)
44
+ backendHealthUrl: 'https://api.example.com/healthz', // v5.2, see below
30
45
  })
31
46
 
32
47
  sentori.user({ id, email, name }) // drives breadth × depth stats
33
- sentori.context({ tenant: 'acme' }) // ambient tags on every event
48
+ sentori.context({ build: 'release', tenant: 'acme' }) // ambient tags;
49
+ // every key becomes a queue
50
+ // slicing dimension on the board
34
51
 
35
52
  sentori.error(new Error('boom')) // what broke
36
53
  sentori.warn('pay.gateway-retry', data) // where users hurt
@@ -45,14 +62,59 @@ Auto-wired (no configuration):
45
62
  - iOS `NSException` + Android uncaught-exception handlers
46
63
  - Warn scenario detectors: rage taps, long freezes, slow cold start
47
64
  (slow API stays opt-in) — tune with `init({ detect })`
48
- - Signal ring: recent taps, navigation, traces ride along on every
49
- error/warn as the "what the user was doing" timeline
65
+ - Signal ring: the last 60 s of taps (with coordinates), navigation,
66
+ http and traces ride along on every error/warn as the "what the
67
+ user was doing" timeline
50
68
  - B-type replay: rolling wireframe buffer, shipped only when an
51
- error/warn actually fires (`init({ replaySeconds })`)
69
+ error/warn actually fires (`init({ replaySeconds })`); opt-in
70
+ pixel replay via `replayScreens: true`, with native-side masking
71
+ (`registerMaskQuery`) so tagged views never exist in any frame
72
+ - Cold-start measurement with a pre-warm guard: processes started
73
+ in the background (FCM, JobScheduler, iOS prewarming) are flagged
74
+ and never counted as slow starts
52
75
 
53
76
  Identity is hashed on-device with a salted hash — the server never
54
77
  sees the raw email.
55
78
 
79
+ ## Launch measurement (v5.6)
80
+
81
+ One number ending at `init()` cannot represent user-perceived
82
+ launch. Stage it instead:
83
+
84
+ ```tsx
85
+ sentori.launch.mark('bootstrap') // optional waypoints, anywhere
86
+ sentori.launch.mark('first-tree')
87
+ sentori.launch.complete() // when YOUR app counts as usable
88
+ ```
89
+
90
+ `complete()` emits one `app.launch` trace with segment durations
91
+ (native span → each waypoint → complete). The dashboard's
92
+ Instruments page aggregates p50/p90/p95 per release from it. Apps
93
+ that never call the marks keep the plain cold-start behaviour.
94
+
95
+ ## Custom breadcrumbs (v5.5)
96
+
97
+ Feed your own context into the signal ring — same fire-and-forget
98
+ guarantees as the verbs:
99
+
100
+ ```tsx
101
+ import { pushSignal } from '@goliapkg/sentori-react-native'
102
+
103
+ // in your API interceptor — the one place that knows which
104
+ // requests matter (Sentori deliberately does not patch fetch/XHR):
105
+ pushSignal('http', { method, url, status, ms }) // status 0 = no response
106
+ ```
107
+
108
+ `http` entries render as request lines on the case timeline; any
109
+ other kind renders with its data as key=value pairs.
110
+
111
+ ## Backend availability (v5.2)
112
+
113
+ `init({ backendHealthUrl })` — the URL rides along with event
114
+ batches (the app itself never pings anything); the Sentori server
115
+ probes it once a minute and shows uptime + latency on the project
116
+ card.
117
+
56
118
  ## React extras
57
119
 
58
120
  ```tsx
@@ -60,14 +122,16 @@ import {
60
122
  ErrorBoundary, // React idiom for the error verb
61
123
  RageTapCapture, // wrap your root to feed the rage-tap detector
62
124
  useTraceNavigation, // pass your react-navigation ref
125
+ registerMaskQuery, // nativeIDs to black out in every captured frame
63
126
  } from '@goliapkg/sentori-react-native'
64
127
  ```
65
128
 
66
129
  ## Build pipeline
67
130
 
68
- `@goliapkg/sentori-cli` uploads sourcemaps (failures never block a
69
- release — friendly notice, exit 0) and registers `probe()`
70
- tripwires per release. See MIGRATION.md §6.
131
+ `@goliapkg/sentori-cli` uploads sourcemaps, dSYMs, Proguard maps
132
+ and native source bundles (failures never block a release —
133
+ friendly notice, exit 0) and registers `probe()` tripwires per
134
+ release. See MIGRATION.md §6.
71
135
 
72
136
  ## License
73
137
 
package/lib/transport.js CHANGED
@@ -15,7 +15,7 @@ const MAX_RETRY = 3;
15
15
  const STORAGE_KEY = '@sentori/pending';
16
16
  const MAX_PERSISTED = 1000;
17
17
  // Pinned to package.json by a test — bump both together.
18
- const SDK_VERSION = '5.6.0';
18
+ const SDK_VERSION = '5.6.1';
19
19
  let _queue = [];
20
20
  let _assertStats = new Map();
21
21
  let _flushTimer = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goliapkg/sentori-react-native",
3
- "version": "5.6.0",
3
+ "version": "5.6.1",
4
4
  "description": "Sentori SDK for React Native \u2014 JS-layer error capture, native crash handlers (iOS / Android), batched transport, fetch + react-navigation tracing.",
5
5
  "license": "Apache-2.0 OR MIT",
6
6
  "author": "GOLIA K.K. <takagi@golia.jp> (https://golia.jp)",
package/src/transport.ts CHANGED
@@ -20,7 +20,7 @@ const STORAGE_KEY = '@sentori/pending';
20
20
  const MAX_PERSISTED = 1000;
21
21
 
22
22
  // Pinned to package.json by a test — bump both together.
23
- const SDK_VERSION = '5.6.0';
23
+ const SDK_VERSION = '5.6.1';
24
24
 
25
25
  let _queue: WireEvent[] = [];
26
26
  let _assertStats = new Map<string, AssertStat>();