Skip to content

Commit a04bcf0

Browse files
suryaiyer95claude
andcommitted
feat: [AI-5975] add sql_quality telemetry for issue prevention metrics
Add a new `sql_quality` telemetry event that fires whenever tools successfully detect SQL issues — turning findings into measurable "issues prevented" data in App Insights. Architecture: - New `sql_quality` event type in `Telemetry.Event` with `finding_count`, `by_severity`, `by_category`, `has_schema`, `dialect`, `duration_ms` - New `Telemetry.Finding` interface and `aggregateFindings()` helper - Centralized emission in `tool.ts` — checks `metadata.findings` array after any tool completes, aggregates counts, emits event - Tools populate `metadata.findings` with `{category, severity}` pairs: - `sql_analyze`: issue type + severity from lint/semantic/safety analysis - `altimate_core_validate`: classified validation errors (missing_table, missing_column, syntax_error, type_mismatch) - `altimate_core_semantics`: rule/type + severity from semantic checks - `altimate_core_fix`: fix_applied / unfixable_error categories - `altimate_core_correct`: correction_applied findings - `altimate_core_equivalence`: equivalence_difference findings PII-safe: only category names and severity levels flow to telemetry, never SQL content. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 12ed190 commit a04bcf0

9 files changed

Lines changed: 394 additions & 11 deletions

File tree

packages/opencode/src/altimate/telemetry/index.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,23 @@ export namespace Telemetry {
405405
masked_args?: string
406406
duration_ms: number
407407
}
408+
// altimate_change start — sql quality telemetry for issue prevention metrics
409+
| {
410+
type: "sql_quality"
411+
timestamp: number
412+
session_id: string
413+
tool_name: string
414+
tool_category: string
415+
finding_count: number
416+
/** JSON-encoded Record<string, number> — count per severity level */
417+
by_severity: string
418+
/** JSON-encoded Record<string, number> — count per issue category */
419+
by_category: string
420+
has_schema: boolean
421+
dialect: string
422+
duration_ms: number
423+
}
424+
// altimate_change end
408425

409426
const ERROR_PATTERNS: Array<{
410427
class: Telemetry.Event & { type: "core_failure" } extends { error_class: infer C } ? C : never
@@ -774,6 +791,28 @@ export namespace Telemetry {
774791
}
775792
}
776793

