@llmops/core 0.5.3 → 0.6.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/{bun-sqlite-dialect-DQa87s1D.cjs → bun-sqlite-dialect-DFKD-iqI.cjs} +1 -1
- package/dist/db/index.cjs +5 -2
- package/dist/db/index.d.cts +2 -2
- package/dist/db/index.d.mts +2 -2
- package/dist/db/index.mjs +2 -2
- package/dist/{db-B9jJgYNw.cjs → db-C6ApWDjW.cjs} +310 -6
- package/dist/{db-DX_QaIkx.mjs → db-CQvUnGBp.mjs} +289 -3
- package/dist/{index-LRmy4sz9.d.mts → index-BosemZ_J.d.mts} +676 -1
- package/dist/{index-BtSgIKup.d.cts → index-DdG7GtcE.d.cts} +676 -1
- package/dist/index.cjs +380 -77
- package/dist/index.d.cts +253 -3
- package/dist/index.d.mts +253 -3
- package/dist/index.mjs +369 -77
- package/dist/{neon-dialect-BBGTCnek.cjs → neon-dialect-DNyVaL-1.cjs} +1 -1
- package/dist/{neon-dialect-BBWePgOv.cjs → neon-dialect-SqAJhPFS.cjs} +1 -1
- package/dist/{node-sqlite-dialect-DLKHH0RE.cjs → node-sqlite-dialect-DI0PJyHV.cjs} +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as schemas, B as
|
|
1
|
+
import { A as schemas, B as any, C as llmRequestsSchema, D as playgroundsSchema, E as playgroundRunsSchema, F as variantVersionsSchema, G as object, H as boolean, I as variantsSchema, J as union, K as record, L as workspaceSettingsSchema, M as spansSchema, N as targetingRulesSchema, O as providerConfigsSchema, P as tracesSchema, R as zod_default, S as guardrailConfigsSchema, T as playgroundResultsSchema, U as literal, V as array, W as number, Y as unknown, _ as datasetVersionRecordsSchema, a as matchType, b as environmentSecretsSchema, c as logger, d as validatePartialTableData, f as validateTableData, g as datasetRecordsSchema, h as configsSchema, i as getMigrations, j as spanEventsSchema, k as providerGuardrailOverridesSchema, l as parsePartialTableData, m as configVariantsSchema, n as createDatabaseFromConnection, o as runAutoMigrations, p as SCHEMA_METADATA, q as string, r as detectDatabaseType, s as getAuthClientOptions, t as createDatabase, u as parseTableData, v as datasetVersionsSchema, w as playgroundColumnSchema, x as environmentsSchema, y as datasetsSchema, z as _enum } from "./db-CQvUnGBp.mjs";
|
|
2
2
|
import { n as executeWithSchema, t as createNeonDialect } from "./neon-dialect-DySGBYUi.mjs";
|
|
3
3
|
import gateway from "@llmops/gateway";
|
|
4
4
|
import { sql } from "kysely";
|
|
@@ -8,6 +8,20 @@ import { createRandomStringGenerator } from "@better-auth/utils/random";
|
|
|
8
8
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
9
9
|
import jsonLogic from "json-logic-js";
|
|
10
10
|
|
|
11
|
+
//#region src/constants/headers.ts
|
|
12
|
+
/**
|
|
13
|
+
* Custom HTTP headers used for trace context propagation
|
|
14
|
+
* between SDK clients and the LLMOps gateway.
|
|
15
|
+
*/
|
|
16
|
+
const LLMOPS_TRACE_ID_HEADER = "x-llmops-trace-id";
|
|
17
|
+
const LLMOPS_TRACE_NAME_HEADER = "x-llmops-trace-name";
|
|
18
|
+
const LLMOPS_SPAN_NAME_HEADER = "x-llmops-span-name";
|
|
19
|
+
const LLMOPS_SESSION_ID_HEADER = "x-llmops-session-id";
|
|
20
|
+
const LLMOPS_USER_ID_HEADER = "x-llmops-user-id";
|
|
21
|
+
const LLMOPS_SPAN_ID_HEADER = "x-llmops-span-id";
|
|
22
|
+
const LLMOPS_REQUEST_ID_HEADER = "x-llmops-request-id";
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
11
25
|
//#region src/providers/supported-providers.ts
|
|
12
26
|
/**
|
|
13
27
|
* Supported providers - derived from @llmops/gateway providers
|
|
@@ -1994,7 +2008,11 @@ const insertLLMRequestSchema = zod_default.object({
|
|
|
1994
2008
|
isStreaming: zod_default.boolean().default(false),
|
|
1995
2009
|
userId: zod_default.string().nullable().optional(),
|
|
1996
2010
|
tags: zod_default.record(zod_default.string(), zod_default.string()).default({}),
|
|
1997
|
-
guardrailResults: guardrailResultsSchema.nullable().optional()
|
|
2011
|
+
guardrailResults: guardrailResultsSchema.nullable().optional(),
|
|
2012
|
+
traceId: zod_default.string().nullable().optional(),
|
|
2013
|
+
spanId: zod_default.string().nullable().optional(),
|
|
2014
|
+
parentSpanId: zod_default.string().nullable().optional(),
|
|
2015
|
+
sessionId: zod_default.string().nullable().optional()
|
|
1998
2016
|
});
|
|
1999
2017
|
/**
|
|
2000
2018
|
* Schema for listing LLM requests
|
|
@@ -2051,7 +2069,7 @@ const costSummarySchema = zod_default.object({
|
|
|
2051
2069
|
* Helper to create column reference for SQL
|
|
2052
2070
|
* Uses sql.ref() to properly quote column names for the database
|
|
2053
2071
|
*/
|
|
2054
|
-
const col = (name) => sql.ref(name);
|
|
2072
|
+
const col$1 = (name) => sql.ref(name);
|
|
2055
2073
|
const tableCol = (table, name) => sql.ref(`${table}.${name}`);
|
|
2056
2074
|
const createLLMRequestsDataLayer = (db) => {
|
|
2057
2075
|
return {
|
|
@@ -2086,6 +2104,10 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2086
2104
|
userId: req.userId ?? null,
|
|
2087
2105
|
tags: JSON.stringify(req.tags),
|
|
2088
2106
|
guardrailResults: req.guardrailResults ? JSON.stringify(req.guardrailResults) : null,
|
|
2107
|
+
traceId: req.traceId ?? null,
|
|
2108
|
+
spanId: req.spanId ?? null,
|
|
2109
|
+
parentSpanId: req.parentSpanId ?? null,
|
|
2110
|
+
sessionId: req.sessionId ?? null,
|
|
2089
2111
|
createdAt: now,
|
|
2090
2112
|
updatedAt: now
|
|
2091
2113
|
}));
|
|
@@ -2120,6 +2142,10 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2120
2142
|
userId: req.userId ?? null,
|
|
2121
2143
|
tags: JSON.stringify(req.tags),
|
|
2122
2144
|
guardrailResults: req.guardrailResults ? JSON.stringify(req.guardrailResults) : null,
|
|
2145
|
+
traceId: req.traceId ?? null,
|
|
2146
|
+
spanId: req.spanId ?? null,
|
|
2147
|
+
parentSpanId: req.parentSpanId ?? null,
|
|
2148
|
+
sessionId: req.sessionId ?? null,
|
|
2123
2149
|
createdAt: now,
|
|
2124
2150
|
updatedAt: now
|
|
2125
2151
|
}).returningAll().executeTakeFirst();
|
|
@@ -2135,14 +2161,14 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2135
2161
|
if (providerConfigId) baseQuery = baseQuery.where("providerConfigId", "=", providerConfigId);
|
|
2136
2162
|
if (provider) baseQuery = baseQuery.where("provider", "=", provider);
|
|
2137
2163
|
if (model) baseQuery = baseQuery.where("model", "=", model);
|
|
2138
|
-
if (startDate) baseQuery = baseQuery.where(sql`${col("createdAt")} >= ${startDate.toISOString()}`);
|
|
2139
|
-
if (endDate) baseQuery = baseQuery.where(sql`${col("createdAt")} <= ${endDate.toISOString()}`);
|
|
2164
|
+
if (startDate) baseQuery = baseQuery.where(sql`${col$1("createdAt")} >= ${startDate.toISOString()}`);
|
|
2165
|
+
if (endDate) baseQuery = baseQuery.where(sql`${col$1("createdAt")} <= ${endDate.toISOString()}`);
|
|
2140
2166
|
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2141
2167
|
if (values.length === 0) continue;
|
|
2142
|
-
if (values.length === 1) baseQuery = baseQuery.where(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
2168
|
+
if (values.length === 1) baseQuery = baseQuery.where(sql`${col$1("tags")}->>${key} = ${values[0]}`);
|
|
2143
2169
|
else {
|
|
2144
2170
|
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2145
|
-
baseQuery = baseQuery.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
2171
|
+
baseQuery = baseQuery.where(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2146
2172
|
}
|
|
2147
2173
|
}
|
|
2148
2174
|
const countResult = await baseQuery.select(sql`COUNT(*)`.as("total")).executeTakeFirst();
|
|
@@ -2162,23 +2188,23 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2162
2188
|
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
2163
2189
|
const { startDate, endDate, configId, variantId, environmentId, tags } = result.data;
|
|
2164
2190
|
let query = db.selectFrom("llm_requests").select([
|
|
2165
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2166
|
-
sql`COALESCE(SUM(${col("inputCost")}), 0)`.as("totalInputCost"),
|
|
2167
|
-
sql`COALESCE(SUM(${col("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2168
|
-
sql`COALESCE(SUM(${col("promptTokens")}), 0)`.as("totalPromptTokens"),
|
|
2169
|
-
sql`COALESCE(SUM(${col("completionTokens")}), 0)`.as("totalCompletionTokens"),
|
|
2170
|
-
sql`COALESCE(SUM(${col("totalTokens")}), 0)`.as("totalTokens"),
|
|
2191
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2192
|
+
sql`COALESCE(SUM(${col$1("inputCost")}), 0)`.as("totalInputCost"),
|
|
2193
|
+
sql`COALESCE(SUM(${col$1("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2194
|
+
sql`COALESCE(SUM(${col$1("promptTokens")}), 0)`.as("totalPromptTokens"),
|
|
2195
|
+
sql`COALESCE(SUM(${col$1("completionTokens")}), 0)`.as("totalCompletionTokens"),
|
|
2196
|
+
sql`COALESCE(SUM(${col$1("totalTokens")}), 0)`.as("totalTokens"),
|
|
2171
2197
|
sql`COUNT(*)`.as("requestCount")
|
|
2172
|
-
]).where(sql`${col("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col("createdAt")} <= ${endDate.toISOString()}`);
|
|
2198
|
+
]).where(sql`${col$1("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col$1("createdAt")} <= ${endDate.toISOString()}`);
|
|
2173
2199
|
if (configId) query = query.where("configId", "=", configId);
|
|
2174
2200
|
if (variantId) query = query.where("variantId", "=", variantId);
|
|
2175
2201
|
if (environmentId) query = query.where("environmentId", "=", environmentId);
|
|
2176
2202
|
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2177
2203
|
if (values.length === 0) continue;
|
|
2178
|
-
if (values.length === 1) query = query.where(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
2204
|
+
if (values.length === 1) query = query.where(sql`${col$1("tags")}->>${key} = ${values[0]}`);
|
|
2179
2205
|
else {
|
|
2180
2206
|
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2181
|
-
query = query.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
2207
|
+
query = query.where(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2182
2208
|
}
|
|
2183
2209
|
}
|
|
2184
2210
|
return await query.executeTakeFirst();
|
|
@@ -2190,13 +2216,13 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2190
2216
|
return db.selectFrom("llm_requests").select([
|
|
2191
2217
|
"provider",
|
|
2192
2218
|
"model",
|
|
2193
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2194
|
-
sql`COALESCE(SUM(${col("inputCost")}), 0)`.as("totalInputCost"),
|
|
2195
|
-
sql`COALESCE(SUM(${col("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2196
|
-
sql`COALESCE(SUM(${col("totalTokens")}), 0)`.as("totalTokens"),
|
|
2219
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2220
|
+
sql`COALESCE(SUM(${col$1("inputCost")}), 0)`.as("totalInputCost"),
|
|
2221
|
+
sql`COALESCE(SUM(${col$1("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2222
|
+
sql`COALESCE(SUM(${col$1("totalTokens")}), 0)`.as("totalTokens"),
|
|
2197
2223
|
sql`COUNT(*)`.as("requestCount"),
|
|
2198
|
-
sql`AVG(${col("latencyMs")})`.as("avgLatencyMs")
|
|
2199
|
-
]).where(sql`${col("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col("createdAt")} <= ${endDate.toISOString()}`).groupBy(["provider", "model"]).orderBy(sql`SUM(${col("cost")})`, "desc").execute();
|
|
2224
|
+
sql`AVG(${col$1("latencyMs")})`.as("avgLatencyMs")
|
|
2225
|
+
]).where(sql`${col$1("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col$1("createdAt")} <= ${endDate.toISOString()}`).groupBy(["provider", "model"]).orderBy(sql`SUM(${col$1("cost")})`, "desc").execute();
|
|
2200
2226
|
},
|
|
2201
2227
|
getCostByProvider: async (params) => {
|
|
2202
2228
|
const result = await dateRangeSchema.safeParseAsync(params);
|
|
@@ -2204,13 +2230,13 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2204
2230
|
const { startDate, endDate } = result.data;
|
|
2205
2231
|
return db.selectFrom("llm_requests").select([
|
|
2206
2232
|
"provider",
|
|
2207
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2208
|
-
sql`COALESCE(SUM(${col("inputCost")}), 0)`.as("totalInputCost"),
|
|
2209
|
-
sql`COALESCE(SUM(${col("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2210
|
-
sql`COALESCE(SUM(${col("totalTokens")}), 0)`.as("totalTokens"),
|
|
2233
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2234
|
+
sql`COALESCE(SUM(${col$1("inputCost")}), 0)`.as("totalInputCost"),
|
|
2235
|
+
sql`COALESCE(SUM(${col$1("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2236
|
+
sql`COALESCE(SUM(${col$1("totalTokens")}), 0)`.as("totalTokens"),
|
|
2211
2237
|
sql`COUNT(*)`.as("requestCount"),
|
|
2212
|
-
sql`AVG(${col("latencyMs")})`.as("avgLatencyMs")
|
|
2213
|
-
]).where(sql`${col("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col("createdAt")} <= ${endDate.toISOString()}`).groupBy("provider").orderBy(sql`SUM(${col("cost")})`, "desc").execute();
|
|
2238
|
+
sql`AVG(${col$1("latencyMs")})`.as("avgLatencyMs")
|
|
2239
|
+
]).where(sql`${col$1("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col$1("createdAt")} <= ${endDate.toISOString()}`).groupBy("provider").orderBy(sql`SUM(${col$1("cost")})`, "desc").execute();
|
|
2214
2240
|
},
|
|
2215
2241
|
getCostByConfig: async (params) => {
|
|
2216
2242
|
const result = await dateRangeSchema.safeParseAsync(params);
|
|
@@ -2236,90 +2262,90 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2236
2262
|
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
2237
2263
|
const { startDate, endDate } = result.data;
|
|
2238
2264
|
return db.selectFrom("llm_requests").select([
|
|
2239
|
-
sql`DATE(${col("createdAt")})`.as("date"),
|
|
2240
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2241
|
-
sql`COALESCE(SUM(${col("inputCost")}), 0)`.as("totalInputCost"),
|
|
2242
|
-
sql`COALESCE(SUM(${col("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2243
|
-
sql`COALESCE(SUM(${col("totalTokens")}), 0)`.as("totalTokens"),
|
|
2265
|
+
sql`DATE(${col$1("createdAt")})`.as("date"),
|
|
2266
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2267
|
+
sql`COALESCE(SUM(${col$1("inputCost")}), 0)`.as("totalInputCost"),
|
|
2268
|
+
sql`COALESCE(SUM(${col$1("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2269
|
+
sql`COALESCE(SUM(${col$1("totalTokens")}), 0)`.as("totalTokens"),
|
|
2244
2270
|
sql`COUNT(*)`.as("requestCount")
|
|
2245
|
-
]).where(sql`${col("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col("createdAt")} <= ${endDate.toISOString()}`).groupBy(sql`DATE(${col("createdAt")})`).orderBy(sql`DATE(${col("createdAt")})`, "asc").execute();
|
|
2271
|
+
]).where(sql`${col$1("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col$1("createdAt")} <= ${endDate.toISOString()}`).groupBy(sql`DATE(${col$1("createdAt")})`).orderBy(sql`DATE(${col$1("createdAt")})`, "asc").execute();
|
|
2246
2272
|
},
|
|
2247
2273
|
getCostSummary: async (params) => {
|
|
2248
2274
|
const result = await costSummarySchema.safeParseAsync(params);
|
|
2249
2275
|
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
2250
2276
|
const { startDate, endDate, groupBy, configId, variantId, environmentId, tags } = result.data;
|
|
2251
|
-
let baseQuery = db.selectFrom("llm_requests").where(sql`${col("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col("createdAt")} <= ${endDate.toISOString()}`);
|
|
2277
|
+
let baseQuery = db.selectFrom("llm_requests").where(sql`${col$1("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col$1("createdAt")} <= ${endDate.toISOString()}`);
|
|
2252
2278
|
if (configId) baseQuery = baseQuery.where("configId", "=", configId);
|
|
2253
2279
|
if (variantId) baseQuery = baseQuery.where("variantId", "=", variantId);
|
|
2254
2280
|
if (environmentId) baseQuery = baseQuery.where("environmentId", "=", environmentId);
|
|
2255
2281
|
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2256
2282
|
if (values.length === 0) continue;
|
|
2257
|
-
if (values.length === 1) baseQuery = baseQuery.where(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
2283
|
+
if (values.length === 1) baseQuery = baseQuery.where(sql`${col$1("tags")}->>${key} = ${values[0]}`);
|
|
2258
2284
|
else {
|
|
2259
2285
|
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2260
|
-
baseQuery = baseQuery.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
2286
|
+
baseQuery = baseQuery.where(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2261
2287
|
}
|
|
2262
2288
|
}
|
|
2263
2289
|
switch (groupBy) {
|
|
2264
2290
|
case "day": return baseQuery.select([
|
|
2265
|
-
sql`DATE(${col("createdAt")})`.as("groupKey"),
|
|
2266
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2291
|
+
sql`DATE(${col$1("createdAt")})`.as("groupKey"),
|
|
2292
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2267
2293
|
sql`COUNT(*)`.as("requestCount"),
|
|
2268
|
-
sql`COALESCE(SUM(${col("totalTokens")}), 0)`.as("totalTokens")
|
|
2269
|
-
]).groupBy(sql`DATE(${col("createdAt")})`).orderBy(sql`DATE(${col("createdAt")})`, "asc").execute();
|
|
2294
|
+
sql`COALESCE(SUM(${col$1("totalTokens")}), 0)`.as("totalTokens")
|
|
2295
|
+
]).groupBy(sql`DATE(${col$1("createdAt")})`).orderBy(sql`DATE(${col$1("createdAt")})`, "asc").execute();
|
|
2270
2296
|
case "hour": return baseQuery.select([
|
|
2271
|
-
sql`DATE_TRUNC('hour', ${col("createdAt")})`.as("groupKey"),
|
|
2272
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2297
|
+
sql`DATE_TRUNC('hour', ${col$1("createdAt")})`.as("groupKey"),
|
|
2298
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2273
2299
|
sql`COUNT(*)`.as("requestCount"),
|
|
2274
|
-
sql`COALESCE(SUM(${col("totalTokens")}), 0)`.as("totalTokens")
|
|
2275
|
-
]).groupBy(sql`DATE_TRUNC('hour', ${col("createdAt")})`).orderBy(sql`DATE_TRUNC('hour', ${col("createdAt")})`, "asc").execute();
|
|
2300
|
+
sql`COALESCE(SUM(${col$1("totalTokens")}), 0)`.as("totalTokens")
|
|
2301
|
+
]).groupBy(sql`DATE_TRUNC('hour', ${col$1("createdAt")})`).orderBy(sql`DATE_TRUNC('hour', ${col$1("createdAt")})`, "asc").execute();
|
|
2276
2302
|
case "model": return baseQuery.select([
|
|
2277
|
-
sql`${col("provider")} || '/' || ${col("model")}`.as("groupKey"),
|
|
2278
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2303
|
+
sql`${col$1("provider")} || '/' || ${col$1("model")}`.as("groupKey"),
|
|
2304
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2279
2305
|
sql`COUNT(*)`.as("requestCount")
|
|
2280
|
-
]).groupBy(["provider", "model"]).orderBy(sql`SUM(${col("cost")})`, "desc").execute();
|
|
2306
|
+
]).groupBy(["provider", "model"]).orderBy(sql`SUM(${col$1("cost")})`, "desc").execute();
|
|
2281
2307
|
case "provider": return baseQuery.select([
|
|
2282
|
-
sql`${col("provider")}`.as("groupKey"),
|
|
2283
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2308
|
+
sql`${col$1("provider")}`.as("groupKey"),
|
|
2309
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2284
2310
|
sql`COUNT(*)`.as("requestCount")
|
|
2285
|
-
]).groupBy("provider").orderBy(sql`SUM(${col("cost")})`, "desc").execute();
|
|
2311
|
+
]).groupBy("provider").orderBy(sql`SUM(${col$1("cost")})`, "desc").execute();
|
|
2286
2312
|
case "config": return baseQuery.select([
|
|
2287
|
-
sql`COALESCE(${col("configId")}::text, 'no-config')`.as("groupKey"),
|
|
2288
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2313
|
+
sql`COALESCE(${col$1("configId")}::text, 'no-config')`.as("groupKey"),
|
|
2314
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2289
2315
|
sql`COUNT(*)`.as("requestCount")
|
|
2290
|
-
]).groupBy("configId").orderBy(sql`SUM(${col("cost")})`, "desc").execute();
|
|
2316
|
+
]).groupBy("configId").orderBy(sql`SUM(${col$1("cost")})`, "desc").execute();
|
|
2291
2317
|
case "endpoint": return baseQuery.select([
|
|
2292
|
-
sql`COALESCE(${col("endpoint")}, 'unknown')`.as("groupKey"),
|
|
2293
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2318
|
+
sql`COALESCE(${col$1("endpoint")}, 'unknown')`.as("groupKey"),
|
|
2319
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2294
2320
|
sql`COUNT(*)`.as("requestCount")
|
|
2295
|
-
]).groupBy("endpoint").orderBy(sql`SUM(${col("cost")})`, "desc").execute();
|
|
2321
|
+
]).groupBy("endpoint").orderBy(sql`SUM(${col$1("cost")})`, "desc").execute();
|
|
2296
2322
|
case "tags": {
|
|
2297
|
-
const conditions = [sql`${col("createdAt")} >= ${startDate.toISOString()}`, sql`${col("createdAt")} <= ${endDate.toISOString()}`];
|
|
2298
|
-
if (configId) conditions.push(sql`${col("configId")} = ${configId}`);
|
|
2299
|
-
if (variantId) conditions.push(sql`${col("variantId")} = ${variantId}`);
|
|
2300
|
-
if (environmentId) conditions.push(sql`${col("environmentId")} = ${environmentId}`);
|
|
2323
|
+
const conditions = [sql`${col$1("createdAt")} >= ${startDate.toISOString()}`, sql`${col$1("createdAt")} <= ${endDate.toISOString()}`];
|
|
2324
|
+
if (configId) conditions.push(sql`${col$1("configId")} = ${configId}`);
|
|
2325
|
+
if (variantId) conditions.push(sql`${col$1("variantId")} = ${variantId}`);
|
|
2326
|
+
if (environmentId) conditions.push(sql`${col$1("environmentId")} = ${environmentId}`);
|
|
2301
2327
|
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2302
2328
|
if (values.length === 0) continue;
|
|
2303
|
-
if (values.length === 1) conditions.push(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
2329
|
+
if (values.length === 1) conditions.push(sql`${col$1("tags")}->>${key} = ${values[0]}`);
|
|
2304
2330
|
else {
|
|
2305
2331
|
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2306
|
-
conditions.push(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
2332
|
+
conditions.push(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2307
2333
|
}
|
|
2308
2334
|
}
|
|
2309
2335
|
const whereClause = sql.join(conditions, sql` AND `);
|
|
2310
2336
|
return (await sql`
|
|
2311
2337
|
SELECT t.key || ':' || t.value as "groupKey",
|
|
2312
|
-
COALESCE(SUM(${col("cost")}), 0) as "totalCost",
|
|
2338
|
+
COALESCE(SUM(${col$1("cost")}), 0) as "totalCost",
|
|
2313
2339
|
COUNT(*) as "requestCount"
|
|
2314
|
-
FROM "llm_requests", jsonb_each_text(${col("tags")}) t
|
|
2340
|
+
FROM "llm_requests", jsonb_each_text(${col$1("tags")}) t
|
|
2315
2341
|
WHERE ${whereClause}
|
|
2316
2342
|
GROUP BY t.key, t.value
|
|
2317
|
-
ORDER BY SUM(${col("cost")}) DESC
|
|
2343
|
+
ORDER BY SUM(${col$1("cost")}) DESC
|
|
2318
2344
|
`.execute(db)).rows;
|
|
2319
2345
|
}
|
|
2320
2346
|
default: return baseQuery.select([
|
|
2321
2347
|
sql`'total'`.as("groupKey"),
|
|
2322
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2348
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2323
2349
|
sql`COUNT(*)`.as("requestCount")
|
|
2324
2350
|
]).execute();
|
|
2325
2351
|
}
|
|
@@ -2330,22 +2356,22 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2330
2356
|
const { startDate, endDate, configId, variantId, environmentId, tags } = result.data;
|
|
2331
2357
|
let query = db.selectFrom("llm_requests").select([
|
|
2332
2358
|
sql`COUNT(*)`.as("totalRequests"),
|
|
2333
|
-
sql`COUNT(CASE WHEN ${col("statusCode")} >= 200 AND ${col("statusCode")} < 300 THEN 1 END)`.as("successfulRequests"),
|
|
2334
|
-
sql`COUNT(CASE WHEN ${col("statusCode")} >= 400 THEN 1 END)`.as("failedRequests"),
|
|
2335
|
-
sql`COUNT(CASE WHEN ${col("isStreaming")} = true THEN 1 END)`.as("streamingRequests"),
|
|
2336
|
-
sql`AVG(${col("latencyMs")})`.as("avgLatencyMs"),
|
|
2337
|
-
sql`MAX(${col("latencyMs")})`.as("maxLatencyMs"),
|
|
2338
|
-
sql`MIN(${col("latencyMs")})`.as("minLatencyMs")
|
|
2339
|
-
]).where(sql`${col("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col("createdAt")} <= ${endDate.toISOString()}`);
|
|
2359
|
+
sql`COUNT(CASE WHEN ${col$1("statusCode")} >= 200 AND ${col$1("statusCode")} < 300 THEN 1 END)`.as("successfulRequests"),
|
|
2360
|
+
sql`COUNT(CASE WHEN ${col$1("statusCode")} >= 400 THEN 1 END)`.as("failedRequests"),
|
|
2361
|
+
sql`COUNT(CASE WHEN ${col$1("isStreaming")} = true THEN 1 END)`.as("streamingRequests"),
|
|
2362
|
+
sql`AVG(${col$1("latencyMs")})`.as("avgLatencyMs"),
|
|
2363
|
+
sql`MAX(${col$1("latencyMs")})`.as("maxLatencyMs"),
|
|
2364
|
+
sql`MIN(${col$1("latencyMs")})`.as("minLatencyMs")
|
|
2365
|
+
]).where(sql`${col$1("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col$1("createdAt")} <= ${endDate.toISOString()}`);
|
|
2340
2366
|
if (configId) query = query.where("configId", "=", configId);
|
|
2341
2367
|
if (variantId) query = query.where("variantId", "=", variantId);
|
|
2342
2368
|
if (environmentId) query = query.where("environmentId", "=", environmentId);
|
|
2343
2369
|
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2344
2370
|
if (values.length === 0) continue;
|
|
2345
|
-
if (values.length === 1) query = query.where(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
2371
|
+
if (values.length === 1) query = query.where(sql`${col$1("tags")}->>${key} = ${values[0]}`);
|
|
2346
2372
|
else {
|
|
2347
2373
|
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2348
|
-
query = query.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
2374
|
+
query = query.where(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2349
2375
|
}
|
|
2350
2376
|
}
|
|
2351
2377
|
return await query.executeTakeFirst();
|
|
@@ -3087,6 +3113,271 @@ const createTargetingRulesDataLayer = (db) => {
|
|
|
3087
3113
|
};
|
|
3088
3114
|
};
|
|
3089
3115
|
|
|
3116
|
+
//#endregion
|
|
3117
|
+
//#region src/datalayer/traces.ts
|
|
3118
|
+
const col = (name) => sql.ref(name);
|
|
3119
|
+
/**
|
|
3120
|
+
* Schema for upserting a trace
|
|
3121
|
+
*/
|
|
3122
|
+
const upsertTraceSchema = zod_default.object({
|
|
3123
|
+
traceId: zod_default.string(),
|
|
3124
|
+
name: zod_default.string().nullable().optional(),
|
|
3125
|
+
sessionId: zod_default.string().nullable().optional(),
|
|
3126
|
+
userId: zod_default.string().nullable().optional(),
|
|
3127
|
+
status: zod_default.enum([
|
|
3128
|
+
"unset",
|
|
3129
|
+
"ok",
|
|
3130
|
+
"error"
|
|
3131
|
+
]).default("unset"),
|
|
3132
|
+
startTime: zod_default.date(),
|
|
3133
|
+
endTime: zod_default.date().nullable().optional(),
|
|
3134
|
+
durationMs: zod_default.number().int().nullable().optional(),
|
|
3135
|
+
spanCount: zod_default.number().int().default(1),
|
|
3136
|
+
totalInputTokens: zod_default.number().int().default(0),
|
|
3137
|
+
totalOutputTokens: zod_default.number().int().default(0),
|
|
3138
|
+
totalTokens: zod_default.number().int().default(0),
|
|
3139
|
+
totalCost: zod_default.number().int().default(0),
|
|
3140
|
+
tags: zod_default.record(zod_default.string(), zod_default.string()).default({}),
|
|
3141
|
+
metadata: zod_default.record(zod_default.string(), zod_default.unknown()).default({})
|
|
3142
|
+
});
|
|
3143
|
+
/**
|
|
3144
|
+
* Schema for inserting spans
|
|
3145
|
+
*/
|
|
3146
|
+
const insertSpanSchema = zod_default.object({
|
|
3147
|
+
traceId: zod_default.string(),
|
|
3148
|
+
spanId: zod_default.string(),
|
|
3149
|
+
parentSpanId: zod_default.string().nullable().optional(),
|
|
3150
|
+
name: zod_default.string(),
|
|
3151
|
+
kind: zod_default.number().int().default(1),
|
|
3152
|
+
status: zod_default.number().int().default(0),
|
|
3153
|
+
statusMessage: zod_default.string().nullable().optional(),
|
|
3154
|
+
startTime: zod_default.date(),
|
|
3155
|
+
endTime: zod_default.date().nullable().optional(),
|
|
3156
|
+
durationMs: zod_default.number().int().nullable().optional(),
|
|
3157
|
+
provider: zod_default.string().nullable().optional(),
|
|
3158
|
+
model: zod_default.string().nullable().optional(),
|
|
3159
|
+
promptTokens: zod_default.number().int().default(0),
|
|
3160
|
+
completionTokens: zod_default.number().int().default(0),
|
|
3161
|
+
totalTokens: zod_default.number().int().default(0),
|
|
3162
|
+
cost: zod_default.number().int().default(0),
|
|
3163
|
+
configId: zod_default.string().uuid().nullable().optional(),
|
|
3164
|
+
variantId: zod_default.string().uuid().nullable().optional(),
|
|
3165
|
+
environmentId: zod_default.string().uuid().nullable().optional(),
|
|
3166
|
+
providerConfigId: zod_default.string().uuid().nullable().optional(),
|
|
3167
|
+
requestId: zod_default.string().uuid().nullable().optional(),
|
|
3168
|
+
source: zod_default.enum(["gateway", "otlp"]).default("gateway"),
|
|
3169
|
+
input: zod_default.unknown().nullable().optional(),
|
|
3170
|
+
output: zod_default.unknown().nullable().optional(),
|
|
3171
|
+
attributes: zod_default.record(zod_default.string(), zod_default.unknown()).default({})
|
|
3172
|
+
});
|
|
3173
|
+
/**
|
|
3174
|
+
* Schema for inserting span events
|
|
3175
|
+
*/
|
|
3176
|
+
const insertSpanEventSchema = zod_default.object({
|
|
3177
|
+
traceId: zod_default.string(),
|
|
3178
|
+
spanId: zod_default.string(),
|
|
3179
|
+
name: zod_default.string(),
|
|
3180
|
+
timestamp: zod_default.date(),
|
|
3181
|
+
attributes: zod_default.record(zod_default.string(), zod_default.unknown()).default({})
|
|
3182
|
+
});
|
|
3183
|
+
/**
|
|
3184
|
+
* Schema for listing traces
|
|
3185
|
+
*/
|
|
3186
|
+
const listTracesSchema = zod_default.object({
|
|
3187
|
+
limit: zod_default.number().int().positive().max(1e3).default(50),
|
|
3188
|
+
offset: zod_default.number().int().nonnegative().default(0),
|
|
3189
|
+
sessionId: zod_default.string().optional(),
|
|
3190
|
+
userId: zod_default.string().optional(),
|
|
3191
|
+
status: zod_default.enum([
|
|
3192
|
+
"unset",
|
|
3193
|
+
"ok",
|
|
3194
|
+
"error"
|
|
3195
|
+
]).optional(),
|
|
3196
|
+
name: zod_default.string().optional(),
|
|
3197
|
+
startDate: zod_default.date().optional(),
|
|
3198
|
+
endDate: zod_default.date().optional(),
|
|
3199
|
+
tags: zod_default.record(zod_default.string(), zod_default.array(zod_default.string())).optional()
|
|
3200
|
+
});
|
|
3201
|
+
/**
|
|
3202
|
+
* Schema for trace stats query
|
|
3203
|
+
*/
|
|
3204
|
+
const traceStatsSchema = zod_default.object({
|
|
3205
|
+
startDate: zod_default.date(),
|
|
3206
|
+
endDate: zod_default.date(),
|
|
3207
|
+
sessionId: zod_default.string().optional(),
|
|
3208
|
+
userId: zod_default.string().optional()
|
|
3209
|
+
});
|
|
3210
|
+
const createTracesDataLayer = (db) => {
|
|
3211
|
+
return {
|
|
3212
|
+
upsertTrace: async (data) => {
|
|
3213
|
+
const result = await upsertTraceSchema.safeParseAsync(data);
|
|
3214
|
+
if (!result.success) throw new LLMOpsError(`Invalid trace data: ${result.error.message}`);
|
|
3215
|
+
const trace = result.data;
|
|
3216
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3217
|
+
await sql`
|
|
3218
|
+
INSERT INTO "traces" (
|
|
3219
|
+
"id", "traceId", "name", "sessionId", "userId", "status",
|
|
3220
|
+
"startTime", "endTime", "durationMs", "spanCount",
|
|
3221
|
+
"totalInputTokens", "totalOutputTokens", "totalTokens", "totalCost",
|
|
3222
|
+
"tags", "metadata", "createdAt", "updatedAt"
|
|
3223
|
+
) VALUES (
|
|
3224
|
+
${randomUUID()}, ${trace.traceId}, ${trace.name ?? null}, ${trace.sessionId ?? null},
|
|
3225
|
+
${trace.userId ?? null}, ${trace.status},
|
|
3226
|
+
${trace.startTime.toISOString()}, ${trace.endTime?.toISOString() ?? null},
|
|
3227
|
+
${trace.durationMs ?? null}, ${trace.spanCount},
|
|
3228
|
+
${trace.totalInputTokens}, ${trace.totalOutputTokens},
|
|
3229
|
+
${trace.totalTokens}, ${trace.totalCost},
|
|
3230
|
+
${JSON.stringify(trace.tags)}::jsonb, ${JSON.stringify(trace.metadata)}::jsonb,
|
|
3231
|
+
${now}, ${now}
|
|
3232
|
+
)
|
|
3233
|
+
ON CONFLICT ("traceId") DO UPDATE SET
|
|
3234
|
+
"name" = COALESCE(EXCLUDED."name", "traces"."name"),
|
|
3235
|
+
"sessionId" = COALESCE(EXCLUDED."sessionId", "traces"."sessionId"),
|
|
3236
|
+
"userId" = COALESCE(EXCLUDED."userId", "traces"."userId"),
|
|
3237
|
+
"status" = CASE
|
|
3238
|
+
WHEN EXCLUDED."status" = 'error' THEN 'error'
|
|
3239
|
+
WHEN EXCLUDED."status" = 'ok' AND "traces"."status" != 'error' THEN 'ok'
|
|
3240
|
+
ELSE "traces"."status"
|
|
3241
|
+
END,
|
|
3242
|
+
"startTime" = LEAST("traces"."startTime", EXCLUDED."startTime"),
|
|
3243
|
+
"endTime" = GREATEST(
|
|
3244
|
+
COALESCE("traces"."endTime", EXCLUDED."endTime"),
|
|
3245
|
+
COALESCE(EXCLUDED."endTime", "traces"."endTime")
|
|
3246
|
+
),
|
|
3247
|
+
"durationMs" = EXTRACT(EPOCH FROM (
|
|
3248
|
+
GREATEST(
|
|
3249
|
+
COALESCE("traces"."endTime", EXCLUDED."endTime"),
|
|
3250
|
+
COALESCE(EXCLUDED."endTime", "traces"."endTime")
|
|
3251
|
+
) -
|
|
3252
|
+
LEAST("traces"."startTime", EXCLUDED."startTime")
|
|
3253
|
+
))::integer * 1000,
|
|
3254
|
+
"spanCount" = "traces"."spanCount" + EXCLUDED."spanCount",
|
|
3255
|
+
"totalInputTokens" = "traces"."totalInputTokens" + EXCLUDED."totalInputTokens",
|
|
3256
|
+
"totalOutputTokens" = "traces"."totalOutputTokens" + EXCLUDED."totalOutputTokens",
|
|
3257
|
+
"totalTokens" = "traces"."totalTokens" + EXCLUDED."totalTokens",
|
|
3258
|
+
"totalCost" = "traces"."totalCost" + EXCLUDED."totalCost",
|
|
3259
|
+
"tags" = "traces"."tags" || EXCLUDED."tags",
|
|
3260
|
+
"metadata" = "traces"."metadata" || EXCLUDED."metadata",
|
|
3261
|
+
"updatedAt" = ${now}
|
|
3262
|
+
`.execute(db);
|
|
3263
|
+
},
|
|
3264
|
+
batchInsertSpans: async (spans) => {
|
|
3265
|
+
if (spans.length === 0) return { count: 0 };
|
|
3266
|
+
const validatedSpans = await Promise.all(spans.map(async (span) => {
|
|
3267
|
+
const result = await insertSpanSchema.safeParseAsync(span);
|
|
3268
|
+
if (!result.success) throw new LLMOpsError(`Invalid span data: ${result.error.message}`);
|
|
3269
|
+
return result.data;
|
|
3270
|
+
}));
|
|
3271
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3272
|
+
const values = validatedSpans.map((span) => ({
|
|
3273
|
+
id: randomUUID(),
|
|
3274
|
+
traceId: span.traceId,
|
|
3275
|
+
spanId: span.spanId,
|
|
3276
|
+
parentSpanId: span.parentSpanId ?? null,
|
|
3277
|
+
name: span.name,
|
|
3278
|
+
kind: span.kind,
|
|
3279
|
+
status: span.status,
|
|
3280
|
+
statusMessage: span.statusMessage ?? null,
|
|
3281
|
+
startTime: span.startTime.toISOString(),
|
|
3282
|
+
endTime: span.endTime?.toISOString() ?? null,
|
|
3283
|
+
durationMs: span.durationMs ?? null,
|
|
3284
|
+
provider: span.provider ?? null,
|
|
3285
|
+
model: span.model ?? null,
|
|
3286
|
+
promptTokens: span.promptTokens,
|
|
3287
|
+
completionTokens: span.completionTokens,
|
|
3288
|
+
totalTokens: span.totalTokens,
|
|
3289
|
+
cost: span.cost,
|
|
3290
|
+
configId: span.configId ?? null,
|
|
3291
|
+
variantId: span.variantId ?? null,
|
|
3292
|
+
environmentId: span.environmentId ?? null,
|
|
3293
|
+
providerConfigId: span.providerConfigId ?? null,
|
|
3294
|
+
requestId: span.requestId ?? null,
|
|
3295
|
+
source: span.source,
|
|
3296
|
+
input: span.input != null ? JSON.stringify(span.input) : null,
|
|
3297
|
+
output: span.output != null ? JSON.stringify(span.output) : null,
|
|
3298
|
+
attributes: JSON.stringify(span.attributes),
|
|
3299
|
+
createdAt: now,
|
|
3300
|
+
updatedAt: now
|
|
3301
|
+
}));
|
|
3302
|
+
await db.insertInto("spans").values(values).onConflict((oc) => oc.column("spanId").doNothing()).execute();
|
|
3303
|
+
return { count: values.length };
|
|
3304
|
+
},
|
|
3305
|
+
batchInsertSpanEvents: async (events) => {
|
|
3306
|
+
if (events.length === 0) return { count: 0 };
|
|
3307
|
+
const validatedEvents = await Promise.all(events.map(async (event) => {
|
|
3308
|
+
const result = await insertSpanEventSchema.safeParseAsync(event);
|
|
3309
|
+
if (!result.success) throw new LLMOpsError(`Invalid span event data: ${result.error.message}`);
|
|
3310
|
+
return result.data;
|
|
3311
|
+
}));
|
|
3312
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3313
|
+
const values = validatedEvents.map((event) => ({
|
|
3314
|
+
id: randomUUID(),
|
|
3315
|
+
traceId: event.traceId,
|
|
3316
|
+
spanId: event.spanId,
|
|
3317
|
+
name: event.name,
|
|
3318
|
+
timestamp: event.timestamp.toISOString(),
|
|
3319
|
+
attributes: JSON.stringify(event.attributes),
|
|
3320
|
+
createdAt: now
|
|
3321
|
+
}));
|
|
3322
|
+
await db.insertInto("span_events").values(values).execute();
|
|
3323
|
+
return { count: values.length };
|
|
3324
|
+
},
|
|
3325
|
+
listTraces: async (params) => {
|
|
3326
|
+
const result = await listTracesSchema.safeParseAsync(params || {});
|
|
3327
|
+
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
3328
|
+
const { limit, offset, sessionId, userId, status, name, startDate, endDate, tags } = result.data;
|
|
3329
|
+
let baseQuery = db.selectFrom("traces");
|
|
3330
|
+
if (sessionId) baseQuery = baseQuery.where("sessionId", "=", sessionId);
|
|
3331
|
+
if (userId) baseQuery = baseQuery.where("userId", "=", userId);
|
|
3332
|
+
if (status) baseQuery = baseQuery.where("status", "=", status);
|
|
3333
|
+
if (name) baseQuery = baseQuery.where(sql`${col("name")} ILIKE ${"%" + name + "%"}`);
|
|
3334
|
+
if (startDate) baseQuery = baseQuery.where(sql`${col("startTime")} >= ${startDate.toISOString()}`);
|
|
3335
|
+
if (endDate) baseQuery = baseQuery.where(sql`${col("startTime")} <= ${endDate.toISOString()}`);
|
|
3336
|
+
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
3337
|
+
if (values.length === 0) continue;
|
|
3338
|
+
if (values.length === 1) baseQuery = baseQuery.where(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
3339
|
+
else {
|
|
3340
|
+
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
3341
|
+
baseQuery = baseQuery.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
3342
|
+
}
|
|
3343
|
+
}
|
|
3344
|
+
const countResult = await baseQuery.select(sql`COUNT(*)`.as("total")).executeTakeFirst();
|
|
3345
|
+
const total = Number(countResult?.total ?? 0);
|
|
3346
|
+
return {
|
|
3347
|
+
data: await baseQuery.selectAll().orderBy("startTime", "desc").limit(limit).offset(offset).execute(),
|
|
3348
|
+
total,
|
|
3349
|
+
limit,
|
|
3350
|
+
offset
|
|
3351
|
+
};
|
|
3352
|
+
},
|
|
3353
|
+
getTraceWithSpans: async (traceId) => {
|
|
3354
|
+
const trace = await db.selectFrom("traces").selectAll().where("traceId", "=", traceId).executeTakeFirst();
|
|
3355
|
+
if (!trace) return void 0;
|
|
3356
|
+
return {
|
|
3357
|
+
trace,
|
|
3358
|
+
spans: await db.selectFrom("spans").selectAll().where("traceId", "=", traceId).orderBy("startTime", "asc").execute(),
|
|
3359
|
+
events: await db.selectFrom("span_events").selectAll().where("traceId", "=", traceId).orderBy("timestamp", "asc").execute()
|
|
3360
|
+
};
|
|
3361
|
+
},
|
|
3362
|
+
getTraceStats: async (params) => {
|
|
3363
|
+
const result = await traceStatsSchema.safeParseAsync(params);
|
|
3364
|
+
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
3365
|
+
const { startDate, endDate, sessionId, userId } = result.data;
|
|
3366
|
+
let query = db.selectFrom("traces").select([
|
|
3367
|
+
sql`COUNT(*)`.as("totalTraces"),
|
|
3368
|
+
sql`COALESCE(AVG(${col("durationMs")}), 0)`.as("avgDurationMs"),
|
|
3369
|
+
sql`COUNT(CASE WHEN ${col("status")} = 'error' THEN 1 END)`.as("errorCount"),
|
|
3370
|
+
sql`COALESCE(SUM(${col("totalCost")}), 0)`.as("totalCost"),
|
|
3371
|
+
sql`COALESCE(SUM(${col("totalTokens")}), 0)`.as("totalTokens"),
|
|
3372
|
+
sql`COALESCE(SUM(${col("spanCount")}), 0)`.as("totalSpans")
|
|
3373
|
+
]).where(sql`${col("startTime")} >= ${startDate.toISOString()}`).where(sql`${col("startTime")} <= ${endDate.toISOString()}`);
|
|
3374
|
+
if (sessionId) query = query.where("sessionId", "=", sessionId);
|
|
3375
|
+
if (userId) query = query.where("userId", "=", userId);
|
|
3376
|
+
return query.executeTakeFirst();
|
|
3377
|
+
}
|
|
3378
|
+
};
|
|
3379
|
+
};
|
|
3380
|
+
|
|
3090
3381
|
//#endregion
|
|
3091
3382
|
//#region src/datalayer/variants.ts
|
|
3092
3383
|
const createVariant = zod_default.object({ name: zod_default.string() });
|
|
@@ -3380,6 +3671,7 @@ function createDataLayer(db) {
|
|
|
3380
3671
|
...createProviderConfigsDataLayer(db),
|
|
3381
3672
|
...createProviderGuardrailOverridesDataLayer(db),
|
|
3382
3673
|
...createTargetingRulesDataLayer(db),
|
|
3674
|
+
...createTracesDataLayer(db),
|
|
3383
3675
|
...createVariantDataLayer(db),
|
|
3384
3676
|
...createVariantVersionsDataLayer(db),
|
|
3385
3677
|
...createWorkspaceSettingsDataLayer(db)
|
|
@@ -3958,4 +4250,4 @@ var ManifestRouter = class {
|
|
|
3958
4250
|
};
|
|
3959
4251
|
|
|
3960
4252
|
//#endregion
|
|
3961
|
-
export { COST_SUMMARY_GROUP_BY, CacheService, DEFAULT_PROVIDER_ENV_VARS, FileCacheBackend, MS, ManifestBuilder, ManifestRouter, ManifestService, MemoryCacheBackend, ModelsDevPricingProvider, SCHEMA_METADATA, SupportedProviders, calculateCost, chatCompletionCreateParamsBaseSchema, configVariantsSchema, configsSchema, createConfigDataLayer, createConfigVariantDataLayer, createDataLayer, createDatabase, createDatabaseFromConnection, createDatasetsDataLayer, createEnvironmentDataLayer, createEnvironmentSecretDataLayer, createGuardrailConfigsDataLayer, createLLMRequestsDataLayer, createNeonDialect, createPlaygroundDataLayer, createPlaygroundResultsDataLayer, createPlaygroundRunsDataLayer, createProviderConfigsDataLayer, createProviderGuardrailOverridesDataLayer, createTargetingRulesDataLayer, createVariantDataLayer, createVariantVersionsDataLayer, createWorkspaceSettingsDataLayer, datasetRecordsSchema, datasetVersionRecordsSchema, datasetVersionsSchema, datasetsSchema, detectDatabaseType, dollarsToMicroDollars, environmentSecretsSchema, environmentsSchema, executeWithSchema, formatCost, gateway, generateId, getAuthClientOptions, getDefaultPricingProvider, getDefaultProviders, getMigrations, guardrailConfigsSchema, llmRequestsSchema, llmopsConfigSchema, logger, matchType, mergeWithDefaultProviders, microDollarsToDollars, parsePartialTableData, parseTableData, playgroundColumnSchema, playgroundResultsSchema, playgroundRunsSchema, playgroundsSchema, providerConfigsSchema, providerGuardrailOverridesSchema, runAutoMigrations, schemas, targetingRulesSchema, validateLLMOpsConfig, validatePartialTableData, validateTableData, variantJsonDataSchema, variantVersionsSchema, variantsSchema, workspaceSettingsSchema };
|
|
4253
|
+
export { COST_SUMMARY_GROUP_BY, CacheService, DEFAULT_PROVIDER_ENV_VARS, FileCacheBackend, LLMOPS_REQUEST_ID_HEADER, LLMOPS_SESSION_ID_HEADER, LLMOPS_SPAN_ID_HEADER, LLMOPS_SPAN_NAME_HEADER, LLMOPS_TRACE_ID_HEADER, LLMOPS_TRACE_NAME_HEADER, LLMOPS_USER_ID_HEADER, MS, ManifestBuilder, ManifestRouter, ManifestService, MemoryCacheBackend, ModelsDevPricingProvider, SCHEMA_METADATA, SupportedProviders, calculateCost, chatCompletionCreateParamsBaseSchema, configVariantsSchema, configsSchema, createConfigDataLayer, createConfigVariantDataLayer, createDataLayer, createDatabase, createDatabaseFromConnection, createDatasetsDataLayer, createEnvironmentDataLayer, createEnvironmentSecretDataLayer, createGuardrailConfigsDataLayer, createLLMRequestsDataLayer, createNeonDialect, createPlaygroundDataLayer, createPlaygroundResultsDataLayer, createPlaygroundRunsDataLayer, createProviderConfigsDataLayer, createProviderGuardrailOverridesDataLayer, createTargetingRulesDataLayer, createTracesDataLayer, createVariantDataLayer, createVariantVersionsDataLayer, createWorkspaceSettingsDataLayer, datasetRecordsSchema, datasetVersionRecordsSchema, datasetVersionsSchema, datasetsSchema, detectDatabaseType, dollarsToMicroDollars, environmentSecretsSchema, environmentsSchema, executeWithSchema, formatCost, gateway, generateId, getAuthClientOptions, getDefaultPricingProvider, getDefaultProviders, getMigrations, guardrailConfigsSchema, llmRequestsSchema, llmopsConfigSchema, logger, matchType, mergeWithDefaultProviders, microDollarsToDollars, parsePartialTableData, parseTableData, playgroundColumnSchema, playgroundResultsSchema, playgroundRunsSchema, playgroundsSchema, providerConfigsSchema, providerGuardrailOverridesSchema, runAutoMigrations, schemas, spanEventsSchema, spansSchema, targetingRulesSchema, tracesSchema, validateLLMOpsConfig, validatePartialTableData, validateTableData, variantJsonDataSchema, variantVersionsSchema, variantsSchema, workspaceSettingsSchema };
|