convex-tracer 0.1.0 → 0.1.1
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/client/helpers.d.ts.map +1 -1
- package/dist/client/index.d.ts +24 -4
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +18 -1
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/component.d.ts +55 -10
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/lib.d.ts +58 -25
- package/dist/component/lib.d.ts.map +1 -1
- package/dist/component/lib.js +60 -21
- package/dist/component/lib.js.map +1 -1
- package/dist/component/schema.d.ts +25 -18
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +6 -1
- package/dist/component/schema.js.map +1 -1
- package/dist/component/types.d.ts +138 -80
- package/dist/component/types.d.ts.map +1 -1
- package/dist/component/types.js +2 -0
- package/dist/component/types.js.map +1 -1
- package/package.json +1 -1
- package/src/client/helpers.ts +11 -1
- package/src/client/index.ts +42 -9
- package/src/component/_generated/component.ts +61 -10
- package/src/component/lib.ts +72 -28
- package/src/component/schema.ts +6 -1
- package/src/component/types.ts +4 -0
- package/dist/client/_generated/_ignore.d.ts +0 -1
- package/dist/client/_generated/_ignore.d.ts.map +0 -1
- package/dist/client/_generated/_ignore.js +0 -3
- package/dist/client/_generated/_ignore.js.map +0 -1
- package/dist/client/helpers.d.ts +0 -31
- package/dist/client/helpers.js +0 -177
- package/dist/client/helpers.js.map +0 -1
- package/dist/client/tracer-api/index.d.ts +0 -27
- package/dist/client/tracer-api/index.js +0 -177
- package/dist/client/tracer-api/index.js.map +0 -1
- package/dist/client/tracer-api/types.d.ts +0 -143
- package/dist/client/tracer-api/types.js +0 -2
- package/dist/client/tracer-api/types.js.map +0 -1
- package/dist/client/types.d.ts +0 -168
- package/dist/client/types.js +0 -2
- package/dist/client/types.js.map +0 -1
- package/dist/component/_generated/api.d.ts +0 -36
- package/dist/component/_generated/api.js +0 -31
- package/dist/component/_generated/api.js.map +0 -1
- package/dist/component/_generated/dataModel.d.ts +0 -46
- package/dist/component/_generated/dataModel.js +0 -11
- package/dist/component/_generated/dataModel.js.map +0 -1
- package/dist/component/_generated/server.d.ts +0 -121
- package/dist/component/_generated/server.js +0 -78
- package/dist/component/_generated/server.js.map +0 -1
- package/dist/component/convex.config.d.ts +0 -3
- package/dist/component/convex.config.d.ts.map +0 -1
- package/dist/component/convex.config.js +0 -3
- package/dist/component/convex.config.js.map +0 -1
- package/dist/react/index.d.ts +0 -6
- package/dist/react/index.js +0 -11
- package/dist/react/index.js.map +0 -1
- package/dist/react/types.d.ts +0 -8
- package/dist/react/types.js +0 -2
- package/dist/react/types.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/component/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAc,MAAM,eAAe,CAAC;AAC9C,OAAO,MAAM,MAAM,UAAU,CAAC;AAE9B,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;IAC1D,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;CAC1B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS;KAC/C,IAAI,CAAC,cAAc,CAAC;KACpB,IAAI,CAAC,SAAS,CAAC;KACf,MAAM,CAAC;IACN,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,YAAY,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACpC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;CAC1B,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;IACrE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;CAC1B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;CACvC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC;IAC1C,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC;CAC9B,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/component/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,CAAC,EAAc,MAAM,eAAe,CAAC;AAC9C,OAAO,MAAM,MAAM,UAAU,CAAC;AAE9B,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;IAC1D,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;CAC1B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC;AAElE,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS;KAC/C,IAAI,CAAC,cAAc,CAAC;KACpB,IAAI,CAAC,SAAS,CAAC;KACf,MAAM,CAAC;IACN,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,YAAY,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACpC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;CAC1B,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;IACrE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;CAC1B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;CACvC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC;IAC1C,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC;CAC9B,CAAC,CAAC"}
|
package/package.json
CHANGED
package/src/client/helpers.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { GenericDataModel } from "convex/server";
|
|
1
|
+
import type { Auth, GenericDataModel } from "convex/server";
|
|
2
2
|
import type { ObjectType, PropertyValidators } from "convex/values";
|
|
3
3
|
import type { ComponentApi } from "../component/_generated/component";
|
|
4
4
|
import TracerAPI from "./tracer-api/index";
|
|
@@ -25,6 +25,14 @@ function pick<T extends Record<string, any>, Keys extends (keyof T)[]>(
|
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
async function getAuthUserId(ctx: { auth: Auth }) {
|
|
29
|
+
const identity = await ctx.auth.getUserIdentity();
|
|
30
|
+
if (identity === null) return "anonymous";
|
|
31
|
+
|
|
32
|
+
const [userId] = identity.subject.split("|");
|
|
33
|
+
return userId;
|
|
34
|
+
}
|
|
35
|
+
|
|
28
36
|
export function extractTraceContext<Args extends Record<string, unknown>>(
|
|
29
37
|
allArgs: ArgsWithTraceContext<Args>,
|
|
30
38
|
): { existingContext?: TraceContext; args: Args } {
|
|
@@ -90,11 +98,13 @@ export async function setupTraceContext(
|
|
|
90
98
|
};
|
|
91
99
|
}
|
|
92
100
|
|
|
101
|
+
const userId = await getAuthUserId(ctx);
|
|
93
102
|
const traceId = await ctx.runMutation(component.lib.createTrace, {
|
|
94
103
|
status: "pending",
|
|
95
104
|
sampleRate,
|
|
96
105
|
metadata: {},
|
|
97
106
|
source: "backend",
|
|
107
|
+
userId,
|
|
98
108
|
});
|
|
99
109
|
|
|
100
110
|
const spanId = await ctx.runMutation(component.lib.createSpan, {
|
package/src/client/index.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
FunctionType,
|
|
3
|
+
GenericQueryCtx,
|
|
4
|
+
paginationOptsValidator,
|
|
5
|
+
} from "convex/server";
|
|
2
6
|
import {
|
|
3
7
|
actionGeneric,
|
|
4
|
-
type GenericActionCtx,
|
|
5
|
-
type GenericDataModel,
|
|
6
|
-
type GenericMutationCtx,
|
|
7
8
|
internalActionGeneric,
|
|
8
9
|
internalMutationGeneric,
|
|
9
10
|
mutationGeneric,
|
|
11
|
+
type GenericActionCtx,
|
|
12
|
+
type GenericDataModel,
|
|
13
|
+
type GenericMutationCtx,
|
|
10
14
|
type RegisteredAction,
|
|
11
15
|
type RegisteredMutation,
|
|
12
16
|
} from "convex/server";
|
|
@@ -14,7 +18,7 @@ import type { Infer, PropertyValidators } from "convex/values";
|
|
|
14
18
|
import { v } from "convex/values";
|
|
15
19
|
import type { ComponentApi } from "../component/_generated/component";
|
|
16
20
|
import { statusValidator } from "../component/schema";
|
|
17
|
-
import type
|
|
21
|
+
import { type CompleteTrace, type paginatedTraces } from "../component/types";
|
|
18
22
|
import type { EmptyObject } from "../react/types";
|
|
19
23
|
import {
|
|
20
24
|
executeTracedHandler,
|
|
@@ -40,6 +44,11 @@ import type {
|
|
|
40
44
|
TracerHandler,
|
|
41
45
|
} from "./types";
|
|
42
46
|
|
|
47
|
+
export {
|
|
48
|
+
severityValidator,
|
|
49
|
+
sourceValidator,
|
|
50
|
+
statusValidator,
|
|
51
|
+
} from "../component/schema";
|
|
43
52
|
export * from "../component/types";
|
|
44
53
|
|
|
45
54
|
const DEFAULT_CONFIG: Required<TracerConfig> = {
|
|
@@ -571,6 +580,9 @@ export class Tracer<DataModel extends GenericDataModel> {
|
|
|
571
580
|
* @param status - The status of the traces to retrieve.
|
|
572
581
|
* @param limit - The maximum number of traces to retrieve.
|
|
573
582
|
* @param userId - The ID of the user to retrieve traces for.
|
|
583
|
+
* @param paginationOpts - Convex pagination options.
|
|
584
|
+
* @returns A pagination result containing the page of results and a
|
|
585
|
+
* cursor to continue paginating.
|
|
574
586
|
* @example
|
|
575
587
|
* ```ts
|
|
576
588
|
* // In a convex function (query, mutation, or action)
|
|
@@ -580,13 +592,34 @@ export class Tracer<DataModel extends GenericDataModel> {
|
|
|
580
592
|
*/
|
|
581
593
|
listTraces: async (
|
|
582
594
|
ctx: GenericFunctionContext<DataModel>,
|
|
583
|
-
args
|
|
595
|
+
args: {
|
|
584
596
|
status?: Infer<typeof statusValidator>;
|
|
585
|
-
limit?: number;
|
|
586
597
|
userId?: string;
|
|
598
|
+
paginationOpts: Infer<typeof paginationOptsValidator>;
|
|
599
|
+
},
|
|
600
|
+
): Promise<paginatedTraces> => {
|
|
601
|
+
return await ctx.runQuery(this.component.lib.listTraces, args);
|
|
602
|
+
},
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Searches for traces by function name.
|
|
606
|
+
* @param functionName - The name of the function to search for.
|
|
607
|
+
* @param userId - The ID of the user to search for.
|
|
608
|
+
* @param status - The status of the traces to search for.
|
|
609
|
+
* @param paginationOpts - Convex pagination options.
|
|
610
|
+
* @returns A pagination result containing the page of results and a
|
|
611
|
+
* cursor to continue paginating.
|
|
612
|
+
*/
|
|
613
|
+
searchTraces: async (
|
|
614
|
+
ctx: GenericFunctionContext<DataModel>,
|
|
615
|
+
args: {
|
|
616
|
+
functionName: string;
|
|
617
|
+
userId?: string;
|
|
618
|
+
status?: Infer<typeof statusValidator>;
|
|
619
|
+
paginationOpts: Infer<typeof paginationOptsValidator>;
|
|
587
620
|
},
|
|
588
|
-
): Promise<
|
|
589
|
-
return await ctx.runQuery(this.component.lib.
|
|
621
|
+
): Promise<paginatedTraces> => {
|
|
622
|
+
return await ctx.runQuery(this.component.lib.searchTraces, args);
|
|
590
623
|
},
|
|
591
624
|
};
|
|
592
625
|
}
|
|
@@ -86,6 +86,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
86
86
|
sampleRate: number;
|
|
87
87
|
source: "frontend" | "backend";
|
|
88
88
|
status: "pending" | "success" | "error";
|
|
89
|
+
userId: "anonymous" | string;
|
|
89
90
|
},
|
|
90
91
|
string,
|
|
91
92
|
Name
|
|
@@ -97,6 +98,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
97
98
|
null | {
|
|
98
99
|
_creationTime: number;
|
|
99
100
|
_id: string;
|
|
101
|
+
functionName?: string;
|
|
100
102
|
metadata?: Record<string, any>;
|
|
101
103
|
preserve?: boolean;
|
|
102
104
|
sampleRate: number;
|
|
@@ -137,20 +139,69 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
137
139
|
"query",
|
|
138
140
|
"internal",
|
|
139
141
|
{
|
|
140
|
-
|
|
142
|
+
paginationOpts: {
|
|
143
|
+
cursor: string | null;
|
|
144
|
+
endCursor?: string | null;
|
|
145
|
+
id?: number;
|
|
146
|
+
maximumBytesRead?: number;
|
|
147
|
+
maximumRowsRead?: number;
|
|
148
|
+
numItems: number;
|
|
149
|
+
};
|
|
141
150
|
status?: "pending" | "success" | "error";
|
|
142
151
|
userId?: string;
|
|
143
152
|
},
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
153
|
+
{
|
|
154
|
+
continueCursor: string;
|
|
155
|
+
isDone: boolean;
|
|
156
|
+
page: Array<{
|
|
157
|
+
_creationTime: number;
|
|
158
|
+
_id: string;
|
|
159
|
+
functionName?: string;
|
|
160
|
+
metadata?: Record<string, any>;
|
|
161
|
+
preserve?: boolean;
|
|
162
|
+
sampleRate: number;
|
|
163
|
+
status: "pending" | "success" | "error";
|
|
164
|
+
updatedAt: number;
|
|
165
|
+
userId?: string;
|
|
166
|
+
}>;
|
|
167
|
+
pageStatus?: "SplitRecommended" | "SplitRequired" | null;
|
|
168
|
+
splitCursor?: string | null;
|
|
169
|
+
},
|
|
170
|
+
Name
|
|
171
|
+
>;
|
|
172
|
+
searchTraces: FunctionReference<
|
|
173
|
+
"query",
|
|
174
|
+
"internal",
|
|
175
|
+
{
|
|
176
|
+
functionName: string;
|
|
177
|
+
paginationOpts: {
|
|
178
|
+
cursor: string | null;
|
|
179
|
+
endCursor?: string | null;
|
|
180
|
+
id?: number;
|
|
181
|
+
maximumBytesRead?: number;
|
|
182
|
+
maximumRowsRead?: number;
|
|
183
|
+
numItems: number;
|
|
184
|
+
};
|
|
185
|
+
status?: "pending" | "success" | "error";
|
|
152
186
|
userId?: string;
|
|
153
|
-
}
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
continueCursor: string;
|
|
190
|
+
isDone: boolean;
|
|
191
|
+
page: Array<{
|
|
192
|
+
_creationTime: number;
|
|
193
|
+
_id: string;
|
|
194
|
+
functionName?: string;
|
|
195
|
+
metadata?: Record<string, any>;
|
|
196
|
+
preserve?: boolean;
|
|
197
|
+
sampleRate: number;
|
|
198
|
+
status: "pending" | "success" | "error";
|
|
199
|
+
updatedAt: number;
|
|
200
|
+
userId?: string;
|
|
201
|
+
}>;
|
|
202
|
+
pageStatus?: "SplitRecommended" | "SplitRequired" | null;
|
|
203
|
+
splitCursor?: string | null;
|
|
204
|
+
},
|
|
154
205
|
Name
|
|
155
206
|
>;
|
|
156
207
|
updateSpanMetadata: FunctionReference<
|
package/src/component/lib.ts
CHANGED
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
* Internal mutations for managing traces, spans, and logs.
|
|
3
3
|
* These are called automatically by the tracing system to persist data immediately.
|
|
4
4
|
*/
|
|
5
|
+
import { paginationOptsValidator } from "convex/server";
|
|
5
6
|
import { v } from "convex/values";
|
|
6
7
|
import type { Id } from "./_generated/dataModel.js";
|
|
7
8
|
import { mutation, query, type MutationCtx } from "./_generated/server.js";
|
|
8
|
-
import
|
|
9
|
+
import {
|
|
9
10
|
severityValidator,
|
|
10
11
|
sourceValidator,
|
|
11
12
|
statusValidator,
|
|
12
13
|
} from "./schema.js";
|
|
13
|
-
import { vCompleteTrace } from "./types.js";
|
|
14
|
+
import { vCompleteTrace, vPaginatedTraces } from "./types.js";
|
|
14
15
|
|
|
15
16
|
// ============================================================================
|
|
16
17
|
// Trace Operations
|
|
@@ -26,6 +27,7 @@ export const createTrace = mutation({
|
|
|
26
27
|
sampleRate: v.number(),
|
|
27
28
|
metadata: v.optional(v.record(v.string(), v.any())),
|
|
28
29
|
source: sourceValidator,
|
|
30
|
+
userId: v.union(v.literal("anonymous"), v.string()),
|
|
29
31
|
},
|
|
30
32
|
returns: v.id("traces"),
|
|
31
33
|
handler: async (ctx, args): Promise<Id<"traces">> => {
|
|
@@ -34,6 +36,7 @@ export const createTrace = mutation({
|
|
|
34
36
|
sampleRate: args.sampleRate,
|
|
35
37
|
updatedAt: Date.now(),
|
|
36
38
|
metadata: args.metadata,
|
|
39
|
+
userId: args.userId,
|
|
37
40
|
});
|
|
38
41
|
},
|
|
39
42
|
});
|
|
@@ -305,34 +308,75 @@ export const getTrace = query({
|
|
|
305
308
|
export const listTraces = query({
|
|
306
309
|
args: {
|
|
307
310
|
status: v.optional(statusValidator),
|
|
308
|
-
limit: v.optional(v.number()),
|
|
309
311
|
userId: v.optional(v.string()),
|
|
312
|
+
paginationOpts: paginationOptsValidator,
|
|
310
313
|
},
|
|
311
|
-
returns:
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
314
|
+
returns: vPaginatedTraces,
|
|
315
|
+
handler: async (ctx, { status, userId, paginationOpts }) => {
|
|
316
|
+
const query = ctx.db.query("traces");
|
|
317
|
+
|
|
318
|
+
if (status && !userId) {
|
|
319
|
+
return await query
|
|
320
|
+
.withIndex("by_status", (q) => q.eq("status", status))
|
|
321
|
+
.order("desc")
|
|
322
|
+
.paginate(paginationOpts);
|
|
323
|
+
} else if (!status && userId) {
|
|
324
|
+
return await query
|
|
325
|
+
.withIndex("by_userId", (q) => q.eq("userId", userId))
|
|
326
|
+
.order("desc")
|
|
327
|
+
.paginate(paginationOpts);
|
|
328
|
+
} else if (status && userId) {
|
|
329
|
+
return await query
|
|
330
|
+
.withIndex("by_status_and_userId", (q) =>
|
|
331
|
+
q.eq("status", status).eq("userId", userId),
|
|
332
|
+
)
|
|
333
|
+
.order("desc")
|
|
334
|
+
.paginate(paginationOpts);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return await query.order("desc").paginate(paginationOpts);
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
export const searchTraces = query({
|
|
342
|
+
args: {
|
|
343
|
+
functionName: v.string(),
|
|
344
|
+
userId: v.optional(v.string()),
|
|
345
|
+
status: v.optional(statusValidator),
|
|
346
|
+
paginationOpts: paginationOptsValidator,
|
|
347
|
+
},
|
|
348
|
+
returns: vPaginatedTraces,
|
|
349
|
+
handler: async (ctx, { functionName, paginationOpts, userId, status }) => {
|
|
350
|
+
const query = ctx.db.query("traces");
|
|
351
|
+
|
|
352
|
+
if (userId && !status) {
|
|
353
|
+
return await query
|
|
354
|
+
.withSearchIndex("by_function_name", (q) =>
|
|
355
|
+
q.search("functionName", functionName).eq("userId", userId),
|
|
356
|
+
)
|
|
357
|
+
.paginate(paginationOpts);
|
|
358
|
+
} else if (status && !userId) {
|
|
359
|
+
return await query
|
|
360
|
+
.withSearchIndex("by_function_name", (q) =>
|
|
361
|
+
q.search("functionName", functionName).eq("status", status),
|
|
362
|
+
)
|
|
363
|
+
.paginate(paginationOpts);
|
|
364
|
+
} else if (userId && status) {
|
|
365
|
+
return await query
|
|
366
|
+
.withSearchIndex("by_function_name", (q) =>
|
|
367
|
+
q
|
|
368
|
+
.search("functionName", functionName)
|
|
369
|
+
.eq("userId", userId)
|
|
370
|
+
.eq("status", status),
|
|
371
|
+
)
|
|
372
|
+
.paginate(paginationOpts);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return await query
|
|
376
|
+
.withSearchIndex("by_function_name", (q) =>
|
|
377
|
+
q.search("functionName", functionName),
|
|
378
|
+
)
|
|
379
|
+
.paginate(paginationOpts);
|
|
336
380
|
},
|
|
337
381
|
});
|
|
338
382
|
|
package/src/component/schema.ts
CHANGED
|
@@ -25,11 +25,16 @@ export default defineSchema({
|
|
|
25
25
|
preserve: v.optional(v.boolean()),
|
|
26
26
|
updatedAt: v.number(),
|
|
27
27
|
metadata: v.optional(v.record(v.string(), v.any())),
|
|
28
|
+
functionName: v.optional(v.string()),
|
|
28
29
|
userId: v.optional(v.string()),
|
|
29
30
|
})
|
|
30
31
|
.index("by_status", ["status"])
|
|
31
32
|
.index("by_userId", ["userId"])
|
|
32
|
-
.index("by_status_and_userId", ["status", "userId"])
|
|
33
|
+
.index("by_status_and_userId", ["status", "userId"])
|
|
34
|
+
.searchIndex("by_function_name", {
|
|
35
|
+
searchField: "functionName",
|
|
36
|
+
filterFields: ["status", "userId"],
|
|
37
|
+
}),
|
|
33
38
|
|
|
34
39
|
spans: defineTable({
|
|
35
40
|
traceId: v.id("traces"),
|
package/src/component/types.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { paginationResultValidator } from "convex/server";
|
|
1
2
|
import { v, type Infer } from "convex/values";
|
|
2
3
|
import schema from "./schema";
|
|
3
4
|
|
|
@@ -6,6 +7,8 @@ export const vTrace = schema.tables.traces.validator.extend({
|
|
|
6
7
|
_creationTime: v.number(),
|
|
7
8
|
});
|
|
8
9
|
|
|
10
|
+
export const vPaginatedTraces = paginationResultValidator(vTrace);
|
|
11
|
+
|
|
9
12
|
export const vSpan = schema.tables.spans.validator
|
|
10
13
|
.omit("parentSpanId")
|
|
11
14
|
.omit("traceId")
|
|
@@ -36,3 +39,4 @@ export type Span = Infer<typeof vSpan>;
|
|
|
36
39
|
export type Log = Infer<typeof vLog>;
|
|
37
40
|
export type SpanWithLogs = Infer<typeof vSpanWithLogs>;
|
|
38
41
|
export type CompleteTrace = Infer<typeof vCompleteTrace>;
|
|
42
|
+
export type paginatedTraces = Infer<typeof vPaginatedTraces>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=_ignore.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_ignore.d.ts","sourceRoot":"","sources":["../../../src/client/_generated/_ignore.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_ignore.js","sourceRoot":"","sources":["../../../src/client/_generated/_ignore.ts"],"names":[],"mappings":";AAAA,kEAAkE"}
|
package/dist/client/helpers.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { GenericDataModel } from "convex/server";
|
|
2
|
-
import type { ObjectType, PropertyValidators } from "convex/values";
|
|
3
|
-
import type { ComponentApi } from "../component/_generated/component";
|
|
4
|
-
import type { ArgsWithTraceContext, LogArgs, OptionalArgsObject, StrippedGenericFunctionContext, TraceContext, TracedFunctionOptions, TracedResult, TracerConfig, TracerHandler } from "./types";
|
|
5
|
-
export declare function extractTraceContext<Args extends Record<string, unknown>>(allArgs: ArgsWithTraceContext<Args>): {
|
|
6
|
-
existingContext?: TraceContext;
|
|
7
|
-
args: Args;
|
|
8
|
-
};
|
|
9
|
-
export declare function prepareLogArgs<Args extends PropertyValidators>(args: ObjectType<Args>, logArgs: LogArgs<Args>): unknown | undefined;
|
|
10
|
-
export declare function setupTraceContext(ctx: StrippedGenericFunctionContext<GenericDataModel>, component: ComponentApi, existingContext: TraceContext | undefined, startTime: number, functionName: string, sampleRate: number, retentionMinutes: number, preserveErrors: boolean, spanData: {
|
|
11
|
-
functionName?: string;
|
|
12
|
-
args?: unknown;
|
|
13
|
-
}): Promise<{
|
|
14
|
-
traceId: string;
|
|
15
|
-
spanId: string;
|
|
16
|
-
traceContext: TraceContext;
|
|
17
|
-
isRoot: boolean;
|
|
18
|
-
}>;
|
|
19
|
-
export declare function executeTracedHandler<Args extends PropertyValidators, Output, EnhancedCtx>(params: {
|
|
20
|
-
ctx: StrippedGenericFunctionContext<GenericDataModel>;
|
|
21
|
-
component: ComponentApi;
|
|
22
|
-
traceId: string;
|
|
23
|
-
spanId: string;
|
|
24
|
-
startTime: number;
|
|
25
|
-
config: TracedFunctionOptions<EnhancedCtx, Args, Output> & TracerConfig;
|
|
26
|
-
args: OptionalArgsObject<Args>;
|
|
27
|
-
handler: TracerHandler<EnhancedCtx, Args>;
|
|
28
|
-
enhancedCtx: EnhancedCtx;
|
|
29
|
-
isRoot: boolean;
|
|
30
|
-
}): Promise<TracedResult<Output>>;
|
|
31
|
-
//# sourceMappingURL=helpers.d.ts.map
|
package/dist/client/helpers.js
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/client/helpers.ts"],"names":[],"mappings":"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"}
|