@blyp/core 0.1.22 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -726
- package/dist/ai/anthropic.js +7 -7
- package/dist/ai/anthropic.mjs +7 -7
- package/dist/ai/better-agent/index.d.ts +3 -0
- package/dist/ai/better-agent/normalize.d.ts +18 -0
- package/dist/ai/better-agent/plugin.d.ts +3 -0
- package/dist/ai/better-agent/tracker.d.ts +35 -0
- package/dist/ai/better-agent.js +701 -0
- package/dist/ai/better-agent.mjs +701 -0
- package/dist/ai/openai.js +4 -4
- package/dist/ai/openai.mjs +4 -4
- package/dist/ai/shared/trace.d.ts +3 -0
- package/dist/ai/shared/types.d.ts +12 -2
- package/dist/index.js +9 -9
- package/dist/index.mjs +9 -9
- package/package.json +14 -1
package/README.md
CHANGED
|
@@ -1,186 +1,73 @@
|
|
|
1
1
|
# Blyp Logger
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
> *The silent observer for your applications*
|
|
6
|
-
|
|
7
|
-
**Blyp** is a high-performance, runtime-adaptive logger for standalone apps and modern TypeScript web frameworks. It combines Bun-friendly runtime detection, structured NDJSON file logging, browser-to-server log ingestion, and framework-specific HTTP logging helpers.
|
|
3
|
+
**Blyp** is a TypeScript logger for standalone apps and modern web frameworks.
|
|
4
|
+
It gives you structured logging, framework adapters, client-to-server log ingestion, and optional connectors without turning the root README into a full manual.
|
|
8
5
|
|
|
9
6
|
[](https://bun.sh)
|
|
10
7
|
[](https://www.typescriptlang.org)
|
|
11
8
|
[](https://elysiajs.com)
|
|
12
9
|
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
- **Runtime detection** — Automatically optimizes for Bun vs Node.js
|
|
16
|
-
- **TypeScript** — Full type safety throughout
|
|
17
|
-
- **Framework integrations** — Elysia, Hono, Express, Fastify, NestJS, Next.js App Router, React Router, Astro, Nitro, Nuxt, TanStack Start, SvelteKit, Cloudflare Workers
|
|
18
|
-
- **Expo integration** — Mobile client logging for Expo apps with structured backend sync
|
|
19
|
-
- **PostHog connector** — Automatic or manual PostHog log forwarding for server, browser, and Expo flows
|
|
20
|
-
- **Databuddy connector** — Automatic or manual Databuddy log forwarding and handled-error tracking for server, browser, and Expo flows
|
|
21
|
-
- **OTLP connector** — Automatic or manual OpenTelemetry log forwarding for Grafana, Datadog, Honeycomb, and any OTLP-compatible backend
|
|
22
|
-
- **Connector delivery queue** — Optional server-side memory + SQLite retry queue for connector delivery without Redis
|
|
23
|
-
- **Standalone usage** — Use without any framework
|
|
24
|
-
- **Structured file logging** — NDJSON with size-based rotation and gzip archives
|
|
25
|
-
- **Database logging** — Serverless-friendly persistence with Prisma and Drizzle adapters for Postgres and MySQL
|
|
26
|
-
- **Client log sync** — Browser logs ingested into your backend stream
|
|
27
|
-
- **AI SDK tracing** — AI SDK middleware-based tracing for `generateText` and `streamText` flows
|
|
28
|
-
|
|
29
|
-
## Project structure
|
|
10
|
+
## Highlights
|
|
30
11
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
├── index.ts # Main source export bridge
|
|
39
|
-
├── src/
|
|
40
|
-
│ ├── core/ # Logger runtime and file logging internals
|
|
41
|
-
│ ├── connectors/ # Connector implementations
|
|
42
|
-
│ ├── frameworks/ # Framework implementations
|
|
43
|
-
│ ├── shared/ # Shared runtime/error utilities
|
|
44
|
-
│ └── types/
|
|
45
|
-
│ ├── framework.types.ts # Shared public contracts
|
|
46
|
-
│ ├── connectors/
|
|
47
|
-
│ │ └── posthog.ts # Connector-specific source types
|
|
48
|
-
│ └── frameworks/
|
|
49
|
-
│ └── elysia.ts # Framework-specific source types
|
|
50
|
-
├── tests/
|
|
51
|
-
│ ├── frameworks/ # One test file per server integration
|
|
52
|
-
│ ├── helpers/ # Shared test utilities
|
|
53
|
-
│ ├── *.test.ts # Focused core tests
|
|
54
|
-
│ └── README.md # Test documentation
|
|
55
|
-
└── README.md
|
|
56
|
-
```
|
|
12
|
+
- Use it in standalone apps or with framework adapters.
|
|
13
|
+
- Create structured, request-scoped logs with `createStructuredLog`.
|
|
14
|
+
- Redact common secrets before logs reach output or downstream sinks.
|
|
15
|
+
- Ingest logs from browser and Expo apps into your backend flow.
|
|
16
|
+
- Forward logs to optional connectors such as PostHog, Better Stack, Sentry, Databuddy, and OTLP targets.
|
|
17
|
+
- Built for Bun-first setups with support for supported Node runtimes.
|
|
18
|
+
- Full TypeScript support across the main package and subpath exports.
|
|
57
19
|
|
|
58
20
|
## Installation
|
|
59
21
|
|
|
60
22
|
```bash
|
|
61
23
|
bun add @blyp/core
|
|
62
|
-
npx expo install expo-network
|
|
63
24
|
```
|
|
64
25
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
## Stability
|
|
26
|
+
`npm install @blyp/core` | `pnpm add @blyp/core` | `yarn add @blyp/core`
|
|
68
27
|
|
|
69
|
-
|
|
28
|
+
If you use the Expo logger, also install `expo-network`.
|
|
70
29
|
|
|
71
|
-
|
|
30
|
+
```bash
|
|
31
|
+
npx expo install expo-network
|
|
32
|
+
```
|
|
72
33
|
|
|
73
|
-
|
|
34
|
+
## Quick start
|
|
74
35
|
|
|
75
|
-
```
|
|
36
|
+
```ts
|
|
76
37
|
import { logger } from '@blyp/core';
|
|
77
38
|
|
|
78
|
-
logger.info('
|
|
79
|
-
logger.success('
|
|
80
|
-
logger.error('
|
|
81
|
-
logger.warning('Warning message');
|
|
39
|
+
logger.info('Server started', { port: 3000 });
|
|
40
|
+
logger.success('Connected to database');
|
|
41
|
+
logger.error('Payment failed', { orderId: 'ord_123' });
|
|
82
42
|
```
|
|
83
43
|
|
|
84
|
-
|
|
44
|
+
## Structured logs
|
|
85
45
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
```typescript
|
|
46
|
+
```ts
|
|
89
47
|
import { createStructuredLog } from '@blyp/core';
|
|
90
48
|
|
|
91
|
-
const
|
|
49
|
+
const log = createStructuredLog('checkout', {
|
|
92
50
|
service: 'web-api',
|
|
93
51
|
level: 'info',
|
|
94
52
|
timestamp: new Date().toISOString(),
|
|
95
53
|
});
|
|
96
54
|
|
|
97
|
-
|
|
55
|
+
log.set({
|
|
98
56
|
user: { id: 1, plan: 'pro' },
|
|
99
57
|
cart: { items: 3, total: 9999 },
|
|
100
58
|
});
|
|
101
59
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
structuredLog.emit({ status: 200 });
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
Framework usage with Elysia:
|
|
108
|
-
|
|
109
|
-
```typescript
|
|
110
|
-
import { createStructuredLog } from '@blyp/core';
|
|
111
|
-
import { Elysia } from 'elysia';
|
|
112
|
-
import { createLogger } from '@blyp/core/elysia';
|
|
113
|
-
|
|
114
|
-
const app = new Elysia()
|
|
115
|
-
.use(createLogger({ level: 'info' }))
|
|
116
|
-
.post('/hello', ({ set }) => {
|
|
117
|
-
const structuredLog = createStructuredLog<{
|
|
118
|
-
message: string;
|
|
119
|
-
level: string;
|
|
120
|
-
timestamp: string;
|
|
121
|
-
hostname?: string;
|
|
122
|
-
port?: number;
|
|
123
|
-
}>('test', {
|
|
124
|
-
message: 'Hello Elysia',
|
|
125
|
-
level: 'info',
|
|
126
|
-
timestamp: new Date().toISOString(),
|
|
127
|
-
hostname: app.server?.hostname,
|
|
128
|
-
port: app.server?.port,
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
structuredLog.info('route started');
|
|
132
|
-
structuredLog.emit({ status: 200 });
|
|
133
|
-
|
|
134
|
-
set.status = 200;
|
|
135
|
-
return 'ok';
|
|
136
|
-
});
|
|
60
|
+
log.info('checkout started');
|
|
61
|
+
log.emit({ status: 200 });
|
|
137
62
|
```
|
|
138
63
|
|
|
139
|
-
Inside framework handlers,
|
|
140
|
-
|
|
141
|
-
### Automatic redaction
|
|
142
|
-
|
|
143
|
-
Blyp redacts sensitive values before they reach the console, files, database adapters, connectors, client ingestion, or framework request logs.
|
|
144
|
-
|
|
145
|
-
Default redacted keys:
|
|
64
|
+
Inside framework handlers, `createStructuredLog(...)` binds to the active request logger automatically. The final structured record is written when you call `.emit()`.
|
|
146
65
|
|
|
147
|
-
|
|
66
|
+
## Framework example
|
|
148
67
|
|
|
149
|
-
Blyp
|
|
68
|
+
Blyp supports Elysia, Hono, Express, Fastify, NestJS, Next.js App Router, React Router, Astro, Nitro, Nuxt, TanStack Start, SvelteKit, and Cloudflare Workers.
|
|
150
69
|
|
|
151
70
|
```ts
|
|
152
|
-
export default {
|
|
153
|
-
redact: {
|
|
154
|
-
keys: ['my_custom_secret', 'internal_token'],
|
|
155
|
-
paths: ['user.ssn', 'payment.**.raw'],
|
|
156
|
-
patterns: [/MY_ORG_[A-Z0-9]{32}/],
|
|
157
|
-
disablePatternScanning: false,
|
|
158
|
-
},
|
|
159
|
-
};
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
Notes:
|
|
163
|
-
|
|
164
|
-
- `redact.paths` supports exact paths, `*`, and `**`
|
|
165
|
-
- regex `patterns` require executable config such as `blyp.config.ts`
|
|
166
|
-
- request headers such as `Authorization`, `Cookie`, `Set-Cookie`, `X-API-Key`, and `X-Auth-Token` are redacted by default
|
|
167
|
-
- Blyp preserves keys and replaces values with `[REDACTED]` or a typed marker
|
|
168
|
-
|
|
169
|
-
### Errors
|
|
170
|
-
|
|
171
|
-
```typescript
|
|
172
|
-
import { createError } from '@blyp/core';
|
|
173
|
-
|
|
174
|
-
throw createError({ status: 404, message: 'Not found' });
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
For the full error API (`HTTP_CODES`, `extend`, `create`), see [Full documentation](docs/README.md#errors).
|
|
178
|
-
|
|
179
|
-
### Framework integrations
|
|
180
|
-
|
|
181
|
-
Blyp supports **Elysia**, **Hono**, **Express**, **Fastify**, **NestJS**, **Next.js**, **React Router**, **Astro**, **Nitro**, **Nuxt**, **TanStack Start**, **SvelteKit**, and **Cloudflare Workers**. Example with Elysia:
|
|
182
|
-
|
|
183
|
-
```typescript
|
|
184
71
|
import { Elysia } from 'elysia';
|
|
185
72
|
import { createLogger } from '@blyp/core/elysia';
|
|
186
73
|
|
|
@@ -190,603 +77,42 @@ const app = new Elysia()
|
|
|
190
77
|
.listen(3000);
|
|
191
78
|
```
|
|
192
79
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
```typescript
|
|
196
|
-
import { createLogger } from '@blyp/core/express';
|
|
197
|
-
|
|
198
|
-
app.use(createLogger({
|
|
199
|
-
includePaths: ['/api/**'],
|
|
200
|
-
ignorePaths: ['/api/internal/**'],
|
|
201
|
-
}));
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
`includePaths` works as an allowlist for automatic `http_request` and `http_error` logs. It uses the same wildcard matching as `ignorePaths`. When both are configured, Blyp logs only included paths and then removes any path that also matches `ignorePaths`.
|
|
205
|
-
|
|
206
|
-
For other frameworks, client logging, advanced configuration, and utilities, see [Full documentation](docs/README.md).
|
|
207
|
-
|
|
208
|
-
### Expo
|
|
209
|
-
|
|
210
|
-
```typescript
|
|
211
|
-
import { createExpoLogger } from '@blyp/core/expo';
|
|
212
|
-
|
|
213
|
-
const logger = createExpoLogger({
|
|
214
|
-
endpoint: 'https://api.example.com/inngest',
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
logger.info('app mounted');
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
Expo uses the runtime `fetch` implementation for delivery and `expo-network` for connectivity metadata. Install `expo-network` in your app and use an absolute ingestion URL.
|
|
221
|
-
|
|
222
|
-
### Durable connector retries
|
|
223
|
-
|
|
224
|
-
Server-side connector delivery can be queued and retried with an internal Blyp-managed SQLite file. This is opt-in, uses at-least-once delivery semantics, and currently applies to server connector log forwarding only.
|
|
225
|
-
|
|
226
|
-
```typescript
|
|
227
|
-
import { createStandaloneLogger } from '@blyp/core/standalone';
|
|
228
|
-
|
|
229
|
-
const logger = createStandaloneLogger({
|
|
230
|
-
connectors: {
|
|
231
|
-
betterstack: {
|
|
232
|
-
enabled: true,
|
|
233
|
-
sourceToken: process.env.BETTERSTACK_TOKEN,
|
|
234
|
-
ingestingHost: 'https://in.logs.betterstack.com',
|
|
235
|
-
},
|
|
236
|
-
delivery: {
|
|
237
|
-
enabled: true,
|
|
238
|
-
durableQueuePath: '.blyp/connectors.sqlite',
|
|
239
|
-
retry: {
|
|
240
|
-
maxAttempts: 8,
|
|
241
|
-
initialBackoffMs: 500,
|
|
242
|
-
maxBackoffMs: 30000,
|
|
243
|
-
},
|
|
244
|
-
},
|
|
245
|
-
},
|
|
246
|
-
});
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
Notes:
|
|
250
|
-
|
|
251
|
-
- Blyp stores the durable queue in its own SQLite file, not your app database.
|
|
252
|
-
- Blyp uses an in-memory hot buffer first, then persists retryable connector failures to SQLite.
|
|
253
|
-
- Older runtimes without built-in SQLite support fall back to memory-only retries with a warning.
|
|
254
|
-
- Exception capture remains best-effort direct delivery in this first version.
|
|
255
|
-
|
|
256
|
-
### AI tracing
|
|
257
|
-
|
|
258
|
-
Use `@blyp/core/ai/vercel` for Vercel AI SDK middleware, or the provider wrappers when you want direct SDK instrumentation without a universal LLM abstraction.
|
|
259
|
-
|
|
260
|
-
Common case:
|
|
261
|
-
|
|
262
|
-
```typescript
|
|
263
|
-
import { streamText } from 'ai';
|
|
264
|
-
import { anthropic } from '@ai-sdk/anthropic';
|
|
265
|
-
import { blypModel } from '@blyp/core/ai/vercel';
|
|
266
|
-
|
|
267
|
-
const model = blypModel(anthropic('claude-sonnet-4-5'), {
|
|
268
|
-
operation: 'support_chat',
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
const result = streamText({
|
|
272
|
-
model,
|
|
273
|
-
prompt: 'Write a refund reply for this customer',
|
|
274
|
-
});
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
Advanced middleware usage:
|
|
278
|
-
|
|
279
|
-
```typescript
|
|
280
|
-
import { wrapLanguageModel } from 'ai';
|
|
281
|
-
import { anthropic } from '@ai-sdk/anthropic';
|
|
282
|
-
import { blypMiddleware } from '@blyp/core/ai/vercel';
|
|
283
|
-
|
|
284
|
-
const model = wrapLanguageModel({
|
|
285
|
-
model: anthropic('claude-sonnet-4-5'),
|
|
286
|
-
middleware: blypMiddleware({
|
|
287
|
-
operation: 'support_chat',
|
|
288
|
-
}),
|
|
289
|
-
});
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
By default Blyp logs one structured `ai_trace` record per AI SDK call with provider, model, operation, token usage, finish reason, timing, and best-effort tool events. Prompt, response, reasoning, tool input, tool output, and stream chunk capture are off by default. When Blyp request context is active, AI traces inherit the active request-scoped logger automatically.
|
|
293
|
-
|
|
294
|
-
Direct provider wrappers:
|
|
295
|
-
|
|
296
|
-
```typescript
|
|
297
|
-
import OpenAI from 'openai';
|
|
298
|
-
import Anthropic from '@anthropic-ai/sdk';
|
|
299
|
-
import { wrapOpenAI } from '@blyp/core/ai/openai';
|
|
300
|
-
import { wrapAnthropic } from '@blyp/core/ai/anthropic';
|
|
301
|
-
|
|
302
|
-
const openai = wrapOpenAI(new OpenAI({ apiKey: process.env.OPENAI_API_KEY }), {
|
|
303
|
-
operation: 'draft_blog_intro',
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
const anthropic = wrapAnthropic(new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }), {
|
|
307
|
-
operation: 'summarize_ticket',
|
|
308
|
-
});
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
OpenRouter is supported through the OpenAI-compatible path:
|
|
312
|
-
|
|
313
|
-
```typescript
|
|
314
|
-
import OpenAI from 'openai';
|
|
315
|
-
import { wrapOpenAI } from '@blyp/core/ai/openai';
|
|
316
|
-
|
|
317
|
-
const client = wrapOpenAI(
|
|
318
|
-
new OpenAI({
|
|
319
|
-
apiKey: process.env.OPENROUTER_API_KEY,
|
|
320
|
-
baseURL: 'https://openrouter.ai/api/v1',
|
|
321
|
-
}),
|
|
322
|
-
{
|
|
323
|
-
provider: 'openrouter',
|
|
324
|
-
operation: 'route_experiment',
|
|
325
|
-
}
|
|
326
|
-
);
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
Optional transport tracing:
|
|
330
|
-
|
|
331
|
-
```typescript
|
|
332
|
-
import OpenAI from 'openai';
|
|
333
|
-
import { blypFetch } from '@blyp/core/ai/fetch';
|
|
334
|
-
|
|
335
|
-
const client = new OpenAI({
|
|
336
|
-
apiKey: process.env.OPENAI_API_KEY,
|
|
337
|
-
fetch: blypFetch(fetch),
|
|
338
|
-
});
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
### Database logging
|
|
342
|
-
|
|
343
|
-
Use `destination: 'database'` when you cannot rely on filesystem writes, such as serverless deployments. Database mode requires an executable config file like `blyp.config.ts` because Prisma and Drizzle adapters are runtime objects.
|
|
344
|
-
|
|
345
|
-
Prisma:
|
|
346
|
-
|
|
347
|
-
```typescript
|
|
348
|
-
import { PrismaClient } from '@prisma/client';
|
|
349
|
-
import { createPrismaDatabaseAdapter } from '@blyp/core/database';
|
|
350
|
-
|
|
351
|
-
const prisma = new PrismaClient();
|
|
352
|
-
|
|
353
|
-
export default {
|
|
354
|
-
destination: 'database',
|
|
355
|
-
database: {
|
|
356
|
-
dialect: 'postgres',
|
|
357
|
-
adapter: createPrismaDatabaseAdapter({
|
|
358
|
-
client: prisma,
|
|
359
|
-
model: 'blypLog',
|
|
360
|
-
}),
|
|
361
|
-
},
|
|
362
|
-
};
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
Drizzle:
|
|
366
|
-
|
|
367
|
-
```typescript
|
|
368
|
-
import { createDrizzleDatabaseAdapter } from '@blyp/core/database';
|
|
369
|
-
import { db } from './db';
|
|
370
|
-
import { blypLogs } from './db/schema/blyp';
|
|
371
|
-
|
|
372
|
-
export default {
|
|
373
|
-
destination: 'database',
|
|
374
|
-
database: {
|
|
375
|
-
dialect: 'mysql',
|
|
376
|
-
adapter: createDrizzleDatabaseAdapter({
|
|
377
|
-
db,
|
|
378
|
-
table: blypLogs,
|
|
379
|
-
}),
|
|
380
|
-
},
|
|
381
|
-
};
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
In database mode, Blyp keeps connectors working as usual and replaces only the primary local persistence backend. Promise-based and hook-driven framework integrations such as Hono, Elysia, Next.js, React Router, Astro, Nitro, Nuxt, SvelteKit, and TanStack Start flush database writes before the request finishes. In callback-style servers, call `await logger.flush()` at your own boundary when you need a hard durability point.
|
|
385
|
-
|
|
386
|
-
Use the Blyp CLI to scaffold the schema and migrations:
|
|
387
|
-
|
|
388
|
-
```bash
|
|
389
|
-
blyp logs init --adapter prisma --dialect postgres
|
|
390
|
-
blyp logs init --adapter drizzle --dialect mysql
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
### Better Stack
|
|
394
|
-
|
|
395
|
-
Use `connectors.betterstack` when you want Blyp logs forwarded into Better Stack through `@logtail/node`:
|
|
396
|
-
|
|
397
|
-
Install the optional peer dependencies for this connector when you enable it:
|
|
398
|
-
|
|
399
|
-
```bash
|
|
400
|
-
bun add @logtail/node @sentry/node
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
```typescript
|
|
404
|
-
export default {
|
|
405
|
-
connectors: {
|
|
406
|
-
betterstack: {
|
|
407
|
-
enabled: true,
|
|
408
|
-
mode: 'auto',
|
|
409
|
-
sourceToken: process.env.SOURCE_TOKEN,
|
|
410
|
-
ingestingHost: process.env.INGESTING_HOST,
|
|
411
|
-
errorTracking: {
|
|
412
|
-
dsn: process.env.BETTERSTACK_ERROR_TRACKING_DSN,
|
|
413
|
-
tracesSampleRate: 1.0,
|
|
414
|
-
},
|
|
415
|
-
},
|
|
416
|
-
},
|
|
417
|
-
};
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
`INGESTING_HOST` must be a full absolute `http://` or `https://` URL. Blyp does not auto-read `SOURCE_TOKEN` or `INGESTING_HOST`; wire them through your config explicitly.
|
|
421
|
-
|
|
422
|
-
In `auto` mode, the normal Blyp server loggers forward to Better Stack automatically. In `manual` mode, use `@blyp/core/betterstack`:
|
|
423
|
-
|
|
424
|
-
```typescript
|
|
425
|
-
import {
|
|
426
|
-
captureBetterStackException,
|
|
427
|
-
createBetterStackErrorTracker,
|
|
428
|
-
createBetterStackLogger,
|
|
429
|
-
createStructuredBetterStackLogger,
|
|
430
|
-
} from '@blyp/core/betterstack';
|
|
431
|
-
|
|
432
|
-
createBetterStackLogger().info('manual better stack log');
|
|
433
|
-
createBetterStackErrorTracker().capture(new Error('manual better stack exception'));
|
|
434
|
-
captureBetterStackException(new Error('wrapped better stack exception'));
|
|
435
|
-
|
|
436
|
-
const structured = createStructuredBetterStackLogger('checkout', {
|
|
437
|
-
orderId: 'ord_123',
|
|
438
|
-
});
|
|
439
|
-
structured.info('manual start');
|
|
440
|
-
structured.emit({ status: 200 });
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
When `connectors.betterstack.errorTracking.dsn` is configured, Blyp captures handled server errors into Better Stack error tracking using the Sentry SDK. Client `error` and `critical` logs requested through the Better Stack connector are promoted to exceptions as well.
|
|
444
|
-
|
|
445
|
-
Browser and Expo loggers can request server-side Better Stack forwarding through the existing ingestion endpoint:
|
|
446
|
-
|
|
447
|
-
```typescript
|
|
448
|
-
import { createClientLogger } from '@blyp/core/client';
|
|
449
|
-
|
|
450
|
-
const logger = createClientLogger({
|
|
451
|
-
endpoint: '/inngest',
|
|
452
|
-
connector: 'betterstack',
|
|
453
|
-
});
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
```typescript
|
|
457
|
-
import { createExpoLogger } from '@blyp/core/expo';
|
|
458
|
-
|
|
459
|
-
const logger = createExpoLogger({
|
|
460
|
-
endpoint: 'https://api.example.com/inngest',
|
|
461
|
-
connector: 'betterstack',
|
|
462
|
-
});
|
|
463
|
-
```
|
|
464
|
-
|
|
465
|
-
The browser and Expo connector flow still posts to Blyp first. Blyp forwards to Better Stack only when the server connector is configured. Browser and Expo apps do not use `@logtail/browser` directly. Workers remain out of scope for this connector.
|
|
466
|
-
|
|
467
|
-
### PostHog
|
|
468
|
-
|
|
469
|
-
Use `blyp.config.ts` when you want to read the PostHog project key from the environment:
|
|
470
|
-
|
|
471
|
-
Install the optional peer dependencies for this connector when you enable it:
|
|
472
|
-
|
|
473
|
-
```bash
|
|
474
|
-
bun add posthog-node @opentelemetry/api-logs @opentelemetry/exporter-logs-otlp-http @opentelemetry/resources @opentelemetry/sdk-logs
|
|
475
|
-
```
|
|
476
|
-
|
|
477
|
-
```typescript
|
|
478
|
-
export default {
|
|
479
|
-
connectors: {
|
|
480
|
-
posthog: {
|
|
481
|
-
enabled: true,
|
|
482
|
-
mode: 'auto',
|
|
483
|
-
projectKey: process.env.POSTHOG_PROJECT_KEY,
|
|
484
|
-
errorTracking: {
|
|
485
|
-
enabled: true,
|
|
486
|
-
mode: 'auto',
|
|
487
|
-
},
|
|
488
|
-
},
|
|
489
|
-
},
|
|
490
|
-
};
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
In `auto` mode, the normal Blyp server loggers forward to PostHog automatically. In `manual` mode, use `@blyp/core/posthog`:
|
|
494
|
-
|
|
495
|
-
```typescript
|
|
496
|
-
import {
|
|
497
|
-
capturePosthogException,
|
|
498
|
-
createPosthogErrorTracker,
|
|
499
|
-
createPosthogLogger,
|
|
500
|
-
createStructuredPosthogLogger,
|
|
501
|
-
} from '@blyp/core/posthog';
|
|
502
|
-
|
|
503
|
-
createPosthogLogger().info('manual posthog log');
|
|
504
|
-
createPosthogErrorTracker().capture(new Error('manual posthog exception'));
|
|
505
|
-
capturePosthogException(new Error('wrapped posthog exception'));
|
|
506
|
-
|
|
507
|
-
const structured = createStructuredPosthogLogger('checkout', { orderId: 'ord_123' });
|
|
508
|
-
structured.info('manual start');
|
|
509
|
-
structured.emit({ status: 200 });
|
|
510
|
-
```
|
|
511
|
-
|
|
512
|
-
`connectors.posthog.errorTracking.mode: 'auto'` also captures Blyp handled server errors and can enable uncaught exception / unhandled rejection autocapture through `enableExceptionAutocapture`.
|
|
513
|
-
|
|
514
|
-
Browser and Expo loggers can request server-side PostHog forwarding through the existing ingestion endpoint:
|
|
515
|
-
|
|
516
|
-
```typescript
|
|
517
|
-
import { createClientLogger } from '@blyp/core/client';
|
|
518
|
-
|
|
519
|
-
const logger = createClientLogger({
|
|
520
|
-
endpoint: '/inngest',
|
|
521
|
-
connector: 'posthog',
|
|
522
|
-
});
|
|
523
|
-
```
|
|
524
|
-
|
|
525
|
-
Client `error` and `critical` logs requested through the PostHog connector are promoted to PostHog exceptions only when server-side PostHog error tracking is enabled in `auto` mode.
|
|
526
|
-
|
|
527
|
-
The client and Expo connector flow still posts to Blyp first. Blyp forwards to PostHog only when the server connector is configured, and browser or Expo apps do not use `posthog-node` directly. Workers remain out of scope for this connector.
|
|
528
|
-
|
|
529
|
-
### Databuddy
|
|
530
|
-
|
|
531
|
-
Use `connectors.databuddy` when you want Blyp logs and handled errors forwarded into Databuddy:
|
|
532
|
-
|
|
533
|
-
Install the optional peer dependency for this connector when you enable it:
|
|
534
|
-
|
|
535
|
-
```bash
|
|
536
|
-
bun add @databuddy/sdk
|
|
537
|
-
```
|
|
538
|
-
|
|
539
|
-
```typescript
|
|
540
|
-
export default {
|
|
541
|
-
connectors: {
|
|
542
|
-
databuddy: {
|
|
543
|
-
enabled: true,
|
|
544
|
-
mode: 'auto',
|
|
545
|
-
apiKey: process.env.DATABUDDY_API_KEY,
|
|
546
|
-
websiteId: process.env.DATABUDDY_WEBSITE_ID,
|
|
547
|
-
enableBatching: true,
|
|
548
|
-
},
|
|
549
|
-
},
|
|
550
|
-
};
|
|
551
|
-
```
|
|
552
|
-
|
|
553
|
-
Databuddy requires both `apiKey` and `websiteId`. Blyp treats the connector as unavailable until both are configured.
|
|
554
|
-
|
|
555
|
-
In `auto` mode, normal Blyp server loggers forward to Databuddy automatically and handled errors are captured as Databuddy `error` events. In `manual` mode, use `@blyp/core/databuddy`:
|
|
556
|
-
|
|
557
|
-
```typescript
|
|
558
|
-
import {
|
|
559
|
-
captureDatabuddyException,
|
|
560
|
-
createDatabuddyErrorTracker,
|
|
561
|
-
createDatabuddyLogger,
|
|
562
|
-
createStructuredDatabuddyLogger,
|
|
563
|
-
} from '@blyp/core/databuddy';
|
|
564
|
-
|
|
565
|
-
createDatabuddyLogger().info('manual databuddy log');
|
|
566
|
-
createDatabuddyErrorTracker().capture(new Error('manual databuddy exception'));
|
|
567
|
-
captureDatabuddyException(new Error('wrapped databuddy exception'));
|
|
568
|
-
|
|
569
|
-
const structured = createStructuredDatabuddyLogger('checkout', { orderId: 'ord_123' });
|
|
570
|
-
structured.info('manual start');
|
|
571
|
-
structured.emit({ status: 200 });
|
|
572
|
-
```
|
|
573
|
-
|
|
574
|
-
Browser and Expo loggers can request server-side Databuddy forwarding through the existing ingestion endpoint:
|
|
575
|
-
|
|
576
|
-
```typescript
|
|
577
|
-
import { createClientLogger } from '@blyp/core/client';
|
|
578
|
-
|
|
579
|
-
const logger = createClientLogger({
|
|
580
|
-
endpoint: '/inngest',
|
|
581
|
-
connector: 'databuddy',
|
|
582
|
-
});
|
|
583
|
-
```
|
|
584
|
-
|
|
585
|
-
Client `error` and `critical` logs requested through the Databuddy connector are promoted to Databuddy `error` events only when server-side Databuddy is enabled in `auto` mode. The client and Expo connector flow still posts to Blyp first. Blyp forwards to Databuddy only when the server connector is configured.
|
|
586
|
-
|
|
587
|
-
### Sentry
|
|
588
|
-
|
|
589
|
-
Use `connectors.sentry` when you want Blyp logs forwarded into Sentry Logs:
|
|
590
|
-
|
|
591
|
-
Install the optional peer dependency for this connector when you enable it:
|
|
592
|
-
|
|
593
|
-
```bash
|
|
594
|
-
bun add @sentry/node
|
|
595
|
-
```
|
|
596
|
-
|
|
597
|
-
```typescript
|
|
598
|
-
export default {
|
|
599
|
-
connectors: {
|
|
600
|
-
sentry: {
|
|
601
|
-
enabled: true,
|
|
602
|
-
mode: 'auto',
|
|
603
|
-
dsn: process.env.SENTRY_DSN,
|
|
604
|
-
environment: process.env.SENTRY_ENVIRONMENT,
|
|
605
|
-
release: process.env.SENTRY_RELEASE,
|
|
606
|
-
},
|
|
607
|
-
},
|
|
608
|
-
};
|
|
609
|
-
```
|
|
610
|
-
|
|
611
|
-
In `auto` mode, normal Blyp server loggers forward to Sentry automatically. In `manual` mode, use `@blyp/core/sentry`:
|
|
612
|
-
|
|
613
|
-
```typescript
|
|
614
|
-
import { createSentryLogger, createStructuredSentryLogger } from '@blyp/core/sentry';
|
|
615
|
-
|
|
616
|
-
createSentryLogger().info('manual sentry log');
|
|
617
|
-
|
|
618
|
-
const structured = createStructuredSentryLogger('checkout', {
|
|
619
|
-
orderId: 'ord_123',
|
|
620
|
-
});
|
|
621
|
-
structured.info('manual start');
|
|
622
|
-
structured.emit({ status: 200 });
|
|
623
|
-
```
|
|
624
|
-
|
|
625
|
-
Browser and Expo loggers can request server-side forwarding through Blyp's ingestion endpoint:
|
|
626
|
-
|
|
627
|
-
```typescript
|
|
628
|
-
import { createClientLogger } from '@blyp/core/client';
|
|
629
|
-
|
|
630
|
-
const logger = createClientLogger({
|
|
631
|
-
endpoint: '/inngest',
|
|
632
|
-
connector: 'sentry',
|
|
633
|
-
});
|
|
634
|
-
```
|
|
635
|
-
|
|
636
|
-
```typescript
|
|
637
|
-
import { createExpoLogger } from '@blyp/core/expo';
|
|
638
|
-
|
|
639
|
-
const logger = createExpoLogger({
|
|
640
|
-
endpoint: 'https://api.example.com/inngest',
|
|
641
|
-
connector: 'sentry',
|
|
642
|
-
});
|
|
643
|
-
```
|
|
644
|
-
|
|
645
|
-
The browser and Expo Sentry flow still posts to Blyp first. Blyp forwards to Sentry only when the server connector is configured. If Sentry was already initialized by the app, Blyp reuses that client instead of replacing it.
|
|
646
|
-
|
|
647
|
-
### OTLP
|
|
648
|
-
|
|
649
|
-
Use `connectors.otlp` when you want to send logs to named OTLP-compatible backends such as Grafana Cloud, Datadog, Honeycomb, or a self-hosted OpenTelemetry Collector:
|
|
650
|
-
|
|
651
|
-
Install the optional peer dependencies for this connector when you enable it:
|
|
652
|
-
|
|
653
|
-
```bash
|
|
654
|
-
bun add @opentelemetry/api-logs @opentelemetry/exporter-logs-otlp-http @opentelemetry/resources @opentelemetry/sdk-logs
|
|
655
|
-
```
|
|
656
|
-
|
|
657
|
-
```typescript
|
|
658
|
-
export default {
|
|
659
|
-
connectors: {
|
|
660
|
-
otlp: [
|
|
661
|
-
{
|
|
662
|
-
name: 'grafana',
|
|
663
|
-
enabled: true,
|
|
664
|
-
mode: 'auto',
|
|
665
|
-
endpoint: 'http://localhost:4318',
|
|
666
|
-
headers: {
|
|
667
|
-
'x-scope-orgid': process.env.GRAFANA_SCOPE_ID!,
|
|
668
|
-
},
|
|
669
|
-
auth: process.env.GRAFANA_AUTH,
|
|
670
|
-
},
|
|
671
|
-
{
|
|
672
|
-
name: 'honeycomb',
|
|
673
|
-
enabled: true,
|
|
674
|
-
mode: 'manual',
|
|
675
|
-
endpoint: 'https://api.honeycomb.io',
|
|
676
|
-
headers: {
|
|
677
|
-
'x-honeycomb-team': process.env.HONEYCOMB_API_KEY!,
|
|
678
|
-
},
|
|
679
|
-
},
|
|
680
|
-
],
|
|
681
|
-
},
|
|
682
|
-
};
|
|
683
|
-
```
|
|
684
|
-
|
|
685
|
-
In `auto` mode, normal Blyp server loggers forward to every ready OTLP target automatically. In `manual` mode, use `@blyp/core/otlp` and select a named target:
|
|
686
|
-
|
|
687
|
-
```typescript
|
|
688
|
-
import { createOtlpLogger, createStructuredOtlpLogger } from '@blyp/core/otlp';
|
|
689
|
-
|
|
690
|
-
createOtlpLogger({
|
|
691
|
-
name: 'grafana',
|
|
692
|
-
}).info('manual otlp log');
|
|
693
|
-
|
|
694
|
-
const structured = createStructuredOtlpLogger(
|
|
695
|
-
'checkout',
|
|
696
|
-
{ orderId: 'ord_123' },
|
|
697
|
-
{ name: 'honeycomb' }
|
|
698
|
-
);
|
|
699
|
-
structured.info('manual start');
|
|
700
|
-
structured.emit({ status: 200 });
|
|
701
|
-
```
|
|
702
|
-
|
|
703
|
-
Browser and Expo loggers can request server-side forwarding to a named OTLP target through the existing ingestion endpoint:
|
|
80
|
+
See the [framework integration docs](docs/README.md#framework-integrations) for the full adapter matrix and framework-specific examples.
|
|
704
81
|
|
|
705
|
-
|
|
706
|
-
import { createClientLogger } from '@blyp/core/client';
|
|
82
|
+
## More features
|
|
707
83
|
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
```typescript
|
|
715
|
-
import { createExpoLogger } from '@blyp/core/expo';
|
|
716
|
-
|
|
717
|
-
const logger = createExpoLogger({
|
|
718
|
-
endpoint: 'https://api.example.com/inngest',
|
|
719
|
-
connector: { type: 'otlp', name: 'grafana' },
|
|
720
|
-
});
|
|
721
|
-
```
|
|
722
|
-
|
|
723
|
-
The browser and Expo OTLP flows still post to Blyp first. Blyp forwards to the named OTLP target only when that server connector is configured and ready.
|
|
724
|
-
|
|
725
|
-
Log levels, HTTP request logging, and file logging (rotation, archives, reading stored logs) are documented in [docs](docs/README.md#file-logging).
|
|
84
|
+
- [Automatic redaction](docs/README.md#automatic-redaction) for common secrets, headers, and custom patterns.
|
|
85
|
+
- [Client and Expo logging](docs/README.md#client) for browser and mobile apps that send logs through your backend.
|
|
86
|
+
- [AI tracing](docs/README.md#ai-sdk-tracing) for Vercel AI SDK, Better Agent, OpenAI, Anthropic, and compatible transports.
|
|
87
|
+
- [Database logging](docs/README.md#database-logging) when file persistence is not the right fit.
|
|
88
|
+
- Connector forwarding for [PostHog](docs/README.md#posthog-connector), [Databuddy](docs/README.md#databuddy-connector), [Better Stack](docs/README.md#better-stack-connector), [Sentry](docs/README.md#sentry-connector), and [OTLP](docs/README.md#otlp-connector).
|
|
726
89
|
|
|
727
|
-
##
|
|
90
|
+
## Documentation
|
|
728
91
|
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
92
|
+
- [Full documentation](docs/README.md)
|
|
93
|
+
- [Framework integrations](docs/README.md#framework-integrations)
|
|
94
|
+
- [Client and Expo logging](docs/README.md#client)
|
|
95
|
+
- [AI tracing](docs/README.md#ai-sdk-tracing)
|
|
96
|
+
- [Database logging](docs/README.md#database-logging)
|
|
97
|
+
- [PostHog connector](docs/README.md#posthog-connector)
|
|
98
|
+
- [Databuddy connector](docs/README.md#databuddy-connector)
|
|
99
|
+
- [Better Stack connector](docs/README.md#better-stack-connector)
|
|
100
|
+
- [Sentry connector](docs/README.md#sentry-connector)
|
|
101
|
+
- [OTLP connector](docs/README.md#otlp-connector)
|
|
102
|
+
- [Stability policy](STABILITY.md)
|
|
103
|
+
- [Security policy](SECURITY.md)
|
|
104
|
+
- [Contributing](CONTRIBUTING.md)
|
|
105
|
+
- [Test docs](tests/README.md)
|
|
736
106
|
|
|
737
107
|
## Development
|
|
738
108
|
|
|
739
|
-
**Prerequisites:** [Bun](https://bun.sh) 1.2+ (or [Node.js](https://nodejs.org) 18+), [TypeScript](https://www.typescriptlang.org) 5.0+
|
|
740
|
-
|
|
741
109
|
```bash
|
|
742
|
-
git clone https://github.com/Blyphq/blyp.git
|
|
743
|
-
cd blyp
|
|
744
110
|
bun install
|
|
745
111
|
bun run test
|
|
746
112
|
bun run build
|
|
747
113
|
bun run type-check
|
|
748
114
|
```
|
|
749
115
|
|
|
750
|
-
## Publishing
|
|
751
|
-
|
|
752
|
-
GitHub Actions publishes the package to npm when a GitHub Release is published. Add an `NPM_TOKEN` repository secret before using the workflow. The publish workflow uses npm provenance attestation, and maintainers should rotate `NPM_TOKEN` every 90 days.
|
|
753
|
-
|
|
754
|
-
## Security
|
|
755
|
-
|
|
756
|
-
Security issues should be reported through GitHub's private advisory flow for this repository. Public issue reports are not the right channel for suspected vulnerabilities. Security details and disclosure expectations are in [SECURITY.md](SECURITY.md).
|
|
757
|
-
|
|
758
|
-
## Runtime dependencies
|
|
759
|
-
|
|
760
|
-
Blyp keeps its shipped runtime dependency surface small and documents each direct dependency:
|
|
761
|
-
|
|
762
|
-
- `pino`: core structured logger engine
|
|
763
|
-
- `pino-pretty`: human-readable local and development console output when `pretty` mode is enabled
|
|
764
|
-
- `jiti`: runtime loading for `blyp.config.*` files and optional first-party subpath modules
|
|
765
|
-
- `fflate`: gzip compression and decompression for archived log files and log reading
|
|
766
|
-
- `zod`: runtime validation for shared and client payloads
|
|
767
|
-
|
|
768
|
-
Optional connectors stay in `peerDependencies` so regular installs do not pull large connector-specific transitive trees by default.
|
|
769
|
-
|
|
770
|
-
## Contributing
|
|
771
|
-
|
|
772
|
-
Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for how to get set up and submit changes.
|
|
773
|
-
|
|
774
116
|
## License
|
|
775
117
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
## Acknowledgments
|
|
779
|
-
|
|
780
|
-
[Winston](https://github.com/winstonjs/winston) · [Elysia](https://elysiajs.com) · [Chalk](https://github.com/chalk/chalk) · [Bun](https://bun.sh)
|
|
781
|
-
|
|
782
|
-
## Links
|
|
783
|
-
|
|
784
|
-
- [GitHub Repository](https://github.com/Blyphq/blyp)
|
|
785
|
-
- [NPM Package](https://www.npmjs.com/package/@blyp/core)
|
|
786
|
-
- [Documentation](docs/README.md)
|
|
787
|
-
- [Security Policy](SECURITY.md)
|
|
788
|
-
- [Issues](https://github.com/Blyphq/blyp/issues)
|
|
789
|
-
|
|
790
|
-
---
|
|
791
|
-
|
|
792
|
-
*Blyp silently watches over your applications, logging everything that happens under its watchful gaze.*
|
|
118
|
+
MIT
|