@mastra/mssql 0.2.3 → 0.3.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/.turbo/turbo-build.log +2 -21
- package/CHANGELOG.md +28 -1
- package/dist/index.cjs +1568 -1104
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +2 -4
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1568 -1104
- package/dist/index.js.map +1 -0
- package/dist/storage/domains/legacy-evals/index.d.ts +20 -0
- package/dist/storage/domains/legacy-evals/index.d.ts.map +1 -0
- package/dist/storage/domains/memory/index.d.ts +90 -0
- package/dist/storage/domains/memory/index.d.ts.map +1 -0
- package/dist/storage/domains/operations/index.d.ts +51 -0
- package/dist/storage/domains/operations/index.d.ts.map +1 -0
- package/dist/storage/domains/scores/index.d.ts +46 -0
- package/dist/storage/domains/scores/index.d.ts.map +1 -0
- package/dist/storage/domains/traces/index.d.ts +37 -0
- package/dist/storage/domains/traces/index.d.ts.map +1 -0
- package/dist/storage/domains/utils.d.ts +6 -0
- package/dist/storage/domains/utils.d.ts.map +1 -0
- package/dist/storage/domains/workflows/index.d.ts +36 -0
- package/dist/storage/domains/workflows/index.d.ts.map +1 -0
- package/dist/{_tsup-dts-rollup.d.cts → storage/index.d.ts} +81 -117
- package/dist/storage/index.d.ts.map +1 -0
- package/package.json +6 -6
- package/src/storage/domains/legacy-evals/index.ts +175 -0
- package/src/storage/domains/memory/index.ts +1024 -0
- package/src/storage/domains/operations/index.ts +401 -0
- package/src/storage/domains/scores/index.ts +315 -0
- package/src/storage/domains/traces/index.ts +212 -0
- package/src/storage/domains/utils.ts +12 -0
- package/src/storage/domains/workflows/index.ts +259 -0
- package/src/storage/index.ts +147 -1835
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +1 -1
- package/tsup.config.ts +22 -0
- package/dist/_tsup-dts-rollup.d.ts +0 -251
- package/dist/index.d.cts +0 -4
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import type { PaginationInfo, StoragePagination } from '@mastra/core';
|
|
2
|
+
import { ErrorCategory, ErrorDomain, MastraError } from '@mastra/core/error';
|
|
3
|
+
import type { ScoreRowData } from '@mastra/core/scores';
|
|
4
|
+
import { ScoresStorage, TABLE_SCORERS } from '@mastra/core/storage';
|
|
5
|
+
import type { ConnectionPool } from 'mssql';
|
|
6
|
+
import type { StoreOperationsMSSQL } from '../operations';
|
|
7
|
+
import { getSchemaName, getTableName } from '../utils';
|
|
8
|
+
|
|
9
|
+
function parseJSON(jsonString: string): any {
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(jsonString);
|
|
12
|
+
} catch {
|
|
13
|
+
return jsonString;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function transformScoreRow(row: Record<string, any>): ScoreRowData {
|
|
18
|
+
let input = undefined;
|
|
19
|
+
let output = undefined;
|
|
20
|
+
let preprocessStepResult = undefined;
|
|
21
|
+
let analyzeStepResult = undefined;
|
|
22
|
+
|
|
23
|
+
if (row.input) {
|
|
24
|
+
input = parseJSON(row.input);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (row.output) {
|
|
28
|
+
output = parseJSON(row.output);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (row.preprocessStepResult) {
|
|
32
|
+
preprocessStepResult = parseJSON(row.preprocessStepResult);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (row.analyzeStepResult) {
|
|
36
|
+
analyzeStepResult = parseJSON(row.analyzeStepResult);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
...row,
|
|
41
|
+
input,
|
|
42
|
+
output,
|
|
43
|
+
preprocessStepResult,
|
|
44
|
+
analyzeStepResult,
|
|
45
|
+
createdAt: row.createdAt,
|
|
46
|
+
updatedAt: row.updatedAt,
|
|
47
|
+
} as ScoreRowData;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export class ScoresMSSQL extends ScoresStorage {
|
|
51
|
+
public pool: ConnectionPool;
|
|
52
|
+
private operations: StoreOperationsMSSQL;
|
|
53
|
+
private schema?: string;
|
|
54
|
+
|
|
55
|
+
constructor({
|
|
56
|
+
pool,
|
|
57
|
+
operations,
|
|
58
|
+
schema,
|
|
59
|
+
}: {
|
|
60
|
+
pool: ConnectionPool;
|
|
61
|
+
operations: StoreOperationsMSSQL;
|
|
62
|
+
schema?: string;
|
|
63
|
+
}) {
|
|
64
|
+
super();
|
|
65
|
+
this.pool = pool;
|
|
66
|
+
this.operations = operations;
|
|
67
|
+
this.schema = schema;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async getScoreById({ id }: { id: string }): Promise<ScoreRowData | null> {
|
|
71
|
+
try {
|
|
72
|
+
const request = this.pool.request();
|
|
73
|
+
request.input('p1', id);
|
|
74
|
+
const result = await request.query(
|
|
75
|
+
`SELECT * FROM ${getTableName({ indexName: TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE id = @p1`,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
if (result.recordset.length === 0) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return transformScoreRow(result.recordset[0]);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
throw new MastraError(
|
|
85
|
+
{
|
|
86
|
+
id: 'MASTRA_STORAGE_MSSQL_STORE_GET_SCORE_BY_ID_FAILED',
|
|
87
|
+
domain: ErrorDomain.STORAGE,
|
|
88
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
89
|
+
details: { id },
|
|
90
|
+
},
|
|
91
|
+
error,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async saveScore(score: Omit<ScoreRowData, 'id' | 'createdAt' | 'updatedAt'>): Promise<{ score: ScoreRowData }> {
|
|
97
|
+
try {
|
|
98
|
+
// Generate ID like other storage implementations
|
|
99
|
+
const scoreId = crypto.randomUUID();
|
|
100
|
+
|
|
101
|
+
const { input, output, preprocessStepResult, analyzeStepResult, ...rest } = score;
|
|
102
|
+
await this.operations.insert({
|
|
103
|
+
tableName: TABLE_SCORERS,
|
|
104
|
+
record: {
|
|
105
|
+
id: scoreId,
|
|
106
|
+
...rest,
|
|
107
|
+
input: JSON.stringify(input),
|
|
108
|
+
output: JSON.stringify(output),
|
|
109
|
+
preprocessStepResult: preprocessStepResult ? JSON.stringify(preprocessStepResult) : null,
|
|
110
|
+
analyzeStepResult: analyzeStepResult ? JSON.stringify(analyzeStepResult) : null,
|
|
111
|
+
createdAt: new Date().toISOString(),
|
|
112
|
+
updatedAt: new Date().toISOString(),
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const scoreFromDb = await this.getScoreById({ id: scoreId });
|
|
117
|
+
return { score: scoreFromDb! };
|
|
118
|
+
} catch (error) {
|
|
119
|
+
throw new MastraError(
|
|
120
|
+
{
|
|
121
|
+
id: 'MASTRA_STORAGE_MSSQL_STORE_SAVE_SCORE_FAILED',
|
|
122
|
+
domain: ErrorDomain.STORAGE,
|
|
123
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
124
|
+
},
|
|
125
|
+
error,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async getScoresByScorerId({
|
|
131
|
+
scorerId,
|
|
132
|
+
pagination,
|
|
133
|
+
}: {
|
|
134
|
+
scorerId: string;
|
|
135
|
+
pagination: StoragePagination;
|
|
136
|
+
entityId?: string;
|
|
137
|
+
entityType?: string;
|
|
138
|
+
}): Promise<{ pagination: PaginationInfo; scores: ScoreRowData[] }> {
|
|
139
|
+
try {
|
|
140
|
+
const request = this.pool.request();
|
|
141
|
+
request.input('p1', scorerId);
|
|
142
|
+
|
|
143
|
+
const totalResult = await request.query(
|
|
144
|
+
`SELECT COUNT(*) as count FROM ${getTableName({ indexName: TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [scorerId] = @p1`,
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const total = totalResult.recordset[0]?.count || 0;
|
|
148
|
+
|
|
149
|
+
if (total === 0) {
|
|
150
|
+
return {
|
|
151
|
+
pagination: {
|
|
152
|
+
total: 0,
|
|
153
|
+
page: pagination.page,
|
|
154
|
+
perPage: pagination.perPage,
|
|
155
|
+
hasMore: false,
|
|
156
|
+
},
|
|
157
|
+
scores: [],
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const dataRequest = this.pool.request();
|
|
162
|
+
dataRequest.input('p1', scorerId);
|
|
163
|
+
dataRequest.input('p2', pagination.perPage);
|
|
164
|
+
dataRequest.input('p3', pagination.page * pagination.perPage);
|
|
165
|
+
|
|
166
|
+
const result = await dataRequest.query(
|
|
167
|
+
`SELECT * FROM ${getTableName({ indexName: TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [scorerId] = @p1 ORDER BY [createdAt] DESC OFFSET @p3 ROWS FETCH NEXT @p2 ROWS ONLY`,
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
pagination: {
|
|
172
|
+
total: Number(total),
|
|
173
|
+
page: pagination.page,
|
|
174
|
+
perPage: pagination.perPage,
|
|
175
|
+
hasMore: Number(total) > (pagination.page + 1) * pagination.perPage,
|
|
176
|
+
},
|
|
177
|
+
scores: result.recordset.map(row => transformScoreRow(row)),
|
|
178
|
+
};
|
|
179
|
+
} catch (error) {
|
|
180
|
+
throw new MastraError(
|
|
181
|
+
{
|
|
182
|
+
id: 'MASTRA_STORAGE_MSSQL_STORE_GET_SCORES_BY_SCORER_ID_FAILED',
|
|
183
|
+
domain: ErrorDomain.STORAGE,
|
|
184
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
185
|
+
details: { scorerId },
|
|
186
|
+
},
|
|
187
|
+
error,
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async getScoresByRunId({
|
|
193
|
+
runId,
|
|
194
|
+
pagination,
|
|
195
|
+
}: {
|
|
196
|
+
runId: string;
|
|
197
|
+
pagination: StoragePagination;
|
|
198
|
+
}): Promise<{ pagination: PaginationInfo; scores: ScoreRowData[] }> {
|
|
199
|
+
try {
|
|
200
|
+
const request = this.pool.request();
|
|
201
|
+
request.input('p1', runId);
|
|
202
|
+
|
|
203
|
+
const totalResult = await request.query(
|
|
204
|
+
`SELECT COUNT(*) as count FROM ${getTableName({ indexName: TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [runId] = @p1`,
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
const total = totalResult.recordset[0]?.count || 0;
|
|
208
|
+
|
|
209
|
+
if (total === 0) {
|
|
210
|
+
return {
|
|
211
|
+
pagination: {
|
|
212
|
+
total: 0,
|
|
213
|
+
page: pagination.page,
|
|
214
|
+
perPage: pagination.perPage,
|
|
215
|
+
hasMore: false,
|
|
216
|
+
},
|
|
217
|
+
scores: [],
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const dataRequest = this.pool.request();
|
|
222
|
+
dataRequest.input('p1', runId);
|
|
223
|
+
dataRequest.input('p2', pagination.perPage);
|
|
224
|
+
dataRequest.input('p3', pagination.page * pagination.perPage);
|
|
225
|
+
|
|
226
|
+
const result = await dataRequest.query(
|
|
227
|
+
`SELECT * FROM ${getTableName({ indexName: TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [runId] = @p1 ORDER BY [createdAt] DESC OFFSET @p3 ROWS FETCH NEXT @p2 ROWS ONLY`,
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
pagination: {
|
|
232
|
+
total: Number(total),
|
|
233
|
+
page: pagination.page,
|
|
234
|
+
perPage: pagination.perPage,
|
|
235
|
+
hasMore: Number(total) > (pagination.page + 1) * pagination.perPage,
|
|
236
|
+
},
|
|
237
|
+
scores: result.recordset.map(row => transformScoreRow(row)),
|
|
238
|
+
};
|
|
239
|
+
} catch (error) {
|
|
240
|
+
throw new MastraError(
|
|
241
|
+
{
|
|
242
|
+
id: 'MASTRA_STORAGE_MSSQL_STORE_GET_SCORES_BY_RUN_ID_FAILED',
|
|
243
|
+
domain: ErrorDomain.STORAGE,
|
|
244
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
245
|
+
details: { runId },
|
|
246
|
+
},
|
|
247
|
+
error,
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
async getScoresByEntityId({
|
|
253
|
+
entityId,
|
|
254
|
+
entityType,
|
|
255
|
+
pagination,
|
|
256
|
+
}: {
|
|
257
|
+
pagination: StoragePagination;
|
|
258
|
+
entityId: string;
|
|
259
|
+
entityType: string;
|
|
260
|
+
}): Promise<{ pagination: PaginationInfo; scores: ScoreRowData[] }> {
|
|
261
|
+
try {
|
|
262
|
+
const request = this.pool.request();
|
|
263
|
+
request.input('p1', entityId);
|
|
264
|
+
request.input('p2', entityType);
|
|
265
|
+
|
|
266
|
+
const totalResult = await request.query(
|
|
267
|
+
`SELECT COUNT(*) as count FROM ${getTableName({ indexName: TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [entityId] = @p1 AND [entityType] = @p2`,
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
const total = totalResult.recordset[0]?.count || 0;
|
|
271
|
+
|
|
272
|
+
if (total === 0) {
|
|
273
|
+
return {
|
|
274
|
+
pagination: {
|
|
275
|
+
total: 0,
|
|
276
|
+
page: pagination.page,
|
|
277
|
+
perPage: pagination.perPage,
|
|
278
|
+
hasMore: false,
|
|
279
|
+
},
|
|
280
|
+
scores: [],
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const dataRequest = this.pool.request();
|
|
285
|
+
dataRequest.input('p1', entityId);
|
|
286
|
+
dataRequest.input('p2', entityType);
|
|
287
|
+
dataRequest.input('p3', pagination.perPage);
|
|
288
|
+
dataRequest.input('p4', pagination.page * pagination.perPage);
|
|
289
|
+
|
|
290
|
+
const result = await dataRequest.query(
|
|
291
|
+
`SELECT * FROM ${getTableName({ indexName: TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [entityId] = @p1 AND [entityType] = @p2 ORDER BY [createdAt] DESC OFFSET @p4 ROWS FETCH NEXT @p3 ROWS ONLY`,
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
return {
|
|
295
|
+
pagination: {
|
|
296
|
+
total: Number(total),
|
|
297
|
+
page: pagination.page,
|
|
298
|
+
perPage: pagination.perPage,
|
|
299
|
+
hasMore: Number(total) > (pagination.page + 1) * pagination.perPage,
|
|
300
|
+
},
|
|
301
|
+
scores: result.recordset.map(row => transformScoreRow(row)),
|
|
302
|
+
};
|
|
303
|
+
} catch (error) {
|
|
304
|
+
throw new MastraError(
|
|
305
|
+
{
|
|
306
|
+
id: 'MASTRA_STORAGE_MSSQL_STORE_GET_SCORES_BY_ENTITY_ID_FAILED',
|
|
307
|
+
domain: ErrorDomain.STORAGE,
|
|
308
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
309
|
+
details: { entityId, entityType },
|
|
310
|
+
},
|
|
311
|
+
error,
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { ErrorCategory, ErrorDomain, MastraError } from '@mastra/core/error';
|
|
2
|
+
import type { PaginationInfo, PaginationArgs } from '@mastra/core/storage';
|
|
3
|
+
import { TABLE_TRACES, TracesStorage } from '@mastra/core/storage';
|
|
4
|
+
import { parseFieldKey } from '@mastra/core/utils';
|
|
5
|
+
import sql from 'mssql';
|
|
6
|
+
import type { StoreOperationsMSSQL } from '../operations';
|
|
7
|
+
import { getSchemaName, getTableName } from '../utils';
|
|
8
|
+
|
|
9
|
+
export class TracesMSSQL extends TracesStorage {
|
|
10
|
+
public pool: sql.ConnectionPool;
|
|
11
|
+
private operations: StoreOperationsMSSQL;
|
|
12
|
+
private schema?: string;
|
|
13
|
+
|
|
14
|
+
constructor({
|
|
15
|
+
pool,
|
|
16
|
+
operations,
|
|
17
|
+
schema,
|
|
18
|
+
}: {
|
|
19
|
+
pool: sql.ConnectionPool;
|
|
20
|
+
operations: StoreOperationsMSSQL;
|
|
21
|
+
schema?: string;
|
|
22
|
+
}) {
|
|
23
|
+
super();
|
|
24
|
+
this.pool = pool;
|
|
25
|
+
this.operations = operations;
|
|
26
|
+
this.schema = schema;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** @deprecated use getTracesPaginated instead*/
|
|
30
|
+
public async getTraces(args: {
|
|
31
|
+
name?: string;
|
|
32
|
+
scope?: string;
|
|
33
|
+
attributes?: Record<string, string>;
|
|
34
|
+
filters?: Record<string, any>;
|
|
35
|
+
page: number;
|
|
36
|
+
perPage?: number;
|
|
37
|
+
fromDate?: Date;
|
|
38
|
+
toDate?: Date;
|
|
39
|
+
}): Promise<any[]> {
|
|
40
|
+
if (args.fromDate || args.toDate) {
|
|
41
|
+
(args as any).dateRange = {
|
|
42
|
+
start: args.fromDate,
|
|
43
|
+
end: args.toDate,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const result = await this.getTracesPaginated(args);
|
|
47
|
+
return result.traces;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public async getTracesPaginated(
|
|
51
|
+
args: {
|
|
52
|
+
name?: string;
|
|
53
|
+
scope?: string;
|
|
54
|
+
attributes?: Record<string, string>;
|
|
55
|
+
filters?: Record<string, any>;
|
|
56
|
+
} & PaginationArgs,
|
|
57
|
+
): Promise<
|
|
58
|
+
PaginationInfo & {
|
|
59
|
+
traces: any[];
|
|
60
|
+
}
|
|
61
|
+
> {
|
|
62
|
+
const { name, scope, page = 0, perPage: perPageInput, attributes, filters, dateRange } = args;
|
|
63
|
+
const fromDate = dateRange?.start;
|
|
64
|
+
const toDate = dateRange?.end;
|
|
65
|
+
|
|
66
|
+
const perPage = perPageInput !== undefined ? perPageInput : 100;
|
|
67
|
+
const currentOffset = page * perPage;
|
|
68
|
+
|
|
69
|
+
const paramMap: Record<string, any> = {};
|
|
70
|
+
const conditions: string[] = [];
|
|
71
|
+
let paramIndex = 1;
|
|
72
|
+
|
|
73
|
+
if (name) {
|
|
74
|
+
const paramName = `p${paramIndex++}`;
|
|
75
|
+
conditions.push(`[name] LIKE @${paramName}`);
|
|
76
|
+
paramMap[paramName] = `${name}%`;
|
|
77
|
+
}
|
|
78
|
+
if (scope) {
|
|
79
|
+
const paramName = `p${paramIndex++}`;
|
|
80
|
+
conditions.push(`[scope] = @${paramName}`);
|
|
81
|
+
paramMap[paramName] = scope;
|
|
82
|
+
}
|
|
83
|
+
if (attributes) {
|
|
84
|
+
Object.entries(attributes).forEach(([key, value]) => {
|
|
85
|
+
const parsedKey = parseFieldKey(key);
|
|
86
|
+
const paramName = `p${paramIndex++}`;
|
|
87
|
+
conditions.push(`JSON_VALUE([attributes], '$.${parsedKey}') = @${paramName}`);
|
|
88
|
+
paramMap[paramName] = value;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
if (filters) {
|
|
92
|
+
Object.entries(filters).forEach(([key, value]) => {
|
|
93
|
+
const parsedKey = parseFieldKey(key);
|
|
94
|
+
const paramName = `p${paramIndex++}`;
|
|
95
|
+
conditions.push(`[${parsedKey}] = @${paramName}`);
|
|
96
|
+
paramMap[paramName] = value;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
if (fromDate instanceof Date && !isNaN(fromDate.getTime())) {
|
|
100
|
+
const paramName = `p${paramIndex++}`;
|
|
101
|
+
conditions.push(`[createdAt] >= @${paramName}`);
|
|
102
|
+
paramMap[paramName] = fromDate.toISOString();
|
|
103
|
+
}
|
|
104
|
+
if (toDate instanceof Date && !isNaN(toDate.getTime())) {
|
|
105
|
+
const paramName = `p${paramIndex++}`;
|
|
106
|
+
conditions.push(`[createdAt] <= @${paramName}`);
|
|
107
|
+
paramMap[paramName] = toDate.toISOString();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
111
|
+
|
|
112
|
+
const countQuery = `SELECT COUNT(*) as total FROM ${getTableName({ indexName: TABLE_TRACES, schemaName: getSchemaName(this.schema) })} ${whereClause}`;
|
|
113
|
+
let total = 0;
|
|
114
|
+
try {
|
|
115
|
+
const countRequest = this.pool.request();
|
|
116
|
+
Object.entries(paramMap).forEach(([key, value]) => {
|
|
117
|
+
if (value instanceof Date) {
|
|
118
|
+
countRequest.input(key, sql.DateTime, value);
|
|
119
|
+
} else {
|
|
120
|
+
countRequest.input(key, value);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
const countResult = await countRequest.query(countQuery);
|
|
124
|
+
total = parseInt(countResult.recordset[0].total, 10);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
throw new MastraError(
|
|
127
|
+
{
|
|
128
|
+
id: 'MASTRA_STORAGE_MSSQL_STORE_GET_TRACES_PAGINATED_FAILED_TO_RETRIEVE_TOTAL_COUNT',
|
|
129
|
+
domain: ErrorDomain.STORAGE,
|
|
130
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
131
|
+
details: {
|
|
132
|
+
name: args.name ?? '',
|
|
133
|
+
scope: args.scope ?? '',
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
error,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (total === 0) {
|
|
141
|
+
return {
|
|
142
|
+
traces: [],
|
|
143
|
+
total: 0,
|
|
144
|
+
page,
|
|
145
|
+
perPage,
|
|
146
|
+
hasMore: false,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const dataQuery = `SELECT * FROM ${getTableName({ indexName: TABLE_TRACES, schemaName: getSchemaName(this.schema) })} ${whereClause} ORDER BY [seq_id] DESC OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY`;
|
|
151
|
+
const dataRequest = this.pool.request();
|
|
152
|
+
Object.entries(paramMap).forEach(([key, value]) => {
|
|
153
|
+
if (value instanceof Date) {
|
|
154
|
+
dataRequest.input(key, sql.DateTime, value);
|
|
155
|
+
} else {
|
|
156
|
+
dataRequest.input(key, value);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
dataRequest.input('offset', currentOffset);
|
|
160
|
+
dataRequest.input('limit', perPage);
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
const rowsResult = await dataRequest.query(dataQuery);
|
|
164
|
+
const rows = rowsResult.recordset;
|
|
165
|
+
const traces = rows.map(row => ({
|
|
166
|
+
id: row.id,
|
|
167
|
+
parentSpanId: row.parentSpanId,
|
|
168
|
+
traceId: row.traceId,
|
|
169
|
+
name: row.name,
|
|
170
|
+
scope: row.scope,
|
|
171
|
+
kind: row.kind,
|
|
172
|
+
status: JSON.parse(row.status),
|
|
173
|
+
events: JSON.parse(row.events),
|
|
174
|
+
links: JSON.parse(row.links),
|
|
175
|
+
attributes: JSON.parse(row.attributes),
|
|
176
|
+
startTime: row.startTime,
|
|
177
|
+
endTime: row.endTime,
|
|
178
|
+
other: row.other,
|
|
179
|
+
createdAt: row.createdAt,
|
|
180
|
+
}));
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
traces,
|
|
184
|
+
total,
|
|
185
|
+
page,
|
|
186
|
+
perPage,
|
|
187
|
+
hasMore: currentOffset + traces.length < total,
|
|
188
|
+
};
|
|
189
|
+
} catch (error) {
|
|
190
|
+
throw new MastraError(
|
|
191
|
+
{
|
|
192
|
+
id: 'MASTRA_STORAGE_MSSQL_STORE_GET_TRACES_PAGINATED_FAILED_TO_RETRIEVE_TRACES',
|
|
193
|
+
domain: ErrorDomain.STORAGE,
|
|
194
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
195
|
+
details: {
|
|
196
|
+
name: args.name ?? '',
|
|
197
|
+
scope: args.scope ?? '',
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
error,
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async batchTraceInsert({ records }: { records: Record<string, any>[] }): Promise<void> {
|
|
206
|
+
this.logger.debug('Batch inserting traces', { count: records.length });
|
|
207
|
+
await this.operations.batchInsert({
|
|
208
|
+
tableName: TABLE_TRACES,
|
|
209
|
+
records,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { parseSqlIdentifier } from '@mastra/core/utils';
|
|
2
|
+
|
|
3
|
+
export function getSchemaName(schema?: string) {
|
|
4
|
+
return schema ? `[${parseSqlIdentifier(schema, 'schema name')}]` : undefined;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function getTableName({ indexName, schemaName }: { indexName: string; schemaName?: string }) {
|
|
8
|
+
const parsedIndexName = parseSqlIdentifier(indexName, 'index name');
|
|
9
|
+
const quotedIndexName = `[${parsedIndexName}]`;
|
|
10
|
+
const quotedSchemaName = schemaName;
|
|
11
|
+
return quotedSchemaName ? `${quotedSchemaName}.${quotedIndexName}` : quotedIndexName;
|
|
12
|
+
}
|