mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
added usage test for the vectordb
This commit is contained in:
@@ -403,6 +403,12 @@ App::get('/v1/project/usage')
|
||||
'databasesWritesTotal' => $total[METRIC_DATABASES_OPERATIONS_WRITES],
|
||||
'documentsdbDatabasesReadsTotal' => $total[METRIC_DATABASES_OPERATIONS_READS_DOCUMENTSDB],
|
||||
'documentsdbDatabasesWritesTotal' => $total[METRIC_DATABASES_OPERATIONS_WRITES_DOCUMENTSDB],
|
||||
'vectordbDatabasesTotal' => $total[METRIC_DATABASES_VECTORDB] ?? 0,
|
||||
'vectordbCollectionsTotal' => $total[METRIC_COLLECTIONS_VECTORDB] ?? 0,
|
||||
'vectordbDocumentsTotal' => $total[METRIC_DOCUMENTS_VECTORDB] ?? 0,
|
||||
'vectordbDatabasesStorageTotal' => $total[METRIC_DATABASES_STORAGE_VECTORDB] ?? 0,
|
||||
'vectordbDatabasesReadsTotal' => $total[METRIC_DATABASES_OPERATIONS_READS_VECTORDB] ?? 0,
|
||||
'vectordbDatabasesWritesTotal' => $total[METRIC_DATABASES_OPERATIONS_WRITES_VECTORDB] ?? 0,
|
||||
'executionsBreakdown' => $executionsBreakdown,
|
||||
'bucketsBreakdown' => $bucketsBreakdown,
|
||||
'databasesReads' => $usage[METRIC_DATABASES_OPERATIONS_READS],
|
||||
@@ -410,6 +416,12 @@ App::get('/v1/project/usage')
|
||||
'documentsdbDatabasesReads' => $usage[METRIC_DATABASES_OPERATIONS_READS_DOCUMENTSDB],
|
||||
'documentsdbDatabasesWrites' => $usage[METRIC_DATABASES_OPERATIONS_WRITES_DOCUMENTSDB],
|
||||
'documentsdbDatabasesStorage' => $usage[METRIC_DATABASES_STORAGE_DOCUMENTSDB],
|
||||
'vectordbDatabases' => $usage[METRIC_DATABASES_VECTORDB] ?? [],
|
||||
'vectordbCollections' => $usage[METRIC_COLLECTIONS_VECTORDB] ?? [],
|
||||
'vectordbDocuments' => $usage[METRIC_DOCUMENTS_VECTORDB] ?? [],
|
||||
'vectordbDatabasesStorage' => $usage[METRIC_DATABASES_STORAGE_VECTORDB] ?? [],
|
||||
'vectordbDatabasesReads' => $usage[METRIC_DATABASES_OPERATIONS_READS_VECTORDB] ?? [],
|
||||
'vectordbDatabasesWrites' => $usage[METRIC_DATABASES_OPERATIONS_WRITES_VECTORDB] ?? [],
|
||||
'databasesStorageBreakdown' => $databasesStorageBreakdown,
|
||||
'executionsMbSecondsBreakdown' => $executionsMbSecondsBreakdown,
|
||||
'buildsMbSecondsBreakdown' => $buildsMbSecondsBreakdown,
|
||||
@@ -419,10 +431,14 @@ App::get('/v1/project/usage')
|
||||
'authPhoneCountryBreakdown' => $authPhoneCountryBreakdown,
|
||||
'imageTransformations' => $usage[METRIC_FILES_IMAGES_TRANSFORMED],
|
||||
'imageTransformationsTotal' => $total[METRIC_FILES_IMAGES_TRANSFORMED],
|
||||
'embeddingsText' => $total[METRIC_EMBEDDINGS_TEXT] ?? [],
|
||||
'embeddingsTextTokens' => $total[METRIC_EMBEDDINGS_TEXT_TOTAL_TOKENS],
|
||||
'embeddingsTextDuration' => $total[METRIC_EMBEDDINGS_TEXT_TOTAL_DURATION],
|
||||
'embeddingsTextErrors' => $total[METRIC_EMBEDDINGS_TEXT_TOTAL_ERROR],
|
||||
'embeddingsText' => $usage[METRIC_EMBEDDINGS_TEXT] ?? [],
|
||||
'embeddingsTextTokens' => $usage[METRIC_EMBEDDINGS_TEXT_TOTAL_TOKENS] ?? [],
|
||||
'embeddingsTextDuration' => $usage[METRIC_EMBEDDINGS_TEXT_TOTAL_DURATION] ?? [],
|
||||
'embeddingsTextErrors' => $usage[METRIC_EMBEDDINGS_TEXT_TOTAL_ERROR] ?? [],
|
||||
'embeddingsTextTotal' => $total[METRIC_EMBEDDINGS_TEXT] ?? 0,
|
||||
'embeddingsTextTokensTotal' => $total[METRIC_EMBEDDINGS_TEXT_TOTAL_TOKENS] ?? 0,
|
||||
'embeddingsTextDurationTotal' => $total[METRIC_EMBEDDINGS_TEXT_TOTAL_DURATION] ?? 0,
|
||||
'embeddingsTextErrorsTotal' => $total[METRIC_EMBEDDINGS_TEXT_TOTAL_ERROR] ?? 0,
|
||||
]), Response::MODEL_USAGE_PROJECT);
|
||||
});
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ class StatsUsage extends Action
|
||||
protected array $skipBaseMetrics = [
|
||||
METRIC_DATABASES => true,
|
||||
METRIC_DATABASES_DOCUMENTSDB => true,
|
||||
METRIC_DATABASES_VECTORDB => true,
|
||||
METRIC_BUCKETS => true,
|
||||
METRIC_USERS => true,
|
||||
METRIC_FUNCTIONS => true,
|
||||
@@ -67,8 +68,11 @@ class StatsUsage extends Action
|
||||
METRIC_BUILDS => true,
|
||||
METRIC_COLLECTIONS => true,
|
||||
METRIC_DOCUMENTS => true,
|
||||
METRIC_COLLECTIONS_VECTORDB => true,
|
||||
METRIC_DOCUMENTS_VECTORDB => true,
|
||||
METRIC_DATABASES_STORAGE => true,
|
||||
METRIC_DATABASES_STORAGE_DOCUMENTSDB => true,
|
||||
METRIC_DATABASES_STORAGE_VECTORDB => true,
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -1131,6 +1131,228 @@ class UsageTest extends Scope
|
||||
}
|
||||
|
||||
/** @depends testDocumentsDBStats */
|
||||
public function testPrepareVectorDBStats(array $data): array
|
||||
{
|
||||
$documentsTotal = 0;
|
||||
$collectionsTotal = 0;
|
||||
$vectordbTotal = 0;
|
||||
$databasesTotal = $data['databasesTotal'];
|
||||
$requestsTotal = $data['requestsTotal'];
|
||||
|
||||
for ($i = 0; $i < self::CREATE; $i++) {
|
||||
$name = uniqid() . ' vectordb';
|
||||
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_POST,
|
||||
'/vectordb',
|
||||
array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id']
|
||||
], $this->getHeaders()),
|
||||
[
|
||||
'databaseId' => 'unique()',
|
||||
'name' => $name,
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertEquals($name, $response['body']['name']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
|
||||
$requestsTotal += 1;
|
||||
$vectordbTotal += 1;
|
||||
|
||||
$vectordbId = $response['body']['$id'];
|
||||
|
||||
if ($i < (self::CREATE / 2)) {
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_DELETE,
|
||||
'/vectordb/' . $vectordbId,
|
||||
array_merge([
|
||||
'x-appwrite-project' => $this->getProject()['$id']
|
||||
], $this->getHeaders()),
|
||||
);
|
||||
|
||||
$this->assertEmpty($response['body']);
|
||||
|
||||
$vectordbTotal -= 1;
|
||||
$requestsTotal += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = 0; $i < self::CREATE; $i++) {
|
||||
$name = uniqid() . ' collection';
|
||||
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_POST,
|
||||
'/vectordb/' . $vectordbId . '/collections',
|
||||
array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id']
|
||||
], $this->getHeaders()),
|
||||
[
|
||||
'collectionId' => 'unique()',
|
||||
'name' => $name,
|
||||
'dimension' => 1536,
|
||||
'documentSecurity' => false,
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::create(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertEquals($name, $response['body']['name']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
|
||||
$requestsTotal += 1;
|
||||
$collectionsTotal += 1;
|
||||
|
||||
$collectionId = $response['body']['$id'];
|
||||
|
||||
if ($i < (self::CREATE / 2)) {
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_DELETE,
|
||||
'/vectordb/' . $vectordbId . '/collections/' . $collectionId,
|
||||
array_merge([
|
||||
'x-appwrite-project' => $this->getProject()['$id']
|
||||
], $this->getHeaders()),
|
||||
);
|
||||
|
||||
$this->assertEmpty($response['body']);
|
||||
|
||||
$collectionsTotal -= 1;
|
||||
$requestsTotal += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = 0; $i < self::CREATE; $i++) {
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_POST,
|
||||
'/vectordb/' . $vectordbId . '/collections/' . $collectionId . '/documents',
|
||||
array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id']
|
||||
], $this->getHeaders()),
|
||||
[
|
||||
'documentId' => 'unique()',
|
||||
'data' => [
|
||||
'embeddings' => array_fill(0, 1536, 0.1),
|
||||
'metadata' => [
|
||||
'name' => uniqid() . ' document',
|
||||
'value' => $i
|
||||
]
|
||||
]
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
|
||||
$requestsTotal += 1;
|
||||
$documentsTotal += 1;
|
||||
|
||||
$documentId = $response['body']['$id'];
|
||||
|
||||
if ($i < (self::CREATE / 2)) {
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_DELETE,
|
||||
'/vectordb/' . $vectordbId . '/collections/' . $collectionId . '/documents/' . $documentId,
|
||||
array_merge([
|
||||
'x-appwrite-project' => $this->getProject()['$id']
|
||||
], $this->getHeaders()),
|
||||
);
|
||||
|
||||
$this->assertEmpty($response['body']);
|
||||
|
||||
$documentsTotal -= 1;
|
||||
$requestsTotal += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return array_merge($data, [
|
||||
'vectordbId' => $vectordbId,
|
||||
'vectordbCollectionId' => $collectionId,
|
||||
'requestsTotal' => $requestsTotal,
|
||||
'databasesTotal' => $databasesTotal,
|
||||
'vectordbTotal' => $vectordbTotal,
|
||||
'vectordbCollectionsTotal' => $collectionsTotal,
|
||||
'vectordbDocumentsTotal' => $documentsTotal,
|
||||
]);
|
||||
}
|
||||
|
||||
/** @depends testPrepareVectorDBStats */
|
||||
#[Retry(count: 1)]
|
||||
public function testVectorDBStats(array $data): array
|
||||
{
|
||||
$vectordbId = $data['vectordbId'];
|
||||
$collectionId = $data['vectordbCollectionId'];
|
||||
$requestsTotal = $data['requestsTotal'];
|
||||
$databasesTotal = $data['databasesTotal'];
|
||||
$vectordbTotal = $data['vectordbTotal'];
|
||||
$collectionsTotal = $data['vectordbCollectionsTotal'];
|
||||
$documentsTotal = $data['vectordbDocumentsTotal'];
|
||||
|
||||
$this->assertEventually(function () use ($requestsTotal, $vectordbTotal, $documentsTotal) {
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_GET,
|
||||
'/project/usage',
|
||||
$this->getConsoleHeaders(),
|
||||
[
|
||||
'period' => '1d',
|
||||
'startDate' => self::getToday(),
|
||||
'endDate' => self::getTomorrow(),
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertGreaterThanOrEqual(31, count($response['body']));
|
||||
$this->assertCount(1, $response['body']['requests']);
|
||||
$this->assertCount(1, $response['body']['network']);
|
||||
$this->assertEquals($requestsTotal, $response['body']['requests'][array_key_last($response['body']['requests'])]['value']);
|
||||
$this->validateDates($response['body']['requests']);
|
||||
// vectordbTotal should reflect only VectorDB instances, not relational databases.
|
||||
$this->assertEquals($vectordbTotal, $response['body']['vectordbDatabasesTotal']);
|
||||
$this->assertEquals($documentsTotal, $response['body']['vectordbDocumentsTotal']);
|
||||
});
|
||||
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_GET,
|
||||
'/databases/usage?range=30d',
|
||||
$this->getConsoleHeaders()
|
||||
);
|
||||
|
||||
$this->assertEquals($databasesTotal, $response['body']['databases'][array_key_last($response['body']['databases'])]['value']);
|
||||
$this->validateDates($response['body']['databases']);
|
||||
|
||||
$this->assertEventually(function () use ($vectordbId, $collectionsTotal, $documentsTotal) {
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_GET,
|
||||
'/vectordb/' . $vectordbId . '/usage?range=30d',
|
||||
$this->getConsoleHeaders()
|
||||
);
|
||||
|
||||
$this->assertEquals($collectionsTotal, $response['body']['collections'][array_key_last($response['body']['collections'])]['value']);
|
||||
$this->validateDates($response['body']['collections']);
|
||||
|
||||
$this->assertEquals($documentsTotal, $response['body']['documents'][array_key_last($response['body']['documents'])]['value']);
|
||||
$this->validateDates($response['body']['documents']);
|
||||
});
|
||||
|
||||
$this->assertEventually(function () use ($vectordbId, $collectionId, $documentsTotal) {
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_GET,
|
||||
'/vectordb/' . $vectordbId . '/collections/' . $collectionId . '/usage?range=30d',
|
||||
$this->getConsoleHeaders()
|
||||
);
|
||||
|
||||
$this->assertEquals($documentsTotal, $response['body']['documents'][array_key_last($response['body']['documents'])]['value']);
|
||||
$this->validateDates($response['body']['documents']);
|
||||
});
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/** @depends testVectorDBStats */
|
||||
public function testPrepareFunctionsStats(array $data): array
|
||||
{
|
||||
$executionTime = 0;
|
||||
@@ -1611,7 +1833,7 @@ class UsageTest extends Scope
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], $this->getHeaders()),
|
||||
[
|
||||
'embeddingModel' => 'embeddinggemma',
|
||||
'model' => 'embeddinggemma',
|
||||
'texts' => [
|
||||
'usage test text ' . $i,
|
||||
],
|
||||
@@ -1646,10 +1868,24 @@ class UsageTest extends Scope
|
||||
$this->assertArrayHasKey('embeddingsTextErrors', $response['body']);
|
||||
$this->assertArrayHasKey('embeddingsTextTokens', $response['body']);
|
||||
$this->assertArrayHasKey('embeddingsTextDuration', $response['body']);
|
||||
$this->assertGreaterThan(0, $response['body']['embeddingsText']);
|
||||
$this->assertGreaterThanOrEqual(0, $response['body']['embeddingsTextErrors']);
|
||||
$this->assertGreaterThan(0, $response['body']['embeddingsTextTokens']);
|
||||
$this->assertGreaterThan(0, $response['body']['embeddingsTextDuration']);
|
||||
$this->assertArrayHasKey('embeddingsTextTotal', $response['body']);
|
||||
$this->assertArrayHasKey('embeddingsTextErrorsTotal', $response['body']);
|
||||
$this->assertArrayHasKey('embeddingsTextTokensTotal', $response['body']);
|
||||
$this->assertArrayHasKey('embeddingsTextDurationTotal', $response['body']);
|
||||
|
||||
// Time-series arrays should be non-empty
|
||||
$this->assertNotEmpty($response['body']['embeddingsText']);
|
||||
$this->assertNotEmpty($response['body']['embeddingsTextTokens']);
|
||||
$this->assertNotEmpty($response['body']['embeddingsTextDuration']);
|
||||
$this->validateDates($response['body']['embeddingsText']);
|
||||
$this->validateDates($response['body']['embeddingsTextTokens']);
|
||||
$this->validateDates($response['body']['embeddingsTextDuration']);
|
||||
|
||||
// Total scalars should be greater than 0 (or >= 0 for errors)
|
||||
$this->assertGreaterThan(0, $response['body']['embeddingsTextTotal']);
|
||||
$this->assertGreaterThanOrEqual(0, $response['body']['embeddingsTextErrorsTotal']);
|
||||
$this->assertGreaterThan(0, $response['body']['embeddingsTextTokensTotal']);
|
||||
$this->assertGreaterThan(0, $response['body']['embeddingsTextDurationTotal']);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user