convex-tracer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +592 -0
- package/dist/client/_generated/_ignore.d.ts +1 -0
- package/dist/client/_generated/_ignore.d.ts.map +1 -0
- package/dist/client/_generated/_ignore.js +3 -0
- package/dist/client/_generated/_ignore.js.map +1 -0
- package/dist/client/helpers.d.ts +31 -0
- package/dist/client/helpers.d.ts.map +1 -0
- package/dist/client/helpers.js +177 -0
- package/dist/client/helpers.js.map +1 -0
- package/dist/client/index.d.ts +210 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +355 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/tracer-api/index.d.ts +27 -0
- package/dist/client/tracer-api/index.d.ts.map +1 -0
- package/dist/client/tracer-api/index.js +177 -0
- package/dist/client/tracer-api/index.js.map +1 -0
- package/dist/client/tracer-api/types.d.ts +143 -0
- package/dist/client/tracer-api/types.d.ts.map +1 -0
- package/dist/client/tracer-api/types.js +2 -0
- package/dist/client/tracer-api/types.js.map +1 -0
- package/dist/client/types.d.ts +168 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +2 -0
- package/dist/client/types.js.map +1 -0
- package/dist/component/_generated/api.d.ts +36 -0
- package/dist/component/_generated/api.d.ts.map +1 -0
- package/dist/component/_generated/api.js +31 -0
- package/dist/component/_generated/api.js.map +1 -0
- package/dist/component/_generated/component.d.ts +139 -0
- package/dist/component/_generated/component.d.ts.map +1 -0
- package/dist/component/_generated/component.js +11 -0
- package/dist/component/_generated/component.js.map +1 -0
- package/dist/component/_generated/dataModel.d.ts +46 -0
- package/dist/component/_generated/dataModel.d.ts.map +1 -0
- package/dist/component/_generated/dataModel.js +11 -0
- package/dist/component/_generated/dataModel.js.map +1 -0
- package/dist/component/_generated/server.d.ts +121 -0
- package/dist/component/_generated/server.d.ts.map +1 -0
- package/dist/component/_generated/server.js +78 -0
- package/dist/component/_generated/server.js.map +1 -0
- package/dist/component/convex.config.d.ts +3 -0
- package/dist/component/convex.config.d.ts.map +1 -0
- package/dist/component/convex.config.js +3 -0
- package/dist/component/convex.config.js.map +1 -0
- package/dist/component/lib.d.ts +161 -0
- package/dist/component/lib.d.ts.map +1 -0
- package/dist/component/lib.js +349 -0
- package/dist/component/lib.js.map +1 -0
- package/dist/component/schema.d.ts +75 -0
- package/dist/component/schema.d.ts.map +1 -0
- package/dist/component/schema.js +46 -0
- package/dist/component/schema.js.map +1 -0
- package/dist/component/types.d.ts +286 -0
- package/dist/component/types.d.ts.map +1 -0
- package/dist/component/types.js +28 -0
- package/dist/component/types.js.map +1 -0
- package/dist/react/index.d.ts +6 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +11 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/types.d.ts +8 -0
- package/dist/react/types.d.ts.map +1 -0
- package/dist/react/types.js +2 -0
- package/dist/react/types.js.map +1 -0
- package/package.json +121 -0
- package/src/client/_generated/_ignore.ts +1 -0
- package/src/client/helpers.ts +278 -0
- package/src/client/index.ts +593 -0
- package/src/client/setup.test.ts +26 -0
- package/src/client/tracer-api/index.ts +235 -0
- package/src/client/tracer-api/types.ts +168 -0
- package/src/client/types.ts +257 -0
- package/src/component/_generated/api.ts +52 -0
- package/src/component/_generated/component.ts +199 -0
- package/src/component/_generated/dataModel.ts +60 -0
- package/src/component/_generated/server.ts +161 -0
- package/src/component/convex.config.ts +3 -0
- package/src/component/lib.ts +399 -0
- package/src/component/schema.ts +62 -0
- package/src/component/setup.test.ts +11 -0
- package/src/component/types.ts +38 -0
- package/src/react/index.ts +36 -0
- package/src/react/types.ts +15 -0
- package/src/test.ts +18 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import TracerAPI from "./tracer-api/index";
|
|
2
|
+
function pick(obj, keys) {
|
|
3
|
+
return Object.fromEntries(Object.entries(obj).filter(([k]) => keys.includes(k)));
|
|
4
|
+
}
|
|
5
|
+
export function extractTraceContext(allArgs) {
|
|
6
|
+
const existingContext = allArgs.__traceContext;
|
|
7
|
+
const args = { ...allArgs };
|
|
8
|
+
delete args.__traceContext;
|
|
9
|
+
return { existingContext, args };
|
|
10
|
+
}
|
|
11
|
+
export function prepareLogArgs(args, logArgs) {
|
|
12
|
+
if (!logArgs)
|
|
13
|
+
return undefined;
|
|
14
|
+
if (logArgs === true)
|
|
15
|
+
return args;
|
|
16
|
+
if (Array.isArray(logArgs)) {
|
|
17
|
+
return pick(args, logArgs);
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
export async function setupTraceContext(ctx, component, existingContext, startTime, functionName, sampleRate, retentionMinutes, preserveErrors, spanData) {
|
|
22
|
+
if (existingContext?.traceId) {
|
|
23
|
+
const spanId = await ctx.runMutation(component.lib.createSpan, {
|
|
24
|
+
traceId: existingContext.traceId,
|
|
25
|
+
span: {
|
|
26
|
+
parentSpanId: existingContext.spanId,
|
|
27
|
+
spanName: functionName,
|
|
28
|
+
source: "backend",
|
|
29
|
+
startTime,
|
|
30
|
+
status: "pending",
|
|
31
|
+
functionName: spanData.functionName,
|
|
32
|
+
args: spanData.args,
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
return {
|
|
36
|
+
traceId: existingContext.traceId,
|
|
37
|
+
spanId,
|
|
38
|
+
traceContext: {
|
|
39
|
+
traceId: existingContext.traceId,
|
|
40
|
+
spanId,
|
|
41
|
+
sampleRate: existingContext.sampleRate,
|
|
42
|
+
retentionMinutes: existingContext.retentionMinutes,
|
|
43
|
+
preserveErrors: existingContext.preserveErrors,
|
|
44
|
+
},
|
|
45
|
+
isRoot: false,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const traceId = await ctx.runMutation(component.lib.createTrace, {
|
|
49
|
+
status: "pending",
|
|
50
|
+
sampleRate,
|
|
51
|
+
metadata: {},
|
|
52
|
+
source: "backend",
|
|
53
|
+
});
|
|
54
|
+
const spanId = await ctx.runMutation(component.lib.createSpan, {
|
|
55
|
+
traceId,
|
|
56
|
+
span: {
|
|
57
|
+
spanName: functionName,
|
|
58
|
+
source: "backend",
|
|
59
|
+
startTime: Date.now(),
|
|
60
|
+
status: "pending",
|
|
61
|
+
functionName: spanData.functionName,
|
|
62
|
+
args: spanData.args,
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
return {
|
|
66
|
+
traceId,
|
|
67
|
+
spanId,
|
|
68
|
+
traceContext: {
|
|
69
|
+
traceId,
|
|
70
|
+
spanId,
|
|
71
|
+
sampleRate,
|
|
72
|
+
retentionMinutes,
|
|
73
|
+
preserveErrors,
|
|
74
|
+
},
|
|
75
|
+
isRoot: true,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export async function executeTracedHandler(params) {
|
|
79
|
+
const { ctx, component, traceId, spanId, startTime, config, args, handler, enhancedCtx, isRoot, } = params;
|
|
80
|
+
const defaultConfig = enhancedCtx.tracer
|
|
81
|
+
.config;
|
|
82
|
+
try {
|
|
83
|
+
// Reject any functions that pass a traceId that doesn't exist
|
|
84
|
+
// These params can be passed from the frontend to break tracing
|
|
85
|
+
// Running a tracedFunction without passing ids will create a new trace
|
|
86
|
+
if (traceId) {
|
|
87
|
+
const traceExists = await ctx.runQuery(component.lib.verifyTrace, {
|
|
88
|
+
traceId,
|
|
89
|
+
});
|
|
90
|
+
if (!traceExists)
|
|
91
|
+
throw new Error("Cannot pass a traceId for a trace that doesn't exist");
|
|
92
|
+
}
|
|
93
|
+
// Reject any functions that pass a spanId that doesn't exist
|
|
94
|
+
// These params can be passed from the frontend to break tracing
|
|
95
|
+
if (spanId) {
|
|
96
|
+
const spanExists = await ctx.runQuery(component.lib.verifySpan, {
|
|
97
|
+
spanId,
|
|
98
|
+
});
|
|
99
|
+
if (!spanExists)
|
|
100
|
+
throw new Error("Cannot pass a spanId for a span that doesn't exist");
|
|
101
|
+
}
|
|
102
|
+
if (config.onStart) {
|
|
103
|
+
await config.onStart(enhancedCtx, args);
|
|
104
|
+
}
|
|
105
|
+
const result = await handler(enhancedCtx, args);
|
|
106
|
+
if (config.onSuccess) {
|
|
107
|
+
await config.onSuccess(enhancedCtx, args, result);
|
|
108
|
+
}
|
|
109
|
+
const now = Date.now();
|
|
110
|
+
await ctx
|
|
111
|
+
.runMutation(component.lib.completeSpan, {
|
|
112
|
+
spanId,
|
|
113
|
+
endTime: now,
|
|
114
|
+
duration: now - startTime,
|
|
115
|
+
status: "success",
|
|
116
|
+
result: config.logReturn ? result : undefined,
|
|
117
|
+
})
|
|
118
|
+
.catch((err) => console.error("[Tracer] Failed to complete span with success:", err));
|
|
119
|
+
if (isRoot) {
|
|
120
|
+
await ctx
|
|
121
|
+
.runMutation(component.lib.updateTraceStatus, {
|
|
122
|
+
traceId,
|
|
123
|
+
status: "success",
|
|
124
|
+
})
|
|
125
|
+
.catch((err) => console.error("[Tracer] Failed to update trace status:", err));
|
|
126
|
+
}
|
|
127
|
+
return { success: true, data: result, error: undefined };
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
const error = e;
|
|
131
|
+
if (config.onError) {
|
|
132
|
+
await config.onError(enhancedCtx, args, error);
|
|
133
|
+
}
|
|
134
|
+
const preserveErrors = config.preserveErrors ?? defaultConfig.preserveErrors;
|
|
135
|
+
if (preserveErrors) {
|
|
136
|
+
const tracerAPI = new TracerAPI(ctx, component, traceId, spanId, config);
|
|
137
|
+
await tracerAPI.preserve();
|
|
138
|
+
}
|
|
139
|
+
await ctx
|
|
140
|
+
.runMutation(component.lib.completeSpan, {
|
|
141
|
+
spanId,
|
|
142
|
+
endTime: Date.now(),
|
|
143
|
+
duration: Date.now() - startTime,
|
|
144
|
+
status: "error",
|
|
145
|
+
error: error.message,
|
|
146
|
+
})
|
|
147
|
+
.catch((err) => console.error("[Tracer] Failed to complete span with error:", err));
|
|
148
|
+
if (isRoot) {
|
|
149
|
+
await ctx
|
|
150
|
+
.runMutation(component.lib.updateTraceStatus, {
|
|
151
|
+
traceId,
|
|
152
|
+
status: "error",
|
|
153
|
+
})
|
|
154
|
+
.catch((err) => console.error("[Tracer] Failed to update trace status:", err));
|
|
155
|
+
}
|
|
156
|
+
return { success: false, data: undefined, error: error.message };
|
|
157
|
+
}
|
|
158
|
+
finally {
|
|
159
|
+
const retMins = config.retentionMinutes ?? defaultConfig.retentionMinutes;
|
|
160
|
+
if (!retMins) {
|
|
161
|
+
console.error("[Tracer] retentionMinutes is not defined");
|
|
162
|
+
}
|
|
163
|
+
const sampleRate = config.sampleRate ?? defaultConfig.sampleRate;
|
|
164
|
+
if (!sampleRate) {
|
|
165
|
+
console.error("[Tracer] sampleRate is not defined");
|
|
166
|
+
}
|
|
167
|
+
else if (sampleRate && sampleRate < 1) {
|
|
168
|
+
const MINUTE = 60 * 1000;
|
|
169
|
+
const delayMins = retMins ?? 120;
|
|
170
|
+
const delay = delayMins * MINUTE;
|
|
171
|
+
await ctx.scheduler.runAfter(delay, component.lib.cleanupTrace, {
|
|
172
|
+
traceId,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/client/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { type GenericDataModel, type RegisteredAction, type RegisteredMutation } from "convex/server";
|
|
2
|
+
import type { Infer, PropertyValidators } from "convex/values";
|
|
3
|
+
import type { ComponentApi } from "../component/_generated/component";
|
|
4
|
+
import { statusValidator } from "../component/schema";
|
|
5
|
+
import type { CompleteTrace, Trace } from "../component/types";
|
|
6
|
+
import type { EmptyObject } from "../react/types";
|
|
7
|
+
import type { ActionCtxWithTracer, ExtractOutput, GenericFunctionContext, MutationCtxWithTracer, QueryCtxWithTracer, TracedFunctionConfig, TracedResult, TracerArgs, TracerConfig, TracerHandler } from "./types";
|
|
8
|
+
export * from "../component/types";
|
|
9
|
+
/**
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { components } from "./_generated/api";
|
|
13
|
+
* import { mutation, action } from "./_generated/server";
|
|
14
|
+
* import { Tracer } from "@convex-dev/tracer";
|
|
15
|
+
*
|
|
16
|
+
* export const { tracedQuery, tracedMutation, tracedAction } = new Tracer(components.tracer, {
|
|
17
|
+
* sampleRate: 0.1,
|
|
18
|
+
* preserveErrors: true,
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* export const createPost = tracedMutation({
|
|
22
|
+
* name: "createPost",
|
|
23
|
+
* args: { title: v.string() },
|
|
24
|
+
* handler: async (ctx, args) => {
|
|
25
|
+
* await ctx.tracer.info("Creating post");
|
|
26
|
+
* return await ctx.db.insert("posts", args);
|
|
27
|
+
* },
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare class Tracer<DataModel extends GenericDataModel> {
|
|
32
|
+
readonly component: ComponentApi;
|
|
33
|
+
readonly sampleRate: number;
|
|
34
|
+
readonly preserveErrors: boolean;
|
|
35
|
+
readonly retentionMinutes: number;
|
|
36
|
+
constructor(component: ComponentApi, config?: TracerConfig);
|
|
37
|
+
private createRunTracedFunction;
|
|
38
|
+
private createRestrictedQueryContext;
|
|
39
|
+
private createEnhancedContext;
|
|
40
|
+
private createTracedHandler;
|
|
41
|
+
/**
|
|
42
|
+
* Creates a traced query (runs as mutation internally).
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* export const getUser = tracedQuery({
|
|
46
|
+
* name: "getUser",
|
|
47
|
+
* args: { userId: v.id("users") },
|
|
48
|
+
* onSuccess: async (ctx, args, result) => {
|
|
49
|
+
* await ctx.tracer.info("Succeeded user fetch", { userId: args.userId });
|
|
50
|
+
* },
|
|
51
|
+
* handler: async (ctx, args) => {
|
|
52
|
+
* await ctx.tracer.info("fetching user", { title: args.userId });
|
|
53
|
+
* const user = await ctx.db.get(args.userId);
|
|
54
|
+
* await ctx.tracer.info("user fetched", { userId: args.userId });
|
|
55
|
+
* return user;
|
|
56
|
+
* },
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
tracedQuery: <Ctx extends QueryCtxWithTracer<DataModel>, Args extends PropertyValidators | EmptyObject, Handler extends TracerHandler<Ctx, Args>, Output extends ExtractOutput<Handler>>(tConfig: TracedFunctionConfig<Ctx, Args, Handler, Output>) => RegisteredMutation<"public", TracerArgs<Args>, TracedResult<ExtractOutput<Handler>>>;
|
|
61
|
+
/**
|
|
62
|
+
* Creates a traced query (runs as mutation internally).
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* export const getUser = internalTracedQuery({
|
|
66
|
+
* name: "getUser",
|
|
67
|
+
* args: { userId: v.id("users") },
|
|
68
|
+
* onSuccess: async (ctx, args, result) => {
|
|
69
|
+
* await ctx.tracer.info("Succeeded user fetch", { userId: args.userId });
|
|
70
|
+
* },
|
|
71
|
+
* handler: async (ctx, args) => {
|
|
72
|
+
* await ctx.tracer.info("fetching user", { title: args.userId });
|
|
73
|
+
* const user = await ctx.db.get(args.userId);
|
|
74
|
+
* await ctx.tracer.info("user fetched", { userId: args.userId });
|
|
75
|
+
* return user;
|
|
76
|
+
* },
|
|
77
|
+
* });
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
internalTracedQuery: <Ctx extends QueryCtxWithTracer<DataModel>, Args extends PropertyValidators | EmptyObject, Handler extends TracerHandler<Ctx, Args>, Output extends ExtractOutput<Handler>>(tConfig: TracedFunctionConfig<Ctx, Args, Handler, Output>) => RegisteredMutation<"internal", TracerArgs<Args>, TracedResult<ExtractOutput<Handler>>>;
|
|
81
|
+
/**
|
|
82
|
+
* Creates a traced mutation.
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* export const createUser = tracedMutation({
|
|
86
|
+
* name: "createUser",
|
|
87
|
+
* args: { user: v.object({ name: v.string(), email: v.string() }) },
|
|
88
|
+
* handler: async (ctx, args) => {
|
|
89
|
+
* const existing = await ctx.db
|
|
90
|
+
* .query("users")
|
|
91
|
+
* .withIndex("by_email", (q) => q.eq("email", args.user.email))
|
|
92
|
+
* .first();
|
|
93
|
+
*
|
|
94
|
+
* if (existing) {
|
|
95
|
+
* ctx.tracer.info("User already exists", { user: args.user });
|
|
96
|
+
* return existing._id;
|
|
97
|
+
* }
|
|
98
|
+
*
|
|
99
|
+
* ctx.tracer.info("Adding user", { ...args.user });
|
|
100
|
+
*
|
|
101
|
+
* const userId = await ctx.db.insert("users", { ...args.user });
|
|
102
|
+
* ctx.tracer.info("User added", { userId });
|
|
103
|
+
*
|
|
104
|
+
* await ctx.tracer.withSpan("syncUser", async (span) => {
|
|
105
|
+
* span.info("Syncing user");
|
|
106
|
+
* // do something
|
|
107
|
+
* span.info("User synced");
|
|
108
|
+
* });
|
|
109
|
+
*
|
|
110
|
+
* return userId;
|
|
111
|
+
* },
|
|
112
|
+
* });
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
tracedMutation: <Ctx extends MutationCtxWithTracer<DataModel>, Args extends PropertyValidators | EmptyObject, Handler extends TracerHandler<Ctx, Args>, Output extends ExtractOutput<Handler>>(tConfig: TracedFunctionConfig<Ctx, Args, Handler, Output>) => RegisteredMutation<"public", TracerArgs<Args>, TracedResult<ExtractOutput<Handler>>>;
|
|
116
|
+
/**
|
|
117
|
+
* Creates a traced mutation.
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* export const createUser = internalTracedMutation({
|
|
121
|
+
* name: "createUser",
|
|
122
|
+
* args: { user: v.object({ name: v.string(), email: v.string() }) },
|
|
123
|
+
* handler: async (ctx, args) => {
|
|
124
|
+
* const existing = await ctx.db
|
|
125
|
+
* .query("users")
|
|
126
|
+
* .withIndex("by_email", (q) => q.eq("email", args.user.email))
|
|
127
|
+
* .first();
|
|
128
|
+
*
|
|
129
|
+
* if (existing) {
|
|
130
|
+
* await ctx.tracer.info("User already exists", { user: args.user });
|
|
131
|
+
* return existing._id;
|
|
132
|
+
* }
|
|
133
|
+
*
|
|
134
|
+
* await ctx.tracer.info("Adding user", { ...args.user });
|
|
135
|
+
*
|
|
136
|
+
* const userId = await ctx.db.insert("users", { ...args.user });
|
|
137
|
+
* ctx.tracer.info("User added", { userId });
|
|
138
|
+
*
|
|
139
|
+
* await ctx.tracer.withSpan("syncUser", async (span) => {
|
|
140
|
+
* await span.info("Syncing user");
|
|
141
|
+
* // do something
|
|
142
|
+
* await span.info("User synced");
|
|
143
|
+
* });
|
|
144
|
+
*
|
|
145
|
+
* return userId;
|
|
146
|
+
* },
|
|
147
|
+
* });
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
internalTracedMutation: <Ctx extends MutationCtxWithTracer<DataModel>, Args extends PropertyValidators | EmptyObject, Handler extends TracerHandler<Ctx, Args>, Output extends ExtractOutput<Handler>>(tConfig: TracedFunctionConfig<Ctx, Args, Handler, Output>) => RegisteredMutation<"internal", TracerArgs<Args>, TracedResult<ExtractOutput<Handler>>>;
|
|
151
|
+
/**
|
|
152
|
+
* Creates a traced action.
|
|
153
|
+
* @example
|
|
154
|
+
* ```ts
|
|
155
|
+
* export const someAction = tracedAction({
|
|
156
|
+
* name: "someAction",
|
|
157
|
+
* args: { userId: v.id("users") },
|
|
158
|
+
* handler: async (ctx, args) => {
|
|
159
|
+
* // do something
|
|
160
|
+
* },
|
|
161
|
+
* });
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
tracedAction: <Ctx extends ActionCtxWithTracer<DataModel>, Args extends PropertyValidators | EmptyObject, Handler extends TracerHandler<Ctx, Args>, Output extends ExtractOutput<Handler>>(tConfig: TracedFunctionConfig<Ctx, Args, Handler, Output>) => RegisteredAction<"public", TracerArgs<Args>, TracedResult<Output>>;
|
|
165
|
+
/**
|
|
166
|
+
* Creates a traced action.
|
|
167
|
+
* @example
|
|
168
|
+
* ```ts
|
|
169
|
+
* export const someAction = internalTracedAction({
|
|
170
|
+
* name: "someAction",
|
|
171
|
+
* args: { userId: v.id("users") },
|
|
172
|
+
* handler: async (ctx, args) => {
|
|
173
|
+
* // do something
|
|
174
|
+
* },
|
|
175
|
+
* });
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
internalTracedAction: <Ctx extends ActionCtxWithTracer<DataModel>, Args extends PropertyValidators | EmptyObject, Handler extends TracerHandler<Ctx, Args>, Output extends ExtractOutput<Handler>>(tConfig: TracedFunctionConfig<Ctx, Args, Handler, Output>) => RegisteredAction<"internal", TracerArgs<Args>, TracedResult<Output>>;
|
|
179
|
+
get tracer(): {
|
|
180
|
+
/**
|
|
181
|
+
* Retrieves a trace by its ID.
|
|
182
|
+
* @param traceId - The ID of the trace to retrieve.
|
|
183
|
+
* @example
|
|
184
|
+
* ```ts
|
|
185
|
+
* // In a convex function (query, mutation, or action)
|
|
186
|
+
* // Or in a traced function
|
|
187
|
+
* const trace = await tracer.getTrace("123")
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
getTrace: (ctx: GenericFunctionContext<DataModel>, traceId: string) => Promise<CompleteTrace | null>;
|
|
191
|
+
/**
|
|
192
|
+
* Lists traces with optional filtering by status.
|
|
193
|
+
* @param status - The status of the traces to retrieve.
|
|
194
|
+
* @param limit - The maximum number of traces to retrieve.
|
|
195
|
+
* @param userId - The ID of the user to retrieve traces for.
|
|
196
|
+
* @example
|
|
197
|
+
* ```ts
|
|
198
|
+
* // In a convex function (query, mutation, or action)
|
|
199
|
+
* // Or in a traced function
|
|
200
|
+
* const traces = await tracer.listTraces({ status: "success", limit: 10 })
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
listTraces: (ctx: GenericFunctionContext<DataModel>, args?: {
|
|
204
|
+
status?: Infer<typeof statusValidator>;
|
|
205
|
+
limit?: number;
|
|
206
|
+
userId?: string;
|
|
207
|
+
}) => Promise<Trace[]>;
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,gBAAgB,EAKrB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAE/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAQlD,OAAO,KAAK,EACV,mBAAmB,EAEnB,aAAa,EACb,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAElB,oBAAoB,EAGpB,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,aAAa,EACd,MAAM,SAAS,CAAC;AAEjB,cAAc,oBAAoB,CAAC;AAkBnC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,MAAM,CAAC,SAAS,SAAS,gBAAgB;aAMlC,SAAS,EAAE,YAAY;IALzC,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,cAAc,EAAE,OAAO,CAAC;IACxC,SAAgB,gBAAgB,EAAE,MAAM,CAAC;gBAGvB,SAAS,EAAE,YAAY,EACvC,MAAM,GAAE,YAAiB;IAS3B,OAAO,CAAC,uBAAuB;IA0B/B,OAAO,CAAC,4BAA4B;IAsCpC,OAAO,CAAC,qBAAqB;IAyD7B,OAAO,CAAC,mBAAmB;IAwD3B;;;;;;;;;;;;;;;;;;OAkBG;IACH,WAAW,GACT,GAAG,SAAS,kBAAkB,CAAC,SAAS,CAAC,EACzC,IAAI,SAAS,kBAAkB,GAAG,WAAW,EAC7C,OAAO,SAAS,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,EACxC,MAAM,SAAS,aAAa,CAAC,OAAO,CAAC,EAErC,SAAS,oBAAoB,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,KACxD,kBAAkB,CACnB,QAAQ,EACR,UAAU,CAAC,IAAI,CAAC,EAChB,YAAY,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CACrC,CAYC;IAEF;;;;;;;;;;;;;;;;;;OAkBG;IACH,mBAAmB,GACjB,GAAG,SAAS,kBAAkB,CAAC,SAAS,CAAC,EACzC,IAAI,SAAS,kBAAkB,GAAG,WAAW,EAC7C,OAAO,SAAS,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,EACxC,MAAM,SAAS,aAAa,CAAC,OAAO,CAAC,EAErC,SAAS,oBAAoB,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,KACxD,kBAAkB,CACnB,UAAU,EACV,UAAU,CAAC,IAAI,CAAC,EAChB,YAAY,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CACrC,CAYC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACH,cAAc,GACZ,GAAG,SAAS,qBAAqB,CAAC,SAAS,CAAC,EAC5C,IAAI,SAAS,kBAAkB,GAAG,WAAW,EAC7C,OAAO,SAAS,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,EACxC,MAAM,SAAS,aAAa,CAAC,OAAO,CAAC,EAErC,SAAS,oBAAoB,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,KACxD,kBAAkB,CACnB,QAAQ,EACR,UAAU,CAAC,IAAI,CAAC,EAChB,YAAY,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CACrC,CAYC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACH,sBAAsB,GACpB,GAAG,SAAS,qBAAqB,CAAC,SAAS,CAAC,EAC5C,IAAI,SAAS,kBAAkB,GAAG,WAAW,EAC7C,OAAO,SAAS,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,EACxC,MAAM,SAAS,aAAa,CAAC,OAAO,CAAC,EAErC,SAAS,oBAAoB,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,KACxD,kBAAkB,CACnB,UAAU,EACV,UAAU,CAAC,IAAI,CAAC,EAChB,YAAY,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CACrC,CAYC;IAEF;;;;;;;;;;;;OAYG;IACH,YAAY,GACV,GAAG,SAAS,mBAAmB,CAAC,SAAS,CAAC,EAC1C,IAAI,SAAS,kBAAkB,GAAG,WAAW,EAC7C,OAAO,SAAS,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,EACxC,MAAM,SAAS,aAAa,CAAC,OAAO,CAAC,EAErC,SAAS,oBAAoB,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,KACxD,gBAAgB,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,CAYnE;IAEF;;;;;;;;;;;;OAYG;IACH,oBAAoB,GAClB,GAAG,SAAS,mBAAmB,CAAC,SAAS,CAAC,EAC1C,IAAI,SAAS,kBAAkB,GAAG,WAAW,EAC7C,OAAO,SAAS,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,EACxC,MAAM,SAAS,aAAa,CAAC,OAAO,CAAC,EAErC,SAAS,oBAAoB,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,KACxD,gBAAgB,CAAC,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,CAYrE;IAEF,IAAI,MAAM;QAEN;;;;;;;;;WASG;wBAEI,sBAAsB,CAAC,SAAS,CAAC,WAC7B,MAAM,KACd,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;QAIhC;;;;;;;;;;;WAWG;0BAEI,sBAAsB,CAAC,SAAS,CAAC,SAC/B;YACL,MAAM,CAAC,EAAE,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;YACvC,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,MAAM,CAAC,EAAE,MAAM,CAAC;SACjB,KACA,OAAO,CAAC,KAAK,EAAE,CAAC;MAItB;CACF"}
|