dq-score-trend
Monitor trends in data quality scores over time, including completeness, freshness, validity, and anomaly-free metrics, to identify degradation or improvement.
Instructions
Time-series of the 4-axis DQ score (completeness / freshness / validity / anomaly_free) plus overall_score from DQ_SCORE_TABLE
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| scope | No | Scope filter (only honored when DQ_SCHEMA=generic) |
Implementation Reference
- src/tools/quality-scores.ts:11-41 (handler)Core handler: builds and executes a SQL query against DQ_SCORE_TABLE to return time-series of 4-axis DQ scores (completeness, freshness, validity, anomaly_free) plus overall_score, filtered by a configurable day window and optional scope.
export async function dqScoreTrend(args: z.infer<typeof dqScoreTrendSchema>): Promise<unknown> { const flavor = getDqFlavor(); const cols = getDqColumns(flavor); const backend = config.dq.backend; const filters: string[] = []; const params: unknown[] = []; filters.push(tableTimeWindowSql(flavor, backend, "DAY")); params.push(args.days); if (args.scope && hasScope(flavor)) { filters.push(`${cols.scope} = ?`); params.push(args.scope); } const where = "WHERE " + filters.join(" AND "); const scopeSelect = cols.scope ? `${cols.scope} AS scope, ` : ""; const orderBy = cols.scope ? `${cols.scoreDate} DESC, ${cols.scope}` : `${cols.scoreDate} DESC`; const sql = ` SELECT ${cols.scoreDate} AS score_date, ${scopeSelect} completeness_pct, freshness_pct, validity_pct, anomaly_free_pct, overall_score FROM ${scoreTable()} ${where} ORDER BY ${orderBy}`; const result = await dqQuery(sql, params); const caveats: string[] = []; if (args.scope && !hasScope(flavor)) { caveats.push(`DQ_SCHEMA=${flavor} does not have a scope column — scope filter ignored`); } return { ...result, schema: flavor, caveats }; } - src/tools/quality-scores.ts:6-9 (schema)Zod schema for input validation: accepts 'days' (1-365, default 14) and optional 'scope' string filter.
export const dqScoreTrendSchema = z.object({ days: z.coerce.number().int().min(1).max(365).default(14), scope: z.string().optional().describe("Scope filter (only honored when DQ_SCHEMA=generic)"), }); - src/index.ts:103-103 (registration)Registration of the tool under the 'quality' category via the local 'tool()' helper, which registers with the registry and conditionally adds it to the MCP server.
tool("dq-score-trend", "Time-series of the 4-axis DQ score (completeness / freshness / validity / anomaly_free) plus overall_score from DQ_SCORE_TABLE", dqScoreTrendSchema.shape, wrapToolHandler(dqScoreTrend)); - src/index.ts:41-44 (registration)Import of dqScoreTrendSchema and dqScoreTrend from the quality-scores module into the main index.
import { dqScoreTrendSchema, dqScoreTrend, dqTierStatusSchema, dqTierStatus, } from "./tools/quality-scores.js"; - src/clients/dq-store.ts:97-104 (helper)Helper function that executes the SQL query against the configured backend (Postgres or BigQuery) and returns typed results.
export async function dqQuery(sql: string, params: unknown[] = []): Promise<DqQueryResult> { if (!config.dq.resultsTable) { throw new ConfigMissingError("DQ_RESULTS_TABLE", "Quality category tools"); } const driver = await getDriver(); const rows = await driver.query(sql, params); return { rows, rowCount: rows.length, backend: config.dq.backend, query: sql }; }