@llmops/core 0.5.4 → 0.6.1-beta.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/{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 +382 -77
- package/dist/index.d.cts +254 -3
- package/dist/index.d.mts +254 -3
- package/dist/index.mjs +370 -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,21 @@ 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
|
+
const LLMOPS_INTERNAL_HEADER = "x-llmops-internal";
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
11
26
|
//#region src/providers/supported-providers.ts
|
|
12
27
|
/**
|
|
13
28
|
* Supported providers - derived from @llmops/gateway providers
|
|
@@ -1994,7 +2009,11 @@ const insertLLMRequestSchema = zod_default.object({
|
|
|
1994
2009
|
isStreaming: zod_default.boolean().default(false),
|
|
1995
2010
|
userId: zod_default.string().nullable().optional(),
|
|
1996
2011
|
tags: zod_default.record(zod_default.string(), zod_default.string()).default({}),
|
|
1997
|
-
guardrailResults: guardrailResultsSchema.nullable().optional()
|
|
2012
|
+
guardrailResults: guardrailResultsSchema.nullable().optional(),
|
|
2013
|
+
traceId: zod_default.string().nullable().optional(),
|
|
2014
|
+
spanId: zod_default.string().nullable().optional(),
|
|
2015
|
+
parentSpanId: zod_default.string().nullable().optional(),
|
|
2016
|
+
sessionId: zod_default.string().nullable().optional()
|
|
1998
2017
|
});
|
|
1999
2018
|
/**
|
|
2000
2019
|
* Schema for listing LLM requests
|
|
@@ -2051,7 +2070,7 @@ const costSummarySchema = zod_default.object({
|
|
|
2051
2070
|
* Helper to create column reference for SQL
|
|
2052
2071
|
* Uses sql.ref() to properly quote column names for the database
|
|
2053
2072
|
*/
|
|
2054
|
-
const col = (name) => sql.ref(name);
|
|
2073
|
+
const col$1 = (name) => sql.ref(name);
|
|
2055
2074
|
const tableCol = (table, name) => sql.ref(`${table}.${name}`);
|
|
2056
2075
|
const createLLMRequestsDataLayer = (db) => {
|
|
2057
2076
|
return {
|
|
@@ -2086,6 +2105,10 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2086
2105
|
userId: req.userId ?? null,
|
|
2087
2106
|
tags: JSON.stringify(req.tags),
|
|
2088
2107
|
guardrailResults: req.guardrailResults ? JSON.stringify(req.guardrailResults) : null,
|
|
2108
|
+
traceId: req.traceId ?? null,
|
|
2109
|
+
spanId: req.spanId ?? null,
|
|
2110
|
+
parentSpanId: req.parentSpanId ?? null,
|
|
2111
|
+
sessionId: req.sessionId ?? null,
|
|
2089
2112
|
createdAt: now,
|
|
2090
2113
|
updatedAt: now
|
|
2091
2114
|
}));
|
|
@@ -2120,6 +2143,10 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2120
2143
|
userId: req.userId ?? null,
|
|
2121
2144
|
tags: JSON.stringify(req.tags),
|
|
2122
2145
|
guardrailResults: req.guardrailResults ? JSON.stringify(req.guardrailResults) : null,
|
|
2146
|
+
traceId: req.traceId ?? null,
|
|
2147
|
+
spanId: req.spanId ?? null,
|
|
2148
|
+
parentSpanId: req.parentSpanId ?? null,
|
|
2149
|
+
sessionId: req.sessionId ?? null,
|
|
2123
2150
|
createdAt: now,
|
|
2124
2151
|
updatedAt: now
|
|
2125
2152
|
}).returningAll().executeTakeFirst();
|
|
@@ -2135,14 +2162,14 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2135
2162
|
if (providerConfigId) baseQuery = baseQuery.where("providerConfigId", "=", providerConfigId);
|
|
2136
2163
|
if (provider) baseQuery = baseQuery.where("provider", "=", provider);
|
|
2137
2164
|
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()}`);
|
|
2165
|
+
if (startDate) baseQuery = baseQuery.where(sql`${col$1("createdAt")} >= ${startDate.toISOString()}`);
|
|
2166
|
+
if (endDate) baseQuery = baseQuery.where(sql`${col$1("createdAt")} <= ${endDate.toISOString()}`);
|
|
2140
2167
|
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2141
2168
|
if (values.length === 0) continue;
|
|
2142
|
-
if (values.length === 1) baseQuery = baseQuery.where(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
2169
|
+
if (values.length === 1) baseQuery = baseQuery.where(sql`${col$1("tags")}->>${key} = ${values[0]}`);
|
|
2143
2170
|
else {
|
|
2144
2171
|
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2145
|
-
baseQuery = baseQuery.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
2172
|
+
baseQuery = baseQuery.where(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2146
2173
|
}
|
|
2147
2174
|
}
|
|
2148
2175
|
const countResult = await baseQuery.select(sql`COUNT(*)`.as("total")).executeTakeFirst();
|
|
@@ -2162,23 +2189,23 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2162
2189
|
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
2163
2190
|
const { startDate, endDate, configId, variantId, environmentId, tags } = result.data;
|
|
2164
2191
|
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"),
|
|
2192
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2193
|
+
sql`COALESCE(SUM(${col$1("inputCost")}), 0)`.as("totalInputCost"),
|
|
2194
|
+
sql`COALESCE(SUM(${col$1("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2195
|
+
sql`COALESCE(SUM(${col$1("promptTokens")}), 0)`.as("totalPromptTokens"),
|
|
2196
|
+
sql`COALESCE(SUM(${col$1("completionTokens")}), 0)`.as("totalCompletionTokens"),
|
|
2197
|
+
sql`COALESCE(SUM(${col$1("totalTokens")}), 0)`.as("totalTokens"),
|
|
2171
2198
|
sql`COUNT(*)`.as("requestCount")
|
|
2172
|
-
]).where(sql`${col("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col("createdAt")} <= ${endDate.toISOString()}`);
|
|
2199
|
+
]).where(sql`${col$1("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col$1("createdAt")} <= ${endDate.toISOString()}`);
|
|
2173
2200
|
if (configId) query = query.where("configId", "=", configId);
|
|
2174
2201
|
if (variantId) query = query.where("variantId", "=", variantId);
|
|
2175
2202
|
if (environmentId) query = query.where("environmentId", "=", environmentId);
|
|
2176
2203
|
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2177
2204
|
if (values.length === 0) continue;
|
|
2178
|
-
if (values.length === 1) query = query.where(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
2205
|
+
if (values.length === 1) query = query.where(sql`${col$1("tags")}->>${key} = ${values[0]}`);
|
|
2179
2206
|
else {
|
|
2180
2207
|
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2181
|
-
query = query.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
2208
|
+
query = query.where(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2182
2209
|
}
|
|
2183
2210
|
}
|
|
2184
2211
|
return await query.executeTakeFirst();
|
|
@@ -2190,13 +2217,13 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2190
2217
|
return db.selectFrom("llm_requests").select([
|
|
2191
2218
|
"provider",
|
|
2192
2219
|
"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"),
|
|
2220
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2221
|
+
sql`COALESCE(SUM(${col$1("inputCost")}), 0)`.as("totalInputCost"),
|
|
2222
|
+
sql`COALESCE(SUM(${col$1("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2223
|
+
sql`COALESCE(SUM(${col$1("totalTokens")}), 0)`.as("totalTokens"),
|
|
2197
2224
|
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();
|
|
2225
|
+
sql`AVG(${col$1("latencyMs")})`.as("avgLatencyMs")
|
|
2226
|
+
]).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
2227
|
},
|
|
2201
2228
|
getCostByProvider: async (params) => {
|
|
2202
2229
|
const result = await dateRangeSchema.safeParseAsync(params);
|
|
@@ -2204,13 +2231,13 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2204
2231
|
const { startDate, endDate } = result.data;
|
|
2205
2232
|
return db.selectFrom("llm_requests").select([
|
|
2206
2233
|
"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"),
|
|
2234
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2235
|
+
sql`COALESCE(SUM(${col$1("inputCost")}), 0)`.as("totalInputCost"),
|
|
2236
|
+
sql`COALESCE(SUM(${col$1("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2237
|
+
sql`COALESCE(SUM(${col$1("totalTokens")}), 0)`.as("totalTokens"),
|
|
2211
2238
|
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();
|
|
2239
|
+
sql`AVG(${col$1("latencyMs")})`.as("avgLatencyMs")
|
|
2240
|
+
]).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
2241
|
},
|
|
2215
2242
|
getCostByConfig: async (params) => {
|
|
2216
2243
|
const result = await dateRangeSchema.safeParseAsync(params);
|
|
@@ -2236,90 +2263,90 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2236
2263
|
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
2237
2264
|
const { startDate, endDate } = result.data;
|
|
2238
2265
|
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"),
|
|
2266
|
+
sql`DATE(${col$1("createdAt")})`.as("date"),
|
|
2267
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2268
|
+
sql`COALESCE(SUM(${col$1("inputCost")}), 0)`.as("totalInputCost"),
|
|
2269
|
+
sql`COALESCE(SUM(${col$1("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2270
|
+
sql`COALESCE(SUM(${col$1("totalTokens")}), 0)`.as("totalTokens"),
|
|
2244
2271
|
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();
|
|
2272
|
+
]).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
2273
|
},
|
|
2247
2274
|
getCostSummary: async (params) => {
|
|
2248
2275
|
const result = await costSummarySchema.safeParseAsync(params);
|
|
2249
2276
|
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
2250
2277
|
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()}`);
|
|
2278
|
+
let baseQuery = db.selectFrom("llm_requests").where(sql`${col$1("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col$1("createdAt")} <= ${endDate.toISOString()}`);
|
|
2252
2279
|
if (configId) baseQuery = baseQuery.where("configId", "=", configId);
|
|
2253
2280
|
if (variantId) baseQuery = baseQuery.where("variantId", "=", variantId);
|
|
2254
2281
|
if (environmentId) baseQuery = baseQuery.where("environmentId", "=", environmentId);
|
|
2255
2282
|
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2256
2283
|
if (values.length === 0) continue;
|
|
2257
|
-
if (values.length === 1) baseQuery = baseQuery.where(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
2284
|
+
if (values.length === 1) baseQuery = baseQuery.where(sql`${col$1("tags")}->>${key} = ${values[0]}`);
|
|
2258
2285
|
else {
|
|
2259
2286
|
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2260
|
-
baseQuery = baseQuery.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
2287
|
+
baseQuery = baseQuery.where(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2261
2288
|
}
|
|
2262
2289
|
}
|
|
2263
2290
|
switch (groupBy) {
|
|
2264
2291
|
case "day": return baseQuery.select([
|
|
2265
|
-
sql`DATE(${col("createdAt")})`.as("groupKey"),
|
|
2266
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2292
|
+
sql`DATE(${col$1("createdAt")})`.as("groupKey"),
|
|
2293
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2267
2294
|
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();
|
|
2295
|
+
sql`COALESCE(SUM(${col$1("totalTokens")}), 0)`.as("totalTokens")
|
|
2296
|
+
]).groupBy(sql`DATE(${col$1("createdAt")})`).orderBy(sql`DATE(${col$1("createdAt")})`, "asc").execute();
|
|
2270
2297
|
case "hour": return baseQuery.select([
|
|
2271
|
-
sql`DATE_TRUNC('hour', ${col("createdAt")})`.as("groupKey"),
|
|
2272
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2298
|
+
sql`DATE_TRUNC('hour', ${col$1("createdAt")})`.as("groupKey"),
|
|
2299
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2273
2300
|
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();
|
|
2301
|
+
sql`COALESCE(SUM(${col$1("totalTokens")}), 0)`.as("totalTokens")
|
|
2302
|
+
]).groupBy(sql`DATE_TRUNC('hour', ${col$1("createdAt")})`).orderBy(sql`DATE_TRUNC('hour', ${col$1("createdAt")})`, "asc").execute();
|
|
2276
2303
|
case "model": return baseQuery.select([
|
|
2277
|
-
sql`${col("provider")} || '/' || ${col("model")}`.as("groupKey"),
|
|
2278
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2304
|
+
sql`${col$1("provider")} || '/' || ${col$1("model")}`.as("groupKey"),
|
|
2305
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2279
2306
|
sql`COUNT(*)`.as("requestCount")
|
|
2280
|
-
]).groupBy(["provider", "model"]).orderBy(sql`SUM(${col("cost")})`, "desc").execute();
|
|
2307
|
+
]).groupBy(["provider", "model"]).orderBy(sql`SUM(${col$1("cost")})`, "desc").execute();
|
|
2281
2308
|
case "provider": return baseQuery.select([
|
|
2282
|
-
sql`${col("provider")}`.as("groupKey"),
|
|
2283
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2309
|
+
sql`${col$1("provider")}`.as("groupKey"),
|
|
2310
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2284
2311
|
sql`COUNT(*)`.as("requestCount")
|
|
2285
|
-
]).groupBy("provider").orderBy(sql`SUM(${col("cost")})`, "desc").execute();
|
|
2312
|
+
]).groupBy("provider").orderBy(sql`SUM(${col$1("cost")})`, "desc").execute();
|
|
2286
2313
|
case "config": return baseQuery.select([
|
|
2287
|
-
sql`COALESCE(${col("configId")}::text, 'no-config')`.as("groupKey"),
|
|
2288
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2314
|
+
sql`COALESCE(${col$1("configId")}::text, 'no-config')`.as("groupKey"),
|
|
2315
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2289
2316
|
sql`COUNT(*)`.as("requestCount")
|
|
2290
|
-
]).groupBy("configId").orderBy(sql`SUM(${col("cost")})`, "desc").execute();
|
|
2317
|
+
]).groupBy("configId").orderBy(sql`SUM(${col$1("cost")})`, "desc").execute();
|
|
2291
2318
|
case "endpoint": return baseQuery.select([
|
|
2292
|
-
sql`COALESCE(${col("endpoint")}, 'unknown')`.as("groupKey"),
|
|
2293
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2319
|
+
sql`COALESCE(${col$1("endpoint")}, 'unknown')`.as("groupKey"),
|
|
2320
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2294
2321
|
sql`COUNT(*)`.as("requestCount")
|
|
2295
|
-
]).groupBy("endpoint").orderBy(sql`SUM(${col("cost")})`, "desc").execute();
|
|
2322
|
+
]).groupBy("endpoint").orderBy(sql`SUM(${col$1("cost")})`, "desc").execute();
|
|
2296
2323
|
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}`);
|
|
2324
|
+
const conditions = [sql`${col$1("createdAt")} >= ${startDate.toISOString()}`, sql`${col$1("createdAt")} <= ${endDate.toISOString()}`];
|
|
2325
|
+
if (configId) conditions.push(sql`${col$1("configId")} = ${configId}`);
|
|
2326
|
+
if (variantId) conditions.push(sql`${col$1("variantId")} = ${variantId}`);
|
|
2327
|
+
if (environmentId) conditions.push(sql`${col$1("environmentId")} = ${environmentId}`);
|
|
2301
2328
|
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2302
2329
|
if (values.length === 0) continue;
|
|
2303
|
-
if (values.length === 1) conditions.push(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
2330
|
+
if (values.length === 1) conditions.push(sql`${col$1("tags")}->>${key} = ${values[0]}`);
|
|
2304
2331
|
else {
|
|
2305
2332
|
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2306
|
-
conditions.push(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
2333
|
+
conditions.push(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2307
2334
|
}
|
|
2308
2335
|
}
|
|
2309
2336
|
const whereClause = sql.join(conditions, sql` AND `);
|
|
2310
2337
|
return (await sql`
|
|
2311
2338
|
SELECT t.key || ':' || t.value as "groupKey",
|
|
2312
|
-
COALESCE(SUM(${col("cost")}), 0) as "totalCost",
|
|
2339
|
+
COALESCE(SUM(${col$1("cost")}), 0) as "totalCost",
|
|
2313
2340
|
COUNT(*) as "requestCount"
|
|
2314
|
-
FROM "llm_requests", jsonb_each_text(${col("tags")}) t
|
|
2341
|
+
FROM "llm_requests", jsonb_each_text(${col$1("tags")}) t
|
|
2315
2342
|
WHERE ${whereClause}
|
|
2316
2343
|
GROUP BY t.key, t.value
|
|
2317
|
-
ORDER BY SUM(${col("cost")}) DESC
|
|
2344
|
+
ORDER BY SUM(${col$1("cost")}) DESC
|
|
2318
2345
|
`.execute(db)).rows;
|
|
2319
2346
|
}
|
|
2320
2347
|
default: return baseQuery.select([
|
|
2321
2348
|
sql`'total'`.as("groupKey"),
|
|
2322
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2349
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2323
2350
|
sql`COUNT(*)`.as("requestCount")
|
|
2324
2351
|
]).execute();
|
|
2325
2352
|
}
|
|
@@ -2330,22 +2357,22 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2330
2357
|
const { startDate, endDate, configId, variantId, environmentId, tags } = result.data;
|
|
2331
2358
|
let query = db.selectFrom("llm_requests").select([
|
|
2332
2359
|
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()}`);
|
|
2360
|
+
sql`COUNT(CASE WHEN ${col$1("statusCode")} >= 200 AND ${col$1("statusCode")} < 300 THEN 1 END)`.as("successfulRequests"),
|
|
2361
|
+
sql`COUNT(CASE WHEN ${col$1("statusCode")} >= 400 THEN 1 END)`.as("failedRequests"),
|
|
2362
|
+
sql`COUNT(CASE WHEN ${col$1("isStreaming")} = true THEN 1 END)`.as("streamingRequests"),
|
|
2363
|
+
sql`AVG(${col$1("latencyMs")})`.as("avgLatencyMs"),
|
|
2364
|
+
sql`MAX(${col$1("latencyMs")})`.as("maxLatencyMs"),
|
|
2365
|
+
sql`MIN(${col$1("latencyMs")})`.as("minLatencyMs")
|
|
2366
|
+
]).where(sql`${col$1("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col$1("createdAt")} <= ${endDate.toISOString()}`);
|
|
2340
2367
|
if (configId) query = query.where("configId", "=", configId);
|
|
2341
2368
|
if (variantId) query = query.where("variantId", "=", variantId);
|
|
2342
2369
|
if (environmentId) query = query.where("environmentId", "=", environmentId);
|
|
2343
2370
|
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2344
2371
|
if (values.length === 0) continue;
|
|
2345
|
-
if (values.length === 1) query = query.where(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
2372
|
+
if (values.length === 1) query = query.where(sql`${col$1("tags")}->>${key} = ${values[0]}`);
|
|
2346
2373
|
else {
|
|
2347
2374
|
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2348
|
-
query = query.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
2375
|
+
query = query.where(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2349
2376
|
}
|
|
2350
2377
|
}
|
|
2351
2378
|
return await query.executeTakeFirst();
|
|
@@ -3087,6 +3114,271 @@ const createTargetingRulesDataLayer = (db) => {
|
|
|
3087
3114
|
};
|
|
3088
3115
|
};
|
|
3089
3116
|
|
|
3117
|
+
//#endregion
|
|
3118
|
+
//#region src/datalayer/traces.ts
|
|
3119
|
+
const col = (name) => sql.ref(name);
|
|
3120
|
+
/**
|
|
3121
|
+
* Schema for upserting a trace
|
|
3122
|
+
*/
|
|
3123
|
+
const upsertTraceSchema = zod_default.object({
|
|
3124
|
+
traceId: zod_default.string(),
|
|
3125
|
+
name: zod_default.string().nullable().optional(),
|
|
3126
|
+
sessionId: zod_default.string().nullable().optional(),
|
|
3127
|
+
userId: zod_default.string().nullable().optional(),
|
|
3128
|
+
status: zod_default.enum([
|
|
3129
|
+
"unset",
|
|
3130
|
+
"ok",
|
|
3131
|
+
"error"
|
|
3132
|
+
]).default("unset"),
|
|
3133
|
+
startTime: zod_default.date(),
|
|
3134
|
+
endTime: zod_default.date().nullable().optional(),
|
|
3135
|
+
durationMs: zod_default.number().int().nullable().optional(),
|
|
3136
|
+
spanCount: zod_default.number().int().default(1),
|
|
3137
|
+
totalInputTokens: zod_default.number().int().default(0),
|
|
3138
|
+
totalOutputTokens: zod_default.number().int().default(0),
|
|
3139
|
+
totalTokens: zod_default.number().int().default(0),
|
|
3140
|
+
totalCost: zod_default.number().int().default(0),
|
|
3141
|
+
tags: zod_default.record(zod_default.string(), zod_default.string()).default({}),
|
|
3142
|
+
metadata: zod_default.record(zod_default.string(), zod_default.unknown()).default({})
|
|
3143
|
+
});
|
|
3144
|
+
/**
|
|
3145
|
+
* Schema for inserting spans
|
|
3146
|
+
*/
|
|
3147
|
+
const insertSpanSchema = zod_default.object({
|
|
3148
|
+
traceId: zod_default.string(),
|
|
3149
|
+
spanId: zod_default.string(),
|
|
3150
|
+
parentSpanId: zod_default.string().nullable().optional(),
|
|
3151
|
+
name: zod_default.string(),
|
|
3152
|
+
kind: zod_default.number().int().default(1),
|
|
3153
|
+
status: zod_default.number().int().default(0),
|
|
3154
|
+
statusMessage: zod_default.string().nullable().optional(),
|
|
3155
|
+
startTime: zod_default.date(),
|
|
3156
|
+
endTime: zod_default.date().nullable().optional(),
|
|
3157
|
+
durationMs: zod_default.number().int().nullable().optional(),
|
|
3158
|
+
provider: zod_default.string().nullable().optional(),
|
|
3159
|
+
model: zod_default.string().nullable().optional(),
|
|
3160
|
+
promptTokens: zod_default.number().int().default(0),
|
|
3161
|
+
completionTokens: zod_default.number().int().default(0),
|
|
3162
|
+
totalTokens: zod_default.number().int().default(0),
|
|
3163
|
+
cost: zod_default.number().int().default(0),
|
|
3164
|
+
configId: zod_default.string().uuid().nullable().optional(),
|
|
3165
|
+
variantId: zod_default.string().uuid().nullable().optional(),
|
|
3166
|
+
environmentId: zod_default.string().uuid().nullable().optional(),
|
|
3167
|
+
providerConfigId: zod_default.string().uuid().nullable().optional(),
|
|
3168
|
+
requestId: zod_default.string().uuid().nullable().optional(),
|
|
3169
|
+
source: zod_default.enum(["gateway", "otlp"]).default("gateway"),
|
|
3170
|
+
input: zod_default.unknown().nullable().optional(),
|
|
3171
|
+
output: zod_default.unknown().nullable().optional(),
|
|
3172
|
+
attributes: zod_default.record(zod_default.string(), zod_default.unknown()).default({})
|
|
3173
|
+
});
|
|
3174
|
+
/**
|
|
3175
|
+
* Schema for inserting span events
|
|
3176
|
+
*/
|
|
3177
|
+
const insertSpanEventSchema = zod_default.object({
|
|
3178
|
+
traceId: zod_default.string(),
|
|
3179
|
+
spanId: zod_default.string(),
|
|
3180
|
+
name: zod_default.string(),
|
|
3181
|
+
timestamp: zod_default.date(),
|
|
3182
|
+
attributes: zod_default.record(zod_default.string(), zod_default.unknown()).default({})
|
|
3183
|
+
});
|
|
3184
|
+
/**
|
|
3185
|
+
* Schema for listing traces
|
|
3186
|
+
*/
|
|
3187
|
+
const listTracesSchema = zod_default.object({
|
|
3188
|
+
limit: zod_default.number().int().positive().max(1e3).default(50),
|
|
3189
|
+
offset: zod_default.number().int().nonnegative().default(0),
|
|
3190
|
+
sessionId: zod_default.string().optional(),
|
|
3191
|
+
userId: zod_default.string().optional(),
|
|
3192
|
+
status: zod_default.enum([
|
|
3193
|
+
"unset",
|
|
3194
|
+
"ok",
|
|
3195
|
+
"error"
|
|
3196
|
+
]).optional(),
|
|
3197
|
+
name: zod_default.string().optional(),
|
|
3198
|
+
startDate: zod_default.date().optional(),
|
|
3199
|
+
endDate: zod_default.date().optional(),
|
|
3200
|
+
tags: zod_default.record(zod_default.string(), zod_default.array(zod_default.string())).optional()
|
|
3201
|
+
});
|
|
3202
|
+
/**
|
|
3203
|
+
* Schema for trace stats query
|
|
3204
|
+
*/
|
|
3205
|
+
const traceStatsSchema = zod_default.object({
|
|
3206
|
+
startDate: zod_default.date(),
|
|
3207
|
+
endDate: zod_default.date(),
|
|
3208
|
+
sessionId: zod_default.string().optional(),
|
|
3209
|
+
userId: zod_default.string().optional()
|
|
3210
|
+
});
|
|
3211
|
+
const createTracesDataLayer = (db) => {
|
|
3212
|
+
return {
|
|
3213
|
+
upsertTrace: async (data) => {
|
|
3214
|
+
const result = await upsertTraceSchema.safeParseAsync(data);
|
|
3215
|
+
if (!result.success) throw new LLMOpsError(`Invalid trace data: ${result.error.message}`);
|
|
3216
|
+
const trace = result.data;
|
|
3217
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3218
|
+
await sql`
|
|
3219
|
+
INSERT INTO "traces" (
|
|
3220
|
+
"id", "traceId", "name", "sessionId", "userId", "status",
|
|
3221
|
+
"startTime", "endTime", "durationMs", "spanCount",
|
|
3222
|
+
"totalInputTokens", "totalOutputTokens", "totalTokens", "totalCost",
|
|
3223
|
+
"tags", "metadata", "createdAt", "updatedAt"
|
|
3224
|
+
) VALUES (
|
|
3225
|
+
${randomUUID()}, ${trace.traceId}, ${trace.name ?? null}, ${trace.sessionId ?? null},
|
|
3226
|
+
${trace.userId ?? null}, ${trace.status},
|
|
3227
|
+
${trace.startTime.toISOString()}, ${trace.endTime?.toISOString() ?? null},
|
|
3228
|
+
${trace.durationMs ?? null}, ${trace.spanCount},
|
|
3229
|
+
${trace.totalInputTokens}, ${trace.totalOutputTokens},
|
|
3230
|
+
${trace.totalTokens}, ${trace.totalCost},
|
|
3231
|
+
${JSON.stringify(trace.tags)}::jsonb, ${JSON.stringify(trace.metadata)}::jsonb,
|
|
3232
|
+
${now}, ${now}
|
|
3233
|
+
)
|
|
3234
|
+
ON CONFLICT ("traceId") DO UPDATE SET
|
|
3235
|
+
"name" = COALESCE(EXCLUDED."name", "traces"."name"),
|
|
3236
|
+
"sessionId" = COALESCE(EXCLUDED."sessionId", "traces"."sessionId"),
|
|
3237
|
+
"userId" = COALESCE(EXCLUDED."userId", "traces"."userId"),
|
|
3238
|
+
"status" = CASE
|
|
3239
|
+
WHEN EXCLUDED."status" = 'error' THEN 'error'
|
|
3240
|
+
WHEN EXCLUDED."status" = 'ok' AND "traces"."status" != 'error' THEN 'ok'
|
|
3241
|
+
ELSE "traces"."status"
|
|
3242
|
+
END,
|
|
3243
|
+
"startTime" = LEAST("traces"."startTime", EXCLUDED."startTime"),
|
|
3244
|
+
"endTime" = GREATEST(
|
|
3245
|
+
COALESCE("traces"."endTime", EXCLUDED."endTime"),
|
|
3246
|
+
COALESCE(EXCLUDED."endTime", "traces"."endTime")
|
|
3247
|
+
),
|
|
3248
|
+
"durationMs" = EXTRACT(EPOCH FROM (
|
|
3249
|
+
GREATEST(
|
|
3250
|
+
COALESCE("traces"."endTime", EXCLUDED."endTime"),
|
|
3251
|
+
COALESCE(EXCLUDED."endTime", "traces"."endTime")
|
|
3252
|
+
) -
|
|
3253
|
+
LEAST("traces"."startTime", EXCLUDED."startTime")
|
|
3254
|
+
))::integer * 1000,
|
|
3255
|
+
"spanCount" = "traces"."spanCount" + EXCLUDED."spanCount",
|
|
3256
|
+
"totalInputTokens" = "traces"."totalInputTokens" + EXCLUDED."totalInputTokens",
|
|
3257
|
+
"totalOutputTokens" = "traces"."totalOutputTokens" + EXCLUDED."totalOutputTokens",
|
|
3258
|
+
"totalTokens" = "traces"."totalTokens" + EXCLUDED."totalTokens",
|
|
3259
|
+
"totalCost" = "traces"."totalCost" + EXCLUDED."totalCost",
|
|
3260
|
+
"tags" = "traces"."tags" || EXCLUDED."tags",
|
|
3261
|
+
"metadata" = "traces"."metadata" || EXCLUDED."metadata",
|
|
3262
|
+
"updatedAt" = ${now}
|
|
3263
|
+
`.execute(db);
|
|
3264
|
+
},
|
|
3265
|
+
batchInsertSpans: async (spans) => {
|
|
3266
|
+
if (spans.length === 0) return { count: 0 };
|
|
3267
|
+
const validatedSpans = await Promise.all(spans.map(async (span) => {
|
|
3268
|
+
const result = await insertSpanSchema.safeParseAsync(span);
|
|
3269
|
+
if (!result.success) throw new LLMOpsError(`Invalid span data: ${result.error.message}`);
|
|
3270
|
+
return result.data;
|
|
3271
|
+
}));
|
|
3272
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3273
|
+
const values = validatedSpans.map((span) => ({
|
|
3274
|
+
id: randomUUID(),
|
|
3275
|
+
traceId: span.traceId,
|
|
3276
|
+
spanId: span.spanId,
|
|
3277
|
+
parentSpanId: span.parentSpanId ?? null,
|
|
3278
|
+
name: span.name,
|
|
3279
|
+
kind: span.kind,
|
|
3280
|
+
status: span.status,
|
|
3281
|
+
statusMessage: span.statusMessage ?? null,
|
|
3282
|
+
startTime: span.startTime.toISOString(),
|
|
3283
|
+
endTime: span.endTime?.toISOString() ?? null,
|
|
3284
|
+
durationMs: span.durationMs ?? null,
|
|
3285
|
+
provider: span.provider ?? null,
|
|
3286
|
+
model: span.model ?? null,
|
|
3287
|
+
promptTokens: span.promptTokens,
|
|
3288
|
+
completionTokens: span.completionTokens,
|
|
3289
|
+
totalTokens: span.totalTokens,
|
|
3290
|
+
cost: span.cost,
|
|
3291
|
+
configId: span.configId ?? null,
|
|
3292
|
+
variantId: span.variantId ?? null,
|
|
3293
|
+
environmentId: span.environmentId ?? null,
|
|
3294
|
+
providerConfigId: span.providerConfigId ?? null,
|
|
3295
|
+
requestId: span.requestId ?? null,
|
|
3296
|
+
source: span.source,
|
|
3297
|
+
input: span.input != null ? JSON.stringify(span.input) : null,
|
|
3298
|
+
output: span.output != null ? JSON.stringify(span.output) : null,
|
|
3299
|
+
attributes: JSON.stringify(span.attributes),
|
|
3300
|
+
createdAt: now,
|
|
3301
|
+
updatedAt: now
|
|
3302
|
+
}));
|
|
3303
|
+
await db.insertInto("spans").values(values).onConflict((oc) => oc.column("spanId").doNothing()).execute();
|
|
3304
|
+
return { count: values.length };
|
|
3305
|
+
},
|
|
3306
|
+
batchInsertSpanEvents: async (events) => {
|
|
3307
|
+
if (events.length === 0) return { count: 0 };
|
|
3308
|
+
const validatedEvents = await Promise.all(events.map(async (event) => {
|
|
3309
|
+
const result = await insertSpanEventSchema.safeParseAsync(event);
|
|
3310
|
+
if (!result.success) throw new LLMOpsError(`Invalid span event data: ${result.error.message}`);
|
|
3311
|
+
return result.data;
|
|
3312
|
+
}));
|
|
3313
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3314
|
+
const values = validatedEvents.map((event) => ({
|
|
3315
|
+
id: randomUUID(),
|
|
3316
|
+
traceId: event.traceId,
|
|
3317
|
+
spanId: event.spanId,
|
|
3318
|
+
name: event.name,
|
|
3319
|
+
timestamp: event.timestamp.toISOString(),
|
|
3320
|
+
attributes: JSON.stringify(event.attributes),
|
|
3321
|
+
createdAt: now
|
|
3322
|
+
}));
|
|
3323
|
+
await db.insertInto("span_events").values(values).execute();
|
|
3324
|
+
return { count: values.length };
|
|
3325
|
+
},
|
|
3326
|
+
listTraces: async (params) => {
|
|
3327
|
+
const result = await listTracesSchema.safeParseAsync(params || {});
|
|
3328
|
+
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
3329
|
+
const { limit, offset, sessionId, userId, status, name, startDate, endDate, tags } = result.data;
|
|
3330
|
+
let baseQuery = db.selectFrom("traces");
|
|
3331
|
+
if (sessionId) baseQuery = baseQuery.where("sessionId", "=", sessionId);
|
|
3332
|
+
if (userId) baseQuery = baseQuery.where("userId", "=", userId);
|
|
3333
|
+
if (status) baseQuery = baseQuery.where("status", "=", status);
|
|
3334
|
+
if (name) baseQuery = baseQuery.where(sql`${col("name")} ILIKE ${"%" + name + "%"}`);
|
|
3335
|
+
if (startDate) baseQuery = baseQuery.where(sql`${col("startTime")} >= ${startDate.toISOString()}`);
|
|
3336
|
+
if (endDate) baseQuery = baseQuery.where(sql`${col("startTime")} <= ${endDate.toISOString()}`);
|
|
3337
|
+
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
3338
|
+
if (values.length === 0) continue;
|
|
3339
|
+
if (values.length === 1) baseQuery = baseQuery.where(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
3340
|
+
else {
|
|
3341
|
+
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
3342
|
+
baseQuery = baseQuery.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
3343
|
+
}
|
|
3344
|
+
}
|
|
3345
|
+
const countResult = await baseQuery.select(sql`COUNT(*)`.as("total")).executeTakeFirst();
|
|
3346
|
+
const total = Number(countResult?.total ?? 0);
|
|
3347
|
+
return {
|
|
3348
|
+
data: await baseQuery.selectAll().orderBy("startTime", "desc").limit(limit).offset(offset).execute(),
|
|
3349
|
+
total,
|
|
3350
|
+
limit,
|
|
3351
|
+
offset
|
|
3352
|
+
};
|
|
3353
|
+
},
|
|
3354
|
+
getTraceWithSpans: async (traceId) => {
|
|
3355
|
+
const trace = await db.selectFrom("traces").selectAll().where("traceId", "=", traceId).executeTakeFirst();
|
|
3356
|
+
if (!trace) return void 0;
|
|
3357
|
+
return {
|
|
3358
|
+
trace,
|
|
3359
|
+
spans: await db.selectFrom("spans").selectAll().where("traceId", "=", traceId).orderBy("startTime", "asc").execute(),
|
|
3360
|
+
events: await db.selectFrom("span_events").selectAll().where("traceId", "=", traceId).orderBy("timestamp", "asc").execute()
|
|
3361
|
+
};
|
|
3362
|
+
},
|
|
3363
|
+
getTraceStats: async (params) => {
|
|
3364
|
+
const result = await traceStatsSchema.safeParseAsync(params);
|
|
3365
|
+
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
3366
|
+
const { startDate, endDate, sessionId, userId } = result.data;
|
|
3367
|
+
let query = db.selectFrom("traces").select([
|
|
3368
|
+
sql`COUNT(*)`.as("totalTraces"),
|
|
3369
|
+
sql`COALESCE(AVG(${col("durationMs")}), 0)`.as("avgDurationMs"),
|
|
3370
|
+
sql`COUNT(CASE WHEN ${col("status")} = 'error' THEN 1 END)`.as("errorCount"),
|
|
3371
|
+
sql`COALESCE(SUM(${col("totalCost")}), 0)`.as("totalCost"),
|
|
3372
|
+
sql`COALESCE(SUM(${col("totalTokens")}), 0)`.as("totalTokens"),
|
|
3373
|
+
sql`COALESCE(SUM(${col("spanCount")}), 0)`.as("totalSpans")
|
|
3374
|
+
]).where(sql`${col("startTime")} >= ${startDate.toISOString()}`).where(sql`${col("startTime")} <= ${endDate.toISOString()}`);
|
|
3375
|
+
if (sessionId) query = query.where("sessionId", "=", sessionId);
|
|
3376
|
+
if (userId) query = query.where("userId", "=", userId);
|
|
3377
|
+
return query.executeTakeFirst();
|
|
3378
|
+
}
|
|
3379
|
+
};
|
|
3380
|
+
};
|
|
3381
|
+
|
|
3090
3382
|
//#endregion
|
|
3091
3383
|
//#region src/datalayer/variants.ts
|
|
3092
3384
|
const createVariant = zod_default.object({ name: zod_default.string() });
|
|
@@ -3380,6 +3672,7 @@ function createDataLayer(db) {
|
|
|
3380
3672
|
...createProviderConfigsDataLayer(db),
|
|
3381
3673
|
...createProviderGuardrailOverridesDataLayer(db),
|
|
3382
3674
|
...createTargetingRulesDataLayer(db),
|
|
3675
|
+
...createTracesDataLayer(db),
|
|
3383
3676
|
...createVariantDataLayer(db),
|
|
3384
3677
|
...createVariantVersionsDataLayer(db),
|
|
3385
3678
|
...createWorkspaceSettingsDataLayer(db)
|
|
@@ -3958,4 +4251,4 @@ var ManifestRouter = class {
|
|
|
3958
4251
|
};
|
|
3959
4252
|
|
|
3960
4253
|
//#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 };
|
|
4254
|
+
export { COST_SUMMARY_GROUP_BY, CacheService, DEFAULT_PROVIDER_ENV_VARS, FileCacheBackend, LLMOPS_INTERNAL_HEADER, 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 };
|