|
6 | 6 | use Utopia\Query\Query; |
7 | 7 | use Utopia\Fetch\Client; |
8 | 8 | use Utopia\Usage\Metric; |
| 9 | +use Utopia\Usage\Usage; |
9 | 10 | use Utopia\Validator\Hostname; |
10 | 11 |
|
11 | 12 | /** |
@@ -1006,6 +1007,49 @@ public function setup(): void |
1006 | 1007 | "; |
1007 | 1008 |
|
1008 | 1009 | $this->query($createBillingMvSql); |
| 1010 | + |
| 1011 | + // Create daily aggregation target table (SummingMergeTree) for events |
| 1012 | + $dailyTableName = $tableName . '_daily'; |
| 1013 | + $escapedDailyTable = $this->escapeIdentifier($this->database) . '.' . $this->escapeIdentifier($dailyTableName); |
| 1014 | + |
| 1015 | + $dailyColumns = [ |
| 1016 | + 'metric String', |
| 1017 | + 'tenant Nullable(UInt64)', |
| 1018 | + 'value Int64', |
| 1019 | + 'time DateTime64(3)', |
| 1020 | + ]; |
| 1021 | + |
| 1022 | + $dailyColumnDefs = implode(",\n ", $dailyColumns); |
| 1023 | + |
| 1024 | + $createDailyTableSql = " |
| 1025 | + CREATE TABLE IF NOT EXISTS {$escapedDailyTable} ( |
| 1026 | + {$dailyColumnDefs} |
| 1027 | + ) |
| 1028 | + ENGINE = SummingMergeTree() |
| 1029 | + ORDER BY (tenant, metric, time) |
| 1030 | + SETTINGS allow_nullable_key = 1 |
| 1031 | + "; |
| 1032 | + |
| 1033 | + $this->query($createDailyTableSql); |
| 1034 | + |
| 1035 | + // Create materialized view for daily event aggregation |
| 1036 | + $dailyMvName = $tableName . '_daily_mv'; |
| 1037 | + $escapedDailyMv = $this->escapeIdentifier($this->database) . '.' . $this->escapeIdentifier($dailyMvName); |
| 1038 | + |
| 1039 | + $createDailyMvSql = " |
| 1040 | + CREATE MATERIALIZED VIEW IF NOT EXISTS {$escapedDailyMv} |
| 1041 | + TO {$escapedDailyTable} |
| 1042 | + AS SELECT |
| 1043 | + metric, |
| 1044 | + {$tenantSelect}, |
| 1045 | + sum(value) as value, |
| 1046 | + toStartOfDay(time) as time |
| 1047 | + FROM {$escapedDatabaseAndTable} |
| 1048 | + WHERE type = 'event' |
| 1049 | + GROUP BY metric, tenant, time |
| 1050 | + "; |
| 1051 | + |
| 1052 | + $this->query($createDailyMvSql); |
1009 | 1053 | } |
1010 | 1054 |
|
1011 | 1055 | /** |
@@ -1127,8 +1171,8 @@ private function validateMetricData(string $metric, int $value, string $type, ar |
1127 | 1171 | throw new Exception($prefix . 'Value cannot be negative'); |
1128 | 1172 | } |
1129 | 1173 |
|
1130 | | - if ($type !== 'event' && $type !== 'gauge') { |
1131 | | - throw new \InvalidArgumentException($prefix . "Invalid type '{$type}'. Allowed: event, gauge"); |
| 1174 | + if ($type !== Usage::TYPE_EVENT && $type !== Usage::TYPE_GAUGE) { |
| 1175 | + throw new \InvalidArgumentException($prefix . "Invalid type '{$type}'. Allowed: " . Usage::TYPE_EVENT . ', ' . Usage::TYPE_GAUGE); |
1132 | 1176 | } |
1133 | 1177 |
|
1134 | 1178 | if (!is_array($tags)) { |
@@ -1501,7 +1545,7 @@ public function getTimeSeries(array $metrics, string $interval, string $startDat |
1501 | 1545 | $metricName = $row['metric'] ?? ''; |
1502 | 1546 | $type = $row['type'] ?? 'event'; |
1503 | 1547 | $bucketTime = $row['bucket'] ?? ''; |
1504 | | - $value = ($type === 'event') ? (int) ($row['sum_value'] ?? 0) : (int) ($row['last_value'] ?? 0); |
| 1548 | + $value = ($type === Usage::TYPE_EVENT) ? (int) ($row['sum_value'] ?? 0) : (int) ($row['last_value'] ?? 0); |
1505 | 1549 |
|
1506 | 1550 | if (!isset($output[$metricName])) { |
1507 | 1551 | continue; |
@@ -1630,9 +1674,9 @@ public function getTotal(string $metric, array $queries = []): int |
1630 | 1674 |
|
1631 | 1675 | foreach ($json['data'] as $row) { |
1632 | 1676 | $type = $row['type'] ?? 'event'; |
1633 | | - if ($type === 'event') { |
| 1677 | + if ($type === Usage::TYPE_EVENT) { |
1634 | 1678 | return (int) ($row['sum_val'] ?? 0); |
1635 | | - } elseif ($type === 'gauge') { |
| 1679 | + } elseif ($type === Usage::TYPE_GAUGE) { |
1636 | 1680 | return (int) ($row['last_val'] ?? 0); |
1637 | 1681 | } |
1638 | 1682 | } |
@@ -1709,9 +1753,9 @@ public function getTotalBatch(array $metrics, array $queries = []): array |
1709 | 1753 | continue; |
1710 | 1754 | } |
1711 | 1755 |
|
1712 | | - if ($type === 'event') { |
| 1756 | + if ($type === Usage::TYPE_EVENT) { |
1713 | 1757 | $totals[$metricName] = (int) ($row['sum_val'] ?? 0); |
1714 | | - } elseif ($type === 'gauge') { |
| 1758 | + } elseif ($type === Usage::TYPE_GAUGE) { |
1715 | 1759 | $totals[$metricName] = (int) ($row['last_val'] ?? 0); |
1716 | 1760 | } |
1717 | 1761 | } |
|
0 commit comments