794+
// altimate_change start — sql quality telemetry types
795+
/** Lightweight finding record for quality telemetry. Only category/severity — never SQL content. */
796+
export interface Finding {
797+
category: string
798+
severity: string
799+
}
800+
801+
/** Aggregate an array of findings into counts suitable for the sql_quality event. */
802+
export function aggregateFindings(findings: Finding[]): {
803+
by_severity: Record<string, number>
804+
by_category: Record<string, number>
805+
} {
806+
const by_severity: Record<string, number> = {}
807+
const by_category: Record<string, number> = {}
808+
for (const f of findings) {
809+
by_severity[f.severity] = (by_severity[f.severity] ?? 0) + 1
810+
by_category[f.category] = (by_category[f.category] ?? 0) + 1
811+
}
812+
return { by_severity, by_category }
813+
}
814+
// altimate_change end
815+
777816
export async function shutdown() {
778817
// Wait for init to complete so we know whether telemetry is enabled
779818
// and have a valid endpoint to flush to. init() is fire-and-forget

packages/opencode/src/altimate/tools/altimate-core-correct.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import z from "zod"
22
import { Tool } from "../../tool/tool"
33
import { Dispatcher } from "../native"
4+
import type { Telemetry } from "../telemetry"
45

56
export const AltimateCoreCorrectTool = Tool.define("altimate_core_correct", {
67
description:
@@ -11,21 +12,34 @@ export const AltimateCoreCorrectTool = Tool.define("altimate_core_correct", {
1112
schema_context: z.record(z.string(), z.any()).optional().describe("Inline schema definition"),
1213
}),
1314
async execute(args, ctx) {
15+
const hasSchema = !!(args.schema_path || (args.schema_context && Object.keys(args.schema_context).length > 0))
1416
try {
1517
const result = await Dispatcher.call("altimate_core.correct", {
1618
sql: args.sql,
1719
schema_path: args.schema_path ?? "",
1820
schema_context: args.schema_context,
1921
})
2022
const data = result.data as Record<string, any>
23+
// altimate_change start — sql quality findings for telemetry
24+
const findings: Telemetry.Finding[] = (data.changes ?? []).map(() => ({
25+
category: "correction_applied" as const,
26+
severity: "warning" as const,
27+
}))
28+
// altimate_change end
2129
return {
2230
title: `Correct: ${data.success ? "CORRECTED" : "COULD NOT CORRECT"}`,
23-
metadata: { success: result.success, iterations: data.iterations },
31+
metadata: {
32+
success: result.success,
33+
iterations: data.iterations,
34+
has_schema: hasSchema,
35+
dialect: "snowflake",
36+
...(findings.length > 0 && { findings }),
37+
},
2438
output: formatCorrect(data),
2539
}
2640
} catch (e) {
2741
const msg = e instanceof Error ? e.message : String(e)
28-
return { title: "Correct: ERROR", metadata: { success: false, iterations: 0 }, output: `Failed: ${msg}` }
42+
return { title: "Correct: ERROR", metadata: { success: false, iterations: 0, has_schema: hasSchema, dialect: "snowflake" }, output: `Failed: ${msg}` }
2943
}
3044
},
3145
})

packages/opencode/src/altimate/tools/altimate-core-equivalence.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import z from "zod"
22
import { Tool } from "../../tool/tool"
33
import { Dispatcher } from "../native"
4+
import type { Telemetry } from "../telemetry"
45

56
export const AltimateCoreEquivalenceTool = Tool.define("altimate_core_equivalence", {
67
description:
@@ -12,6 +13,7 @@ export const AltimateCoreEquivalenceTool = Tool.define("altimate_core_equivalenc
1213
schema_context: z.record(z.string(), z.any()).optional().describe("Inline schema definition"),
1314
}),
1415
async execute(args, ctx) {
16+
const hasSchema = !!(args.schema_path || (args.schema_context && Object.keys(args.schema_context).length > 0))
1517
try {
1618
const result = await Dispatcher.call("altimate_core.equivalence", {
1719
sql1: args.sql1,
@@ -20,14 +22,28 @@ export const AltimateCoreEquivalenceTool = Tool.define("altimate_core_equivalenc
2022
schema_context: args.schema_context,
2123
})
2224
const data = result.data as Record<string, any>
25+
// altimate_change start — sql quality findings for telemetry
26+
const findings: Telemetry.Finding[] = []
27+
if (!data.equivalent && data.differences?.length) {
28+
for (const d of data.differences) {
29+
findings.push({ category: "equivalence_difference", severity: "warning" })
30+
}
31+
}
32+
// altimate_change end
2333
return {
2434
title: `Equivalence: ${data.equivalent ? "EQUIVALENT" : "DIFFERENT"}`,
25-
metadata: { success: result.success, equivalent: data.equivalent },
35+
metadata: {
36+
success: result.success,
37+
equivalent: data.equivalent,
38+
has_schema: hasSchema,
39+
dialect: "snowflake",
40+
...(findings.length > 0 && { findings }),
41+
},
2642
output: formatEquivalence(data),
2743
}
2844
} catch (e) {
2945
const msg = e instanceof Error ? e.message : String(e)
30-
return { title: "Equivalence: ERROR", metadata: { success: false, equivalent: false }, output: `Failed: ${msg}` }
46+
return { title: "Equivalence: ERROR", metadata: { success: false, equivalent: false, has_schema: hasSchema, dialect: "snowflake" }, output: `Failed: ${msg}` }
3147
}
3248
},
3349
})

packages/opencode/src/altimate/tools/altimate-core-fix.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import z from "zod"
22
import { Tool } from "../../tool/tool"
33
import { Dispatcher } from "../native"
4+
import type { Telemetry } from "../telemetry"
45

56
export const AltimateCoreFixTool = Tool.define("altimate_core_fix", {
67
description:
@@ -12,6 +13,7 @@ export const AltimateCoreFixTool = Tool.define("altimate_core_fix", {
1213
max_iterations: z.number().optional().describe("Maximum fix iterations (default: 5)"),
1314
}),
1415
async execute(args, ctx) {
16+
const hasSchema = !!(args.schema_path || (args.schema_context && Object.keys(args.schema_context).length > 0))
1517
try {
1618
const result = await Dispatcher.call("altimate_core.fix", {
1719
sql: args.sql,
@@ -20,14 +22,29 @@ export const AltimateCoreFixTool = Tool.define("altimate_core_fix", {
2022
max_iterations: args.max_iterations ?? 5,
2123
})
2224
const data = result.data as Record<string, any>
25+
// altimate_change start — sql quality findings for telemetry
26+
const findings: Telemetry.Finding[] = []
27+
for (const fix of data.fixes_applied ?? data.changes ?? []) {
28+
findings.push({ category: "fix_applied", severity: "warning" })
29+
}
30+
for (const err of data.unfixable_errors ?? []) {
31+
findings.push({ category: "unfixable_error", severity: "error" })
32+
}
33+
// altimate_change end
2334
return {
2435
title: `Fix: ${data.success ? "FIXED" : "COULD NOT FIX"}`,
25-
metadata: { success: result.success, fixed: !!data.fixed_sql },
36+
metadata: {
37+
success: result.success,
38+
fixed: !!data.fixed_sql,
39+
has_schema: hasSchema,
40+
dialect: "snowflake",
41+
...(findings.length > 0 && { findings }),
42+
},
2643
output: formatFix(data),
2744
}
2845
} catch (e) {
2946
const msg = e instanceof Error ? e.message : String(e)
30-
return { title: "Fix: ERROR", metadata: { success: false, fixed: false }, output: `Failed: ${msg}` }
47+
return { title: "Fix: ERROR", metadata: { success: false, fixed: false, has_schema: hasSchema, dialect: "snowflake" }, output: `Failed: ${msg}` }
3148
}
3249
},
3350
})

packages/opencode/src/altimate/tools/altimate-core-semantics.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import z from "zod"
22
import { Tool } from "../../tool/tool"
33
import { Dispatcher } from "../native"
4+
import type { Telemetry } from "../telemetry"
45

56
export const AltimateCoreSemanticsTool = Tool.define("altimate_core_semantics", {
67
description:
@@ -11,6 +12,7 @@ export const AltimateCoreSemanticsTool = Tool.define("altimate_core_semantics",
1112
schema_context: z.record(z.string(), z.any()).optional().describe("Inline schema definition"),
1213
}),
1314
async execute(args, ctx) {
15+
const hasSchema = !!(args.schema_path || (args.schema_context && Object.keys(args.schema_context).length > 0))
1416
try {
1517
const result = await Dispatcher.call("altimate_core.semantics", {
1618
sql: args.sql,
@@ -19,14 +21,27 @@ export const AltimateCoreSemanticsTool = Tool.define("altimate_core_semantics",
1921
})
2022
const data = result.data as Record<string, any>
2123
const issueCount = data.issues?.length ?? 0
24+
// altimate_change start — sql quality findings for telemetry
25+
const findings: Telemetry.Finding[] = (data.issues ?? []).map((issue: any) => ({
26+
category: issue.rule ?? issue.type ?? "semantic_issue",
27+
severity: issue.severity ?? "warning",
28+
}))
29+
// altimate_change end
2230
return {
2331
title: `Semantics: ${data.valid ? "VALID" : `${issueCount} issues`}`,
24-
metadata: { success: result.success, valid: data.valid, issue_count: issueCount },
32+
metadata: {
33+
success: result.success,
34+
valid: data.valid,
35+
issue_count: issueCount,
36+
has_schema: hasSchema,
37+
dialect: "snowflake",
38+
...(findings.length > 0 && { findings }),
39+
},
2540
output: formatSemantics(data),
2641
}
2742
} catch (e) {
2843
const msg = e instanceof Error ? e.message : String(e)
29-
return { title: "Semantics: ERROR", metadata: { success: false, valid: false, issue_count: 0 }, output: `Failed: ${msg}` }
44+
return { title: "Semantics: ERROR", metadata: { success: false, valid: false, issue_count: 0, has_schema: hasSchema, dialect: "snowflake" }, output: `Failed: ${msg}` }
3045
}
3146
},
3247
})

packages/opencode/src/altimate/tools/altimate-core-validate.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import z from "zod"
22
import { Tool } from "../../tool/tool"
33
import { Dispatcher } from "../native"
4+
import type { Telemetry } from "../telemetry"
45

56
export const AltimateCoreValidateTool = Tool.define("altimate_core_validate", {
67
description:
@@ -11,25 +12,48 @@ export const AltimateCoreValidateTool = Tool.define("altimate_core_validate", {
1112
schema_context: z.record(z.string(), z.any()).optional().describe("Inline schema definition"),
1213
}),
1314
async execute(args, ctx) {
15+
const hasSchema = !!(args.schema_path || (args.schema_context && Object.keys(args.schema_context).length > 0))
1416
try {
1517
const result = await Dispatcher.call("altimate_core.validate", {
1618
sql: args.sql,
1719
schema_path: args.schema_path ?? "",
1820
schema_context: args.schema_context,
1921
})
2022
const data = result.data as Record<string, any>
23+
// altimate_change start — sql quality findings for telemetry
24+
const findings: Telemetry.Finding[] = (data.errors ?? []).map((err: any) => ({
25+
category: classifyValidationError(err.message ?? ""),
26+
severity: "error",
27+
}))
28+
// altimate_change end
2129
return {
2230
title: `Validate: ${data.valid ? "VALID" : "INVALID"}`,
23-
metadata: { success: result.success, valid: data.valid },
31+
metadata: {
32+
success: result.success,
33+
valid: data.valid,
34+
has_schema: hasSchema,
35+
dialect: "snowflake",
36+
...(findings.length > 0 && { findings }),
37+
},
2438
output: formatValidate(data),
2539
}
2640
} catch (e) {
2741
const msg = e instanceof Error ? e.message : String(e)
28-
return { title: "Validate: ERROR", metadata: { success: false, valid: false }, output: `Failed: ${msg}` }
42+
return { title: "Validate: ERROR", metadata: { success: false, valid: false, has_schema: hasSchema, dialect: "snowflake" }, output: `Failed: ${msg}` }
2943
}
3044
},
3145
})
3246

47+
function classifyValidationError(message: string): string {
48+
const lower = message.toLowerCase()
49+
// Column check before table — "column not found in table" would match both
50+
if (lower.includes("column") && lower.includes("not found")) return "missing_column"
51+
if (lower.includes("table") && lower.includes("not found")) return "missing_table"
52+
if (lower.includes("syntax")) return "syntax_error"
53+
if (lower.includes("type")) return "type_mismatch"
54+
return "validation_error"
55+
}
56+
3357
function formatValidate(data: Record<string, any>): string {
3458
if (data.error) return `Error: ${data.error}`
3559
if (data.valid) return "SQL is valid."

packages/opencode/src/altimate/tools/sql-analyze.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import z from "zod"
22
import { Tool } from "../../tool/tool"
33
import { Dispatcher } from "../native"
4+
import type { Telemetry } from "../telemetry"
45
import type { SqlAnalyzeResult } from "../native/types"
56

67
export const SqlAnalyzeTool = Tool.define("sql_analyze", {
@@ -21,21 +22,30 @@ export const SqlAnalyzeTool = Tool.define("sql_analyze", {
2122
dialect: args.dialect,
2223
})
2324

25+
// altimate_change start — sql quality findings for telemetry
26+
const findings: Telemetry.Finding[] = result.issues.map((issue) => ({
27+
category: issue.type,
28+
severity: issue.severity,
29+
}))
30+
// altimate_change end
2431
return {
2532
title: `Analyze: ${result.error ? "PARSE ERROR" : `${result.issue_count} issue${result.issue_count !== 1 ? "s" : ""}`} [${result.confidence}]`,
2633
metadata: {
2734
success: result.success,
2835
issueCount: result.issue_count,
2936
confidence: result.confidence,
37+
dialect: args.dialect,
38+
has_schema: false,
3039
...(result.error && { error: result.error }),
40+
...(findings.length > 0 && { findings }),
3141
},
3242
output: formatAnalysis(result),
3343
}
3444
} catch (e) {
3545
const msg = e instanceof Error ? e.message : String(e)
3646
return {
3747
title: "Analyze: ERROR",
38-
metadata: { success: false, issueCount: 0, confidence: "unknown", error: msg },
48+
metadata: { success: false, issueCount: 0, confidence: "unknown", dialect: args.dialect, has_schema: false, error: msg },
3949
output: `Failed to analyze SQL: ${msg}\n\nCheck your connection configuration and try again.`,
4050
}
4151
}

packages/opencode/src/tool/tool.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,25 @@ export namespace Tool {
156156
duration_ms: durationMs,
157157
})
158158
}
159+
// altimate_change start — emit sql_quality when tools report findings
160+
const findings = result.metadata?.findings as Telemetry.Finding[] | undefined
161+
if (Array.isArray(findings) && findings.length > 0) {
162+
const { by_severity, by_category } = Telemetry.aggregateFindings(findings)
163+
Telemetry.track({
164+
type: "sql_quality",
165+
timestamp: Date.now(),
166+
session_id: ctx.sessionID,
167+
tool_name: id,
168+
tool_category: toolCategory,
169+
finding_count: findings.length,
170+
by_severity: JSON.stringify(by_severity),
171+
by_category: JSON.stringify(by_category),
172+
has_schema: result.metadata?.has_schema ?? false,
173+
dialect: (result.metadata?.dialect as string) ?? "unknown",
174+
duration_ms: durationMs,
175+
})
176+
}
177+
// altimate_change end
159178
} catch {
160179
// Telemetry must never break tool execution
161180
}

0 commit comments

Comments
 (0)