Skip to content

Commit ab599d5

Browse files
lohanidamodarclaude
andcommitted
CLO-3954 refactor: single MergeTree table, remove periods, type-based aggregation
- Replace SummingMergeTree + ReplacingMergeTree with single MergeTree table - Remove period column and fan-out; add type column (event/gauge) - Raw append with UUID IDs instead of deterministic dedup - Add SummingMergeTree materialized view for billing (events only) - Query-time aggregation: SUM for events, argMax for gauges - New methods: addBatch, getTimeSeries, getTotal, getTotalBatch - Remove: increment, set, incrementBatch, setBatch, all *ByPeriod* methods - Single collect() method with type parameter replaces collect/collectSet Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent bf67789 commit ab599d5

6 files changed

Lines changed: 717 additions & 1170 deletions

File tree

src/Usage/Adapter.php

Lines changed: 36 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -9,62 +9,6 @@ abstract class Adapter
99
*/
1010
abstract public function getName(): string;
1111

12-
/**
13-
* Increment a metric across all periods (1h, 1d, inf).
14-
*
15-
* Uses additive upsert semantics: if a row with the same deterministic ID exists,
16-
* the value is added to the existing value (SummingMergeTree in ClickHouse,
17-
* upsertDocumentsWithIncrease in Database).
18-
*
19-
* @param string $metric Metric name
20-
* @param int $value Value to add (must be positive)
21-
* @param array<string,mixed> $tags Optional tags
22-
* @return bool
23-
* @throws \Exception
24-
*/
25-
public function increment(string $metric, int $value, array $tags = []): bool
26-
{
27-
$metrics = [];
28-
foreach (array_keys(Usage::PERIODS) as $period) {
29-
$metrics[] = [
30-
'metric' => $metric,
31-
'value' => $value,
32-
'period' => $period,
33-
'tags' => $tags,
34-
];
35-
}
36-
37-
return $this->incrementBatch($metrics);
38-
}
39-
40-
/**
41-
* Set a metric to an absolute value across all periods (1h, 1d, inf).
42-
*
43-
* Uses replace upsert semantics: if a row with the same deterministic ID exists,
44-
* the value replaces the existing value (ReplacingMergeTree in ClickHouse,
45-
* upsertDocuments in Database).
46-
*
47-
* @param string $metric Metric name
48-
* @param int $value Absolute value to set
49-
* @param array<string,mixed> $tags Optional tags
50-
* @return bool
51-
* @throws \Exception
52-
*/
53-
public function set(string $metric, int $value, array $tags = []): bool
54-
{
55-
$metrics = [];
56-
foreach (array_keys(Usage::PERIODS) as $period) {
57-
$metrics[] = [
58-
'metric' => $metric,
59-
'value' => $value,
60-
'period' => $period,
61-
'tags' => $tags,
62-
];
63-
}
64-
65-
return $this->setBatch($metrics);
66-
}
67-
6812
/**
6913
* Check adapter health and connection status
7014
*
@@ -78,79 +22,54 @@ abstract public function healthCheck(): array;
7822
abstract public function setup(): void;
7923

8024
/**
81-
* Increment metrics in batch (additive upsert).
82-
*
83-
* Values with the same deterministic ID are summed together
84-
* (SummingMergeTree in ClickHouse, upsertDocumentsWithIncrease in Database).
85-
*
86-
* @param array<array{metric: string, value: int, period?: string, tags?: array<string,mixed>}> $metrics
87-
* @param int $batchSize Maximum number of metrics per INSERT statement
88-
*/
89-
abstract public function incrementBatch(array $metrics, int $batchSize = 1000): bool;
90-
91-
/**
92-
* Set metrics in batch (replace upsert).
25+
* Add metrics in batch (raw append).
9326
*
94-
* Values with the same deterministic ID are replaced (last write wins)
95-
* (ReplacingMergeTree in ClickHouse, upsertDocuments in Database).
27+
* Appends rows to the single MergeTree table. Each row must include
28+
* a 'type' field ('event' or 'gauge') and a 'metric' name.
9629
*
97-
* @param array<array{metric: string, value: int, period?: string, tags?: array<string,mixed>}> $metrics
30+
* @param array<array{metric: string, value: int, type: string, tags?: array<string,mixed>}> $metrics
9831
* @param int $batchSize Maximum number of metrics per INSERT statement
9932
*/
100-
abstract public function setBatch(array $metrics, int $batchSize = 1000): bool;
33+
abstract public function addBatch(array $metrics, int $batchSize = 1000): bool;
10134

