Merge pull request #10706 from appwrite/feat-screenshot-endpoint-stats

Feat: usage stats for screenshot generated
This commit is contained in:
Damodar Lohani 2025-10-27 12:57:48 +05:45 committed by GitHub
commit 74bcfe1e08
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 12 additions and 1 deletions

View file

@ -1,5 +1,6 @@
<?php <?php
use Appwrite\Event\StatsUsage;
use Appwrite\Extend\Exception; use Appwrite\Extend\Exception;
use Appwrite\SDK\AuthType; use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType; use Appwrite\SDK\ContentType;
@ -641,6 +642,7 @@ App::get('/v1/avatars/screenshots')
->desc('Get webpage screenshot') ->desc('Get webpage screenshot')
->groups(['api', 'avatars']) ->groups(['api', 'avatars'])
->label('scope', 'avatars.read') ->label('scope', 'avatars.read')
->label('usage.metric', METRIC_AVATARS_SCREENSHOTS_GENERATED)
->label('cache', true) ->label('cache', true)
->label('cache.resourceType', 'avatar/screenshot') ->label('cache.resourceType', 'avatar/screenshot')
->label('cache.resource', 'screenshot/{request.url}/{request.width}/{request.height}/{request.scale}/{request.theme}/{request.userAgent}/{request.fullpage}/{request.locale}/{request.timezone}/{request.latitude}/{request.longitude}/{request.accuracy}/{request.touch}/{request.permissions}/{request.sleep}/{request.quality}/{request.output}') ->label('cache.resource', 'screenshot/{request.url}/{request.width}/{request.height}/{request.scale}/{request.theme}/{request.userAgent}/{request.fullpage}/{request.locale}/{request.timezone}/{request.latitude}/{request.longitude}/{request.accuracy}/{request.touch}/{request.permissions}/{request.sleep}/{request.quality}/{request.output}')
@ -680,7 +682,8 @@ App::get('/v1/avatars/screenshots')
->param('quality', -1, new Range(-1, 100), 'Screenshot quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.', true) ->param('quality', -1, new Range(-1, 100), 'Screenshot quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.', true)
->param('output', '', new WhiteList(\array_keys(Config::getParam('storage-outputs')), true), 'Output format type (jpeg, jpg, png, gif and webp).', true) ->param('output', '', new WhiteList(\array_keys(Config::getParam('storage-outputs')), true), 'Output format type (jpeg, jpg, png, gif and webp).', true)
->inject('response') ->inject('response')
->action(function (string $url, array $headers, int $viewportWidth, int $viewportHeight, float $scale, string $theme, string $userAgent, bool $fullpage, string $locale, string $timezone, float $latitude, float $longitude, float $accuracy, bool $touch, array $permissions, int $sleep, int $width, int $height, int $quality, string $output, Response $response) { ->inject('queueForStatsUsage')
->action(function (string $url, array $headers, int $viewportWidth, int $viewportHeight, float $scale, string $theme, string $userAgent, bool $fullpage, string $locale, string $timezone, float $latitude, float $longitude, float $accuracy, bool $touch, array $permissions, int $sleep, int $width, int $height, int $quality, string $output, Response $response, StatsUsage $queueForStatsUsage) {
if (!\extension_loaded('imagick')) { if (!\extension_loaded('imagick')) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing'); throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing');
@ -858,11 +861,14 @@ App::get('/v1/avatars/screenshots')
$outputs = Config::getParam('storage-outputs'); $outputs = Config::getParam('storage-outputs');
$contentType = $outputs[$output] ?? $outputs['png']; $contentType = $outputs[$output] ?? $outputs['png'];
$queueForStatsUsage->addMetric(METRIC_AVATARS_SCREENSHOTS_GENERATED, 1);
$response $response
->addHeader('Cache-Control', 'private, max-age=2592000') // 30 days ->addHeader('Cache-Control', 'private, max-age=2592000') // 30 days
->setContentType($contentType) ->setContentType($contentType)
->file($resizedScreenshot); ->file($resizedScreenshot);
} catch (\Throwable $th) { } catch (\Throwable $th) {
throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED, 'Screenshot generation failed: ' . $th->getMessage()); throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED, 'Screenshot generation failed: ' . $th->getMessage());
} }

View file

@ -585,6 +585,10 @@ App::init()
$data = $cache->load($key, $timestamp); $data = $cache->load($key, $timestamp);
if (!empty($data) && !$cacheLog->isEmpty()) { if (!empty($data) && !$cacheLog->isEmpty()) {
$usageMetric = $route->getLabel('usage.metric', null);
if ($usageMetric === METRIC_AVATARS_SCREENSHOTS_GENERATED) {
$queueForStatsUsage->disableMetric(METRIC_AVATARS_SCREENSHOTS_GENERATED);
}
$parts = explode('/', $cacheLog->getAttribute('resourceType', '')); $parts = explode('/', $cacheLog->getAttribute('resourceType', ''));
$type = $parts[0] ?? null; $type = $parts[0] ?? null;

View file

@ -269,6 +269,7 @@ const METRIC_SITES_OUTBOUND = 'sites.outbound';
const METRIC_SITES_ID_REQUESTS = 'sites.{siteInternalId}.requests'; const METRIC_SITES_ID_REQUESTS = 'sites.{siteInternalId}.requests';
const METRIC_SITES_ID_INBOUND = 'sites.{siteInternalId}.inbound'; const METRIC_SITES_ID_INBOUND = 'sites.{siteInternalId}.inbound';
const METRIC_SITES_ID_OUTBOUND = 'sites.{siteInternalId}.outbound'; const METRIC_SITES_ID_OUTBOUND = 'sites.{siteInternalId}.outbound';
const METRIC_AVATARS_SCREENSHOTS_GENERATED = 'avatars.screenshotsGenerated';
// Resource types // Resource types
const RESOURCE_TYPE_PROJECTS = 'projects'; const RESOURCE_TYPE_PROJECTS = 'projects';