@llmops/core 0.5.2 → 0.5.3-beta.2
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-BzoQ1FE5.d.cts} +725 -50
- package/dist/{index-BtSgIKup.d.cts → index-COXQFD62.d.mts} +725 -50
- package/dist/index.cjs +411 -72
- package/dist/index.d.cts +528 -271
- package/dist/index.d.mts +528 -271
- package/dist/index.mjs +399 -72
- 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
|
|
@@ -2024,6 +2042,18 @@ const dateRangeSchema = zod_default.object({
|
|
|
2024
2042
|
tags: zod_default.record(zod_default.string(), zod_default.array(zod_default.string())).optional()
|
|
2025
2043
|
});
|
|
2026
2044
|
/**
|
|
2045
|
+
* Valid groupBy values for cost summary queries
|
|
2046
|
+
*/
|
|
2047
|
+
const COST_SUMMARY_GROUP_BY = [
|
|
2048
|
+
"day",
|
|
2049
|
+
"hour",
|
|
2050
|
+
"model",
|
|
2051
|
+
"provider",
|
|
2052
|
+
"config",
|
|
2053
|
+
"endpoint",
|
|
2054
|
+
"tags"
|
|
2055
|
+
];
|
|
2056
|
+
/**
|
|
2027
2057
|
* Schema for cost summary with grouping
|
|
2028
2058
|
*/
|
|
2029
2059
|
const costSummarySchema = zod_default.object({
|
|
@@ -2033,19 +2063,13 @@ const costSummarySchema = zod_default.object({
|
|
|
2033
2063
|
variantId: zod_default.string().uuid().optional(),
|
|
2034
2064
|
environmentId: zod_default.string().uuid().optional(),
|
|
2035
2065
|
tags: zod_default.record(zod_default.string(), zod_default.array(zod_default.string())).optional(),
|
|
2036
|
-
groupBy: zod_default.enum(
|
|
2037
|
-
"day",
|
|
2038
|
-
"hour",
|
|
2039
|
-
"model",
|
|
2040
|
-
"provider",
|
|
2041
|
-
"config"
|
|
2042
|
-
]).optional()
|
|
2066
|
+
groupBy: zod_default.enum(COST_SUMMARY_GROUP_BY).optional()
|
|
2043
2067
|
});
|
|
2044
2068
|
/**
|
|
2045
2069
|
* Helper to create column reference for SQL
|
|
2046
2070
|
* Uses sql.ref() to properly quote column names for the database
|
|
2047
2071
|
*/
|
|
2048
|
-
const col = (name) => sql.ref(name);
|
|
2072
|
+
const col$1 = (name) => sql.ref(name);
|
|
2049
2073
|
const tableCol = (table, name) => sql.ref(`${table}.${name}`);
|
|
2050
2074
|
const createLLMRequestsDataLayer = (db) => {
|
|
2051
2075
|
return {
|
|
@@ -2080,6 +2104,10 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2080
2104
|
userId: req.userId ?? null,
|
|
2081
2105
|
tags: JSON.stringify(req.tags),
|
|
2082
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,
|
|
2083
2111
|
createdAt: now,
|
|
2084
2112
|
updatedAt: now
|
|
2085
2113
|
}));
|
|
@@ -2114,6 +2142,10 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2114
2142
|
userId: req.userId ?? null,
|
|
2115
2143
|
tags: JSON.stringify(req.tags),
|
|
2116
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,
|
|
2117
2149
|
createdAt: now,
|
|
2118
2150
|
updatedAt: now
|
|
2119
2151
|
}).returningAll().executeTakeFirst();
|
|
@@ -2129,14 +2161,14 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2129
2161
|
if (providerConfigId) baseQuery = baseQuery.where("providerConfigId", "=", providerConfigId);
|
|
2130
2162
|
if (provider) baseQuery = baseQuery.where("provider", "=", provider);
|
|
2131
2163
|
if (model) baseQuery = baseQuery.where("model", "=", model);
|
|
2132
|
-
if (startDate) baseQuery = baseQuery.where(sql`${col("createdAt")} >= ${startDate.toISOString()}`);
|
|
2133
|
-
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()}`);
|
|
2134
2166
|
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2135
2167
|
if (values.length === 0) continue;
|
|
2136
|
-
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]}`);
|
|
2137
2169
|
else {
|
|
2138
2170
|
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2139
|
-
baseQuery = baseQuery.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
2171
|
+
baseQuery = baseQuery.where(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2140
2172
|
}
|
|
2141
2173
|
}
|
|
2142
2174
|
const countResult = await baseQuery.select(sql`COUNT(*)`.as("total")).executeTakeFirst();
|
|
@@ -2156,23 +2188,23 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2156
2188
|
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
2157
2189
|
const { startDate, endDate, configId, variantId, environmentId, tags } = result.data;
|
|
2158
2190
|
let query = db.selectFrom("llm_requests").select([
|
|
2159
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2160
|
-
sql`COALESCE(SUM(${col("inputCost")}), 0)`.as("totalInputCost"),
|
|
2161
|
-
sql`COALESCE(SUM(${col("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2162
|
-
sql`COALESCE(SUM(${col("promptTokens")}), 0)`.as("totalPromptTokens"),
|
|
2163
|
-
sql`COALESCE(SUM(${col("completionTokens")}), 0)`.as("totalCompletionTokens"),
|
|
2164
|
-
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"),
|
|
2165
2197
|
sql`COUNT(*)`.as("requestCount")
|
|
2166
|
-
]).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()}`);
|
|
2167
2199
|
if (configId) query = query.where("configId", "=", configId);
|
|
2168
2200
|
if (variantId) query = query.where("variantId", "=", variantId);
|
|
2169
2201
|
if (environmentId) query = query.where("environmentId", "=", environmentId);
|
|
2170
2202
|
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2171
2203
|
if (values.length === 0) continue;
|
|
2172
|
-
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]}`);
|
|
2173
2205
|
else {
|
|
2174
2206
|
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2175
|
-
query = query.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
2207
|
+
query = query.where(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2176
2208
|
}
|
|
2177
2209
|
}
|
|
2178
2210
|
return await query.executeTakeFirst();
|
|
@@ -2184,13 +2216,13 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2184
2216
|
return db.selectFrom("llm_requests").select([
|
|
2185
2217
|
"provider",
|
|
2186
2218
|
"model",
|
|
2187
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2188
|
-
sql`COALESCE(SUM(${col("inputCost")}), 0)`.as("totalInputCost"),
|
|
2189
|
-
sql`COALESCE(SUM(${col("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2190
|
-
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"),
|
|
2191
2223
|
sql`COUNT(*)`.as("requestCount"),
|
|
2192
|
-
sql`AVG(${col("latencyMs")})`.as("avgLatencyMs")
|
|
2193
|
-
]).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();
|
|
2194
2226
|
},
|
|
2195
2227
|
getCostByProvider: async (params) => {
|
|
2196
2228
|
const result = await dateRangeSchema.safeParseAsync(params);
|
|
@@ -2198,13 +2230,13 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2198
2230
|
const { startDate, endDate } = result.data;
|
|
2199
2231
|
return db.selectFrom("llm_requests").select([
|
|
2200
2232
|
"provider",
|
|
2201
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2202
|
-
sql`COALESCE(SUM(${col("inputCost")}), 0)`.as("totalInputCost"),
|
|
2203
|
-
sql`COALESCE(SUM(${col("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2204
|
-
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"),
|
|
2205
2237
|
sql`COUNT(*)`.as("requestCount"),
|
|
2206
|
-
sql`AVG(${col("latencyMs")})`.as("avgLatencyMs")
|
|
2207
|
-
]).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();
|
|
2208
2240
|
},
|
|
2209
2241
|
getCostByConfig: async (params) => {
|
|
2210
2242
|
const result = await dateRangeSchema.safeParseAsync(params);
|
|
@@ -2230,61 +2262,90 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2230
2262
|
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
2231
2263
|
const { startDate, endDate } = result.data;
|
|
2232
2264
|
return db.selectFrom("llm_requests").select([
|
|
2233
|
-
sql`DATE(${col("createdAt")})`.as("date"),
|
|
2234
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2235
|
-
sql`COALESCE(SUM(${col("inputCost")}), 0)`.as("totalInputCost"),
|
|
2236
|
-
sql`COALESCE(SUM(${col("outputCost")}), 0)`.as("totalOutputCost"),
|
|
2237
|
-
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"),
|
|
2238
2270
|
sql`COUNT(*)`.as("requestCount")
|
|
2239
|
-
]).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();
|
|
2240
2272
|
},
|
|
2241
2273
|
getCostSummary: async (params) => {
|
|
2242
2274
|
const result = await costSummarySchema.safeParseAsync(params);
|
|
2243
2275
|
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
2244
2276
|
const { startDate, endDate, groupBy, configId, variantId, environmentId, tags } = result.data;
|
|
2245
|
-
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()}`);
|
|
2246
2278
|
if (configId) baseQuery = baseQuery.where("configId", "=", configId);
|
|
2247
2279
|
if (variantId) baseQuery = baseQuery.where("variantId", "=", variantId);
|
|
2248
2280
|
if (environmentId) baseQuery = baseQuery.where("environmentId", "=", environmentId);
|
|
2249
2281
|
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2250
2282
|
if (values.length === 0) continue;
|
|
2251
|
-
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]}`);
|
|
2252
2284
|
else {
|
|
2253
2285
|
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2254
|
-
baseQuery = baseQuery.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
2286
|
+
baseQuery = baseQuery.where(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2255
2287
|
}
|
|
2256
2288
|
}
|
|
2257
2289
|
switch (groupBy) {
|
|
2258
2290
|
case "day": return baseQuery.select([
|
|
2259
|
-
sql`DATE(${col("createdAt")})`.as("groupKey"),
|
|
2260
|
-
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"),
|
|
2261
2293
|
sql`COUNT(*)`.as("requestCount"),
|
|
2262
|
-
sql`COALESCE(SUM(${col("totalTokens")}), 0)`.as("totalTokens")
|
|
2263
|
-
]).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();
|
|
2264
2296
|
case "hour": return baseQuery.select([
|
|
2265
|
-
sql`DATE_TRUNC('hour', ${col("createdAt")})`.as("groupKey"),
|
|
2266
|
-
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"),
|
|
2267
2299
|
sql`COUNT(*)`.as("requestCount"),
|
|
2268
|
-
sql`COALESCE(SUM(${col("totalTokens")}), 0)`.as("totalTokens")
|
|
2269
|
-
]).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();
|
|
2270
2302
|
case "model": return baseQuery.select([
|
|
2271
|
-
sql`${col("provider")} || '/' || ${col("model")}`.as("groupKey"),
|
|
2272
|
-
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"),
|
|
2273
2305
|
sql`COUNT(*)`.as("requestCount")
|
|
2274
|
-
]).groupBy(["provider", "model"]).orderBy(sql`SUM(${col("cost")})`, "desc").execute();
|
|
2306
|
+
]).groupBy(["provider", "model"]).orderBy(sql`SUM(${col$1("cost")})`, "desc").execute();
|
|
2275
2307
|
case "provider": return baseQuery.select([
|
|
2276
|
-
sql`${col("provider")}`.as("groupKey"),
|
|
2277
|
-
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"),
|
|
2278
2310
|
sql`COUNT(*)`.as("requestCount")
|
|
2279
|
-
]).groupBy("provider").orderBy(sql`SUM(${col("cost")})`, "desc").execute();
|
|
2311
|
+
]).groupBy("provider").orderBy(sql`SUM(${col$1("cost")})`, "desc").execute();
|
|
2280
2312
|
case "config": return baseQuery.select([
|
|
2281
|
-
sql`COALESCE(${col("configId")}::text, 'no-config')`.as("groupKey"),
|
|
2282
|
-
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"),
|
|
2315
|
+
sql`COUNT(*)`.as("requestCount")
|
|
2316
|
+
]).groupBy("configId").orderBy(sql`SUM(${col$1("cost")})`, "desc").execute();
|
|
2317
|
+
case "endpoint": return baseQuery.select([
|
|
2318
|
+
sql`COALESCE(${col$1("endpoint")}, 'unknown')`.as("groupKey"),
|
|
2319
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2283
2320
|
sql`COUNT(*)`.as("requestCount")
|
|
2284
|
-
]).groupBy("
|
|
2321
|
+
]).groupBy("endpoint").orderBy(sql`SUM(${col$1("cost")})`, "desc").execute();
|
|
2322
|
+
case "tags": {
|
|
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}`);
|
|
2327
|
+
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2328
|
+
if (values.length === 0) continue;
|
|
2329
|
+
if (values.length === 1) conditions.push(sql`${col$1("tags")}->>${key} = ${values[0]}`);
|
|
2330
|
+
else {
|
|
2331
|
+
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2332
|
+
conditions.push(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
const whereClause = sql.join(conditions, sql` AND `);
|
|
2336
|
+
return (await sql`
|
|
2337
|
+
SELECT t.key || ':' || t.value as "groupKey",
|
|
2338
|
+
COALESCE(SUM(${col$1("cost")}), 0) as "totalCost",
|
|
2339
|
+
COUNT(*) as "requestCount"
|
|
2340
|
+
FROM "llm_requests", jsonb_each_text(${col$1("tags")}) t
|
|
2341
|
+
WHERE ${whereClause}
|
|
2342
|
+
GROUP BY t.key, t.value
|
|
2343
|
+
ORDER BY SUM(${col$1("cost")}) DESC
|
|
2344
|
+
`.execute(db)).rows;
|
|
2345
|
+
}
|
|
2285
2346
|
default: return baseQuery.select([
|
|
2286
2347
|
sql`'total'`.as("groupKey"),
|
|
2287
|
-
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
2348
|
+
sql`COALESCE(SUM(${col$1("cost")}), 0)`.as("totalCost"),
|
|
2288
2349
|
sql`COUNT(*)`.as("requestCount")
|
|
2289
2350
|
]).execute();
|
|
2290
2351
|
}
|
|
@@ -2295,22 +2356,22 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
2295
2356
|
const { startDate, endDate, configId, variantId, environmentId, tags } = result.data;
|
|
2296
2357
|
let query = db.selectFrom("llm_requests").select([
|
|
2297
2358
|
sql`COUNT(*)`.as("totalRequests"),
|
|
2298
|
-
sql`COUNT(CASE WHEN ${col("statusCode")} >= 200 AND ${col("statusCode")} < 300 THEN 1 END)`.as("successfulRequests"),
|
|
2299
|
-
sql`COUNT(CASE WHEN ${col("statusCode")} >= 400 THEN 1 END)`.as("failedRequests"),
|
|
2300
|
-
sql`COUNT(CASE WHEN ${col("isStreaming")} = true THEN 1 END)`.as("streamingRequests"),
|
|
2301
|
-
sql`AVG(${col("latencyMs")})`.as("avgLatencyMs"),
|
|
2302
|
-
sql`MAX(${col("latencyMs")})`.as("maxLatencyMs"),
|
|
2303
|
-
sql`MIN(${col("latencyMs")})`.as("minLatencyMs")
|
|
2304
|
-
]).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()}`);
|
|
2305
2366
|
if (configId) query = query.where("configId", "=", configId);
|
|
2306
2367
|
if (variantId) query = query.where("variantId", "=", variantId);
|
|
2307
2368
|
if (environmentId) query = query.where("environmentId", "=", environmentId);
|
|
2308
2369
|
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
2309
2370
|
if (values.length === 0) continue;
|
|
2310
|
-
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]}`);
|
|
2311
2372
|
else {
|
|
2312
2373
|
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
2313
|
-
query = query.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
2374
|
+
query = query.where(sql`${col$1("tags")}->>${key} IN (${valueList})`);
|
|
2314
2375
|
}
|
|
2315
2376
|
}
|
|
2316
2377
|
return await query.executeTakeFirst();
|
|
@@ -3052,6 +3113,271 @@ const createTargetingRulesDataLayer = (db) => {
|
|
|
3052
3113
|
};
|
|
3053
3114
|
};
|
|
3054
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
|
+
|
|
3055
3381
|
//#endregion
|
|
3056
3382
|
//#region src/datalayer/variants.ts
|
|
3057
3383
|
const createVariant = zod_default.object({ name: zod_default.string() });
|
|
@@ -3345,6 +3671,7 @@ function createDataLayer(db) {
|
|
|
3345
3671
|
...createProviderConfigsDataLayer(db),
|
|
3346
3672
|
...createProviderGuardrailOverridesDataLayer(db),
|
|
3347
3673
|
...createTargetingRulesDataLayer(db),
|
|
3674
|
+
...createTracesDataLayer(db),
|
|
3348
3675
|
...createVariantDataLayer(db),
|
|
3349
3676
|
...createVariantVersionsDataLayer(db),
|
|
3350
3677
|
...createWorkspaceSettingsDataLayer(db)
|
|
@@ -3923,4 +4250,4 @@ var ManifestRouter = class {
|
|
|
3923
4250
|
};
|
|
3924
4251
|
|
|
3925
4252
|
//#endregion
|
|
3926
|
-
export { 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 };
|