@buoy-gg/sentry 0.0.0-stage → 7.0.77
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 +58 -0
- package/README.md +69 -2
- package/lib/commonjs/SentryRoot.js +1 -0
- package/lib/commonjs/audit/auditSource.js +1 -0
- package/lib/commonjs/audit/pii.js +1 -0
- package/lib/commonjs/audit/pii.test.js +1 -0
- package/lib/commonjs/audit/rules.js +1 -0
- package/lib/commonjs/audit/rules.test.js +1 -0
- package/lib/commonjs/capture/attach.js +1 -0
- package/lib/commonjs/capture/attach.test.js +1 -0
- package/lib/commonjs/capture/sentrySDK.js +1 -0
- package/lib/commonjs/capture/sentrySDK.web.js +1 -0
- package/lib/commonjs/components/SentryIcon.js +1 -0
- package/lib/commonjs/components/SentryIcon.native.js +1 -0
- package/lib/commonjs/components/SentryModal.js +1 -0
- package/lib/commonjs/devtools/SentryAuditView.js +1 -0
- package/lib/commonjs/devtools/SentryBody.js +1 -0
- package/lib/commonjs/devtools/SentryCostView.js +1 -0
- package/lib/commonjs/devtools/SentryDropsView.js +1 -0
- package/lib/commonjs/devtools/SentryHeader.js +1 -0
- package/lib/commonjs/devtools/SentryToolView.js +1 -0
- package/lib/commonjs/devtools/attachStatus.js +1 -0
- package/lib/commonjs/devtools/layout.js +1 -0
- package/lib/commonjs/devtools/useSentryController.js +1 -0
- package/lib/commonjs/drops/dropStore.js +1 -0
- package/lib/commonjs/drops/dropStore.test.js +1 -0
- package/lib/commonjs/drops/observe.js +1 -0
- package/lib/commonjs/drops/types.js +1 -0
- package/lib/commonjs/index.js +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/preset.js +1 -0
- package/lib/commonjs/quota/plans.js +1 -0
- package/lib/commonjs/quota/usage.js +1 -0
- package/lib/commonjs/quota/usage.test.js +1 -0
- package/lib/commonjs/store/sanitize.js +1 -0
- package/lib/commonjs/store/sentryEnvelopeStore.js +1 -0
- package/lib/commonjs/sync/sentrySyncAdapter.js +1 -0
- package/lib/commonjs/sync/sentrySyncAdapter.test.js +1 -0
- package/lib/commonjs/types.js +1 -0
- package/lib/module/SentryRoot.js +1 -0
- package/lib/module/audit/auditSource.js +1 -0
- package/lib/module/audit/pii.js +1 -0
- package/lib/module/audit/pii.test.js +1 -0
- package/lib/module/audit/rules.js +1 -0
- package/lib/module/audit/rules.test.js +1 -0
- package/lib/module/capture/attach.js +1 -0
- package/lib/module/capture/attach.test.js +1 -0
- package/lib/module/capture/sentrySDK.js +1 -0
- package/lib/module/capture/sentrySDK.web.js +1 -0
- package/lib/module/components/SentryIcon.js +1 -0
- package/lib/module/components/SentryIcon.native.js +1 -0
- package/lib/module/components/SentryModal.js +1 -0
- package/lib/module/devtools/SentryAuditView.js +1 -0
- package/lib/module/devtools/SentryBody.js +1 -0
- package/lib/module/devtools/SentryCostView.js +1 -0
- package/lib/module/devtools/SentryDropsView.js +1 -0
- package/lib/module/devtools/SentryHeader.js +1 -0
- package/lib/module/devtools/SentryToolView.js +1 -0
- package/lib/module/devtools/attachStatus.js +1 -0
- package/lib/module/devtools/layout.js +1 -0
- package/lib/module/devtools/useSentryController.js +1 -0
- package/lib/module/drops/dropStore.js +1 -0
- package/lib/module/drops/dropStore.test.js +1 -0
- package/lib/module/drops/observe.js +1 -0
- package/lib/module/drops/types.js +1 -0
- package/lib/module/index.js +1 -0
- package/lib/module/preset.js +1 -0
- package/lib/module/quota/plans.js +1 -0
- package/lib/module/quota/usage.js +1 -0
- package/lib/module/quota/usage.test.js +1 -0
- package/lib/module/store/sanitize.js +1 -0
- package/lib/module/store/sentryEnvelopeStore.js +1 -0
- package/lib/module/sync/sentrySyncAdapter.js +1 -0
- package/lib/module/sync/sentrySyncAdapter.test.js +1 -0
- package/lib/module/types.js +1 -0
- package/lib/typescript/SentryRoot.d.ts +17 -0
- package/lib/typescript/audit/auditSource.d.ts +18 -0
- package/lib/typescript/audit/pii.d.ts +32 -0
- package/lib/typescript/audit/pii.test.d.ts +8 -0
- package/lib/typescript/audit/rules.d.ts +57 -0
- package/lib/typescript/audit/rules.test.d.ts +7 -0
- package/lib/typescript/capture/attach.d.ts +18 -0
- package/lib/typescript/capture/attach.test.d.ts +8 -0
- package/lib/typescript/capture/sentrySDK.d.ts +4 -0
- package/lib/typescript/capture/sentrySDK.web.d.ts +4 -0
- package/lib/typescript/components/SentryIcon.d.ts +3 -0
- package/lib/typescript/components/SentryIcon.native.d.ts +3 -0
- package/lib/typescript/components/SentryModal.d.ts +16 -0
- package/lib/typescript/devtools/SentryAuditView.d.ts +19 -0
- package/lib/typescript/devtools/SentryBody.d.ts +15 -0
- package/lib/typescript/devtools/SentryCostView.d.ts +20 -0
- package/lib/typescript/devtools/SentryDropsView.d.ts +17 -0
- package/lib/typescript/devtools/SentryHeader.d.ts +21 -0
- package/lib/typescript/devtools/SentryToolView.d.ts +14 -0
- package/lib/typescript/devtools/attachStatus.d.ts +13 -0
- package/lib/typescript/devtools/layout.d.ts +16 -0
- package/lib/typescript/devtools/useSentryController.d.ts +69 -0
- package/lib/typescript/drops/dropStore.d.ts +48 -0
- package/lib/typescript/drops/dropStore.test.d.ts +7 -0
- package/lib/typescript/drops/observe.d.ts +33 -0
- package/lib/typescript/drops/types.d.ts +50 -0
- package/lib/typescript/index.d.ts +30 -0
- package/lib/typescript/preset.d.ts +36 -0
- package/lib/typescript/quota/plans.d.ts +37 -0
- package/lib/typescript/quota/usage.d.ts +56 -0
- package/lib/typescript/quota/usage.test.d.ts +8 -0
- package/lib/typescript/store/sanitize.d.ts +18 -0
- package/lib/typescript/store/sentryEnvelopeStore.d.ts +49 -0
- package/lib/typescript/sync/sentrySyncAdapter.d.ts +64 -0
- package/lib/typescript/sync/sentrySyncAdapter.test.d.ts +2 -0
- package/lib/typescript/types.d.ts +61 -0
- package/lib/web/index.mjs +1 -0
- package/package.json +99 -3
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded ring buffer of drop records, plus the pure helpers that turn SDK
|
|
3
|
+
* artifacts into them.
|
|
4
|
+
*
|
|
5
|
+
* The parsing lives here rather than in the capture layer so it can be
|
|
6
|
+
* tested without a Sentry client: each helper takes the raw shape the SDK
|
|
7
|
+
* produces and returns records, with no I/O and no globals.
|
|
8
|
+
*/
|
|
9
|
+
import type { DropRecord, DropReason } from "./types";
|
|
10
|
+
type Listener = () => void;
|
|
11
|
+
export declare function recordDrop(drop: Omit<DropRecord, "id">): void;
|
|
12
|
+
/**
|
|
13
|
+
* The reported drops left after subtracting the ones already observed, and
|
|
14
|
+
* the tally updated in place. Pure apart from `tally`, so it tests without a
|
|
15
|
+
* store.
|
|
16
|
+
*/
|
|
17
|
+
export declare function reconcileReported(tally: Map<string, number>, drops: Omit<DropRecord, "id">[]): Omit<DropRecord, "id">[];
|
|
18
|
+
/** Note an observed drop in a tally, for `reconcileReported`. */
|
|
19
|
+
export declare function tallyObserved(tally: Map<string, number>, drop: Omit<DropRecord, "id">): void;
|
|
20
|
+
/** Record SDK-reported drops, minus the ones already recorded as observed. */
|
|
21
|
+
export declare function recordReportedDrops(drops: Omit<DropRecord, "id">[]): void;
|
|
22
|
+
export declare function subscribeDrops(listener: Listener): () => void;
|
|
23
|
+
export declare function getDrops(): DropRecord[];
|
|
24
|
+
export declare function clearDrops(): void;
|
|
25
|
+
/** Replace the whole list from a remote snapshot (desktop mirror mode). */
|
|
26
|
+
export declare function replaceDrops(next: DropRecord[]): void;
|
|
27
|
+
export declare function dropsFromClientReport(payload: unknown, timestamp: number): Omit<DropRecord, "id">[];
|
|
28
|
+
/** Read the RN discard reason off a transaction event, if it carries one. */
|
|
29
|
+
export declare function rnDiscardReason(event: unknown): string | null;
|
|
30
|
+
export declare function dropFromRnDiscard(reason: string, name: string, timestamp: number): Omit<DropRecord, "id">;
|
|
31
|
+
/**
|
|
32
|
+
* Native SDK log line → drop record, or null when the line isn't about a drop.
|
|
33
|
+
*
|
|
34
|
+
* This is the only channel through which a native rate limit or an oversized
|
|
35
|
+
* payload reaches JS, and it only flows when `debug: true`. Matching is kept
|
|
36
|
+
* to unambiguous signals — a status code or an explicit "discard"/"dropp"
|
|
37
|
+
* verb — because native log text varies by SDK version and platform, and a
|
|
38
|
+
* loose matcher inventing drops is worse than missing one.
|
|
39
|
+
*/
|
|
40
|
+
export declare function dropFromNativeLog(message: string, timestamp: number): Omit<DropRecord, "id"> | null;
|
|
41
|
+
/** Group drops by reason for the summary, most units first. */
|
|
42
|
+
export declare function summarizeDrops(drops: DropRecord[]): {
|
|
43
|
+
reason: DropReason;
|
|
44
|
+
units: number;
|
|
45
|
+
records: number;
|
|
46
|
+
}[];
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=dropStore.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Watch the client for drops.
|
|
3
|
+
*
|
|
4
|
+
* Three seams, because no single one sees everything:
|
|
5
|
+
*
|
|
6
|
+
* 1. **Wrapped `beforeSend` / `beforeSendTransaction`** — the only way to
|
|
7
|
+
* observe the most common cause of a missing event. We replace the
|
|
8
|
+
* option with a wrapper that calls the original, records a drop when it
|
|
9
|
+
* returns null, and passes the result through untouched. The user's
|
|
10
|
+
* callback keeps full authority; we never change its answer.
|
|
11
|
+
* 2. **`beforeEnvelope` client reports** — the SDK's own tally of what it
|
|
12
|
+
* discarded, one envelope late.
|
|
13
|
+
* 3. **`onNativeLog`** — native rate limits and oversize rejections, which
|
|
14
|
+
* reach JS through no other channel.
|
|
15
|
+
*
|
|
16
|
+
* Everything here is wrapped in try/catch: this sits on the error-reporting
|
|
17
|
+
* path, and a drop watcher that throws would suppress the very events it
|
|
18
|
+
* exists to explain.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Install the drop watchers on a client. Idempotent per client.
|
|
22
|
+
*
|
|
23
|
+
* Returns true when at least one seam was attached, so the caller can
|
|
24
|
+
* report whether drop attribution is actually live.
|
|
25
|
+
*/
|
|
26
|
+
export declare function observeDrops(client: unknown): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Feed a native SDK log line to the watcher. Wired from the host app's
|
|
29
|
+
* `onNativeLog` (which the SDK only calls when `debug: true`) — exported so
|
|
30
|
+
* an app can forward its own handler's lines without giving up the callback.
|
|
31
|
+
*/
|
|
32
|
+
export declare function noteNativeLog(message: string): void;
|
|
33
|
+
//# sourceMappingURL=observe.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drop attribution — why an event never reached Sentry.
|
|
3
|
+
*
|
|
4
|
+
* The SDK discards events at a dozen points between `captureException` and
|
|
5
|
+
* the wire, and almost all of them are silent: `beforeSend` returning null,
|
|
6
|
+
* a sample-rate roll, dedupe, an event processor, a native 429. "My event
|
|
7
|
+
* isn't in Sentry" is the single most common Sentry support thread, and
|
|
8
|
+
* today the only way to answer it is reading debug logs.
|
|
9
|
+
*
|
|
10
|
+
* Each reason below is a place the SDK can drop something, phrased as the
|
|
11
|
+
* answer a developer actually needs.
|
|
12
|
+
*/
|
|
13
|
+
export type DropReason =
|
|
14
|
+
/** A `beforeSend` / `beforeSendTransaction` callback returned null. */
|
|
15
|
+
"before_send"
|
|
16
|
+
/** `sampleRate` / `tracesSampleRate` rolled against it. */
|
|
17
|
+
| "sample_rate"
|
|
18
|
+
/** An event processor or integration returned null (dedupe, inbound filters). */
|
|
19
|
+
| "event_processor"
|
|
20
|
+
/** RN tracing discarded a transaction it considered empty. */
|
|
21
|
+
| "rn_discard"
|
|
22
|
+
/** The SDK's own client report said the backend/transport dropped it. */
|
|
23
|
+
| "client_report"
|
|
24
|
+
/** Native transport rejected it — rate limit, oversize, cache eviction. */
|
|
25
|
+
| "native"
|
|
26
|
+
/** Recorded by a client report under a reason this tool doesn't model. */
|
|
27
|
+
| "other";
|
|
28
|
+
export interface DropRecord {
|
|
29
|
+
id: number;
|
|
30
|
+
timestamp: number;
|
|
31
|
+
reason: DropReason;
|
|
32
|
+
/** What was dropped: "error", "transaction", "span", "log"… */
|
|
33
|
+
category: string;
|
|
34
|
+
/** How many units this record accounts for (client reports batch them). */
|
|
35
|
+
quantity: number;
|
|
36
|
+
/** One line naming the specific event where we can identify it. */
|
|
37
|
+
detail: string;
|
|
38
|
+
/**
|
|
39
|
+
* Where the finding came from, so a reader can judge it:
|
|
40
|
+
* `observed` — we watched it happen (wrapped callback, discard attribute).
|
|
41
|
+
* `reported` — the SDK told us after the fact (client report, native log).
|
|
42
|
+
*/
|
|
43
|
+
source: "observed" | "reported";
|
|
44
|
+
}
|
|
45
|
+
/** Human copy for each reason: what it means and what to do about it. */
|
|
46
|
+
export declare const DROP_REASON_META: Record<DropReason, {
|
|
47
|
+
label: string;
|
|
48
|
+
explanation: string;
|
|
49
|
+
}>;
|
|
50
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @buoy-gg/sentry — Sentry SDK inspector for React Native.
|
|
3
|
+
*
|
|
4
|
+
* Sees every envelope the app's Sentry SDK sends (via the client's public
|
|
5
|
+
* `beforeEnvelope` hook), with per-item types, sizes, and payloads — so you
|
|
6
|
+
* know exactly what leaves the device before it costs you quota.
|
|
7
|
+
*/
|
|
8
|
+
export { sentryToolPreset, createSentryTool } from "./preset";
|
|
9
|
+
export { SentryRoot } from "./SentryRoot";
|
|
10
|
+
export { installSentryCapture, attachToClient, parseEnvelope } from "./capture/attach";
|
|
11
|
+
export { SentryModal } from "./components/SentryModal";
|
|
12
|
+
export { SentryIcon, SENTRY_ICON_COLOR } from "./components/SentryIcon";
|
|
13
|
+
export { SentryHeader } from "./devtools/SentryHeader";
|
|
14
|
+
export { SentryBody } from "./devtools/SentryBody";
|
|
15
|
+
export { useSentryController, formatBytes, type SentryController, type SentryView, type SentryTab, } from "./devtools/useSentryController";
|
|
16
|
+
export { SentryCostView } from "./devtools/SentryCostView";
|
|
17
|
+
export { SentryToolView } from "./devtools/SentryToolView";
|
|
18
|
+
export { SENTRY_PLANS, SENTRY_PLANS_VERIFIED_ON, DEFAULT_PLAN_ID, CATEGORY_META, getPlan, type SentryPlan, type QuotaCategory, } from "./quota/plans";
|
|
19
|
+
export { computeUsage, projectMonthly, quotaFraction, type UsageReport, type UsageTotals, type UsageContributor, } from "./quota/usage";
|
|
20
|
+
export { SentryDropsView } from "./devtools/SentryDropsView";
|
|
21
|
+
export { getDrops, subscribeDrops, clearDrops, replaceDrops, summarizeDrops, dropsFromClientReport, dropFromNativeLog, dropFromRnDiscard, rnDiscardReason, } from "./drops/dropStore";
|
|
22
|
+
export { observeDrops, noteNativeLog } from "./drops/observe";
|
|
23
|
+
export { DROP_REASON_META, type DropRecord, type DropReason, } from "./drops/types";
|
|
24
|
+
export { SentryAuditView } from "./devtools/SentryAuditView";
|
|
25
|
+
export { auditConfig, worstSeverity, type AuditFinding, type AuditInput, type AuditableOptions, type FindingSeverity, type FindingCategory, } from "./audit/rules";
|
|
26
|
+
export { scanForPii, PII_KIND_LABEL, type PiiFinding, type PiiKind } from "./audit/pii";
|
|
27
|
+
export { sentrySyncAdapter } from "./sync/sentrySyncAdapter";
|
|
28
|
+
export { subscribe, getEnvelopes, getAttachStatus, clearEnvelopes, replaceEnvelopes, replaceAttachStatus, replaceUsage, getMirroredUsage, onClear, } from "./store/sentryEnvelopeStore";
|
|
29
|
+
export type { CapturedEnvelope, CapturedEnvelopeItem, EnvelopeOrigin, SentryAttachStatus, } from "./types";
|
|
30
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-configured Sentry tool for FloatingDevTools.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```tsx
|
|
6
|
+
* import { sentryToolPreset } from '@buoy-gg/sentry';
|
|
7
|
+
*
|
|
8
|
+
* <FloatingDevTools apps={[sentryToolPreset]} />
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
import React from "react";
|
|
12
|
+
import { SentryModal } from "./components/SentryModal";
|
|
13
|
+
export declare const sentryToolPreset: {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
slot: "both";
|
|
18
|
+
icon: ({ size, color }: {
|
|
19
|
+
size: number;
|
|
20
|
+
color?: string;
|
|
21
|
+
}) => React.JSX.Element;
|
|
22
|
+
component: typeof SentryModal;
|
|
23
|
+
};
|
|
24
|
+
/** Create a custom Sentry tool configuration. */
|
|
25
|
+
export declare const createSentryTool: (options?: (Record<never, never> & import("@buoy-gg/shared-ui").ToolPresetOverrides) | undefined) => {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
description: string;
|
|
29
|
+
slot: "both";
|
|
30
|
+
icon: ({ size, color }: {
|
|
31
|
+
size: number;
|
|
32
|
+
color?: string;
|
|
33
|
+
}) => React.JSX.Element;
|
|
34
|
+
component: typeof SentryModal;
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=preset.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sentry billing units and plan quotas.
|
|
3
|
+
*
|
|
4
|
+
* Sentry bills on RECEIPT, not on storage: an event their server-side
|
|
5
|
+
* dynamic sampling later discards is still billed. That is what makes a
|
|
6
|
+
* device-side meter meaningful — every unit counted here is a unit the app
|
|
7
|
+
* has already committed to paying for, and the only lever that removes it
|
|
8
|
+
* without losing data is client-side config.
|
|
9
|
+
*
|
|
10
|
+
* Quotas move. They're data, not logic, so they can be corrected without
|
|
11
|
+
* touching the meter — see `SENTRY_PLANS`. Figures are the published
|
|
12
|
+
* monthly allowances as of 2026-09; `verifiedOn` is stamped so a stale
|
|
13
|
+
* table is visible rather than silently wrong.
|
|
14
|
+
*/
|
|
15
|
+
/** The categories Sentry meters separately. Each has its own quota. */
|
|
16
|
+
export type QuotaCategory = "errors" | "spans" | "replays" | "logBytes" | "attachmentBytes";
|
|
17
|
+
export interface SentryPlan {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
/** Monthly allowance per category. `0` means the plan cannot use it at all. */
|
|
21
|
+
quota: Record<QuotaCategory, number>;
|
|
22
|
+
}
|
|
23
|
+
/** When the numbers below were last checked against sentry.io/pricing. */
|
|
24
|
+
export declare const SENTRY_PLANS_VERIFIED_ON = "2026-09";
|
|
25
|
+
export declare const SENTRY_PLANS: SentryPlan[];
|
|
26
|
+
export declare const DEFAULT_PLAN_ID = "developer";
|
|
27
|
+
export declare function getPlan(planId: string): SentryPlan;
|
|
28
|
+
/** Display metadata for each category, in the order the meter shows them. */
|
|
29
|
+
export declare const CATEGORY_META: {
|
|
30
|
+
key: QuotaCategory;
|
|
31
|
+
label: string;
|
|
32
|
+
/** How the raw number should be rendered. */
|
|
33
|
+
format: "count" | "bytes";
|
|
34
|
+
/** One line on what actually produces this unit — the actionable half. */
|
|
35
|
+
hint: string;
|
|
36
|
+
}[];
|
|
37
|
+
//# sourceMappingURL=plans.d.ts.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn captured envelopes into Sentry billing units, and project a month.
|
|
3
|
+
*
|
|
4
|
+
* The mapping is deliberately literal — each rule is how Sentry actually
|
|
5
|
+
* meters that item, and a wrong rule here makes the whole meter a lie:
|
|
6
|
+
*
|
|
7
|
+
* - `event` → 1 error, unless it's a feedback event (not metered as one)
|
|
8
|
+
* - `transaction` → its span count (root + children), NOT one unit
|
|
9
|
+
* - `replay_event` → 1 replay session
|
|
10
|
+
* - `log` → payload bytes
|
|
11
|
+
* - `attachment` → payload bytes
|
|
12
|
+
*
|
|
13
|
+
* Envelope types with no line here (session, client_report, profile) are
|
|
14
|
+
* either unmetered or metered on a plan dimension this tool doesn't model
|
|
15
|
+
* yet; they're deliberately absent rather than guessed at.
|
|
16
|
+
*/
|
|
17
|
+
import type { CapturedEnvelope } from "../types";
|
|
18
|
+
import type { QuotaCategory } from "./plans";
|
|
19
|
+
export type UsageTotals = Record<QuotaCategory, number>;
|
|
20
|
+
/** One source of billable volume, for the "what is expensive" breakdown. */
|
|
21
|
+
export interface UsageContributor {
|
|
22
|
+
/** Human label — the transaction name, or the item type. */
|
|
23
|
+
label: string;
|
|
24
|
+
category: QuotaCategory;
|
|
25
|
+
/** Units this source contributed. */
|
|
26
|
+
units: number;
|
|
27
|
+
/** How many envelopes it appeared in. */
|
|
28
|
+
occurrences: number;
|
|
29
|
+
}
|
|
30
|
+
export interface UsageReport {
|
|
31
|
+
totals: UsageTotals;
|
|
32
|
+
/** Wall-clock ms between the first and last captured envelope. */
|
|
33
|
+
windowMs: number;
|
|
34
|
+
/** Biggest contributors, most units first (already category-aware). */
|
|
35
|
+
contributors: UsageContributor[];
|
|
36
|
+
}
|
|
37
|
+
export declare function computeUsage(envelopes: CapturedEnvelope[]): UsageReport;
|
|
38
|
+
/** Rate window floor. Projecting from a 2-second sample produces a number
|
|
39
|
+
* with no meaning; below this the UI shows the raw session instead. */
|
|
40
|
+
export declare const MIN_PROJECTION_WINDOW_MS = 30000;
|
|
41
|
+
/**
|
|
42
|
+
* Extrapolate the observed rate to a month.
|
|
43
|
+
*
|
|
44
|
+
* This is honest about what it is: a straight-line projection of ONE
|
|
45
|
+
* session on ONE device. It answers "if usage kept up at the rate I just
|
|
46
|
+
* watched" — useful for catching a config that is orders of magnitude off,
|
|
47
|
+
* not for forecasting a bill. `usable` says whether the window was long
|
|
48
|
+
* enough to mean anything.
|
|
49
|
+
*/
|
|
50
|
+
export declare function projectMonthly(report: UsageReport): {
|
|
51
|
+
usable: boolean;
|
|
52
|
+
totals: UsageTotals;
|
|
53
|
+
};
|
|
54
|
+
/** Fraction of a quota used, or `null` when the plan disallows the category. */
|
|
55
|
+
export declare function quotaFraction(used: number, quota: number): number | null;
|
|
56
|
+
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The billing math is the tool's whole claim to usefulness: if a transaction
|
|
3
|
+
* counts as one unit instead of its spans, the meter under-reports the single
|
|
4
|
+
* most surprising line on a Sentry bill by an order of magnitude. These pin
|
|
5
|
+
* each metering rule, not the plumbing around it.
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=usage.test.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sanitizePayload — deep-convert a captured Sentry payload into JSON-safe values.
|
|
3
|
+
*
|
|
4
|
+
* Envelope payloads are usually already plain JSON (they're about to be
|
|
5
|
+
* serialized onto the wire), but they can carry Errors, bigints, functions in
|
|
6
|
+
* hint-derived fields, and — in pathological beforeSend mutations — cycles.
|
|
7
|
+
* Both the external-sync snapshot and on-device persistence need plain JSON,
|
|
8
|
+
* so this produces a structural copy with cycles broken and strings capped.
|
|
9
|
+
*
|
|
10
|
+
* Same shape as @buoy-gg/console's sanitizer; Sentry payloads run deeper
|
|
11
|
+
* (event → contexts → trace → data …) so the depth cap is higher.
|
|
12
|
+
*/
|
|
13
|
+
/** Max chars of one string kept for inspection / on the wire. */
|
|
14
|
+
export declare const SNAPSHOT_STRING_LIMIT: number;
|
|
15
|
+
export declare function capString(value: string, limit?: number): string;
|
|
16
|
+
/** Deep-sanitize one payload value into JSON-safe values. */
|
|
17
|
+
export declare function sanitizePayload(payload: unknown): unknown;
|
|
18
|
+
//# sourceMappingURL=sanitize.d.ts.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sentryEnvelopeStore
|
|
3
|
+
*
|
|
4
|
+
* Bounded ring buffer of Sentry envelopes captured on their way out of the
|
|
5
|
+
* app, plus the attach status of the capture layer. Consumed by the UI via
|
|
6
|
+
* `useSyncExternalStore` and by the external-sync adapter for the desktop
|
|
7
|
+
* dashboard (which mirrors this same store through `replaceEnvelopes`).
|
|
8
|
+
*
|
|
9
|
+
* The store never touches the Sentry SDK — recording is fed by
|
|
10
|
+
* `capture/attach.ts`. Everything here must be cheap and crash-proof: it sits
|
|
11
|
+
* on the app's error-reporting path, and a capture layer that breaks the
|
|
12
|
+
* thing it observes is worse than no capture at all.
|
|
13
|
+
*
|
|
14
|
+
* The buffer, listeners, clear-forwarding, frame-coalesced emit and the
|
|
15
|
+
* "push to the dashboard NOW" hook all come from shared `createToolStore`;
|
|
16
|
+
* this module only adds the attach status and the public function API.
|
|
17
|
+
*/
|
|
18
|
+
import type { CapturedEnvelope, SentryAttachStatus } from "../types";
|
|
19
|
+
type Listener = () => void;
|
|
20
|
+
/** Append one captured envelope to the buffer. Error envelopes are pushed to
|
|
21
|
+
* the dashboard immediately: an envelope carrying a fatal is likely the app's
|
|
22
|
+
* last send. */
|
|
23
|
+
export declare function recordEnvelope(envelope: Omit<CapturedEnvelope, "id">, options?: {
|
|
24
|
+
urgent?: boolean;
|
|
25
|
+
}): void;
|
|
26
|
+
/** Update the capture layer's attach status. */
|
|
27
|
+
export declare function setAttachStatus(next: SentryAttachStatus): void;
|
|
28
|
+
/** Subscribe to changes (envelopes or status). Returns an unsubscribe function. */
|
|
29
|
+
export declare function subscribe(listener: Listener): () => void;
|
|
30
|
+
/** Current snapshot (stable reference between mutations for useSyncExternalStore). */
|
|
31
|
+
export declare function getEnvelopes(): CapturedEnvelope[];
|
|
32
|
+
/** Current attach status. */
|
|
33
|
+
export declare function getAttachStatus(): SentryAttachStatus;
|
|
34
|
+
/** Clear all captured envelopes. Fires onClear listeners (e.g. to forward the
|
|
35
|
+
* clear to a remote device when running in mirror mode). */
|
|
36
|
+
export declare function clearEnvelopes(): void;
|
|
37
|
+
/** Replace the whole envelope list from a remote snapshot. */
|
|
38
|
+
export declare function replaceEnvelopes(next: CapturedEnvelope[]): void;
|
|
39
|
+
/** Usage totals from a remote snapshot, or null when computing locally. */
|
|
40
|
+
export declare function getMirroredUsage(): unknown;
|
|
41
|
+
/** Supply usage totals from a remote snapshot (desktop mirror mode). */
|
|
42
|
+
export declare function replaceUsage(next: unknown): void;
|
|
43
|
+
/** Replace the attach status from a remote snapshot. */
|
|
44
|
+
export declare function replaceAttachStatus(next: SentryAttachStatus): void;
|
|
45
|
+
/** Register a listener fired when clearEnvelopes() is called. Returns an
|
|
46
|
+
* unsubscribe function. Used by the dashboard to forward clears to the device. */
|
|
47
|
+
export declare function onClear(listener: Listener): () => void;
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=sentryEnvelopeStore.d.ts.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sentrySyncAdapter — streams captured envelopes from the device to the
|
|
3
|
+
* desktop dashboard via @buoy-gg/external-sync.
|
|
4
|
+
*
|
|
5
|
+
* Structurally matches external-sync's `ToolSyncAdapter` WITHOUT importing the
|
|
6
|
+
* package (no hard dependency — auto-discovery in @buoy-gg/core picks it up by
|
|
7
|
+
* export name and announces the "sentry" capability).
|
|
8
|
+
*
|
|
9
|
+
* Envelopes are the fattest payloads any Buoy tool ships (a single event with
|
|
10
|
+
* breadcrumbs and contexts is tens of KB), so the same wire discipline as the
|
|
11
|
+
* console tool applies: per-entry caps, a snapshot budget walked newest-first,
|
|
12
|
+
* and a WeakMap wire cache keyed on entry identity (entries are never mutated).
|
|
13
|
+
*/
|
|
14
|
+
import { type UsageTotals } from "../quota/usage";
|
|
15
|
+
import type { DropRecord } from "../drops/types";
|
|
16
|
+
import type { CapturedEnvelope, SentryAttachStatus } from "../types";
|
|
17
|
+
interface SentrySnapshot {
|
|
18
|
+
status: SentryAttachStatus;
|
|
19
|
+
envelopes: CapturedEnvelope[];
|
|
20
|
+
/**
|
|
21
|
+
* Billing units for the FULL buffer, computed before the wire budget trims
|
|
22
|
+
* envelopes — so the desktop and an MCP client read the same totals the
|
|
23
|
+
* device shows, not a total silently short by whatever didn't fit.
|
|
24
|
+
*/
|
|
25
|
+
usage: {
|
|
26
|
+
session: UsageTotals;
|
|
27
|
+
projectedMonthly: UsageTotals | null;
|
|
28
|
+
windowMs: number;
|
|
29
|
+
topContributors: {
|
|
30
|
+
label: string;
|
|
31
|
+
category: string;
|
|
32
|
+
units: number;
|
|
33
|
+
}[];
|
|
34
|
+
};
|
|
35
|
+
/** Why events went missing. Capped: the summary carries the whole picture,
|
|
36
|
+
* the records are the recent detail. */
|
|
37
|
+
drops: {
|
|
38
|
+
summary: {
|
|
39
|
+
reason: string;
|
|
40
|
+
units: number;
|
|
41
|
+
records: number;
|
|
42
|
+
}[];
|
|
43
|
+
recent: DropRecord[];
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The newest drops for the wire, errors kept. Dropped tracing spans and
|
|
48
|
+
* transactions ("no_parent_span") arrive by the hundred; a plain last-50
|
|
49
|
+
* slice pushed the one dropped error — the answer to "why isn't this in
|
|
50
|
+
* Sentry?" — off the wire after a long session.
|
|
51
|
+
*/
|
|
52
|
+
export declare function wireDrops(drops: DropRecord[]): DropRecord[];
|
|
53
|
+
export declare const sentrySyncAdapter: {
|
|
54
|
+
version: number;
|
|
55
|
+
getSnapshot(): SentrySnapshot;
|
|
56
|
+
subscribe(onChange: () => void): () => void;
|
|
57
|
+
actions: {
|
|
58
|
+
clearEnvelopes(): {
|
|
59
|
+
cleared: true;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
export {};
|
|
64
|
+
//# sourceMappingURL=sentrySyncAdapter.d.ts.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the Sentry inspector.
|
|
3
|
+
*
|
|
4
|
+
* A "captured envelope" is one Sentry envelope observed on its way out of the
|
|
5
|
+
* app (via the client's `beforeEnvelope` hook — the same tee point Sentry's
|
|
6
|
+
* own Spotlight integration uses). Envelopes are the SDK's wire unit: a small
|
|
7
|
+
* JSON header plus a list of items (event / transaction / log / …), each with
|
|
8
|
+
* its own header and payload.
|
|
9
|
+
*/
|
|
10
|
+
/** Where a captured envelope came from. The JS layer is the only source today;
|
|
11
|
+
* `native` arrives with the sidecar listener (native crashes, sessions, replay). */
|
|
12
|
+
export type EnvelopeOrigin = "js" | "native";
|
|
13
|
+
/** One item inside a captured envelope. */
|
|
14
|
+
export interface CapturedEnvelopeItem {
|
|
15
|
+
/** Sentry envelope item type: `event`, `transaction`, `client_report`, `log`,
|
|
16
|
+
* `attachment`, `profile`, `session`, … (open set — new SDKs add types). */
|
|
17
|
+
type: string;
|
|
18
|
+
/** Approximate serialized size of the item payload in bytes. */
|
|
19
|
+
bytes: number;
|
|
20
|
+
/** One-line human summary (error headline, transaction name, log count, …). */
|
|
21
|
+
summary: string;
|
|
22
|
+
/** `transaction` items only: number of spans this transaction carries
|
|
23
|
+
* (children + the root). Spans are Sentry's billing unit for tracing. */
|
|
24
|
+
spanCount?: number;
|
|
25
|
+
/**
|
|
26
|
+
* The item payload, deep-sanitized to JSON-safe values and size-capped for
|
|
27
|
+
* inspection. Missing for binary payloads (attachments, replay recordings).
|
|
28
|
+
*/
|
|
29
|
+
payload?: unknown;
|
|
30
|
+
/** True when the payload was binary (stored as size only, no content). */
|
|
31
|
+
binary?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/** One envelope observed leaving the app. */
|
|
34
|
+
export interface CapturedEnvelope {
|
|
35
|
+
/** Monotonic id, unique per captured envelope. */
|
|
36
|
+
id: number;
|
|
37
|
+
/** Capture time in ms since epoch. */
|
|
38
|
+
timestamp: number;
|
|
39
|
+
/** Which SDK layer produced it. */
|
|
40
|
+
origin: EnvelopeOrigin;
|
|
41
|
+
/** `event_id` from the envelope header, when present. */
|
|
42
|
+
eventId?: string;
|
|
43
|
+
/** The envelope header, sanitized (dsn, sdk, sent_at, trace, …). */
|
|
44
|
+
header?: unknown;
|
|
45
|
+
/** The items the envelope carries, in order. */
|
|
46
|
+
items: CapturedEnvelopeItem[];
|
|
47
|
+
/** Sum of item payload bytes (headers excluded — they're noise at this scale). */
|
|
48
|
+
totalBytes: number;
|
|
49
|
+
}
|
|
50
|
+
/** Where the capture layer currently stands with the host app's Sentry SDK. */
|
|
51
|
+
export type SentryAttachStatus =
|
|
52
|
+
/** Capture installed, no attach attempt has resolved yet. */
|
|
53
|
+
"searching"
|
|
54
|
+
/** Subscribed to a live Sentry client's `beforeEnvelope`. */
|
|
55
|
+
| "attached"
|
|
56
|
+
/** `@sentry/react-native` isn't resolvable and no `getClient` was provided. */
|
|
57
|
+
| "sdk-not-found"
|
|
58
|
+
/** The SDK module exists but no client appeared before the retry window closed
|
|
59
|
+
* (Sentry.init was never called, or it's disabled). */
|
|
60
|
+
| "no-client";
|
|
61
|
+
//# sourceMappingURL=types.d.ts.map
|