feat(usage): add databases.operations.reads.cached metric

Adds a new metric family that counts only reads served from the query
cache layer:

- databases.operations.reads.cached (project-level)
- {databaseInternalId}.databases.operations.reads.cached (per-database)

The existing databases.operations.reads continues to count every read
regardless of source, so direct reads can be derived as
total - cached.

Increments fire from List Documents only when the cache returned a
result. The Get Documents endpoint has no query cache, so it never
increments the cached counter. Scope is the base databases.* family;
documentsdb.* and vectorsdb.* variants are intentionally untouched
for now. No response model changes — the metric is stored only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Damodar Lohani
2026-05-13 01:54:48 +00:00
co-authored by Claude Opus 4.7
parent 35941ddc34
commit 76e4f6648d
3 changed files with 29 additions and 1 deletions
+2
View File
@@ -290,6 +290,8 @@ const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS = '{databaseInternalId}.{collec
const METRIC_DATABASE_ID_COLLECTION_ID_STORAGE = '{databaseInternalId}.{collectionInternalId}.databases.storage';
const METRIC_DATABASES_OPERATIONS_READS = 'databases.operations.reads';
const METRIC_DATABASE_ID_OPERATIONS_READS = '{databaseInternalId}.databases.operations.reads';
const METRIC_DATABASES_OPERATIONS_READS_CACHED = 'databases.operations.reads.cached';
const METRIC_DATABASE_ID_OPERATIONS_READS_CACHED = '{databaseInternalId}.databases.operations.reads.cached';
const METRIC_DATABASES_OPERATIONS_WRITES = 'databases.operations.writes';
const METRIC_DATABASE_ID_OPERATIONS_WRITES = '{databaseInternalId}.databases.operations.writes';
@@ -67,6 +67,22 @@ abstract class Action extends DatabasesAction
return $this->databaseType.'.'.METRIC_DATABASE_ID_OPERATIONS_READS;
}
protected function getDatabasesOperationReadCachedMetric(): ?string
{
if ($this->databaseType === DATABASE_TYPE_LEGACY || $this->databaseType === DATABASE_TYPE_TABLESDB) {
return METRIC_DATABASES_OPERATIONS_READS_CACHED;
}
return null;
}
protected function getDatabasesIdOperationReadCachedMetric(): ?string
{
if ($this->databaseType === DATABASE_TYPE_LEGACY || $this->databaseType === DATABASE_TYPE_TABLESDB) {
return METRIC_DATABASE_ID_OPERATIONS_READS_CACHED;
}
return null;
}
protected function getDatabasesOperationWriteMetric(): string
{
if ($this->databaseType === DATABASE_TYPE_LEGACY || $this->databaseType === DATABASE_TYPE_TABLESDB) {
@@ -129,6 +129,7 @@ class XList extends Action
}
$dbStart = \microtime(true);
$documentsCacheHit = false;
try {
$hasSelects = ! empty(Query::groupByType($queries)['selections']);
@@ -148,7 +149,6 @@ class XList extends Action
$roles = $dbForProject->getAuthorization()->getRoles();
$documentsField = $this->getListCacheField($collection, $roles, $queries, self::LIST_CACHE_FIELD_DOCUMENTS);
$documentsCacheHit = false;
try {
$cachedDocuments = $dbForProject->getCache()->load($cacheKey, $ttl, $documentsField);
} catch (\Throwable) {
@@ -230,6 +230,16 @@ class XList extends Action
->addMetric($this->getDatabasesOperationReadMetric(), max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), $this->getDatabasesIdOperationReadMetric()), $operations);
if ($documentsCacheHit) {
$cachedMetric = $this->getDatabasesOperationReadCachedMetric();
$cachedIdMetric = $this->getDatabasesIdOperationReadCachedMetric();
if ($cachedMetric !== null && $cachedIdMetric !== null) {
$usage
->addMetric($cachedMetric, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), $cachedIdMetric), $operations);
}
}
$response->dynamic(new Document([
'total' => $total,
// rows or documents