feat(telemetry): generic feature-usage telemetry with AI session metrics (#10200)

* feat(telemetry): add generic feature_usage table and batched logging endpoint

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(telemetry): log AI session usage events and document them in telemetry settings

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(telemetry): use escape sequence instead of literal NUL bytes in buffer key

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(telemetry): validate dimensions, decouple retention, keepalive flush

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(telemetry): allowlist feature-usage dimensions and index retention scans

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(telemetry): pin tool-name allowlist and deploy session attribution

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(telemetry): route AI chat usage through feature_usage and drop ai_chat_usage

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(telemetry): slim dimension validation to registered kinds plus key shape

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(telemetry): backfill ai_chat_usage into feature_usage before dropping it

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(telemetry): disclose provider and model identifiers in telemetry settings text

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(telemetry): issue all flush chunks before awaiting so pagehide keeps them

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore: update ee-repo-ref to 6306c072a50937ea9af44a5bcf42345543207486

This commit updates the EE repository reference after PR #672 was merged in windmill-ee-private.

Previous ee-repo-ref: 964f242a0eb44db7f7d26636cc8d76aeabea2b73

New ee-repo-ref: 6306c072a50937ea9af44a5bcf42345543207486

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
This commit is contained in:
hugocasa
2026-07-20 20:56:57 +02:00
committed by GitHub
co-authored by Claude Fable 5 windmill-internal-app[bot] Ruben Fiszel
parent f635bd5ae7
commit 11fda89b52
24 changed files with 566 additions and 122 deletions
@@ -0,0 +1,12 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM feature_usage WHERE day < CURRENT_DATE - 60",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "0390d9e4fae597aabdeef940aa5b5014e1c889ba9181ee3331f128c56c9d22de"
}
@@ -0,0 +1,18 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO feature_usage (feature, kind, key, entity_id, value)\n SELECT * FROM UNNEST($1::text[], $2::text[], $3::text[], $4::text[], $5::bigint[])\n ON CONFLICT (feature, kind, key, entity_id, day)\n DO UPDATE SET value = feature_usage.value + EXCLUDED.value, updated_at = now()",
"describe": {
"columns": [],
"parameters": {
"Left": [
"TextArray",
"TextArray",
"TextArray",
"TextArray",
"Int8Array"
]
},
"nullable": []
},
"hash": "2cdb9076747b61c01b6d389157e42bcbf66f0cc5900c7777141df47776e32fa3"
}
@@ -1,44 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT provider, model, mode,\n COUNT(*)::BIGINT as \"session_count!\",\n COALESCE(SUM(message_count), 0)::BIGINT as \"message_count!\"\n FROM ai_chat_usage\n WHERE created_at > NOW() - INTERVAL '30 days'\n GROUP BY provider, model, mode\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "provider",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "model",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "mode",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "session_count!",
"type_info": "Int8"
},
{
"ordinal": 4,
"name": "message_count!",
"type_info": "Int8"
}
],
"parameters": {
"Left": []
},
"nullable": [
false,
false,
false,
null,
null
]
},
"hash": "3ec92c1682f3ce701028f66f7ce83030e7a7ce32971a5621aceb738a3673f943"
}
@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM ai_chat_usage WHERE created_at < NOW() - INTERVAL '60 days'",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "98746829ab854dff922a04822bc86122e4ceb34cc8993937dff24cdd7ba3fe5f"
}
@@ -1,17 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO ai_chat_usage (session_id, provider, model, mode) VALUES ($1, $2, $3, $4)\n ON CONFLICT (session_id) DO UPDATE SET message_count = ai_chat_usage.message_count + 1",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Varchar",
"Varchar"
]
},
"nullable": []
},
"hash": "b64f0f337aed44840cd68f4c81bd523ec2219920a64783cd5d2972f1826114cc"
}
@@ -0,0 +1,62 @@
{
"db_name": "PostgreSQL",
"query": "\n WITH per_entity AS (\n SELECT feature, kind, key, entity_id,\n SUM(value)::BIGINT AS value,\n MAX(day) AS last_day\n FROM feature_usage\n WHERE day > CURRENT_DATE - 30\n GROUP BY feature, kind, key, entity_id\n )\n SELECT feature, kind, key,\n COUNT(*)::BIGINT AS \"entity_count!\",\n COALESCE(SUM(value), 0)::BIGINT AS \"total_value!\",\n COALESCE(PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY value), 0)::DOUBLE PRECISION AS \"median_value!\",\n COALESCE(PERCENTILE_CONT(0.9) WITHIN GROUP (ORDER BY value), 0)::DOUBLE PRECISION AS \"p90_value!\",\n (COUNT(*) FILTER (WHERE last_day < CURRENT_DATE - 3))::BIGINT AS \"inactive_3d_entity_count!\"\n FROM per_entity\n GROUP BY feature, kind, key\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "feature",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "kind",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "key",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "entity_count!",
"type_info": "Int8"
},
{
"ordinal": 4,
"name": "total_value!",
"type_info": "Int8"
},
{
"ordinal": 5,
"name": "median_value!",
"type_info": "Float8"
},
{
"ordinal": 6,
"name": "p90_value!",
"type_info": "Float8"
},
{
"ordinal": 7,
"name": "inactive_3d_entity_count!",
"type_info": "Int8"
}
],
"parameters": {
"Left": []
},
"nullable": [
false,
false,
false,
null,
null,
null,
null,
null
]
},
"hash": "c3a973b0eea69be747140426cd03f75fb05a27ee759972b76e812b70843eb5e4"
}