10235
/**
103-
* Get usage metrics by period
36+
* Get time series data for metrics with query-time aggregation.
10437
*
105-
* @param array<\Utopia\Query\Query> $queries
106-
* @return array<Metric>
107-
*/
108-
abstract public function getByPeriod(string $metric, string $period, array $queries = []): array;
109-
110-
/**
111-
* Get usage metrics between dates
38+
* Groups data by the specified interval (1h or 1d) and applies
39+
* SUM for event metrics and argMax for gauge metrics.
11240
*
113-
* @param array<\Utopia\Query\Query> $queries
114-
* @return array<Metric>
41+
* @param array<string> $metrics List of metric names
42+
* @param string $interval Aggregation interval: '1h' or '1d'
43+
* @param string $startDate Start datetime string
44+
* @param string $endDate End datetime string
45+
* @param array<\Utopia\Query\Query> $queries Additional query filters
46+
* @param bool $zeroFill Whether to fill gaps with zero values
47+
* @return array<string, array{total: int, data: array<array{value: int, date: string}>}>
11548
*/
116-
abstract public function getBetweenDates(string $metric, string $startDate, string $endDate, array $queries = []): array;
49+
abstract public function getTimeSeries(array $metrics, string $interval, string $startDate, string $endDate, array $queries = [], bool $zeroFill = true): array;
11750

11851
/**
119-
* Count usage metrics by period
52+
* Get total value for a single metric.
12053
*
121-
* @param array<\Utopia\Query\Query> $queries
122-
*/
123-
abstract public function countByPeriod(string $metric, string $period, array $queries = []): int;
124-
125-
/**
126-
* Sum usage metrics by period
54+
* Returns sum for event metrics, latest value for gauge metrics.
55+
* Auto-detects type from stored data.
12756
*
128-
* @param array<\Utopia\Query\Query> $queries
57+
* @param string $metric Metric name
58+
* @param array<\Utopia\Query\Query> $queries Additional query filters
59+
* @return int
12960
*/
130-
abstract public function sumByPeriod(string $metric, string $period, array $queries = []): int;
61+
abstract public function getTotal(string $metric, array $queries = []): int;
13162

13263
/**
133-
* Sum usage metrics by period for multiple metrics in a single query.
64+
* Get totals for multiple metrics in a single query.
13465
*
135-
* Returns an associative array keyed by metric name with the sum as value.
136-
* Metrics not found will have a value of 0.
66+
* Returns sum for event metrics, latest value for gauge metrics.
13767
*
13868
* @param array<string> $metrics List of metric names
139-
* @param array<\Utopia\Query\Query> $queries
69+
* @param array<\Utopia\Query\Query> $queries Additional query filters
14070
* @return array<string, int>
14171
*/
142-
abstract public function sumByPeriodBatch(array $metrics, string $period, array $queries = []): array;
143-
144-
/**
145-
* Get usage metrics by period for multiple metrics in a single query.
146-
*
147-
* Returns an associative array keyed by metric name with arrays of Metric objects as values.
148-
*
149-
* @param array<string> $metrics List of metric names
150-
* @param array<\Utopia\Query\Query> $queries
151-
* @return array<string, array<Metric>>
152-
*/
153-
abstract public function getByPeriodBatch(array $metrics, string $period, array $queries = []): array;
72+
abstract public function getTotalBatch(array $metrics, array $queries = []): array;
15473

15574
/**
15675
* Purge usage metrics matching the given queries.
@@ -176,6 +95,15 @@ abstract public function find(array $queries = []): array;
17695
*/
17796
abstract public function count(array $queries = []): int;
17897

98+
/**
99+
* Sum metric values using Query objects.
100+
*
101+
* @param array<\Utopia\Query\Query> $queries
102+
* @param string $attribute Attribute to sum (default: 'value')
103+
* @return int
104+
*/
105+
abstract public function sum(array $queries = [], string $attribute = 'value'): int;
106+
179107
/**
180108
* Set the namespace prefix for table names.
181109
*

0 commit comments

Comments
 (0)