Skip to content

Commit a33899d

Browse files
committed
Add country column to events table for geo analytics
Adds a LowCardinality(String) country column to the ClickHouse events table, derived from GeoIP lookup on client IP. This enables geographic breakdowns of API requests without requiring high-cardinality IP storage. https://claude.ai/code/session_01UCN4sKD3Zkdbimn3QgTHSB
1 parent 238c7bc commit a33899d

3 files changed

Lines changed: 10 additions & 7 deletions

File tree

src/Usage/Adapter.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Two main data types:
99
*
1010
* 1. **Events** – Append-only log of API requests, executions, bandwidth, etc.
11-
* Rich dimensions (path, method, status, userAgent, resource, …)
11+
* Rich dimensions (path, method, status, userAgent, country, resource, …)
1212
* allow Cloudflare-style analytics with flexible filtering.
1313
* ClickHouse: SummingMergeTree with hourly/daily materialized rollups.
1414
*
@@ -21,7 +21,7 @@ abstract class Adapter
2121
/** Known event dimension columns (validated in filters/groupBy) */
2222
public const EVENT_DIMENSIONS = [
2323
'metric', 'path', 'method', 'status',
24-
'userAgent', 'resource', 'resourceId',
24+
'userAgent', 'country', 'resource', 'resourceId',
2525
];
2626

2727
/** Known gauge dimension columns */
@@ -66,7 +66,7 @@ abstract public function healthCheck(): array;
6666
* - value (int|float) e.g. request count, bytes, ms
6767
*
6868
* Plus optional dimensions:
69-
* - path, method, status, userAgent, resource, resourceId
69+
* - path, method, status, userAgent, country, resource, resourceId
7070
*
7171
* @param array<array<string,mixed>> $events
7272
*/

src/Usage/Adapter/ClickHouse.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
* Stores usage data in two table families:
1414
*
1515
* 1. **events** (SummingMergeTree) – append-only API analytics & metered usage.
16-
* Columns: timestamp, metric, value, path, method, status, userAgent, resource, resourceId, tenant.
17-
* ORDER BY (tenant, metric, resource, resourceId, path, method, status, userAgent, timestamp) for fast range scans.
16+
* Columns: timestamp, metric, value, path, method, status, userAgent, country, resource, resourceId, tenant.
17+
* ORDER BY (tenant, metric, resource, resourceId, path, method, status, userAgent, country, timestamp) for fast range scans.
1818
* Hourly and daily rollups via SummingMergeTree time-bucket grouping.
1919
*
2020
* 2. **gauges** (ReplacingMergeTree) – point-in-time resource counts.
@@ -139,8 +139,8 @@ public function setup(): void
139139
$eventsTable = $this->eventsTable();
140140
$tenantCol = $this->sharedTables ? "tenant Nullable(String),\n " : '';
141141
$orderKey = $this->sharedTables
142-
? '(tenant, metric, resource, resourceId, path, method, status, userAgent, timestamp)'
143-
: '(metric, resource, resourceId, path, method, status, userAgent, timestamp)';
142+
? '(tenant, metric, resource, resourceId, path, method, status, userAgent, country, timestamp)'
143+
: '(metric, resource, resourceId, path, method, status, userAgent, country, timestamp)';
144144

145145
$this->query("
146146
CREATE TABLE IF NOT EXISTS {$eventsTable} (
@@ -151,6 +151,7 @@ public function setup(): void
151151
method LowCardinality(String) DEFAULT '',
152152
status UInt16 DEFAULT 0,
153153
userAgent String DEFAULT '',
154+
country LowCardinality(String) DEFAULT '',
154155
resource LowCardinality(String) DEFAULT '',
155156
resourceId String DEFAULT '',
156157
INDEX idx_metric (metric) TYPE bloom_filter GRANULARITY 1,
@@ -530,6 +531,7 @@ private function buildEventRow(array $event): array
530531
'method' => (string) ($event['method'] ?? ''),
531532
'status' => (int) ($event['status'] ?? 0),
532533
'userAgent' => (string) ($event['userAgent'] ?? ''),
534+
'country' => (string) ($event['country'] ?? ''),
533535
'resource' => (string) ($event['resource'] ?? ''),
534536
'resourceId' => (string) ($event['resourceId'] ?? ''),
535537
];

tests/Usage/UsageUnitTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public function testEventDimensions(): void
3737
$this->assertContains('method', Adapter::EVENT_DIMENSIONS);
3838
$this->assertContains('status', Adapter::EVENT_DIMENSIONS);
3939
$this->assertContains('userAgent', Adapter::EVENT_DIMENSIONS);
40+
$this->assertContains('country', Adapter::EVENT_DIMENSIONS);
4041
$this->assertContains('resource', Adapter::EVENT_DIMENSIONS);
4142
$this->assertContains('resourceId', Adapter::EVENT_DIMENSIONS);
4243
}

0 commit comments

Comments
 (0)