@kubit-ai/sentry 0.1.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/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ Copyright (c) Kubit Inc. All rights reserved.
2
+
3
+ This software and associated files (the "Software") are the proprietary
4
+ and confidential property of Kubit Inc. The Software is provided to
5
+ authorized users solely for the purpose of integrating with the Kubit
6
+ platform.
7
+
8
+ No part of the Software may be copied, modified, distributed, sublicensed,
9
+ or used to create derivative works without the prior written permission
10
+ of Kubit Inc.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
13
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
15
+ KUBIT INC. BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY ARISING
16
+ FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17
+ DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # @kubit-ai/sentry
2
+
3
+ Tee your existing Sentry telemetry into Kubit. The SDK observes the **error**
4
+ and **transaction** events your app already sends to Sentry, translates them to
5
+ OTLP/HTTP+JSON, and POSTs a copy to the Kubit collector with an `x-api-key`
6
+ header. It does **not** replace Sentry and does not change what Sentry
7
+ receives — it runs alongside it.
8
+
9
+ This is the Behavior counterpart to
10
+ [`@kubit-ai/otel`](https://www.npmjs.com/package/@kubit-ai/otel) (the LLM/Agent
11
+ OTel exporter): same wire contract and `KUBIT_OTEL_API_KEY` convention, a
12
+ different *source* (the Sentry SDK's client hooks rather than an OpenTelemetry
13
+ `TracerProvider`).
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm install @kubit-ai/sentry
19
+ # peer: @sentry/core (provided by @sentry/react | @sentry/browser | @sentry/node | …)
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ### Integration
25
+
26
+ ```ts
27
+ import * as Sentry from "@sentry/react";
28
+ import { kubitSentryIntegration } from "@kubit-ai/sentry";
29
+
30
+ Sentry.init({
31
+ dsn: "https://…@sentry.io/…",
32
+ environment: "production", // Sentry env → Kubit deployment.environment
33
+ integrations: [
34
+ kubitSentryIntegration({
35
+ apiKey: "rg.v1…", // required — mint per workspace in the Kubit app
36
+ serviceName: "my-app", // optional — names this app inside the workspace
37
+ // endpoint defaults to prod; set it only to target a non-prod Kubit env
38
+ }),
39
+ ],
40
+ });
41
+ ```
42
+
43
+ The integration registers on the Sentry client's single `afterSendEvent` hook —
44
+ which covers both errors and transactions — so Kubit receives a copy of exactly
45
+ what Sentry sends, after sampling, event processors, and your `beforeSend` /
46
+ `beforeSendTransaction` scrubbing. Events Sentry drops are never exported to
47
+ Kubit.
48
+
49
+ ### Browser, no bundler (`<script>` tag)
50
+
51
+ > **Use this bundle only on a page that doesn't already load Sentry.** It bundles
52
+ > its own `@sentry/browser` and calls `Sentry.init`; on a page that already has
53
+ > Sentry you'd run two Sentry instances — double-reported errors and duplicated
54
+ > bundle weight. If you have a bundler or an existing Sentry on the page, use the
55
+ > `kubitSentryIntegration` path above against that Sentry instead.
56
+
57
+ For a static site that can't run a bundler, build the self-contained browser
58
+ bundle (`npm run build:browser` → `dist/browser/kubit-sentry.global.js`,
59
+ `@sentry/browser` bundled in) and drop the one file in:
60
+
61
+ ```html
62
+ <script src="/kubit-sentry.global.js"></script>
63
+ <script>
64
+ KubitSentry.init({
65
+ dsn: "https://…@sentry.io/…", // your Sentry project
66
+ apiKey: "rg.v1…", // Kubit ingestion key
67
+ endpoint: "https://otel.kubit.ai/v1/traces",
68
+ serviceName: "my-app",
69
+ environment: "production",
70
+ });
71
+
72
+ // Named behavior events (the "clicked / action" family) flow through with
73
+ // their name intact:
74
+ KubitSentry.trackEvent("Product Added", { productId: 1, price: 49.99 });
75
+ </script>
76
+ ```
77
+
78
+ `KubitSentry.init` wires `Sentry.init` with browser tracing (pageload /
79
+ navigation / `http.client` spans — the "page view" and "api call" families)
80
+ plus the Kubit tee. `KubitSentry.trackEvent(name, attributes)` emits a named,
81
+ zero-duration root transaction the tee exports as one OTLP span. The bundle also
82
+ re-exports `Sentry` and `kubitSentryIntegration` on the `KubitSentry` global for
83
+ advanced wiring.
84
+
85
+ ## Configuration
86
+
87
+ | Option | Env var | Default |
88
+ | ---------------- | --------------------- | ----------------------------------- |
89
+ | `apiKey` | `KUBIT_OTEL_API_KEY` | — (required; export is a no-op without it) |
90
+ | `endpoint` | `KUBIT_OTEL_ENDPOINT` | `https://otel.kubit.ai/v1/traces` |
91
+ | `serviceName` | `KUBIT_SERVICE_NAME` | `"sentry-app"` |
92
+ | `serviceVersion` | — | the Sentry event `release` |
93
+ | `debug` | — | `false` |
94
+
95
+ `apiKey` is the only required value — mint it for a **Behavior** workspace in the
96
+ Kubit app (Settings → Workspace API Keys). `serviceName` is the `service.name`
97
+ resource attribute: it names *this app* within the workspace (set it when several
98
+ apps share one workspace; otherwise the default is fine). The Sentry
99
+ **`environment`** is *not* a Kubit option — set it on `Sentry.init({ environment })`
100
+ and the tee copies it to `deployment.environment`.
101
+
102
+ Environment variables are read at runtime in Node; in browser builds your bundler
103
+ must inline them (e.g. via `define` / `EnvironmentPlugin`), or pass the values as
104
+ options instead.
105
+
106
+ **Key handling.** Use a key minted for trace ingestion only. In browser apps
107
+ the key is embedded in the served bundle and visible to end users — treat it
108
+ like your Sentry DSN, and never reuse a key that carries broader permissions.
109
+
110
+ ## What gets sent
111
+
112
+ - **Transactions** → OTLP spans (root from `contexts.trace`, one child per
113
+ `event.spans[]`).
114
+ - **Errors** → one OTLP span with `status = ERROR` carrying an `exception`
115
+ span event per `exception.values[]` (`exception.type` / `.message` /
116
+ `.stacktrace` / `.escaped`), anchored on the trace context when present,
117
+ otherwise on the Sentry `event_id`.
118
+
119
+ `service.*` / `deployment.environment` / browser / OS / device land as OTLP
120
+ resource attributes. Error spans also carry the event's `tags` and `extra` as
121
+ span attributes — anything you don't want exported should be scrubbed in your
122
+ Sentry pipeline (the integration runs after your `beforeSend`, so your existing
123
+ scrubbing applies).
124
+
125
+ ## Limitations
126
+
127
+ - Export is one fire-and-forget POST per event — no batching, sampling, or
128
+ retry. A failed export is dropped (logged via `console.warn` when
129
+ `debug: true`) and never affects your Sentry pipeline.
130
+ - Requests time out after 10 seconds.
131
+ - In browsers, payloads under ~60 KB are sent with `keepalive` so events fired
132
+ near page unload survive navigation; larger payloads may be lost on unload.