Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2134ba58b8 | ||
|
|
c2bcc6c82c | ||
|
|
16550ec8bb | ||
|
|
292f44821d | ||
|
|
9f6f6e4df5 | ||
|
|
3c468dbf44 |
+1
-1
@@ -1 +1 @@
|
|||||||
{ "singleQuote": false, "tabWidth": 4, "trailingComma": "all", "printWidth": 100 }
|
{ "singleQuote": false, "tabWidth": 4, "trailingComma": "all", "printWidth": 100, "semi": true }
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
# One-time bootstrap for the v0.9.1 tag, whose original tag workflow failed before publishing.
|
|
||||||
when:
|
|
||||||
- event: manual
|
|
||||||
|
|
||||||
steps:
|
|
||||||
publish-v0-9-1:
|
|
||||||
image: node:24-bookworm-slim
|
|
||||||
environment:
|
|
||||||
NPM_TOKEN:
|
|
||||||
from_secret: gitea_package_token
|
|
||||||
commands:
|
|
||||||
- corepack enable
|
|
||||||
- corepack prepare pnpm@11.0.0 --activate
|
|
||||||
- apt-get update && apt-get install --yes --no-install-recommends ca-certificates git
|
|
||||||
- pnpm install --frozen-lockfile
|
|
||||||
- test "$(node -p \"require('./package.json').version\")" = "0.9.1"
|
|
||||||
- git rev-parse --verify refs/tags/v0.9.1
|
|
||||||
- pnpm check
|
|
||||||
- pnpm test
|
|
||||||
- pnpm build
|
|
||||||
- npm config set @mifi:registry https://git.mifi.dev/api/packages/mifi/npm/
|
|
||||||
- npm config set -- //git.mifi.dev/api/packages/mifi/npm/:_authToken "$NPM_TOKEN"
|
|
||||||
- pnpm publish --no-git-checks
|
|
||||||
|
|
||||||
notify-bootstrap-failure:
|
|
||||||
image: curlimages/curl:8.14.1
|
|
||||||
depends_on: [publish-v0-9-1]
|
|
||||||
environment:
|
|
||||||
MATTERMOST_BOT_ACCESS_TOKEN:
|
|
||||||
from_secret: mattermost_bot_access_token
|
|
||||||
MATTERMOST_CHANNEL_ID:
|
|
||||||
from_secret: mattermost_pushes_channel_id
|
|
||||||
MATTERMOST_POST_API_URL:
|
|
||||||
from_secret: mattermost_post_api_url
|
|
||||||
commands:
|
|
||||||
- |
|
|
||||||
BODY=$(printf '{"channel_id":"%s","message":"[%s - Build #%s] Package bootstrap failure 💩"}' "$MATTERMOST_CHANNEL_ID" "$CI_REPO" "$CI_PIPELINE_NUMBER")
|
|
||||||
curl --fail --show-error --silent --request POST --header 'Content-Type: application/json' --header "Authorization: Bearer $MATTERMOST_BOT_ACCESS_TOKEN" --data "$BODY" "$MATTERMOST_POST_API_URL"
|
|
||||||
when:
|
|
||||||
- status: [failure]
|
|
||||||
|
|
||||||
notify-bootstrap-success:
|
|
||||||
image: curlimages/curl:8.14.1
|
|
||||||
depends_on: [publish-v0-9-1]
|
|
||||||
environment:
|
|
||||||
MATTERMOST_BOT_ACCESS_TOKEN:
|
|
||||||
from_secret: mattermost_bot_access_token
|
|
||||||
MATTERMOST_CHANNEL_ID:
|
|
||||||
from_secret: mattermost_pushes_channel_id
|
|
||||||
MATTERMOST_POST_API_URL:
|
|
||||||
from_secret: mattermost_post_api_url
|
|
||||||
commands:
|
|
||||||
- |
|
|
||||||
BODY=$(printf '{"channel_id":"%s","message":"[%s - Build #%s] Package bootstrap success 🎉"}' "$MATTERMOST_CHANNEL_ID" "$CI_REPO" "$CI_PIPELINE_NUMBER")
|
|
||||||
curl --fail --show-error --silent --request POST --header 'Content-Type: application/json' --header "Authorization: Bearer $MATTERMOST_BOT_ACCESS_TOKEN" --data "$BODY" "$MATTERMOST_POST_API_URL"
|
|
||||||
when:
|
|
||||||
- status: [success]
|
|
||||||
@@ -3,6 +3,9 @@ when:
|
|||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
|
||||||
|
labels:
|
||||||
|
performance: low
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
verify:
|
verify:
|
||||||
image: node:24-bookworm-slim
|
image: node:24-bookworm-slim
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ when:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- ci
|
- ci
|
||||||
|
|
||||||
|
labels:
|
||||||
|
performance: high
|
||||||
|
|
||||||
clone:
|
clone:
|
||||||
git:
|
git:
|
||||||
image: woodpeckerci/plugin-git
|
image: woodpeckerci/plugin-git
|
||||||
|
|||||||
+18
-5
@@ -1,16 +1,29 @@
|
|||||||
# [1.0.0](https://git.mifi.dev/mifi/logger/compare/v0.10.0...v1.0.0) (2026-08-07)
|
# [1.1.0](https://git.mifi.dev/mifi/logger/compare/v1.0.1...v1.1.0) (2026-08-21)
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* API options object support to control sentry handling; removal of `logger.sentry.` ([234226e](https://git.mifi.dev/mifi/logger/commit/234226e2bbb79acf3b2686890677bd7326c6a0e0))
|
* now supports `async` functions for logging data ([c2bcc6c](https://git.mifi.dev/mifi/logger/commit/c2bcc6c82c675640b85e97f1d78dd7c6e627d8f0))
|
||||||
* API options object support to control sentry handling; removal of `logger.sentry.` ([6bee3a8](https://git.mifi.dev/mifi/logger/commit/6bee3a801da054a613e84d7985050e7e4e367194))
|
* now supports `async` functions for logging data ([16550ec](https://git.mifi.dev/mifi/logger/commit/16550ec8bb7810ccc36c36cbaab5542e4ad66dae))
|
||||||
|
|
||||||
|
## [1.0.1](https://git.mifi.dev/mifi/logger/compare/v1.0.0...v1.0.1) (2026-08-07)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- **sentry:** widen SentryLike so official SDKs assign without adapters ([9f6f6e4](https://git.mifi.dev/mifi/logger/commit/9f6f6e4df52449a84111656a939fda5f59816ea5))
|
||||||
|
- **sentry:** widen SentryLike so official SDKs assign without adapters ([3c468db](https://git.mifi.dev/mifi/logger/commit/3c468dbf44caf119b4ff769cbc158a4c3d9f6c54))
|
||||||
|
|
||||||
|
# [1.0.0](https://git.mifi.dev/mifi/logger/compare/v0.10.0...v1.0.0) (2026-08-07)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- API options object support to control sentry handling; removal of `logger.sentry.` ([234226e](https://git.mifi.dev/mifi/logger/commit/234226e2bbb79acf3b2686890677bd7326c6a0e0))
|
||||||
|
- API options object support to control sentry handling; removal of `logger.sentry.` ([6bee3a8](https://git.mifi.dev/mifi/logger/commit/6bee3a801da054a613e84d7985050e7e4e367194))
|
||||||
|
|
||||||
### BREAKING CHANGES
|
### BREAKING CHANGES
|
||||||
|
|
||||||
* API options object support to control sentry handling; removal of `logger.sentry.`
|
- API options object support to control sentry handling; removal of `logger.sentry.`
|
||||||
* API options object support to control sentry handling; removal of `logger.sentry.`
|
- API options object support to control sentry handling; removal of `logger.sentry.`
|
||||||
|
|
||||||
# [0.10.0](https://git.mifi.dev/mifi/logger/compare/v0.9.3...v0.10.0) (2026-08-05)
|
# [0.10.0](https://git.mifi.dev/mifi/logger/compare/v0.9.3...v0.10.0) (2026-08-05)
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ Copy [`env.example`](./env.example) as a starting point for local or container c
|
|||||||
|
|
||||||
## Sentry
|
## Sentry
|
||||||
|
|
||||||
The Sentry adapter has **no SDK dependency**. Provide the SDK your application already uses via `@mifi/logger/sentry`.
|
The Sentry adapter has **no SDK dependency**. Pass your official `@sentry/node`, `@sentry/browser`, or `@sentry/nextjs` module directly to `createSentrySink` — no consumer adapter or cast is required.
|
||||||
|
|
||||||
**Development never sends to Sentry.** Staging and production attach the sink when `sentry` is configured.
|
**Development never sends to Sentry.** Staging and production attach the sink when `sentry` is configured.
|
||||||
|
|
||||||
@@ -152,6 +152,8 @@ A last argument is treated as options only when every key is `sentry` or `suppre
|
|||||||
|
|
||||||
Logs payload: string message + flat primitive attributes (including `logger.namespace`). Nested objects are not unfurled.
|
Logs payload: string message + flat primitive attributes (including `logger.namespace`). Nested objects are not unfurled.
|
||||||
|
|
||||||
|
Issue severities use Sentry’s union (`warning`, not logger `warn`). The sink maps `warn` → `warning` and `trace` → `debug` for Issues only; Logs keep logger level names (`sentry.logger.warn`).
|
||||||
|
|
||||||
## Custom sinks
|
## Custom sinks
|
||||||
|
|
||||||
Replace the default destinations entirely with `sinks`:
|
Replace the default destinations entirely with `sinks`:
|
||||||
@@ -182,7 +184,7 @@ When `sinks` is provided, the `sentry` option is not used for default sink selec
|
|||||||
| `parseLoggingOverride` | `@mifi/logger` | Parse `debug` / `debug:NS1,NS2` override strings |
|
| `parseLoggingOverride` | `@mifi/logger` | Parse `debug` / `debug:NS1,NS2` override strings |
|
||||||
| `createSentrySink` | `@mifi/logger/sentry` | Adapter for any Sentry-like SDK |
|
| `createSentrySink` | `@mifi/logger/sentry` | Adapter for any Sentry-like SDK |
|
||||||
|
|
||||||
Types: `Logger`, `LoggerOptions`, `LogLevel`, `LoggerEnvironment`, `LogEvent`, `LogSink`, `LogData`, `LogCallOptions`, and (from `/sentry`) `SentryLike`, `SentryScopeLike`, `SentrySink`, `SentrySinkOptions`.
|
Types: `Logger`, `LoggerOptions`, `LogLevel`, `LoggerEnvironment`, `LogEvent`, `LogSink`, `LogData`, `LogCallOptions`, and (from `/sentry`) `SentryLike`, `SentryScopeLike`, `SentrySeverityLevel`, `SentrySink`, `SentrySinkOptions`.
|
||||||
|
|
||||||
Optional destinations live under `src/sinks/` (console, Sentry today; New Relic / Datadog-style adapters can land beside them later). Public import paths stay `@mifi/logger` and `@mifi/logger/sentry`.
|
Optional destinations live under `src/sinks/` (console, Sentry today; New Relic / Datadog-style adapters can land beside them later). Public import paths stay `@mifi/logger` and `@mifi/logger/sentry`.
|
||||||
|
|
||||||
@@ -194,8 +196,13 @@ Any function passed **after** the first argument is invoked only if the event is
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
logger.debug("state", () => buildHugeSnapshot()); // skipped when debug is suppressed
|
logger.debug("state", () => buildHugeSnapshot()); // skipped when debug is suppressed
|
||||||
|
logger.debug("response", async () => ({ data: await res.json(), url }));
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Top-level thenables (including Promises returned from lazy factories, or a Promise passed directly as an argument) are settled before sinks run. The log call stays fire-and-forget (`void`). Settled events set `LogEvent.async`, and the console sink renders an `[async]` label suffix. Nested promises inside plain objects are not walked — compose them inside the async factory. Async emits may appear out of order relative to sync logs.
|
||||||
|
|
||||||
|
Rejection reasons replace rejected thenables in that argument slot; other arguments still emit.
|
||||||
|
|
||||||
## Releases
|
## Releases
|
||||||
|
|
||||||
Woodpecker verifies pull requests and `main`, reports CI to Mattermost, then automatically releases from Conventional Commits merged to `main`. It updates `package.json` and `CHANGELOG.md`, creates a `vX.Y.Z` tag, and publishes to the private `@mifi` registry.
|
Woodpecker verifies pull requests and `main`, reports CI to Mattermost, then automatically releases from Conventional Commits merged to `main`. It updates `package.json` and `CHANGELOG.md`, creates a `vX.Y.Z` tag, and publishes to the private `@mifi` registry.
|
||||||
|
|||||||
+3
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@mifi/logger",
|
"name": "@mifi/logger",
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"description": "Intentional, namespaced logging for browser and Node.js TypeScript applications.",
|
"description": "Intentional, namespaced logging for browser and Node.js TypeScript applications.",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -37,6 +37,7 @@
|
|||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"format:check": "prettier --check .",
|
"format:check": "prettier --check .",
|
||||||
"lint": "oxlint src test",
|
"lint": "oxlint src test",
|
||||||
|
"lint:fix": "oxlint src test --fix",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
"test:watch": "vitest",
|
"test:watch": "vitest",
|
||||||
"pack:check": "pnpm pack --pack-destination .artifacts",
|
"pack:check": "pnpm pack --pack-destination .artifacts",
|
||||||
@@ -45,6 +46,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@semantic-release/changelog": "^7.0.0",
|
"@semantic-release/changelog": "^7.0.0",
|
||||||
"@semantic-release/git": "^11.0.1",
|
"@semantic-release/git": "^11.0.1",
|
||||||
|
"@sentry/node": "^10.69.0",
|
||||||
"@types/node": "^24.0.0",
|
"@types/node": "^24.0.0",
|
||||||
"@vitest/coverage-v8": "^3.0.0",
|
"@vitest/coverage-v8": "^3.0.0",
|
||||||
"oxlint": "^1.0.0",
|
"oxlint": "^1.0.0",
|
||||||
|
|||||||
Generated
+368
@@ -13,6 +13,9 @@ importers:
|
|||||||
"@semantic-release/git":
|
"@semantic-release/git":
|
||||||
specifier: ^11.0.1
|
specifier: ^11.0.1
|
||||||
version: 11.0.1(semantic-release@25.0.8(typescript@6.0.3))
|
version: 11.0.1(semantic-release@25.0.8(typescript@6.0.3))
|
||||||
|
"@sentry/node":
|
||||||
|
specifier: ^10.69.0
|
||||||
|
version: 10.69.0(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))
|
||||||
"@types/node":
|
"@types/node":
|
||||||
specifier: ^24.0.0
|
specifier: ^24.0.0
|
||||||
version: 24.13.3
|
version: 24.13.3
|
||||||
@@ -70,6 +73,26 @@ packages:
|
|||||||
}
|
}
|
||||||
engines: { node: ">=6.0.0" }
|
engines: { node: ">=6.0.0" }
|
||||||
|
|
||||||
|
"@apm-js-collab/code-transformer-bundler-plugins@0.7.4":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-nAfOeZPSUAQvJa1iFT/5oCrTm5YQhMMrfCNthNnaXHZiOQhu1KGuLoIx7HtbAi3wfwaBYLaICPIeenIaEwcXIg==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=18.0.0" }
|
||||||
|
|
||||||
|
"@apm-js-collab/code-transformer@0.18.1":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-u1Hb6bHjWtkSpiprwVP6YaHC1DTN4RAU3zYkUDUe7WMnJwdyU1pwTL9dFKiSJB9IiLue/EQovmyx6xhU7FFtAQ==,
|
||||||
|
}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
"@apm-js-collab/tracing-hooks@0.13.0":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-mTvWz9rnQwx1U3h0XPTHaX7bgfkpipLLTQyjlC2cdhQpQEuoLT0AGzoydeoq2NxfEVv6fWOOETcSbb2nptleyw==,
|
||||||
|
}
|
||||||
|
|
||||||
"@babel/code-frame@7.29.7":
|
"@babel/code-frame@7.29.7":
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -730,6 +753,72 @@ packages:
|
|||||||
integrity: sha512-ByP1v7YL5SMveFPP7+sj0/ZuWCOOg/Chs4NafOMpq6WNIM/hdGY0S7C0TCGDBWu1aGmOxmUIhMx3cO+IdwYZ1Q==,
|
integrity: sha512-ByP1v7YL5SMveFPP7+sj0/ZuWCOOg/Chs4NafOMpq6WNIM/hdGY0S7C0TCGDBWu1aGmOxmUIhMx3cO+IdwYZ1Q==,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"@opentelemetry/api-logs@0.220.0":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-CmVa4ImJ+ynfrPMNaAXHET6Bhb44SwzmfyVJFq9ni2jgXJR/l7C6gfVFddNmHP+ZOkP9cf4f9DBe68qVLTHc9w==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=8.0.0" }
|
||||||
|
|
||||||
|
"@opentelemetry/api@1.9.1":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=8.0.0" }
|
||||||
|
|
||||||
|
"@opentelemetry/core@2.10.0":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-/wNZ8twnEQQA4HoHu22+vcsdru6pWPWxW+7w+FlxT6Id7PE/WIbZmVKkte+PF72e0F2dnImFeHD2syyE1Mw6MQ==,
|
||||||
|
}
|
||||||
|
engines: { node: ^18.19.0 || >=20.6.0 }
|
||||||
|
peerDependencies:
|
||||||
|
"@opentelemetry/api": ">=1.0.0 <1.10.0"
|
||||||
|
|
||||||
|
"@opentelemetry/instrumentation@0.220.0":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-xQx3E2WxP1mDvKzxLxX+CTCtNLa560YJZ3087qYHerl2YmiKpv7AH+dAy7vmx+eVrZ5BwhfWUAVoKOoxCNHcpw==,
|
||||||
|
}
|
||||||
|
engines: { node: ^18.19.0 || >=20.6.0 }
|
||||||
|
peerDependencies:
|
||||||
|
"@opentelemetry/api": ^1.3.0
|
||||||
|
|
||||||
|
"@opentelemetry/resources@2.10.0":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-q6MMm2zhggzsHVNbabYwut+a6nbuQQe3URUoxaojM/8K1IBfwwPzvxIjNi2/lI1TFe+fMHMW9MWhrtDLEXEnkA==,
|
||||||
|
}
|
||||||
|
engines: { node: ^18.19.0 || >=20.6.0 }
|
||||||
|
peerDependencies:
|
||||||
|
"@opentelemetry/api": ">=1.3.0 <1.10.0"
|
||||||
|
|
||||||
|
"@opentelemetry/sdk-trace-base@2.10.0":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-GuYQQT7QD2EeO8lcZLRQzcbOyhqAzL+6WWTKTU9mSUBYBazkEDl+VrQcXQhbB08OWM9anD1aHleVadzulpOaUQ==,
|
||||||
|
}
|
||||||
|
engines: { node: ^18.19.0 || >=20.6.0 }
|
||||||
|
peerDependencies:
|
||||||
|
"@opentelemetry/api": ">=1.3.0 <1.10.0"
|
||||||
|
|
||||||
|
"@opentelemetry/sdk-trace@2.10.0":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-MfQGq3GRmTh5fM/y+OjaO0vj6+luCB1XO2gfXCalKCfgKw0eHL++sm75DNweC6ohlp+aFvACqeE0fYayqdRaoQ==,
|
||||||
|
}
|
||||||
|
engines: { node: ^18.19.0 || >=20.6.0 }
|
||||||
|
peerDependencies:
|
||||||
|
"@opentelemetry/api": ">=1.3.0 <1.10.0"
|
||||||
|
|
||||||
|
"@opentelemetry/semantic-conventions@1.43.0":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=14" }
|
||||||
|
|
||||||
"@oxlint/binding-android-arm-eabi@1.77.0":
|
"@oxlint/binding-android-arm-eabi@1.77.0":
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -1217,6 +1306,69 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
semantic-release: ">=20.1.0"
|
semantic-release: ">=20.1.0"
|
||||||
|
|
||||||
|
"@sentry/conventions@0.16.0":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-fO9PLmHdVURcSPUpWCItWAtgKiMwGdJHbovoSEyLplX5sxs2ugvI4CBPTrkkgqhObnZOD0CnWBKDzSVQYBKEyQ==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=14" }
|
||||||
|
|
||||||
|
"@sentry/core@10.69.0":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-+uuqVEeiDzYuAKjZLqsROKXvRTbl/QeH0gfGRtpYib1cud4rAFWRIkFmcR7Jb7JGFYwmReyQotiTj/hcDszTZg==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=18" }
|
||||||
|
|
||||||
|
"@sentry/node-core@10.69.0":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-IgArHczrZJxkgxoffHscj0NxQrG6kCazgmGQnlf3j58J1ec21YaUu8Tu+7G4Lo5tCiW3teQnwlKW1ttMXSqWRw==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=18" }
|
||||||
|
peerDependencies:
|
||||||
|
"@opentelemetry/api": ^1.9.0
|
||||||
|
"@opentelemetry/core": ^1.30.1 || ^2.1.0
|
||||||
|
"@opentelemetry/exporter-trace-otlp-http": ">=0.57.0 <1"
|
||||||
|
"@opentelemetry/instrumentation": ">=0.57.1 <1"
|
||||||
|
"@opentelemetry/sdk-trace-base": ^1.30.1 || ^2.1.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
"@opentelemetry/api":
|
||||||
|
optional: true
|
||||||
|
"@opentelemetry/core":
|
||||||
|
optional: true
|
||||||
|
"@opentelemetry/exporter-trace-otlp-http":
|
||||||
|
optional: true
|
||||||
|
"@opentelemetry/instrumentation":
|
||||||
|
optional: true
|
||||||
|
"@opentelemetry/sdk-trace-base":
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
"@sentry/node@10.69.0":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-xEXA1YGIiTZbrW6MWV34uS6JGQuQg2ijTI0zed+FsJb9JZKPYel/GZK8Km26vfTVb+yCXFmWZNBesKegNcVdzg==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=18" }
|
||||||
|
|
||||||
|
"@sentry/opentelemetry@10.69.0":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-3FyWV6YcEJuvLrlaKGE1dHXCI+1YO0a62w7PkwlRg8yp6K6YXkmdwu9GjqaYD+Ju4tm7uC7mHIsGFQMm0M7pqQ==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=18" }
|
||||||
|
peerDependencies:
|
||||||
|
"@opentelemetry/api": ^1.9.0
|
||||||
|
"@opentelemetry/core": ^1.30.1 || ^2.1.0
|
||||||
|
"@opentelemetry/sdk-trace-base": ^1.30.1 || ^2.1.0
|
||||||
|
|
||||||
|
"@sentry/server-utils@10.69.0":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-0MwHrA8+nNvMIsqf8m3cXwCBlUjr6AS7N6CZvHJtY1DkqEvQqEbD5VIrhzEyHN/KMZIgQ8XeDCQRhjnXFQGRhg==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=18" }
|
||||||
|
|
||||||
"@simple-libs/stream-utils@1.2.0":
|
"@simple-libs/stream-utils@1.2.0":
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -1431,6 +1583,13 @@ packages:
|
|||||||
integrity: sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g==,
|
integrity: sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g==,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
astring@1.9.0:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==,
|
||||||
|
}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
balanced-match@1.0.2:
|
balanced-match@1.0.2:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -1548,6 +1707,12 @@ packages:
|
|||||||
}
|
}
|
||||||
engines: { node: ">= 14.16.0" }
|
engines: { node: ">= 14.16.0" }
|
||||||
|
|
||||||
|
cjs-module-lexer@2.2.0:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==,
|
||||||
|
}
|
||||||
|
|
||||||
clean-stack@5.3.0:
|
clean-stack@5.3.0:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -1825,6 +1990,12 @@ packages:
|
|||||||
integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==,
|
integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
es-module-lexer@2.3.1:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==,
|
||||||
|
}
|
||||||
|
|
||||||
esbuild@0.27.7:
|
esbuild@0.27.7:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -1862,6 +2033,20 @@ packages:
|
|||||||
}
|
}
|
||||||
engines: { node: ">=12" }
|
engines: { node: ">=12" }
|
||||||
|
|
||||||
|
esquery@1.7.0:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=0.10" }
|
||||||
|
|
||||||
|
estraverse@5.3.0:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=4.0" }
|
||||||
|
|
||||||
estree-walker@3.0.3:
|
estree-walker@3.0.3:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -2143,6 +2328,13 @@ packages:
|
|||||||
}
|
}
|
||||||
engines: { node: ">=18.20" }
|
engines: { node: ">=18.20" }
|
||||||
|
|
||||||
|
import-in-the-middle@3.3.3:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-AiohS3H80sXO6owEltjGX+glb7qXaDhBoJb9XcQVH4UI207xu/bDLUcadVKp7Qe576reg9yr/PXZjV5qx8gfbA==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=18" }
|
||||||
|
|
||||||
import-meta-resolve@4.2.0:
|
import-meta-resolve@4.2.0:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -2491,6 +2683,13 @@ packages:
|
|||||||
integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==,
|
integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meriyah@6.1.4:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-Sz8FzjzI0kN13GK/6MVEsVzMZEPvOhnmmI1lU5+/1cGOiK3QUahntrNNtdVeihrO7t9JpoH75iMNXg6R6uWflQ==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=18.0.0" }
|
||||||
|
|
||||||
micromatch@4.0.8:
|
micromatch@4.0.8:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -2546,6 +2745,12 @@ packages:
|
|||||||
integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==,
|
integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module-details-from-path@1.0.4:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==,
|
||||||
|
}
|
||||||
|
|
||||||
ms@2.1.3:
|
ms@2.1.3:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -3070,6 +3275,13 @@ packages:
|
|||||||
}
|
}
|
||||||
engines: { node: ">=0.10.0" }
|
engines: { node: ">=0.10.0" }
|
||||||
|
|
||||||
|
require-in-the-middle@8.0.1:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=9.3.0 || >=8.10.0 <9.0.0" }
|
||||||
|
|
||||||
resolve-from@4.0.0:
|
resolve-from@4.0.0:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -3106,6 +3318,12 @@ packages:
|
|||||||
engines: { node: ^22.14.0 || >= 24.10.0 }
|
engines: { node: ^22.14.0 || >= 24.10.0 }
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
semifies@1.0.0:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-xXR3KGeoxTNWPD4aBvL5NUpMTT7WMANr3EWnaS190QVkY52lqqcVRD7Q05UVbBhiWDGWMlJEUam9m7uFFGVScw==,
|
||||||
|
}
|
||||||
|
|
||||||
semver-regex@4.0.5:
|
semver-regex@4.0.5:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -3852,6 +4070,30 @@ snapshots:
|
|||||||
"@jridgewell/gen-mapping": 0.3.13
|
"@jridgewell/gen-mapping": 0.3.13
|
||||||
"@jridgewell/trace-mapping": 0.3.31
|
"@jridgewell/trace-mapping": 0.3.31
|
||||||
|
|
||||||
|
"@apm-js-collab/code-transformer-bundler-plugins@0.7.4":
|
||||||
|
dependencies:
|
||||||
|
"@apm-js-collab/code-transformer": 0.18.1
|
||||||
|
es-module-lexer: 2.3.1
|
||||||
|
magic-string: 0.30.21
|
||||||
|
module-details-from-path: 1.0.4
|
||||||
|
|
||||||
|
"@apm-js-collab/code-transformer@0.18.1":
|
||||||
|
dependencies:
|
||||||
|
"@types/estree": 1.0.9
|
||||||
|
astring: 1.9.0
|
||||||
|
esquery: 1.7.0
|
||||||
|
meriyah: 6.1.4
|
||||||
|
semifies: 1.0.0
|
||||||
|
source-map: 0.6.1
|
||||||
|
|
||||||
|
"@apm-js-collab/tracing-hooks@0.13.0":
|
||||||
|
dependencies:
|
||||||
|
"@apm-js-collab/code-transformer": 0.18.1
|
||||||
|
debug: 4.4.3
|
||||||
|
module-details-from-path: 1.0.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
"@babel/code-frame@7.29.7":
|
"@babel/code-frame@7.29.7":
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-validator-identifier": 7.29.7
|
"@babel/helper-validator-identifier": 7.29.7
|
||||||
@@ -4126,6 +4368,49 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@octokit/openapi-types": 28.0.0
|
"@octokit/openapi-types": 28.0.0
|
||||||
|
|
||||||
|
"@opentelemetry/api-logs@0.220.0":
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/api": 1.9.1
|
||||||
|
|
||||||
|
"@opentelemetry/api@1.9.1": {}
|
||||||
|
|
||||||
|
"@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1)":
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/api": 1.9.1
|
||||||
|
"@opentelemetry/semantic-conventions": 1.43.0
|
||||||
|
|
||||||
|
"@opentelemetry/instrumentation@0.220.0(@opentelemetry/api@1.9.1)":
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/api": 1.9.1
|
||||||
|
"@opentelemetry/api-logs": 0.220.0
|
||||||
|
import-in-the-middle: 3.3.3
|
||||||
|
require-in-the-middle: 8.0.1
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
|
"@opentelemetry/resources@2.10.0(@opentelemetry/api@1.9.1)":
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/api": 1.9.1
|
||||||
|
"@opentelemetry/core": 2.10.0(@opentelemetry/api@1.9.1)
|
||||||
|
"@opentelemetry/semantic-conventions": 1.43.0
|
||||||
|
|
||||||
|
"@opentelemetry/sdk-trace-base@2.10.0(@opentelemetry/api@1.9.1)":
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/api": 1.9.1
|
||||||
|
"@opentelemetry/core": 2.10.0(@opentelemetry/api@1.9.1)
|
||||||
|
"@opentelemetry/resources": 2.10.0(@opentelemetry/api@1.9.1)
|
||||||
|
"@opentelemetry/sdk-trace": 2.10.0(@opentelemetry/api@1.9.1)
|
||||||
|
"@opentelemetry/semantic-conventions": 1.43.0
|
||||||
|
|
||||||
|
"@opentelemetry/sdk-trace@2.10.0(@opentelemetry/api@1.9.1)":
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/api": 1.9.1
|
||||||
|
"@opentelemetry/core": 2.10.0(@opentelemetry/api@1.9.1)
|
||||||
|
"@opentelemetry/resources": 2.10.0(@opentelemetry/api@1.9.1)
|
||||||
|
"@opentelemetry/semantic-conventions": 1.43.0
|
||||||
|
|
||||||
|
"@opentelemetry/semantic-conventions@1.43.0": {}
|
||||||
|
|
||||||
"@oxlint/binding-android-arm-eabi@1.77.0":
|
"@oxlint/binding-android-arm-eabi@1.77.0":
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -4369,6 +4654,58 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
"@sentry/conventions@0.16.0": {}
|
||||||
|
|
||||||
|
"@sentry/core@10.69.0":
|
||||||
|
dependencies:
|
||||||
|
"@sentry/conventions": 0.16.0
|
||||||
|
|
||||||
|
"@sentry/node-core@10.69.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.220.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.10.0(@opentelemetry/api@1.9.1))":
|
||||||
|
dependencies:
|
||||||
|
"@sentry/conventions": 0.16.0
|
||||||
|
"@sentry/core": 10.69.0
|
||||||
|
"@sentry/opentelemetry": 10.69.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.10.0(@opentelemetry/api@1.9.1))
|
||||||
|
import-in-the-middle: 3.3.3
|
||||||
|
optionalDependencies:
|
||||||
|
"@opentelemetry/api": 1.9.1
|
||||||
|
"@opentelemetry/core": 2.10.0(@opentelemetry/api@1.9.1)
|
||||||
|
"@opentelemetry/instrumentation": 0.220.0(@opentelemetry/api@1.9.1)
|
||||||
|
"@opentelemetry/sdk-trace-base": 2.10.0(@opentelemetry/api@1.9.1)
|
||||||
|
|
||||||
|
"@sentry/node@10.69.0(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))":
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/api": 1.9.1
|
||||||
|
"@opentelemetry/instrumentation": 0.220.0(@opentelemetry/api@1.9.1)
|
||||||
|
"@opentelemetry/sdk-trace-base": 2.10.0(@opentelemetry/api@1.9.1)
|
||||||
|
"@sentry/conventions": 0.16.0
|
||||||
|
"@sentry/core": 10.69.0
|
||||||
|
"@sentry/node-core": 10.69.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.220.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.10.0(@opentelemetry/api@1.9.1))
|
||||||
|
"@sentry/opentelemetry": 10.69.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.10.0(@opentelemetry/api@1.9.1))
|
||||||
|
"@sentry/server-utils": 10.69.0
|
||||||
|
import-in-the-middle: 3.3.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- "@opentelemetry/core"
|
||||||
|
- "@opentelemetry/exporter-trace-otlp-http"
|
||||||
|
- supports-color
|
||||||
|
|
||||||
|
"@sentry/opentelemetry@10.69.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.10.0(@opentelemetry/api@1.9.1))":
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/api": 1.9.1
|
||||||
|
"@opentelemetry/core": 2.10.0(@opentelemetry/api@1.9.1)
|
||||||
|
"@opentelemetry/sdk-trace-base": 2.10.0(@opentelemetry/api@1.9.1)
|
||||||
|
"@sentry/conventions": 0.16.0
|
||||||
|
"@sentry/core": 10.69.0
|
||||||
|
|
||||||
|
"@sentry/server-utils@10.69.0":
|
||||||
|
dependencies:
|
||||||
|
"@apm-js-collab/code-transformer-bundler-plugins": 0.7.4
|
||||||
|
"@apm-js-collab/tracing-hooks": 0.13.0
|
||||||
|
"@sentry/conventions": 0.16.0
|
||||||
|
"@sentry/core": 10.69.0
|
||||||
|
meriyah: 6.1.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
"@simple-libs/stream-utils@1.2.0": {}
|
"@simple-libs/stream-utils@1.2.0": {}
|
||||||
|
|
||||||
"@sindresorhus/is@4.6.0": {}
|
"@sindresorhus/is@4.6.0": {}
|
||||||
@@ -4494,6 +4831,8 @@ snapshots:
|
|||||||
estree-walker: 3.0.3
|
estree-walker: 3.0.3
|
||||||
js-tokens: 10.0.0
|
js-tokens: 10.0.0
|
||||||
|
|
||||||
|
astring@1.9.0: {}
|
||||||
|
|
||||||
balanced-match@1.0.2: {}
|
balanced-match@1.0.2: {}
|
||||||
|
|
||||||
balanced-match@4.0.4: {}
|
balanced-match@4.0.4: {}
|
||||||
@@ -4552,6 +4891,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
readdirp: 4.1.2
|
readdirp: 4.1.2
|
||||||
|
|
||||||
|
cjs-module-lexer@2.2.0: {}
|
||||||
|
|
||||||
clean-stack@5.3.0:
|
clean-stack@5.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
escape-string-regexp: 5.0.0
|
escape-string-regexp: 5.0.0
|
||||||
@@ -4700,6 +5041,8 @@ snapshots:
|
|||||||
|
|
||||||
es-module-lexer@1.7.0: {}
|
es-module-lexer@1.7.0: {}
|
||||||
|
|
||||||
|
es-module-lexer@2.3.1: {}
|
||||||
|
|
||||||
esbuild@0.27.7:
|
esbuild@0.27.7:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@esbuild/aix-ppc64": 0.27.7
|
"@esbuild/aix-ppc64": 0.27.7
|
||||||
@@ -4764,6 +5107,12 @@ snapshots:
|
|||||||
|
|
||||||
escape-string-regexp@5.0.0: {}
|
escape-string-regexp@5.0.0: {}
|
||||||
|
|
||||||
|
esquery@1.7.0:
|
||||||
|
dependencies:
|
||||||
|
estraverse: 5.3.0
|
||||||
|
|
||||||
|
estraverse@5.3.0: {}
|
||||||
|
|
||||||
estree-walker@3.0.3:
|
estree-walker@3.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/estree": 1.0.9
|
"@types/estree": 1.0.9
|
||||||
@@ -4957,6 +5306,12 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
import-in-the-middle@3.3.3:
|
||||||
|
dependencies:
|
||||||
|
cjs-module-lexer: 2.2.0
|
||||||
|
es-module-lexer: 2.3.1
|
||||||
|
module-details-from-path: 1.0.4
|
||||||
|
|
||||||
import-meta-resolve@4.2.0: {}
|
import-meta-resolve@4.2.0: {}
|
||||||
|
|
||||||
indent-string@5.0.0: {}
|
indent-string@5.0.0: {}
|
||||||
@@ -5121,6 +5476,8 @@ snapshots:
|
|||||||
|
|
||||||
merge-stream@2.0.0: {}
|
merge-stream@2.0.0: {}
|
||||||
|
|
||||||
|
meriyah@6.1.4: {}
|
||||||
|
|
||||||
micromatch@4.0.8:
|
micromatch@4.0.8:
|
||||||
dependencies:
|
dependencies:
|
||||||
braces: 3.0.3
|
braces: 3.0.3
|
||||||
@@ -5149,6 +5506,8 @@ snapshots:
|
|||||||
pkg-types: 1.3.1
|
pkg-types: 1.3.1
|
||||||
ufo: 1.6.4
|
ufo: 1.6.4
|
||||||
|
|
||||||
|
module-details-from-path@1.0.4: {}
|
||||||
|
|
||||||
ms@2.1.3: {}
|
ms@2.1.3: {}
|
||||||
|
|
||||||
mz@2.7.0:
|
mz@2.7.0:
|
||||||
@@ -5398,6 +5757,13 @@ snapshots:
|
|||||||
|
|
||||||
require-directory@2.1.1: {}
|
require-directory@2.1.1: {}
|
||||||
|
|
||||||
|
require-in-the-middle@8.0.1:
|
||||||
|
dependencies:
|
||||||
|
debug: 4.4.3
|
||||||
|
module-details-from-path: 1.0.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
resolve-from@4.0.0: {}
|
resolve-from@4.0.0: {}
|
||||||
|
|
||||||
resolve-from@5.0.0: {}
|
resolve-from@5.0.0: {}
|
||||||
@@ -5471,6 +5837,8 @@ snapshots:
|
|||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
|
|
||||||
|
semifies@1.0.0: {}
|
||||||
|
|
||||||
semver-regex@4.0.5: {}
|
semver-regex@4.0.5: {}
|
||||||
|
|
||||||
semver@7.8.5: {}
|
semver@7.8.5: {}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Severity threshold for log filtering, ordered from most to least verbose.
|
||||||
|
*
|
||||||
|
* | Level | Meaning |
|
||||||
|
* |-----------|----------------------------------------------|
|
||||||
|
* | `trace` | Extremely detailed diagnostics |
|
||||||
|
* | `debug` | Development diagnostics |
|
||||||
|
* | `info` | Routine operational messages |
|
||||||
|
* | `warn` | Unexpected but recoverable conditions |
|
||||||
|
* | `error` | Failures that need attention |
|
||||||
|
* | `silent` | Suppresses all console-bound output |
|
||||||
|
*
|
||||||
|
* A logger emits events at or above its configured threshold (e.g. `warn`
|
||||||
|
* allows `warn` and `error`).
|
||||||
|
*/
|
||||||
|
export enum LogLevel {
|
||||||
|
TRACE = "trace",
|
||||||
|
DEBUG = "debug",
|
||||||
|
INFO = "info",
|
||||||
|
WARN = "warn",
|
||||||
|
ERROR = "error",
|
||||||
|
SILENT = "silent",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deployment stage used to pick a default log level when none is configured
|
||||||
|
* explicitly or via runtime overrides.
|
||||||
|
*/
|
||||||
|
export enum LoggerEnvironment {
|
||||||
|
DEVELOPMENT = "development",
|
||||||
|
STAGING = "staging",
|
||||||
|
PRODUCTION = "production",
|
||||||
|
}
|
||||||
+51
-12
@@ -1,7 +1,6 @@
|
|||||||
import { createConsoleSink } from "./sinks/console";
|
import { createConsoleSink } from "./sinks/console";
|
||||||
import type {
|
import type {
|
||||||
LogCallOptions,
|
LogCallOptions,
|
||||||
LogData,
|
|
||||||
LogEvent,
|
LogEvent,
|
||||||
Logger,
|
Logger,
|
||||||
LoggerEnvironment,
|
LoggerEnvironment,
|
||||||
@@ -178,16 +177,41 @@ function namespaceMatches(namespace: string | undefined, filters: readonly strin
|
|||||||
/**
|
/**
|
||||||
* Evaluates lazy log arguments: every argument after the first that is a
|
* Evaluates lazy log arguments: every argument after the first that is a
|
||||||
* zero-arg function is invoked; earlier arguments and non-functions are kept.
|
* zero-arg function is invoked; earlier arguments and non-functions are kept.
|
||||||
|
* Returned thenables are left as-is for {@link settleArguments}.
|
||||||
*
|
*
|
||||||
* @param arguments_ - Raw call arguments (message first, then optional data).
|
* @param arguments_ - Raw call arguments (message first, then optional data).
|
||||||
* @returns Arguments with lazy factories resolved to their return values.
|
* @returns Arguments with lazy factories invoked (may still contain thenables).
|
||||||
*/
|
*/
|
||||||
function evaluate(arguments_: readonly unknown[]): readonly unknown[] {
|
function evaluate(arguments_: readonly unknown[]): readonly unknown[] {
|
||||||
return arguments_.map((argument, index) =>
|
return arguments_.map((argument, index) =>
|
||||||
index > 0 && typeof argument === "function" ? (argument as () => LogData)() : argument,
|
index > 0 && typeof argument === "function" ? (argument as () => unknown)() : argument,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Duck-type check for Promise-like values. */
|
||||||
|
function isThenable(value: unknown): value is PromiseLike<unknown> {
|
||||||
|
return (
|
||||||
|
value !== null &&
|
||||||
|
(typeof value === "object" || typeof value === "function") &&
|
||||||
|
typeof (value as { then?: unknown }).then === "function"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settles top-level thenables in evaluated arguments.
|
||||||
|
* Fulfilled values replace the thenable; rejection reasons replace rejected ones.
|
||||||
|
*/
|
||||||
|
async function settleArguments(arguments_: readonly unknown[]): Promise<readonly unknown[]> {
|
||||||
|
const settled = await Promise.allSettled(
|
||||||
|
arguments_.map((argument) => (isThenable(argument) ? argument : Promise.resolve(argument))),
|
||||||
|
);
|
||||||
|
return settled.map((result) => (result.status === "fulfilled" ? result.value : result.reason));
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasThenable(arguments_: readonly unknown[]): boolean {
|
||||||
|
return arguments_.some(isThenable);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves Sentry sink options from `options.sentry` or a Sentry sink in `sinks`.
|
* Resolves Sentry sink options from `options.sentry` or a Sentry sink in `sinks`.
|
||||||
* Development always yields `undefined` (nothing is sent to Sentry).
|
* Development always yields `undefined` (nothing is sent to Sentry).
|
||||||
@@ -224,6 +248,8 @@ function resolveSentrySinkOptions(
|
|||||||
*
|
*
|
||||||
* Functions passed after the first argument are evaluated lazily — only when
|
* Functions passed after the first argument are evaluated lazily — only when
|
||||||
* the event is emitted — so expensive snapshots stay cheap when suppressed.
|
* the event is emitted — so expensive snapshots stay cheap when suppressed.
|
||||||
|
* Async factories and top-level Promises are settled before sinks run
|
||||||
|
* (fire-and-forget); such events set {@link LogEvent.async}.
|
||||||
*
|
*
|
||||||
* @param options - Logger configuration. See {@link LoggerOptions}.
|
* @param options - Logger configuration. See {@link LoggerOptions}.
|
||||||
* @returns A {@link Logger} instance.
|
* @returns A {@link Logger} instance.
|
||||||
@@ -239,6 +265,7 @@ function resolveSentrySinkOptions(
|
|||||||
*
|
*
|
||||||
* logger.error("Request failed", error);
|
* logger.error("Request failed", error);
|
||||||
* logger.debug("skipped in production", () => hugeObject());
|
* logger.debug("skipped in production", () => hugeObject());
|
||||||
|
* logger.debug("response", async () => ({ data: await res.json() }));
|
||||||
* logger.warn("investigate", { id: 1 }, { sentry: true });
|
* logger.warn("investigate", { id: 1 }, { sentry: true });
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@@ -269,6 +296,9 @@ export function createLogger(options: LoggerOptions): Logger {
|
|||||||
levelRank(level) >= levelRank(threshold) &&
|
levelRank(level) >= levelRank(threshold) &&
|
||||||
(!runtimeOverride?.namespaces.length ||
|
(!runtimeOverride?.namespaces.length ||
|
||||||
namespaceMatches(namespace, runtimeOverride.namespaces));
|
namespaceMatches(namespace, runtimeOverride.namespaces));
|
||||||
|
const deliver = (event: LogEvent) => {
|
||||||
|
sinks.forEach((sink) => sink.emit(event));
|
||||||
|
};
|
||||||
const emit = (level: Exclude<LogLevel, "silent">, arguments_: readonly unknown[]) => {
|
const emit = (level: Exclude<LogLevel, "silent">, arguments_: readonly unknown[]) => {
|
||||||
const split = splitLogCallArguments(arguments_);
|
const split = splitLogCallArguments(arguments_);
|
||||||
const sendToConsole = enabled(level);
|
const sendToConsole = enabled(level);
|
||||||
@@ -281,17 +311,26 @@ export function createLogger(options: LoggerOptions): Logger {
|
|||||||
(Boolean(sentrySinkOptions?.logs) &&
|
(Boolean(sentrySinkOptions?.logs) &&
|
||||||
levelRank(level) >= levelRank(sentrySinkOptions.logLevel)));
|
levelRank(level) >= levelRank(sentrySinkOptions.logLevel)));
|
||||||
if (!sendToConsole && !sendToSentryIssue && !sendToSentryLogs) return;
|
if (!sendToConsole && !sendToSentryIssue && !sendToSentryLogs) return;
|
||||||
const event: LogEvent = {
|
const timestamp = new Date();
|
||||||
|
const evaluated = evaluate(split.arguments);
|
||||||
|
const base = {
|
||||||
level,
|
level,
|
||||||
namespace,
|
namespace,
|
||||||
arguments: evaluate(split.arguments),
|
timestamp,
|
||||||
timestamp: new Date(),
|
|
||||||
environment: options.environment,
|
environment: options.environment,
|
||||||
sendToSentryLogs,
|
sendToSentryLogs,
|
||||||
sendToSentryIssue,
|
sendToSentryIssue,
|
||||||
sendToConsole,
|
sendToConsole,
|
||||||
};
|
};
|
||||||
sinks.forEach((sink) => sink.emit(event));
|
if (!hasThenable(evaluated)) {
|
||||||
|
deliver({ ...base, arguments: evaluated });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void settleArguments(evaluated)
|
||||||
|
.then((settled) => deliver({ ...base, arguments: settled, async: true }))
|
||||||
|
.catch(() => {
|
||||||
|
/* allSettled absorbs rejections; defensive against unexpected throw */
|
||||||
|
});
|
||||||
};
|
};
|
||||||
const consoleMethod = (
|
const consoleMethod = (
|
||||||
method: keyof Console | "profile" | "profileEnd",
|
method: keyof Console | "profile" | "profileEnd",
|
||||||
@@ -301,11 +340,11 @@ export function createLogger(options: LoggerOptions): Logger {
|
|||||||
if (!enabled(level)) return;
|
if (!enabled(level)) return;
|
||||||
const console_ = globalThis.console as Console & Record<string, unknown>;
|
const console_ = globalThis.console as Console & Record<string, unknown>;
|
||||||
const fn = console_[method];
|
const fn = console_[method];
|
||||||
if (typeof fn === "function")
|
if (typeof fn !== "function") return;
|
||||||
(fn as (...items: unknown[]) => void).apply(
|
(fn as (...items: unknown[]) => void).apply(
|
||||||
console_,
|
console_,
|
||||||
Array.from(prefix(namespace, evaluate(arguments_))),
|
Array.from(prefix(namespace, evaluate(arguments_))),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
const api: Logger = {
|
const api: Logger = {
|
||||||
namespace,
|
namespace,
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ function supportsAnsi(): boolean {
|
|||||||
*
|
*
|
||||||
* - Skips events where `sendToConsole` is `false`.
|
* - Skips events where `sendToConsole` is `false`.
|
||||||
* - Maps `trace` to `console.debug`.
|
* - Maps `trace` to `console.debug`.
|
||||||
* - Prefixes a styled namespace label (`[A][B]` or `[LOG]`).
|
* - Prefixes a styled namespace label (`[A][B]` or `[LOG]`), plus `[async]`
|
||||||
|
* when {@link LogEvent.async} is set.
|
||||||
* - Uses CSS `%c` styling in browsers and ANSI colors on Node TTYs.
|
* - Uses CSS `%c` styling in browsers and ANSI colors on Node TTYs.
|
||||||
* - Node `error` level uses `console.error` (stderr).
|
* - Node `error` level uses `console.error` (stderr).
|
||||||
*
|
*
|
||||||
@@ -55,7 +56,10 @@ export function createConsoleSink(): LogSink {
|
|||||||
const console_ = globalThis.console as Console & Record<string, unknown>;
|
const console_ = globalThis.console as Console & Record<string, unknown>;
|
||||||
const fn = console_[method];
|
const fn = console_[method];
|
||||||
if (typeof fn !== "function") return;
|
if (typeof fn !== "function") return;
|
||||||
const label = event.namespace ? `[${event.namespace.split(":").join("][")}]` : "[LOG]";
|
const labelBase = event.namespace
|
||||||
|
? `[${event.namespace.split(":").join("][")}]`
|
||||||
|
: "[LOG]";
|
||||||
|
const label = event.async ? `${labelBase}[async]` : labelBase;
|
||||||
const arguments_ = isBrowser()
|
const arguments_ = isBrowser()
|
||||||
? [`%c${label}`, BROWSER_STYLE_BY_LEVEL[event.level], ...event.arguments]
|
? [`%c${label}`, BROWSER_STYLE_BY_LEVEL[event.level], ...event.arguments]
|
||||||
: supportsAnsi()
|
: supportsAnsi()
|
||||||
|
|||||||
+38
-6
@@ -1,5 +1,11 @@
|
|||||||
import type { LogEvent, LogLevel, LogSink } from "../types";
|
import type { LogEvent, LogLevel, LogSink } from "../types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sentry Issue severity levels (`@sentry/core` `SeverityLevel`).
|
||||||
|
* Note: Issues use `"warning"`; Logs use `"warn"`.
|
||||||
|
*/
|
||||||
|
export type SentrySeverityLevel = "fatal" | "error" | "warning" | "log" | "info" | "debug";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options for {@link createSentrySink}.
|
* Options for {@link createSentrySink}.
|
||||||
*
|
*
|
||||||
@@ -23,13 +29,16 @@ export interface SentrySinkOptions {
|
|||||||
/**
|
/**
|
||||||
* Minimal Sentry scope surface required by {@link createSentrySink}.
|
* Minimal Sentry scope surface required by {@link createSentrySink}.
|
||||||
* Satisfied by `@sentry/browser`, `@sentry/node`, `@sentry/nextjs`, etc.
|
* Satisfied by `@sentry/browser`, `@sentry/node`, `@sentry/nextjs`, etc.
|
||||||
|
*
|
||||||
|
* Method parameter types are intentionally aligned with Sentry's public API
|
||||||
|
* (contravariance) so `typeof Sentry` assigns to {@link SentryLike} without adapters.
|
||||||
*/
|
*/
|
||||||
export interface SentryScopeLike {
|
export interface SentryScopeLike {
|
||||||
/**
|
/**
|
||||||
* Sets the severity for the event about to be captured.
|
* Sets the severity for the event about to be captured.
|
||||||
* @param level - Logger level string (e.g. `"error"`, `"info"`).
|
* @param level - Sentry Issue severity (`"warning"`, not logger `"warn"`).
|
||||||
*/
|
*/
|
||||||
setLevel(level: string): void;
|
setLevel(level: SentrySeverityLevel): void;
|
||||||
/**
|
/**
|
||||||
* Attaches a string tag to the event.
|
* Attaches a string tag to the event.
|
||||||
* @param key - Tag name (this package uses `"logger.namespace"`).
|
* @param key - Tag name (this package uses `"logger.namespace"`).
|
||||||
@@ -59,6 +68,8 @@ export interface SentryLoggerApiLike {
|
|||||||
* Minimal Sentry client surface required by {@link createSentrySink}.
|
* Minimal Sentry client surface required by {@link createSentrySink}.
|
||||||
* Pass your app's Sentry SDK module; this package does not depend on Sentry.
|
* Pass your app's Sentry SDK module; this package does not depend on Sentry.
|
||||||
*
|
*
|
||||||
|
* Structural typing matches official `@sentry/*` exports — no consumer adapter needed.
|
||||||
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* import * as Sentry from "@sentry/nextjs";
|
* import * as Sentry from "@sentry/nextjs";
|
||||||
@@ -80,10 +91,11 @@ export interface SentryLike {
|
|||||||
captureException(error: Error): void;
|
captureException(error: Error): void;
|
||||||
/**
|
/**
|
||||||
* Captures a string message when no `Error` is present in the arguments.
|
* Captures a string message when no `Error` is present in the arguments.
|
||||||
|
* Second argument matches Sentry's optional severity / capture-context slot.
|
||||||
* @param message - Joined string arguments, or a fallback.
|
* @param message - Joined string arguments, or a fallback.
|
||||||
* @param level - Event severity.
|
* @param captureContext - Issue severity (use {@link toSentrySeverity} mapping).
|
||||||
*/
|
*/
|
||||||
captureMessage(message: string, level: string): void;
|
captureMessage(message: string, captureContext?: SentrySeverityLevel): void | string;
|
||||||
/** Structured Logs API. Required when using `{ logs: true }` or `{ sentry: true }`. */
|
/** Structured Logs API. Required when using `{ logs: true }` or `{ sentry: true }`. */
|
||||||
logger?: SentryLoggerApiLike;
|
logger?: SentryLoggerApiLike;
|
||||||
}
|
}
|
||||||
@@ -103,6 +115,21 @@ export function isSentrySink(sink: LogSink): sink is SentrySink {
|
|||||||
return "kind" in sink && (sink as { kind?: unknown }).kind === "sentry";
|
return "kind" in sink && (sink as { kind?: unknown }).kind === "sentry";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps a logger level to a Sentry **Issue** {@link SentrySeverityLevel}.
|
||||||
|
*
|
||||||
|
* - `"warn"` → `"warning"` (Issues API; Logs keep `"warn"`)
|
||||||
|
* - `"trace"` → `"debug"` (closest Issue severity)
|
||||||
|
* - other levels map by name (`error`, `info`, `debug`)
|
||||||
|
*
|
||||||
|
* @param level - Logger emit level (never `silent`).
|
||||||
|
*/
|
||||||
|
export function toSentrySeverity(level: Exclude<LogLevel, "silent">): SentrySeverityLevel {
|
||||||
|
if (level === "warn") return "warning";
|
||||||
|
if (level === "trace") return "debug";
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
function isAttributeValue(value: unknown): value is string | number | boolean {
|
function isAttributeValue(value: unknown): value is string | number | boolean {
|
||||||
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
||||||
}
|
}
|
||||||
@@ -120,6 +147,7 @@ export function toSentryLogPayload(event: LogEvent): {
|
|||||||
event.arguments.filter((item) => typeof item === "string").join(" ") || "Log event";
|
event.arguments.filter((item) => typeof item === "string").join(" ") || "Log event";
|
||||||
const attributes: Record<string, string | number | boolean> = {};
|
const attributes: Record<string, string | number | boolean> = {};
|
||||||
if (event.namespace) attributes["logger.namespace"] = event.namespace;
|
if (event.namespace) attributes["logger.namespace"] = event.namespace;
|
||||||
|
if (event.async) attributes.async = true;
|
||||||
for (const item of event.arguments) {
|
for (const item of event.arguments) {
|
||||||
if (!item || typeof item !== "object" || item instanceof Error || Array.isArray(item))
|
if (!item || typeof item !== "object" || item instanceof Error || Array.isArray(item))
|
||||||
continue;
|
continue;
|
||||||
@@ -143,6 +171,9 @@ export function toSentryLogPayload(event: LogEvent): {
|
|||||||
* event with `{ sentry: true }` on the log call. Suppress an Issue with
|
* event with `{ sentry: true }` on the log call. Suppress an Issue with
|
||||||
* `{ suppressSentry: true }`.
|
* `{ suppressSentry: true }`.
|
||||||
*
|
*
|
||||||
|
* Official `@sentry/node`, `@sentry/browser`, and `@sentry/nextjs` modules are
|
||||||
|
* assignable to {@link SentryLike} directly — no adapter object required.
|
||||||
|
*
|
||||||
* @param sentry - Any object implementing {@link SentryLike} (typically the Sentry SDK).
|
* @param sentry - Any object implementing {@link SentryLike} (typically the Sentry SDK).
|
||||||
* @param options - Optional Logs configuration.
|
* @param options - Optional Logs configuration.
|
||||||
* @returns A sink to pass as `sentry` or inside `sinks` on {@link createLogger}.
|
* @returns A sink to pass as `sentry` or inside `sinks` on {@link createLogger}.
|
||||||
@@ -174,12 +205,13 @@ export function createSentrySink(sentry: SentryLike, options: SentrySinkOptions
|
|||||||
if (event.sendToSentryIssue) {
|
if (event.sendToSentryIssue) {
|
||||||
const error = event.arguments.find((item): item is Error => item instanceof Error);
|
const error = event.arguments.find((item): item is Error => item instanceof Error);
|
||||||
const { message, attributes } = toSentryLogPayload(event);
|
const { message, attributes } = toSentryLogPayload(event);
|
||||||
|
const severity = toSentrySeverity(event.level);
|
||||||
sentry.withScope((scope) => {
|
sentry.withScope((scope) => {
|
||||||
scope.setLevel(event.level);
|
scope.setLevel(severity);
|
||||||
if (event.namespace) scope.setTag("logger.namespace", event.namespace);
|
if (event.namespace) scope.setTag("logger.namespace", event.namespace);
|
||||||
scope.setExtras(attributes);
|
scope.setExtras(attributes);
|
||||||
if (error) sentry.captureException(error);
|
if (error) sentry.captureException(error);
|
||||||
else sentry.captureMessage(message, event.level);
|
else sentry.captureMessage(message, severity);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-5
@@ -1,3 +1,5 @@
|
|||||||
|
import { LogLevel as LogLevelEnum, LoggerEnvironment as LoggerEnvironmentEnum } from "./constants";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Severity threshold for log filtering, ordered from most to least verbose.
|
* Severity threshold for log filtering, ordered from most to least verbose.
|
||||||
*
|
*
|
||||||
@@ -13,7 +15,7 @@
|
|||||||
* A logger emits events at or above its configured threshold (e.g. `warn`
|
* A logger emits events at or above its configured threshold (e.g. `warn`
|
||||||
* allows `warn` and `error`).
|
* allows `warn` and `error`).
|
||||||
*/
|
*/
|
||||||
export type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "silent";
|
export type LogLevel = `${LogLevelEnum}`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deployment stage used to pick a default log level when none is configured
|
* Deployment stage used to pick a default log level when none is configured
|
||||||
@@ -24,20 +26,23 @@ export type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "silent";
|
|||||||
* - `staging` → `warn`
|
* - `staging` → `warn`
|
||||||
* - `production` → `error`
|
* - `production` → `error`
|
||||||
*/
|
*/
|
||||||
export type LoggerEnvironment = "development" | "staging" | "production";
|
export type LoggerEnvironment = `${LoggerEnvironmentEnum}`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A value passed as a log argument after the message.
|
* A value passed as a log argument after the message.
|
||||||
*
|
*
|
||||||
* Prefer a zero-argument function for expensive payloads: it is only invoked
|
* Prefer a zero-argument function for expensive payloads: it is only invoked
|
||||||
* when the event is actually emitted, so suppressed logs avoid the work.
|
* when the event is actually emitted, so suppressed logs avoid the work.
|
||||||
|
* The factory may be `async` or otherwise return a `Promise`; top-level
|
||||||
|
* thenables are settled before sinks see the event (fire-and-forget).
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* logger.debug("state", () => expensiveSnapshot());
|
* logger.debug("state", () => expensiveSnapshot());
|
||||||
|
* logger.debug("response", async () => ({ data: await res.json() }));
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export type LogData = unknown | (() => unknown);
|
export type LogData = unknown | (() => unknown | Promise<unknown>);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Per-call options for `trace` / `debug` / `log` / `info` / `warn` / `error`
|
* Per-call options for `trace` / `debug` / `log` / `info` / `warn` / `error`
|
||||||
@@ -73,10 +78,13 @@ export interface LogEvent {
|
|||||||
namespace?: string;
|
namespace?: string;
|
||||||
/**
|
/**
|
||||||
* Evaluated arguments for the event (call options already stripped).
|
* Evaluated arguments for the event (call options already stripped).
|
||||||
* Lazy `() => unknown` functions have already been invoked.
|
* Lazy factories have been invoked and top-level thenables settled;
|
||||||
|
* rejection reasons appear in place of rejected thenables.
|
||||||
*/
|
*/
|
||||||
arguments: readonly unknown[];
|
arguments: readonly unknown[];
|
||||||
/** Wall-clock time when the event was created. */
|
/**
|
||||||
|
* Wall-clock time when the log call was made (before awaiting thenables).
|
||||||
|
*/
|
||||||
timestamp: Date;
|
timestamp: Date;
|
||||||
/** Deployment stage from {@link LoggerOptions.environment}. */
|
/** Deployment stage from {@link LoggerOptions.environment}. */
|
||||||
environment: LoggerEnvironment;
|
environment: LoggerEnvironment;
|
||||||
@@ -95,6 +103,11 @@ export interface LogEvent {
|
|||||||
* should be rendered by console-oriented sinks.
|
* should be rendered by console-oriented sinks.
|
||||||
*/
|
*/
|
||||||
sendToConsole: boolean;
|
sendToConsole: boolean;
|
||||||
|
/**
|
||||||
|
* `true` when emit was deferred to settle top-level thenables.
|
||||||
|
* Omitted for fully synchronous emits. Console sinks render `[async]`.
|
||||||
|
*/
|
||||||
|
async?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||||
|
import { createConsoleSink } from "../src/index";
|
||||||
|
import type { LogEvent } from "../src/index";
|
||||||
|
|
||||||
|
function event(overrides: Partial<LogEvent> = {}): LogEvent {
|
||||||
|
return {
|
||||||
|
level: "debug",
|
||||||
|
namespace: "API",
|
||||||
|
arguments: ["hello"],
|
||||||
|
timestamp: new Date(),
|
||||||
|
environment: "development",
|
||||||
|
sendToSentryLogs: false,
|
||||||
|
sendToSentryIssue: false,
|
||||||
|
sendToConsole: true,
|
||||||
|
...overrides,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("createConsoleSink", () => {
|
||||||
|
afterEach(() => {
|
||||||
|
vi.restoreAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("appends [async] to the namespace label when event.async is set", () => {
|
||||||
|
const debug = vi.spyOn(console, "debug").mockImplementation(() => undefined);
|
||||||
|
createConsoleSink().emit(event({ async: true }));
|
||||||
|
expect(debug).toHaveBeenCalled();
|
||||||
|
const first = debug.mock.calls[0]?.[0];
|
||||||
|
expect(String(first)).toContain("[API][async]");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("omits [async] for synchronous events", () => {
|
||||||
|
const debug = vi.spyOn(console, "debug").mockImplementation(() => undefined);
|
||||||
|
createConsoleSink().emit(event());
|
||||||
|
expect(debug).toHaveBeenCalled();
|
||||||
|
const first = debug.mock.calls[0]?.[0];
|
||||||
|
expect(String(first)).toContain("[API]");
|
||||||
|
expect(String(first)).not.toContain("[async]");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -40,6 +40,43 @@ describe("createLogger", () => {
|
|||||||
expect(expensive).toHaveBeenCalledTimes(1);
|
expect(expensive).toHaveBeenCalledTimes(1);
|
||||||
expect(destination.events).toHaveLength(1);
|
expect(destination.events).toHaveLength(1);
|
||||||
expect(destination.events[0]?.arguments).toEqual(["kept", { huge: "snapshot" }]);
|
expect(destination.events[0]?.arguments).toEqual(["kept", { huge: "snapshot" }]);
|
||||||
|
expect(destination.events[0]?.async).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("never starts suppressed async lazy factories", () => {
|
||||||
|
const destination = sink();
|
||||||
|
const expensive = vi.fn(async () => ({ huge: "snapshot" }));
|
||||||
|
const logger = createLogger({ environment: "production", sinks: [destination.sink] });
|
||||||
|
logger.debug("ignored", expensive);
|
||||||
|
expect(expensive).not.toHaveBeenCalled();
|
||||||
|
expect(destination.events).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("settles async lazy factories before emitting and sets async", async () => {
|
||||||
|
const destination = sink();
|
||||||
|
const factory = vi.fn(async () => ({ data: 1 }));
|
||||||
|
const logger = createLogger({ environment: "development", sinks: [destination.sink] });
|
||||||
|
logger.debug("response", factory);
|
||||||
|
expect(factory).toHaveBeenCalledTimes(1);
|
||||||
|
expect(destination.events).toHaveLength(0);
|
||||||
|
await vi.waitFor(() => expect(destination.events).toHaveLength(1));
|
||||||
|
expect(destination.events[0]).toMatchObject({
|
||||||
|
arguments: ["response", { data: 1 }],
|
||||||
|
async: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("unwraps direct Promise arguments and keeps rejection reasons", async () => {
|
||||||
|
const destination = sink();
|
||||||
|
const reason = new Error("boom");
|
||||||
|
const logger = createLogger({ environment: "development", sinks: [destination.sink] });
|
||||||
|
logger.error("failed", { id: 1 }, Promise.reject(reason));
|
||||||
|
expect(destination.events).toHaveLength(0);
|
||||||
|
await vi.waitFor(() => expect(destination.events).toHaveLength(1));
|
||||||
|
expect(destination.events[0]).toMatchObject({
|
||||||
|
arguments: ["failed", { id: 1 }, reason],
|
||||||
|
async: true,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("applies session namespace filtering to namespace descendants", () => {
|
it("applies session namespace filtering to namespace descendants", () => {
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* Compile-time regression: official Sentry SDKs must assign to {@link SentryLike}
|
||||||
|
* without casts or consumer adapters. Checked by `pnpm check` (`tsc --noEmit`).
|
||||||
|
*/
|
||||||
|
import * as Sentry from "@sentry/node";
|
||||||
|
import { createSentrySink, type SentryLike } from "../src/sentry";
|
||||||
|
|
||||||
|
const _sdk: SentryLike = Sentry;
|
||||||
|
createSentrySink(Sentry);
|
||||||
|
createSentrySink(Sentry, { logs: true });
|
||||||
|
|
||||||
|
const stub: SentryLike = {
|
||||||
|
withScope: (callback) =>
|
||||||
|
callback({
|
||||||
|
setLevel: () => undefined,
|
||||||
|
setTag: () => undefined,
|
||||||
|
setExtras: () => undefined,
|
||||||
|
}),
|
||||||
|
captureException: () => undefined,
|
||||||
|
captureMessage: () => undefined,
|
||||||
|
logger: {
|
||||||
|
trace: () => undefined,
|
||||||
|
debug: () => undefined,
|
||||||
|
info: () => undefined,
|
||||||
|
warn: () => undefined,
|
||||||
|
error: () => undefined,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
createSentrySink(stub);
|
||||||
|
createSentrySink(stub, { logs: true });
|
||||||
+82
-2
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it, vi } from "vitest";
|
import { describe, expect, it, vi } from "vitest";
|
||||||
import { createLogger } from "../src/index";
|
import { createLogger, type LogEvent } from "../src/index";
|
||||||
import { createSentrySink, toSentryLogPayload } from "../src/sentry";
|
import { createSentrySink, toSentryLogPayload, toSentrySeverity } from "../src/sentry";
|
||||||
|
|
||||||
function createFakeSentry() {
|
function createFakeSentry() {
|
||||||
const scope = { setLevel: vi.fn(), setTag: vi.fn(), setExtras: vi.fn() };
|
const scope = { setLevel: vi.fn(), setTag: vi.fn(), setExtras: vi.fn() };
|
||||||
@@ -21,6 +21,29 @@ function createFakeSentry() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function issueEvent(overrides: Partial<LogEvent> = {}): LogEvent {
|
||||||
|
return {
|
||||||
|
level: "error",
|
||||||
|
arguments: ["message"],
|
||||||
|
timestamp: new Date(),
|
||||||
|
environment: "production",
|
||||||
|
sendToSentryLogs: false,
|
||||||
|
sendToSentryIssue: true,
|
||||||
|
sendToConsole: false,
|
||||||
|
...overrides,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("toSentrySeverity", () => {
|
||||||
|
it("maps logger levels to Sentry Issue severities", () => {
|
||||||
|
expect(toSentrySeverity("warn")).toBe("warning");
|
||||||
|
expect(toSentrySeverity("trace")).toBe("debug");
|
||||||
|
expect(toSentrySeverity("error")).toBe("error");
|
||||||
|
expect(toSentrySeverity("info")).toBe("info");
|
||||||
|
expect(toSentrySeverity("debug")).toBe("debug");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("toSentryLogPayload", () => {
|
describe("toSentryLogPayload", () => {
|
||||||
it("joins string messages and flattens primitive object attributes", () => {
|
it("joins string messages and flattens primitive object attributes", () => {
|
||||||
expect(
|
expect(
|
||||||
@@ -43,6 +66,21 @@ describe("toSentryLogPayload", () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("includes async when the event was deferred for thenables", () => {
|
||||||
|
expect(
|
||||||
|
toSentryLogPayload({
|
||||||
|
level: "debug",
|
||||||
|
arguments: ["response"],
|
||||||
|
timestamp: new Date(),
|
||||||
|
environment: "development",
|
||||||
|
sendToSentryLogs: true,
|
||||||
|
sendToSentryIssue: false,
|
||||||
|
sendToConsole: true,
|
||||||
|
async: true,
|
||||||
|
}).attributes,
|
||||||
|
).toEqual({ async: true });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("createSentrySink", () => {
|
describe("createSentrySink", () => {
|
||||||
@@ -111,4 +149,46 @@ describe("createSentrySink", () => {
|
|||||||
expect(sentry.captureException).not.toHaveBeenCalled();
|
expect(sentry.captureException).not.toHaveBeenCalled();
|
||||||
expect(sentry.logger.warn).not.toHaveBeenCalled();
|
expect(sentry.logger.warn).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("maps warn → warning on the Issues path and keeps warn on the Logs path", () => {
|
||||||
|
const { scope, sentry } = createFakeSentry();
|
||||||
|
const sink = createSentrySink(sentry, { logs: true });
|
||||||
|
|
||||||
|
sink.emit(
|
||||||
|
issueEvent({
|
||||||
|
level: "warn",
|
||||||
|
arguments: ["degraded"],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
expect(scope.setLevel).toHaveBeenCalledWith("warning");
|
||||||
|
expect(sentry.captureMessage).toHaveBeenCalledWith("degraded", "warning");
|
||||||
|
expect(sentry.logger.warn).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
sink.emit({
|
||||||
|
level: "warn",
|
||||||
|
namespace: "API",
|
||||||
|
arguments: ["slow", { ms: 10 }],
|
||||||
|
timestamp: new Date(),
|
||||||
|
environment: "production",
|
||||||
|
sendToSentryLogs: true,
|
||||||
|
sendToSentryIssue: false,
|
||||||
|
sendToConsole: false,
|
||||||
|
});
|
||||||
|
expect(sentry.logger.warn).toHaveBeenCalledWith("slow", {
|
||||||
|
"logger.namespace": "API",
|
||||||
|
ms: 10,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("maps error Issue severity as error", () => {
|
||||||
|
const { scope, sentry } = createFakeSentry();
|
||||||
|
createSentrySink(sentry).emit(
|
||||||
|
issueEvent({
|
||||||
|
level: "error",
|
||||||
|
arguments: ["failed"],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
expect(scope.setLevel).toHaveBeenCalledWith("error");
|
||||||
|
expect(sentry.captureMessage).toHaveBeenCalledWith("failed", "error");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-2
@@ -6,8 +6,7 @@
|
|||||||
"strict": true,
|
"strict": true,
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"verbatimModuleSyntax": true,
|
"verbatimModuleSyntax": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true
|
||||||
"ignoreDeprecations": "6.0"
|
|
||||||
},
|
},
|
||||||
"include": ["src", "test", "tsup.config.ts", "vitest.config.ts"]
|
"include": ["src", "test", "tsup.config.ts", "vitest.config.ts"]
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -3,7 +3,13 @@ import { defineConfig } from "tsup";
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
entry: { index: "src/index.ts", sentry: "src/sentry.ts" },
|
entry: { index: "src/index.ts", sentry: "src/sentry.ts" },
|
||||||
format: ["esm", "cjs"],
|
format: ["esm", "cjs"],
|
||||||
dts: true,
|
// tsup injects baseUrl for DTS; TS 6 treats that as an error until tsup stops
|
||||||
|
// (https://github.com/egoist/tsup/issues/1388)
|
||||||
|
dts: {
|
||||||
|
compilerOptions: {
|
||||||
|
ignoreDeprecations: "6.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
clean: true,
|
clean: true,
|
||||||
target: "es2022",
|
target: "es2022",
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user