@maestro-js/agent-skills 1.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/choosing-an-npm-package/SKILL.md +72 -0
- package/dist/maestro-cli/SKILL.md +257 -0
- package/dist/maestro-packages/SKILL.md +42 -0
- package/dist/maestro-packages/broadcast.md +306 -0
- package/dist/maestro-packages/cache-control.md +337 -0
- package/dist/maestro-packages/cache.md +397 -0
- package/dist/maestro-packages/config.md +203 -0
- package/dist/maestro-packages/context.md +365 -0
- package/dist/maestro-packages/crypt.md +253 -0
- package/dist/maestro-packages/db.md +391 -0
- package/dist/maestro-packages/events.md +295 -0
- package/dist/maestro-packages/exceptions.md +231 -0
- package/dist/maestro-packages/form.md +391 -0
- package/dist/maestro-packages/hash.md +248 -0
- package/dist/maestro-packages/helpers.md +249 -0
- package/dist/maestro-packages/log.md +321 -0
- package/dist/maestro-packages/mail.md +365 -0
- package/dist/maestro-packages/metrics.md +236 -0
- package/dist/maestro-packages/queue.md +284 -0
- package/dist/maestro-packages/rate-limiting.md +206 -0
- package/dist/maestro-packages/react-router-file-routes.md +337 -0
- package/dist/maestro-packages/recurring-jobs.md +353 -0
- package/dist/maestro-packages/sql.md +316 -0
- package/dist/maestro-packages/tracing.md +240 -0
- package/package.json +33 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tracing
|
|
3
|
+
description: "Distributed tracing package built on OpenTelemetry with pluggable providers (Sentry, Maestro). Use when working with @maestro-js/tracing. Key capabilities: wrap functions for automatic span tracking, create active spans with duration measurement, proxy entire objects for tracing, serialize/deserialize trace context across process boundaries (dehydrate/hydrate), add custom log transports for span events, integrate Sentry as a tracing provider."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @maestro-js/tracing
|
|
7
|
+
|
|
8
|
+
Distributed tracing built on OpenTelemetry. Tracks function calls, durations, and parent/child relationships across the request lifecycle with pluggable providers (Sentry or the built-in Maestro tracer).
|
|
9
|
+
|
|
10
|
+
## Quick Setup
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { Tracing } from '@maestro-js/tracing'
|
|
14
|
+
|
|
15
|
+
// Use the default Maestro tracer (works out of the box)
|
|
16
|
+
const result = Tracing.startActiveSpan('my-operation', () => {
|
|
17
|
+
return doWork()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
// Or set Sentry as the provider
|
|
21
|
+
import * as Sentry from '@sentry/node'
|
|
22
|
+
Tracing.setProvider(Tracing.providers.sentry(Sentry))
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Providers
|
|
26
|
+
|
|
27
|
+
### Maestro (default)
|
|
28
|
+
|
|
29
|
+
The `MaestroTracerProvider` is set as the global OpenTelemetry tracer provider automatically on import. It wraps every span to capture attributes, start/end times, and parent span IDs, then logs them through the built-in `Log` transport system.
|
|
30
|
+
|
|
31
|
+
No configuration required -- it works immediately.
|
|
32
|
+
|
|
33
|
+
### Sentry
|
|
34
|
+
|
|
35
|
+
Pass a Sentry SDK instance to configure Sentry as the tracing backend. The factory sets up the `SentrySampler`, `SentrySpanProcessor`, `SentryPropagator`, and `SentryContextManager`.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import * as Sentry from '@sentry/node'
|
|
39
|
+
import { Tracing } from '@maestro-js/tracing'
|
|
40
|
+
|
|
41
|
+
Sentry.init({ dsn: '...', tracesSampleRate: 1.0 })
|
|
42
|
+
Tracing.setProvider(Tracing.providers.sentry(Sentry))
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The Sentry provider expects an object with:
|
|
46
|
+
- `getClient()` -- returns the Sentry client
|
|
47
|
+
- `SentryContextManager` -- the context manager constructor
|
|
48
|
+
- `validateOpenTelemetrySetup()` -- validates the OTEL integration
|
|
49
|
+
|
|
50
|
+
## API Reference
|
|
51
|
+
|
|
52
|
+
### `Tracing.startActiveSpan(name, fn)`
|
|
53
|
+
|
|
54
|
+
Start a span that becomes the active span for the duration of `fn`. Automatically ends the span when `fn` returns or when the returned Promise resolves/rejects.
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
// Simple string name
|
|
58
|
+
Tracing.startActiveSpan('fetch-user', () => {
|
|
59
|
+
return db.query('SELECT * FROM users WHERE id = ?', [userId])
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
// With SpanOptions
|
|
63
|
+
Tracing.startActiveSpan({ name: 'fetch-user', attributes: { userId } }, () => {
|
|
64
|
+
return db.query('SELECT * FROM users WHERE id = ?', [userId])
|
|
65
|
+
})
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### `Tracing.wrap(name, fn)`
|
|
69
|
+
|
|
70
|
+
Return a new function that automatically creates a span on every invocation. The wrapped function preserves the original function's properties.
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
const tracedFetch = Tracing.wrap('fetch-data', fetchData)
|
|
74
|
+
await tracedFetch(url) // each call creates a span
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### `Tracing.isWrapped(fn)`
|
|
78
|
+
|
|
79
|
+
Check whether a function has already been wrapped by the current tracer.
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
if (!Tracing.isWrapped(myFn)) {
|
|
83
|
+
myFn = Tracing.wrap('myFn', myFn)
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### `Tracing.proxy(obj, options?)`
|
|
88
|
+
|
|
89
|
+
Wrap an entire object so every function call on it is traced. Nested objects are proxied recursively with dotted tracer names. Use `options.ignore` to skip specific properties.
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
const tracedService = Tracing.proxy(userService)
|
|
93
|
+
await tracedService.findById(123) // creates span "findById"
|
|
94
|
+
|
|
95
|
+
// Ignore specific methods
|
|
96
|
+
const tracedService = Tracing.proxy(userService, {
|
|
97
|
+
ignore: ({ name }) => name === 'toString'
|
|
98
|
+
})
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The `ignore` option accepts a single predicate or an array of predicates with signature `(options: { name: string; tracer: string | null }) => boolean`.
|
|
102
|
+
|
|
103
|
+
### `Tracing.getTracer(name)`
|
|
104
|
+
|
|
105
|
+
Get a named tracer for a specific package or module. Returns an object with `wrap`, `proxy`, `startActiveSpan`, and `isWrapped` scoped to that tracer name.
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
const { wrap, startActiveSpan, proxy } = Tracing.getTracer('my-package')
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The default export (`Tracing.wrap`, `Tracing.startActiveSpan`, etc.) uses the `'maestro'` tracer.
|
|
112
|
+
|
|
113
|
+
### `Tracing.getActiveSpan()`
|
|
114
|
+
|
|
115
|
+
Return the currently active OpenTelemetry span, or `undefined` if none.
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
const span = Tracing.getActiveSpan()
|
|
119
|
+
span?.setAttribute('user.id', userId)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### `Tracing.addTransport(transport)`
|
|
123
|
+
|
|
124
|
+
Add a log transport that receives a `TraceLogMessage` for every completed span.
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
Tracing.addTransport({
|
|
128
|
+
info(message: Tracing.LogMessage) {
|
|
129
|
+
console.log(`[${message.name}] ${message.endTime - message.startTime}ms`)
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`TraceLogMessage` shape:
|
|
135
|
+
- `name` -- span name
|
|
136
|
+
- `id` -- span ID
|
|
137
|
+
- `parentId` -- parent span ID or `null`
|
|
138
|
+
- `startTime` / `endTime` -- `performance.now()` timestamps
|
|
139
|
+
- `instrumentation` -- instrumentation library name or `null`
|
|
140
|
+
- `attributes` -- key-value span attributes
|
|
141
|
+
|
|
142
|
+
### `Tracing.dehydrate()`
|
|
143
|
+
|
|
144
|
+
Serialize the current trace context for transmission across process boundaries (e.g., into a queue job payload). Returns `null` if no active span.
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
const serialized = Tracing.dehydrate()
|
|
148
|
+
// { traceId, spanId, traceFlags, traceState }
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### `Tracing.hydrate(trace, callback)`
|
|
152
|
+
|
|
153
|
+
Restore a serialized trace context and execute `callback` within it. The hydrated span is marked as remote, establishing the parent/child relationship across processes.
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
Tracing.hydrate(serializedTrace, () => {
|
|
157
|
+
// This runs within the original trace context
|
|
158
|
+
Tracing.startActiveSpan('process-job', () => {
|
|
159
|
+
return processJob(payload)
|
|
160
|
+
})
|
|
161
|
+
})
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### `Tracing.setProvider(provider)`
|
|
165
|
+
|
|
166
|
+
Set the underlying OpenTelemetry `TracerProvider` delegate. The `MaestroTracerProvider` wraps this delegate to add logging and instrumentation.
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
Tracing.setProvider(Tracing.providers.sentry(Sentry))
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Common Patterns
|
|
173
|
+
|
|
174
|
+
### Trace a queue job across processes
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
// Producer: serialize trace context into the job payload
|
|
178
|
+
Tracing.startActiveSpan('enqueue-email', () => {
|
|
179
|
+
const trace = Tracing.dehydrate()
|
|
180
|
+
Queue.dispatch('send-email', { to, subject, body, trace })
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
// Consumer: restore trace context when processing the job
|
|
184
|
+
function handleSendEmail(payload) {
|
|
185
|
+
Tracing.hydrate(payload.trace, () => {
|
|
186
|
+
Tracing.startActiveSpan('send-email', () => {
|
|
187
|
+
return mail.send(payload)
|
|
188
|
+
})
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Trace an entire service object
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
const rawService = {
|
|
197
|
+
async getUser(id: number) { /* ... */ },
|
|
198
|
+
async updateUser(id: number, data: any) { /* ... */ },
|
|
199
|
+
helpers: {
|
|
200
|
+
formatName(user: any) { /* ... */ }
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// All methods (including nested helpers.formatName) get spans
|
|
204
|
+
const service = Tracing.proxy(rawService)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Create a package-scoped tracer
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
const { wrap, startActiveSpan } = Tracing.getTracer('billing')
|
|
211
|
+
|
|
212
|
+
export const createInvoice = wrap('createInvoice', async (order: Order) => {
|
|
213
|
+
return startActiveSpan('validate', () => validateOrder(order))
|
|
214
|
+
})
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Cross-Package Integration
|
|
218
|
+
|
|
219
|
+
- **@maestro-js/log** -- `MaestroTracerProvider` uses `Log.create()` internally; span completion events are emitted through the log transport system
|
|
220
|
+
- **@maestro-js/context** -- spans preserve `AsyncLocalStorage` context; `Context.runWith` is used to restore the correct store when logging span events
|
|
221
|
+
- **@maestro-js/queue** -- use `dehydrate`/`hydrate` to propagate trace context through queue job payloads
|
|
222
|
+
|
|
223
|
+
## Types
|
|
224
|
+
|
|
225
|
+
```ts
|
|
226
|
+
declare namespace Tracing {
|
|
227
|
+
type Attributes = TracingAttributes
|
|
228
|
+
type LogMessage = TraceLogMessage
|
|
229
|
+
type Provider = api.TracerProvider
|
|
230
|
+
type DehydratedTrace = SerializedTrace
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Package Info
|
|
235
|
+
|
|
236
|
+
- **Package**: `@maestro-js/tracing`
|
|
237
|
+
- **Dependencies**: `@opentelemetry/api`, `@opentelemetry/sdk-trace-node`, `@sentry/opentelemetry`, `@maestro-js/log`, `@maestro-js/context`
|
|
238
|
+
- **No tests currently** (`echo 'No tests yet'`)
|
|
239
|
+
- Build: `pnpm --filter @maestro-js/tracing build`
|
|
240
|
+
- Typecheck: `pnpm --filter @maestro-js/tracing typecheck`
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@maestro-js/agent-skills",
|
|
3
|
+
"description": "Agent skills for the @maestro-js framework.",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"default": "./dist/index.js"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@types/node": "^22.19.11"
|
|
13
|
+
},
|
|
14
|
+
"version": "1.0.0-alpha.0",
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "restricted"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"license": "UNLICENSED",
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=22.18.0"
|
|
24
|
+
},
|
|
25
|
+
"repository": "https://github.com/Marcato-Partners/maestro-js",
|
|
26
|
+
"scripts": {
|
|
27
|
+
"generate-skills": "node scripts/generate-package-skills.ts",
|
|
28
|
+
"generate-choosing-npm-package-skill": "node scripts/generate-choosing-npm-package-skill.ts",
|
|
29
|
+
"generate-maestro-cli-skill": "node scripts/generate-maestro-cli-skill.ts",
|
|
30
|
+
"build": "node scripts/generate-package-skills.ts && node scripts/generate-choosing-npm-package-skill.ts && node scripts/generate-maestro-cli-skill.ts",
|
|
31
|
+
"typecheck": "tsc --noEmit"
|
|
32
|
+
}
|
|
33
|
+
}
|