@sigx/lynx-observability 0.6.1 → 0.8.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.
Files changed (3) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +107 -107
  3. package/package.json +3 -3
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025-2026 Andreas Ekdahl
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Andreas Ekdahl
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,107 +1,107 @@
1
- # @sigx/lynx-observability
2
-
3
- Opt-in **production error capture** and **provider-agnostic log/error sinks** for sigx-lynx. Builds on the logger in [`@sigx/lynx-core`](https://sigx.dev/lynx/modules/core/overview/): uncaught errors are funneled in as `error`-level records, and a "sink" is just a `LogTransport`. No hard dependency on any vendor SDK.
4
-
5
- > Logging itself ships in the framework (`import { createLogger } from '@sigx/lynx'`). This package adds the *production* pieces — catching crashes and shipping records off-device — and is installed only when you want them.
6
-
7
- ## 📚 Documentation
8
-
9
- Full guides, API reference and live examples → **[https://sigx.dev/lynx/](https://sigx.dev/lynx/)**
10
-
11
- ## Install
12
-
13
- ```sh
14
- pnpm add @sigx/lynx-observability
15
- ```
16
-
17
- ## Quick start — declarative (recommended)
18
-
19
- Declare it in `signalx.config.ts` and it auto-wires in **release** builds — no code in your app entry:
20
-
21
- ```ts
22
- // signalx.config.ts
23
- export default defineLynxConfig({
24
- name: 'my-app',
25
- logging: {
26
- level: 'warn', // logger level (also dev: 'debug' / release: 'warn' default)
27
- namespaces: { disabled: ['http'] },// silence namespaces at startup
28
- production: {
29
- sink: { url: 'https://logs.example.com/ingest', headers: { 'x-api-key': KEY }, sampleRate: 0.25 },
30
- captureErrors: true, // default
31
- },
32
- },
33
- });
34
- ```
35
-
36
- Just install the package (`pnpm add @sigx/lynx-observability`) — `@sigx/lynx-plugin` prepends the init for you in release builds. (Dev uses the console streamer; observability auto-wiring is release-only.)
37
-
38
- ## Quick start — manual
39
-
40
- Or wire it yourself, `Sentry.init()`-style (call once in your app entry):
41
-
42
- ```ts
43
- import { initObservability } from '@sigx/lynx-observability';
44
-
45
- initObservability({
46
- level: 'warn', // optional: override the default level
47
- captureErrors: true, // default — catch uncaught errors / rejections
48
- sink: { // optional remote sink
49
- url: 'https://logs.example.com/ingest',
50
- headers: { 'x-api-key': API_KEY },
51
- sampleRate: 0.25, // keep 25% of non-error records; errors always kept
52
- },
53
- });
54
- ```
55
-
56
- That's it: uncaught errors now flow to your logs (and the `sigx dev` terminal in development), and records at/above the level are batched and POSTed to your endpoint.
57
-
58
- ## Pieces (compose them yourself)
59
-
60
- - **`installErrorCapture(opts?)`** — registers Lynx's `lynx.onError` (background thread) plus `globalThis` `error`/`unhandledrejection` handlers, normalizes whatever was thrown into an `Error`, and logs it at `error` level under the `uncaught` namespace. The `Error` rides in the record's `fields`, so transports can treat it as an exception (with a stack). Idempotent; returns an uninstall function.
61
- - **`createHttpSink(opts)`** — a batching `LogTransport` that POSTs `{ records: [...] }` as JSON to `opts.url`. Options: `batchSize`, `flushIntervalMs`, `sampleRate`, `minLevel`, `headers`, `excludeNamespaces`. `Error` fields are serialized to `{ name, message, stack }`. It excludes the `http` namespace by default (its own POSTs log there) and swallows its own send failures, so it can't feed back into itself. Has a `.flush()` for graceful shutdown.
62
- - **`toError(value)`** — the normalization helper, exported for reuse.
63
-
64
- ```ts
65
- import { addTransport } from '@sigx/lynx';
66
- import { createHttpSink, installErrorCapture } from '@sigx/lynx-observability';
67
-
68
- addTransport(createHttpSink({ url, minLevel: 'info' }));
69
- const uninstall = installErrorCapture({ onError: (e) => myAnalytics.track('crash', e.message) });
70
- ```
71
-
72
- ## Wire format
73
-
74
- The sink POSTs:
75
-
76
- ```json
77
- { "records": [ { "level": "error", "namespace": "uncaught", "msg": "[lynx] …", "fields": [ { "name": "TypeError", "message": "…", "stack": "…" } ], "ts": 1733740000000 } ] }
78
- ```
79
-
80
- ## Provider adapters
81
-
82
- There's no built-in vendor coupling — any provider is a `LogTransport`. Errors arrive as `error`-level records with the `Error` in `fields[0]`, so an adapter can split exceptions from breadcrumbs. Example **Sentry** adapter (Sentry is an optional peer in *your* app, not a dependency of this package):
83
-
84
- ```ts
85
- import * as Sentry from '@sentry/browser'; // your app's dep
86
- import { addTransport, installErrorCapture, type LogRecord } from '@sigx/lynx';
87
-
88
- Sentry.init({ dsn: SENTRY_DSN });
89
-
90
- addTransport((r: LogRecord) => {
91
- const err = r.fields.find((f) => f instanceof Error) as Error | undefined;
92
- if (r.level.name === 'error' && err) {
93
- Sentry.captureException(err);
94
- } else {
95
- Sentry.addBreadcrumb({ category: r.namespace, message: r.msg, level: r.level.name });
96
- }
97
- });
98
- installErrorCapture();
99
- ```
100
-
101
- The same shape works for Datadog, a custom backend, etc.
102
-
103
- ## Notes
104
-
105
- - `lynx.onError` is **background-thread only** upstream; main-thread error capture may need a separate path in the future.
106
- - For readable stack traces in release builds, upload your source maps to your provider (out of scope here).
107
- - Declarative `signalx.config.ts` `logging.production` config auto-wires this package in release builds (see Quick start above); `initObservability()` remains for manual/dev setup.
1
+ # @sigx/lynx-observability
2
+
3
+ Opt-in **production error capture** and **provider-agnostic log/error sinks** for sigx-lynx. Builds on the logger in [`@sigx/lynx-core`](https://sigx.dev/lynx/modules/core/overview/): uncaught errors are funneled in as `error`-level records, and a "sink" is just a `LogTransport`. No hard dependency on any vendor SDK.
4
+
5
+ > Logging itself ships in the framework (`import { createLogger } from '@sigx/lynx'`). This package adds the *production* pieces — catching crashes and shipping records off-device — and is installed only when you want them.
6
+
7
+ ## 📚 Documentation
8
+
9
+ Full guides, API reference and live examples → **[https://sigx.dev/lynx/](https://sigx.dev/lynx/)**
10
+
11
+ ## Install
12
+
13
+ ```sh
14
+ pnpm add @sigx/lynx-observability
15
+ ```
16
+
17
+ ## Quick start — declarative (recommended)
18
+
19
+ Declare it in `signalx.config.ts` and it auto-wires in **release** builds — no code in your app entry:
20
+
21
+ ```ts
22
+ // signalx.config.ts
23
+ export default defineLynxConfig({
24
+ name: 'my-app',
25
+ logging: {
26
+ level: 'warn', // logger level (also dev: 'debug' / release: 'warn' default)
27
+ namespaces: { disabled: ['http'] },// silence namespaces at startup
28
+ production: {
29
+ sink: { url: 'https://logs.example.com/ingest', headers: { 'x-api-key': KEY }, sampleRate: 0.25 },
30
+ captureErrors: true, // default
31
+ },
32
+ },
33
+ });
34
+ ```
35
+
36
+ Just install the package (`pnpm add @sigx/lynx-observability`) — `@sigx/lynx-plugin` prepends the init for you in release builds. (Dev uses the console streamer; observability auto-wiring is release-only.)
37
+
38
+ ## Quick start — manual
39
+
40
+ Or wire it yourself, `Sentry.init()`-style (call once in your app entry):
41
+
42
+ ```ts
43
+ import { initObservability } from '@sigx/lynx-observability';
44
+
45
+ initObservability({
46
+ level: 'warn', // optional: override the default level
47
+ captureErrors: true, // default — catch uncaught errors / rejections
48
+ sink: { // optional remote sink
49
+ url: 'https://logs.example.com/ingest',
50
+ headers: { 'x-api-key': API_KEY },
51
+ sampleRate: 0.25, // keep 25% of non-error records; errors always kept
52
+ },
53
+ });
54
+ ```
55
+
56
+ That's it: uncaught errors now flow to your logs (and the `sigx dev` terminal in development), and records at/above the level are batched and POSTed to your endpoint.
57
+
58
+ ## Pieces (compose them yourself)
59
+
60
+ - **`installErrorCapture(opts?)`** — registers Lynx's `lynx.onError` (background thread) plus `globalThis` `error`/`unhandledrejection` handlers, normalizes whatever was thrown into an `Error`, and logs it at `error` level under the `uncaught` namespace. The `Error` rides in the record's `fields`, so transports can treat it as an exception (with a stack). Idempotent; returns an uninstall function.
61
+ - **`createHttpSink(opts)`** — a batching `LogTransport` that POSTs `{ records: [...] }` as JSON to `opts.url`. Options: `batchSize`, `flushIntervalMs`, `sampleRate`, `minLevel`, `headers`, `excludeNamespaces`. `Error` fields are serialized to `{ name, message, stack }`. It excludes the `http` namespace by default (its own POSTs log there) and swallows its own send failures, so it can't feed back into itself. Has a `.flush()` for graceful shutdown.
62
+ - **`toError(value)`** — the normalization helper, exported for reuse.
63
+
64
+ ```ts
65
+ import { addTransport } from '@sigx/lynx';
66
+ import { createHttpSink, installErrorCapture } from '@sigx/lynx-observability';
67
+
68
+ addTransport(createHttpSink({ url, minLevel: 'info' }));
69
+ const uninstall = installErrorCapture({ onError: (e) => myAnalytics.track('crash', e.message) });
70
+ ```
71
+
72
+ ## Wire format
73
+
74
+ The sink POSTs:
75
+
76
+ ```json
77
+ { "records": [ { "level": "error", "namespace": "uncaught", "msg": "[lynx] …", "fields": [ { "name": "TypeError", "message": "…", "stack": "…" } ], "ts": 1733740000000 } ] }
78
+ ```
79
+
80
+ ## Provider adapters
81
+
82
+ There's no built-in vendor coupling — any provider is a `LogTransport`. Errors arrive as `error`-level records with the `Error` in `fields[0]`, so an adapter can split exceptions from breadcrumbs. Example **Sentry** adapter (Sentry is an optional peer in *your* app, not a dependency of this package):
83
+
84
+ ```ts
85
+ import * as Sentry from '@sentry/browser'; // your app's dep
86
+ import { addTransport, installErrorCapture, type LogRecord } from '@sigx/lynx';
87
+
88
+ Sentry.init({ dsn: SENTRY_DSN });
89
+
90
+ addTransport((r: LogRecord) => {
91
+ const err = r.fields.find((f) => f instanceof Error) as Error | undefined;
92
+ if (r.level.name === 'error' && err) {
93
+ Sentry.captureException(err);
94
+ } else {
95
+ Sentry.addBreadcrumb({ category: r.namespace, message: r.msg, level: r.level.name });
96
+ }
97
+ });
98
+ installErrorCapture();
99
+ ```
100
+
101
+ The same shape works for Datadog, a custom backend, etc.
102
+
103
+ ## Notes
104
+
105
+ - `lynx.onError` is **background-thread only** upstream; main-thread error capture may need a separate path in the future.
106
+ - For readable stack traces in release builds, upload your source maps to your provider (out of scope here).
107
+ - Declarative `signalx.config.ts` `logging.production` config auto-wires this package in release builds (see Quick start above); `initObservability()` remains for manual/dev setup.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sigx/lynx-observability",
3
- "version": "0.6.1",
3
+ "version": "0.8.0",
4
4
  "description": "Opt-in production error capture + provider-agnostic log/error sinks for sigx-lynx",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -38,8 +38,8 @@
38
38
  "url": "https://github.com/signalxjs/lynx/issues"
39
39
  },
40
40
  "dependencies": {
41
- "@sigx/lynx-core": "^0.6.1",
42
- "@sigx/lynx-http": "^0.6.1"
41
+ "@sigx/lynx-core": "^0.8.0",
42
+ "@sigx/lynx-http": "^0.8.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@typescript/native-preview": "7.0.0-dev.20260521.1",