(feat): precomputed guage write in stats resources

This commit is contained in:
Jake Barnby
2026-04-07 23:45:59 +12:00
parent e3b1eead55
commit fdca14e659
2 changed files with 82 additions and 1 deletions
+43 -1
View File
@@ -9,6 +9,18 @@ class StatsResources extends Event
{
protected bool $critical = false;
/**
* Pre-computed gauge metric snapshots to write to the stats collection. When non-empty,
* the StatsResources worker takes the fast path: it writes these directly via
* upsertDocuments (replace semantics) and skips the standard counting work.
*
* Each entry is a tuple of (metric key, value). The worker writes one stats document per
* (metric, period) tuple using the project's region.
*
* @var array<int, array{metric: string, value: int}>
*/
protected array $gauges = [];
public function __construct(protected Publisher $publisher)
{
parent::__construct($publisher);
@@ -18,6 +30,35 @@ class StatsResources extends Event
->setClass(System::getEnv('_APP_STATS_RESOURCES_CLASS_NAME', Event::STATS_RESOURCES_CLASS_NAME));
}
/**
* Set the full set of pre-computed gauge metrics for this message. Replaces any
* previously-set gauges.
*
* @param array<int, array{metric: string, value: int}> $gauges
*/
public function setGauges(array $gauges): self
{
$this->gauges = $gauges;
return $this;
}
/**
* Append a single pre-computed gauge metric to this message.
*/
public function addGauge(string $metric, int $value): self
{
$this->gauges[] = ['metric' => $metric, 'value' => $value];
return $this;
}
/**
* @return array<int, array{metric: string, value: int}>
*/
public function getGauges(): array
{
return $this->gauges;
}
/**
* Prepare the payload for the usage event.
*
@@ -26,7 +67,8 @@ class StatsResources extends Event
protected function preparePayload(): array
{
return [
'project' => $this->project
'project' => $this->project,
'gauges' => $this->gauges,
];
}
}
@@ -79,9 +79,48 @@ class StatsResources extends Action
// Reset documents for each job
$this->documents = [];
$gauges = $payload['gauges'] ?? [];
if (!empty($gauges)) {
$this->writeGauges($getLogsDB, $project, $gauges);
return;
}
$this->countForProject($dbForPlatform, $getLogsDB, $getProjectDB, $getDatabasesDB, $project);
}
/**
* Write a batch of pre-computed gauge metrics to the logs database for one project.
*
* Builds (1h, 1d, inf) period documents for each metric using the existing
* createStatsDocuments helper, then commits via writeDocuments — same code path the
* standard counting flow uses, just with externally-supplied values.
*
* @param callable $getLogsDB
* @param Document $project
* @param array<int, array{metric: string, value: int}> $gauges
*/
protected function writeGauges(callable $getLogsDB, Document $project, array $gauges): void
{
$region = $project->getAttribute('region', '');
foreach ($gauges as $gauge) {
$metric = $gauge['metric'] ?? '';
if ($metric === '') {
continue;
}
$value = (int) ($gauge['value'] ?? 0);
$this->createStatsDocuments($region, $metric, $value);
}
if ($this->documents === []) {
return;
}
/** @var \Utopia\Database\Database $dbForLogs */
$dbForLogs = call_user_func($getLogsDB, $project);
$this->writeDocuments($dbForLogs, $project);
}
protected function countForProject(Database $dbForPlatform, callable $getLogsDB, callable $getProjectDB, callable $getDatabasesDB, Document $project): void
{
/** @var \Utopia\Database\Database $dbForLogs */