Skip to content

Fix remove duplicate metrics from stats usage#1

Open
DhirenMhatre wants to merge 27 commits into
1.9.xfrom
fix-remove-duplicate-metrics-from-stats-usage
Open

Fix remove duplicate metrics from stats usage#1
DhirenMhatre wants to merge 27 commits into
1.9.xfrom
fix-remove-duplicate-metrics-from-stats-usage

Conversation

@DhirenMhatre
Copy link
Copy Markdown

What does this PR do?

(Provide a description of what this PR does and why it's needed.)

Test Plan

(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Screenshots may also be helpful.)

Related PRs and Issues

  • (Related PR or issue)

Checklist

  • Have you read the Contributing Guidelines on issues?
  • If the PR includes a change to an API's metadata (desc, label, params, etc.), does it also include updated API specs and example docs?

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 20, 2026

Policy Check Failed

✗ 3/3 policy checks failed:

• Need 2 more approval(s) (0/2) — comment LGTM or approve via review
• Missing ticket reference (expected: JIRA-, ENG-, #*)
• 12 code file(s) changed but no test files added


To merge this PR:

  1. Address the failed checks listed above
  2. Ensure branch protection requires the codity/policy-check status

Configure policies in your dashboard

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 20, 2026

PR Summary

What Changed

  • Fixed duplicate metrics in stats usage by separating resource counts (databases, collections, storage) into dbForLogs and operation metrics (reads, writes, compute) into dbForProject.
  • Consolidated all resource metric collection into the StatsResources worker, removing redundant real-time updates from API controllers and other workers.
  • Added sizeActual field to File model for accurate storage tracking, distinct from original upload size.

Key Changes by Area

Stats System: StatsResources worker is now the single source of truth for resource counting. Removed duplicate metric emissions from api.php shared controller, Builds.php, and Messaging.php workers.

API Controllers: Updated databases.php, functions.php, storage.php, and project.php to query dbForLogs for resource metrics using getDocument('stats', md5('_inf_' . $metric)) pattern.

Storage Metrics: Simplified StatsUsageDump.php by removing complex database storage calculation logic and switching to batch document writes. Added sizeActual field to File response model.

Configuration: Reduced _APP_STATS_RESOURCES_INTERVAL from 3600 to 15 seconds in .env, and set to 5 seconds in CI tests for faster execution.

Files Changed

File Changes Summary
.env Reduced _APP_STATS_RESOURCES_INTERVAL from 3600 to 15 seconds
.github/workflows/tests.yml Set _APP_STATS_RESOURCES_INTERVAL=5 for faster test execution
app/controllers/api/databases.php Removed inline metric calls; updated to query dbForLogs for resource metrics
app/controllers/api/functions.php Split metrics into logsDB and projectDB; fixed metric key mapping
app/controllers/api/project.php Updated to read metrics from dbForLogs
app/controllers/api/storage.php Updated to use dbForLogs for bucket/file/storage metrics
app/controllers/shared/api.php Removed duplicate metric emissions for databases, collections, documents, buckets, files, functions, deployments
app/init.php Added dbForLogs resource for direct injection
src/Appwrite/Platform/Workers/Builds.php Removed duplicate metric emissions
src/Appwrite/Platform/Workers/Messaging.php Removed duplicate metric emissions
src/Appwrite/Platform/Workers/StatsResources.php Updated metric naming to use METRIC_RESOURCE_TYPE_ID_* constants; removed $dbForLogs parameter from internal methods
src/Appwrite/Platform/Workers/StatsUsageDump.php Removed handleDatabaseStorage method; simplified to batch document writes
src/Appwrite/Utopia/Response/Model/File.php Added sizeActual field for actual file size tracking
tests/e2e/General/UsageTest.php Updated to use sizeActual; added sleep calls for timing stability
tests/e2e/Services/Databases/DatabasesConsoleClientTest.php Minor test adjustments
tests/e2e/Services/Health/HealthCustomServerTest.php Added health check for stats-usage-dump queue

Review Focus Areas

  • Verify StatsResources worker correctly aggregates all resource counts without gaps from removed inline emissions.
  • Check sizeActual vs sizeOriginal usage in storage calculations and client responses.
  • Confirm metric reads in API controllers handle missing stats documents gracefully.

Architecture

Design Decisions: The split between dbForLogs (resource counts) and dbForProject (operations) prevents double-counting while keeping operational metrics in the project DB for low-latency queries. Batch writes in StatsUsageDump replace per-document writes for efficiency. The sizeActual field separates billing-relevant storage from original upload size, which may differ due to compression or metadata.

Risks: The removal of real-time metric updates creates a dependency on the StatsResources worker running reliably. If the worker stalls, resource counts will lag. This is an intentional tradeoff for data consistency. The interval reduction to 15 seconds increases worker load; monitor for queue buildup under high resource churn.

Merge Status

NOT MERGEABLE — PR Score 30/100, below threshold (50)

  • [H2] 3 critical dependency CVEs detected
  • [H4] PR quality score (30) is below merge floor (50)
  • [H5] 5 HIGH-severity inline review findings need resolution (threshold: 3)
  • [H6] Code quality raw score (33) is below merge floor (40)

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 20, 2026

Greptile Summary

This PR refactors how usage metrics are sourced and written: resource-count and storage metrics are now exclusively computed by the StatsResources worker and read by usage endpoints from dbForLogs, while operational metrics continue to flow through the event queue into dbForProject. The StatsUsageDump worker is simplified to batch-write all metrics to both databases unconditionally, replacing a complex per-metric routing and database-storage recalculation path.

  • Metric routing split: usage endpoints now inject dbForLogs directly (via a new dbForLogs resource in init.php) and query resource/storage totals from it; event-listener increments for counts/storage are removed from api.php, Builds.php, and Messaging.php.
  • StatsUsageDump simplification: the skipBaseMetrics/skipParentIdMetrics filter lists and the entire handleDatabaseStorage recalculation path are removed; all queued metric documents are now batch-written to both project and logs databases.
  • sizeActual field added to the File response model and used in the usage e2e test to track real file sizes.

Confidence Score: 3/5

Not safe to merge as-is: the per-function usage endpoint returns wrong time-series data for builds and buildsStorage, and the default polling interval in .env will hammer the database in production.

The builds and buildsStorage data fields in /v1/functions/:functionId/usage were not updated to use $logsDBMetrics — they still reference $metrics[2] (execution-compute data) and $metrics[3] (builds MB-seconds), so every consumer of that endpoint gets wrong series data. The committed .env value for _APP_STATS_RESOURCES_INTERVAL was left at 15 seconds instead of 3600, causing StatsResources to run expensive full-table counts 240× more frequently in production. The rest of the refactor looks structurally sound.

app/controllers/api/functions.php (wrong metric array indices at lines 723-724) and .env (polling interval set to 15 s instead of the original 3600 s)

Important Files Changed

Filename Overview
app/controllers/api/functions.php Splits metrics into logsDB and projectDB reads, but leaves builds and buildsStorage time-series pointing at wrong $metrics indices — they return executionsCompute and buildsMbSeconds data respectively.
.env Default _APP_STATS_RESOURCES_INTERVAL reduced from 3600 s to 15 s — a 240x increase in polling frequency that will add significant database load in production.
app/controllers/api/databases.php Correctly splits stats queries between logsDB and projectDB; updates all response document index references to match the new split arrays.
app/controllers/api/storage.php Migrates storage-usage reads to logsDB via injected dbForLogs; uses inconsistent array-access $result['value'] ?? 0 where the rest of the PR uses getAttribute('value', 0).
app/controllers/shared/api.php Removes all event-listener count increments for databases, collections, documents, buckets, files, functions, and deployments — these are now exclusively tracked by StatsResources.
src/Appwrite/Platform/Workers/StatsUsageDump.php Removes metric skip filters and database-storage recalculation path; batch-writes all metrics to both projectDB and logsDB unconditionally.
src/Appwrite/Platform/Workers/StatsResources.php Drops dbForLogs parameter from count methods — resource counts/storage are now written only to projectDB by this worker.

Reviews (1): Last reviewed commit: "improve stats fetching from db" | Re-trigger Greptile

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 20, 2026

Code Quality Report — test-org-codity/appwrite · PR #1

Scanned: 2026-05-20 18:41 UTC | Score: 33/100 | Provider: github

Executive Summary

Severity Count
Critical 0
High 2
Medium 3
Low 51
Top Findings

[CQ-LLM-002] app/controllers/api/databases.php:4230 (Duplication · HIGH)

Issue: The code contains duplicated logic for handling metrics across different sections.
Suggestion: Extract the metric handling logic into a separate function to adhere to DRY principles.

foreach ([...$logsDBMetrics,...$metrics] as $metric) { ... }

[CQ-LLM-003] app/controllers/api/databases.php:4293 (Error_Handling · HIGH)

Issue: The code does not handle potential null values returned from database queries, which may lead to runtime errors.
Suggestion: Add null checks after database calls to ensure robustness.

$result = $dbForProject->getDocument('stats', md5('_inf_' . $metric));

[CQ-LLM-001] app/controllers/api/databases.php:4186 (Complexity · MEDIUM)

Issue: The function 'updateAttribute' has deep nesting due to multiple nested loops and conditionals.
Suggestion: Consider refactoring the function to reduce nesting and improve readability.

foreach ($logsDBMetrics as $metric) { ... }

[CQ-LLM-004] app/controllers/api/databases.php:4186 (Performance · MEDIUM)

Issue: The use of multiple database queries in loops can lead to performance issues (N+1 query problem).
Suggestion: Batch queries or optimize the database access pattern to reduce the number of queries.

foreach ($logsDBMetrics as $metric) { ... }

[CQ-LLM-006] app/controllers/api/databases.php:4186 (Maintainability · MEDIUM)

Issue: The use of magic strings for metric names can lead to maintainability issues.
Suggestion: Define constants for metric names to improve readability and maintainability.

md5('_inf_' . $metric)

[CQ-008] .env:90 (Maintainability · LOW)

Issue: Magic number 15 in code
Suggestion: Extract to a named constant

_APP_STATS_RESOURCES_INTERVAL=15

[CQ-009] app/controllers/api/databases.php:3352 (Style · LOW)

Issue: Line exceeds 120 characters (140 chars)
Suggestion: Break long lines into multiple lines for readability

            ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WR...

[CQ-009] app/controllers/api/databases.php:4136 (Style · LOW)

Issue: Line exceeds 120 characters (130 chars)
Suggestion: Break long lines into multiple lines for readability

            ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WR...

[CQ-LLM-005] app/controllers/api/databases.php:4186 (Documentation · LOW)

Issue: Missing docstrings for the new parameters added to the action function.
Suggestion: Add docstrings to describe the purpose and usage of the new parameters.

->action(function (string $range, Response $response, Database $dbForProject, Database $dbForLogs) { ... }

[CQ-002] app/controllers/api/databases.php:4201 (Complexity · LOW)

Issue: Deep nesting detected (depth ~5)
Suggestion: Extract nested blocks into helper functions

Query::equal('metric', [$metric]),

Per-File Breakdown

File Critical High Medium Low Total
.env 0 0 0 1 1
app/controllers/api/databases.php 0 2 3 19 24
app/controllers/api/functions.php 0 0 0 19 19
app/controllers/api/project.php 0 0 0 2 2
app/controllers/api/storage.php 0 0 0 1 1
src/Appwrite/Platform/Workers/StatsResources.php 0 0 0 2 2
src/Appwrite/Platform/Workers/StatsUsageDump.php 0 0 0 6 6
src/Appwrite/Utopia/Response/Model/File.php 0 0 0 1 1

Recommendations

  1. Resolve High severity issues, especially error handling gaps and performance bottlenecks.
  • Run automated tests after applying fixes to verify no regressions.

@DhirenMhatre
Copy link
Copy Markdown
Author

@codity review

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 20, 2026

Policy Check Failed

✗ 3/3 policy checks failed:

• Need 2 more approval(s) (0/2) — comment LGTM or approve via review
• Missing ticket reference (expected: JIRA-, ENG-, #*)
• 12 code file(s) changed but no test files added


To merge this PR:

  1. Address the failed checks listed above
  2. Ensure branch protection requires the codity/policy-check status

Configure policies in your dashboard

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 20, 2026

PR Summary

What Changed

  • Fixed duplicate metrics by splitting resource counts (databases, collections, files) into dbForLogs and operation metrics (reads/writes) into dbForProject.
  • Removed real-time metric tracking from API controllers and workers. Resource stats now flow only through the StatsResources background worker.
  • Simplified storage calculations by adding sizeActual to File responses and removing redundant aggregation logic.

Key Changes by Area

Metrics Pipeline: Consolidated all resource counting into StatsResources worker. Removed duplicate submissions from Builds, Messaging, and API controllers.

Database Layer: Added dbForLogs as a first-class resource in app/init.php:1564. Updated usage endpoints to query correct database per metric type using MD5 hash IDs.

Storage Tracking: Replaced complex handleDatabaseStorage logic with direct sizeActual field on File model.

Configuration: Reduced _APP_STATS_RESOURCES_INTERVAL from 3600s to 15s (5s in tests) for faster aggregation.

Files Changed

File Changes Summary
.env Reduced stats aggregation interval to 15 seconds
.github/workflows/tests.yml Reduced test stats interval to 5 seconds
app/controllers/api/databases.php Split metrics queries between dbForLogs and dbForProject
app/controllers/api/functions.php Split metrics queries; removed real-time tracking
app/controllers/api/project.php Updated to use dbForLogs directly with MD5 hash IDs
app/controllers/api/storage.php Updated to use dbForLogs directly with MD5 hash IDs
app/controllers/shared/api.php Removed real-time metric tracking (lines 109-165)
app/init.php Added dbForLogs resource dependency (line 1564)
src/Appwrite/Platform/Workers/Builds.php Removed duplicate build metrics (lines 712-715)
src/Appwrite/Platform/Workers/Messaging.php Removed duplicate messages metric (line 303)
src/Appwrite/Platform/Workers/StatsResources.php Removed dbForLogs parameter from count methods
src/Appwrite/Platform/Workers/StatsUsageDump.php Removed storage calculation logic; batch write all documents
src/Appwrite/Utopia/Response/Model/File.php Added sizeActual field
tests/e2e/General/UsageTest.php Updated to use sizeActual; added timing delays
tests/e2e/Services/Databases/DatabasesConsoleClientTest.php Added documentsTotal assertion
tests/e2e/Services/Health/HealthCustomServerTest.php Added stats-usage-dump queue health check

Review Focus Areas

  • Verify sizeActual correctly represents physical storage vs logical sizeOriginal.
  • Check that removing real-time tracking doesn't break metrics during high-load scenarios before worker processes.
  • Confirm MD5 hash ID lookups in dbForLogs handle collisions safely.

Architecture

Design Decisions: The split between dbForLogs (resource counts) and dbForProject (operations) reflects that resource metadata changes infrequently and needs strong consistency, while operation metrics are high-volume and time-series optimized. Removing real-time tracking trades immediate metric visibility for accuracy, accepting that stats will lag by the aggregation interval (now 15s).

Risks: The 15-second aggregation interval is intentionally aggressive for faster feedback, but may increase load on dbForLogs. If this proves too high in production, the interval can be tuned without code changes. The removal of real-time tracking means metrics will be stale during the aggregation window. This is an intentional tradeoff for correctness.

Merge Status

NOT MERGEABLE — PR Score 21/100, below threshold (50)

  • [H2] 3 critical dependency CVEs detected
  • [H4] PR quality score (21) is below merge floor (50)
  • [H5] 7 HIGH-severity inline review findings need resolution (threshold: 3)
  • [H6] Code quality raw score (35) is below merge floor (40)

Query::equal('metric', [$deploymentMetric]),
Query::equal('period', ['inf'])
]);
$deploymentValue = $dbForProject->getDocument('stats', md5('_inf_' . $deploymentMetric));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional High

Project usage now reads function deployment storage from the project DB even though this PR moved deployment/build storage metrics to the logs DB, so calling the project usage endpoint after creating a function deployment returns 0 for that function's storage.

Also reported at: app/controllers/api/project.php L212

Read both deployment and build storage metrics from $dbForLogs here (and use getAttribute('value', 0) consistently), because StatsUsageDump/StatsResources now populate those metrics in the logs DB instead of the project DB.

Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: app/controllers/api/project.php
Lines: 225-225
Issue Type: functional-high
Severity: high

Issue Description:
Project usage now reads function deployment storage from the project DB even though this PR moved deployment/build storage metrics to the logs DB, so calling the project usage endpoint after creating a function deployment returns 0 for that function's storage.

_Also reported at: `app/controllers/api/project.php` L212_

Current Code:
$deploymentValue  = $dbForProject->getDocument('stats', md5('_inf_' . $deploymentMetric));

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

Comment on lines +4426 to 4428
->action(function (string $databaseId, string $range, string $collectionId, Response $response, Database $dbForProject, Database $dbForLogs) {

$database = $dbForProject->getDocument('databases', $databaseId);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional High

The collection usage endpoint dereferences $database->getInternalId() before verifying the database exists, so add a database emptiness check before building collection paths.

Suggested fix
    ->action(function (string $databaseId, string $range, string $collectionId, Response $response, Database $dbForProject, Database $dbForLogs) {

        $database = $dbForProject->getDocument('databases', $databaseId);

        if ($database->isEmpty()) {
            throw new Exception(Exception::DATABASE_NOT_FOUND);
        }

        $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: app/controllers/api/databases.php
Lines: 4426-4428
Issue Type: functional-high
Severity: high

Issue Description:
The collection usage endpoint dereferences `$database->getInternalId()` before verifying the database exists, so add a database emptiness check before building collection paths.

Current Code:
    ->action(function (string $databaseId, string $range, string $collectionId, Response $response, Database $dbForProject, Database $dbForLogs) {

        $database = $dbForProject->getDocument('databases', $databaseId);
        $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

Comment on lines 723 to 724
'builds' => $usage[$metrics[2]]['data'],
'buildsStorage' => $usage[$metrics[3]]['data'],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional High

The per-function builds and buildsStorage fields now point at execution and MB-seconds metrics, so map them to the logsDBMetrics entries introduced above.

Suggested fix
            'builds' => $usage[$logsDBMetrics[2]]['data'],
            'buildsStorage' => $usage[$logsDBMetrics[3]]['data'],
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: app/controllers/api/functions.php
Lines: 723-724
Issue Type: functional-high
Severity: high

Issue Description:
The per-function builds and buildsStorage fields now point at execution and MB-seconds metrics, so map them to the logsDBMetrics entries introduced above.

Current Code:
            'builds' => $usage[$metrics[2]]['data'],
            'buildsStorage' => $usage[$metrics[3]]['data'],

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

Comment on lines +1890 to +1897
Authorization::skip(function () use ($dbForLogs, $bucket, $days, $metrics, &$stats) {
foreach ($metrics as $metric) {
$db = ($metric === str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED))
? $dbForLogs
: $dbForProject;

$result = $db->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
]);

$result = $dbForLogs->getDocument('stats', md5('_inf_' . $metric));
$stats[$metric]['total'] = $result['value'] ?? 0;

$limit = $days['limit'];
$period = $days['period'];
$results = $db->find('stats', [
$results = $dbForLogs->find('stats', [
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional High

This route now reads bucket file and storage metrics from the logs database, but those metrics are still produced in the project database here, so keep using the original split database selection for bucket metrics.

Suggested fix
        Authorization::skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) {
            foreach ($metrics as $metric) {
                $db = ($metric === str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED))
                    ? $dbForLogs
                    : $dbForProject;

                $result = $db->getDocument('stats', md5('_inf_' . $metric));
                $stats[$metric]['total'] = $result['value'] ?? 0;

                $limit = $days['limit'];
                $period = $days['period'];
                $results = $db->find('stats', [
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: app/controllers/api/storage.php
Lines: 1890-1897
Issue Type: functional-high
Severity: high

Issue Description:
This route now reads bucket file and storage metrics from the logs database, but those metrics are still produced in the project database here, so keep using the original split database selection for bucket metrics.

Current Code:
        Authorization::skip(function () use ($dbForLogs, $bucket, $days, $metrics, &$stats) {
            foreach ($metrics as $metric) {
                $result = $dbForLogs->getDocument('stats', md5('_inf_' . $metric));
                $stats[$metric]['total'] = $result['value'] ?? 0;

                $limit = $days['limit'];
                $period = $days['period'];
                $results = $dbForLogs->find('stats', [

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 20, 2026

Security Scan Summary

Metric Value
Vulnerabilities Critical: 0
Overall Risk Clean
Files Scanned 14

No critical security issues detected

Scan completed in 53.7s

Security scan powered by Codity.ai

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 20, 2026

Dependency vulnerability scanning

Metric Value
Vulnerabilities Found 8
Scanner composer audit
View vulnerability details (8 items)

1. google/protobuf 4.29.3

CVE: GHSA-p2gh-cfq4-4wjc
Severity: HIGH
Fixed in: 4.33.6

Protobuf: Denial of Service issue through malicious messages containing negative varints or deep recursion


2. phpseclib/phpseclib 3.0.43

CVE: GHSA-3qpq-r242-jqj7
Severity: CRITICAL
Fixed in: 1.0.29

phpseclib has a CVE-2024-27355 mitigation bypass — OID amplification DoS in ASN1::decodeOID()


3. phpseclib/phpseclib 3.0.43

CVE: GHSA-94g3-g5v7-q4jg
Severity: MEDIUM
Fixed in: 3.0.50

phpseclib's AES-CBC unpadding susceptible to padding oracle timing attack


4. phpseclib/phpseclib 3.0.43

CVE: GHSA-r854-jrxh-36qx
Severity: MEDIUM
Fixed in: 1.0.28

phpseclib has a variable-time HMAC comparison in SSH2::get_binary_packet() using != instead of hash_equals()


5. webonyx/graphql-php 14.11.10

CVE: GHSA-68jq-c3rv-pcrr
Severity: MEDIUM
Fixed in: 15.31.5

graphql-php is affected by a Denial of Service via quadratic complexity in OverlappingFieldsCanBeMerged validation


6. webonyx/graphql-php 14.11.10

CVE: GHSA-fc86-6rv6-2jpm
Severity: CRITICAL
Fixed in: 15.32.2

webonyx/graphql-php has quadratic validation cost in OverlappingFieldsCanBeMerged via inline fragments


7. webonyx/graphql-php 14.11.10

CVE: GHSA-r7cg-qjjm-xhqq
Severity: CRITICAL
Fixed in: 15.32.3

webonyx/graphql-php has unbounded recursion in parser that causes stack overflow on crafted nested input


8. phpunit/phpunit 9.6.22

CVE: GHSA-vvj3-c3rp-c85p
Severity: HIGH
Fixed in: 8.5.52

PHPUnit Vulnerable to Unsafe Deserialization in PHPT Code Coverage Handling

Powered by Codity.ai · Docs

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 20, 2026

License Compliance Scan

Metric Value
Packages Scanned 132
High Risk (Strong Copyleft) 0
Medium Risk (Weak Copyleft) 3
Low Risk (Permissive) 129
Unknown License 0

All licenses are low-risk and compliant

Medium Risk Licenses - 3 packages

LGPL-2.1-only (1 packages):

  • phpmailer/phpmailer 6.9.1

LGPL-2.1-or-later (1 packages):

  • php-amqplib/php-amqplib 3.7.3

LGPL-3.0-or-later (1 packages):

  • matomo/device-detector 6.1.6

Powered by Codity.ai · Docs

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 20, 2026

Code Quality Report — test-org-codity/appwrite · PR #1

Scanned: 2026-05-20 19:21 UTC | Score: 35/100 | Provider: github

Executive Summary

Severity Count
Critical 0
High 1
Medium 3
Low 51
Top Findings

[CQ-LLM-002] app/controllers/api/databases.php:4186 (Duplication · HIGH)

Issue: The code for fetching metrics from both logs and project databases is duplicated.
Suggestion: Extract the common logic into a separate function to adhere to the DRY principle.

Authorization::skip(function () use ($dbForLogs, $days, $logsDBMetrics, &$stats) { ... });

[CQ-LLM-001] app/controllers/api/databases.php:4186 (Complexity · MEDIUM)

Issue: The function 'updateAttribute' has deep nesting due to multiple nested loops and conditionals.
Suggestion: Consider refactoring the function to reduce nesting and improve readability.

foreach ([...$logsDBMetrics,...$metrics] as $metric) {

[CQ-LLM-005] app/controllers/api/databases.php:4186 (Maintainability · MEDIUM)

Issue: The use of magic strings for metric names can lead to maintenance issues.
Suggestion: Define constants for metric names to improve maintainability and reduce the risk of typos.

md5('_inf_' . $metric)

[CQ-LLM-003] app/controllers/api/databases.php:4293 (Error_Handling · MEDIUM)

Issue: The code does not handle potential null values returned from the database queries.
Suggestion: Add null checks to ensure that the code does not throw exceptions when accessing attributes of potentially null results.

$stats[$metric]['total'] = $result['value'] ?? 0;

[CQ-008] .env:90 (Maintainability · LOW)

Issue: Magic number 15 in code
Suggestion: Extract to a named constant

_APP_STATS_RESOURCES_INTERVAL=15

[CQ-009] app/controllers/api/databases.php:3352 (Style · LOW)

Issue: Line exceeds 120 characters (140 chars)
Suggestion: Break long lines into multiple lines for readability

            ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WR...

[CQ-009] app/controllers/api/databases.php:4136 (Style · LOW)

Issue: Line exceeds 120 characters (130 chars)
Suggestion: Break long lines into multiple lines for readability

            ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WR...

[CQ-LLM-004] app/controllers/api/databases.php:4186 (Documentation · LOW)

Issue: Missing docstring for the action function in the updateAttribute method.
Suggestion: Add a docstring to describe the purpose and parameters of the action function.

->action(function (string $range, Response $response, Database $dbForProject, Database $dbForLogs) {

[CQ-002] app/controllers/api/databases.php:4201 (Complexity · LOW)

Issue: Deep nesting detected (depth ~5)
Suggestion: Extract nested blocks into helper functions

Query::equal('metric', [$metric]),

[CQ-002] app/controllers/api/databases.php:4202 (Complexity · LOW)

Issue: Deep nesting detected (depth ~5)
Suggestion: Extract nested blocks into helper functions

Query::equal('period', [$period]),

Per-File Breakdown

File Critical High Medium Low Total
.env 0 0 0 1 1
app/controllers/api/databases.php 0 1 3 19 23
app/controllers/api/functions.php 0 0 0 19 19
app/controllers/api/project.php 0 0 0 2 2
app/controllers/api/storage.php 0 0 0 1 1
src/Appwrite/Platform/Workers/StatsResources.php 0 0 0 2 2
src/Appwrite/Platform/Workers/StatsUsageDump.php 0 0 0 6 6
src/Appwrite/Utopia/Response/Model/File.php 0 0 0 1 1

Recommendations

  1. Resolve High severity issues, especially error handling gaps and performance bottlenecks.
  • Run automated tests after applying fixes to verify no regressions.

@DhirenMhatre
Copy link
Copy Markdown
Author

@codity review

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 24, 2026

Policy Check Failed

✗ 3/3 policy checks failed:

• Need 2 more approval(s) (0/2) — comment LGTM or approve via review
• Missing ticket reference (expected: JIRA-, ENG-, #*)
• 12 code file(s) changed but no test files added


To merge this PR:

  1. Address the failed checks listed above
  2. Ensure branch protection requires the codity/policy-check status

Configure policies in your dashboard

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 24, 2026

PR Summary

What Changed

  • Separated metrics into two databases: resource counts (databases, collections, storage) now live in dbForLogs, while operation metrics (reads/writes, compute) stay in dbForProject. This fixes duplicate metrics caused by recording the same data in both places.
  • Removed real-time metric tracking from API controllers and workers. Stats are now calculated exclusively by the StatsResources background worker.
  • Added sizeActual field to File model to track actual storage bytes separately from original upload size.

Key Changes by Area

Configuration: Reduced _APP_STATS_RESOURCES_INTERVAL from 3600 to 15 seconds (5 seconds in CI) for faster stats processing.

API Controllers: Updated usage endpoints in databases.php, functions.php, storage.php, users.php, and project.php to query dbForLogs for resource metrics and dbForProject for operation metrics. Replaced findOne() with getDocument() using MD5 hash IDs.

Workers: Removed duplicate metric recording from StatsUsage.php, Builds.php, and Messaging.php. Simplified StatsResources.php by removing unused $dbForLogs parameters. Streamlined StatsUsageDump.php to write metrics in batches instead of individually.

Data Model: Added sizeActual field to File.php response model.

Files Changed

File Changes Summary
.env Reduced _APP_STATS_RESOURCES_INTERVAL to 15 seconds
.github/workflows/tests.yml Set _APP_STATS_RESOURCES_INTERVAL=5 for CI
app/controllers/api/databases.php Split metrics queries between dbForLogs and dbForProject; removed inline storage tracking
app/controllers/api/functions.php Split metrics queries; updated getFunctionUsage() and getUsage()
app/controllers/api/project.php Updated breakdown queries to use getDocument with MD5 hash IDs
app/controllers/api/storage.php Updated to fetch metrics from dbForLogs
app/controllers/shared/api.php Removed real-time metric tracking (lines 109-163)
app/init.php Added dbForLogs resource for direct injection
src/Appwrite/Platform/Workers/Builds.php Removed duplicate build metrics
src/Appwrite/Platform/Workers/Messaging.php Removed METRIC_MESSAGES counter
src/Appwrite/Platform/Workers/StatsResources.php Simplified method signatures; updated to use METRIC_RESOURCE_TYPE_ID_* constants
src/Appwrite/Platform/Workers/StatsUsageDump.php Removed database storage calculation; simplified to batch writes
src/Appwrite/Utopia/Response/Model/File.php Added sizeActual field
tests/e2e/General/UsageTest.php Updated to use sizeActual; added sleeps for async stats; commented out storage tests

Review Focus Areas

  • Verify dbForLogs vs dbForProject metric routing is correct in all usage endpoints. A misrouted metric will show zero values or stale data.
  • Check that removing real-time tracking does not break any user-facing stats. The StatsResources worker must run frequently enough (now 15s) to prevent visible lag.
  • Confirm sizeActual is populated correctly for all file uploads. Missing values will break storage usage calculations.

Architecture

Design Decisions: The split between dbForLogs (resource counts) and dbForProject (operations) is intentional. Resource counts change slowly and are calculated by background workers. Operation metrics change rapidly and need real-time accuracy. This tradeoff sacrifices some consistency latency for correctness.

Risks:

  • Intentional: Stats now depend on background worker execution. If StatsResources fails or falls behind, usage data will lag. This is acceptable for the single-source-of-truth benefit.
  • Unintentional: The removed database storage calculation in StatsUsageDump.php may have been load-bearing for some billing flows. Verify no downstream systems depend on this.

Merge Status

NOT MERGEABLE — PR Score 20/100, below threshold (50)

  • [H2] 3 critical dependency CVEs detected
  • [H4] PR quality score (20) is below merge floor (50)
  • [H5] 7 HIGH-severity inline review findings need resolution (threshold: 3)
  • [H6] Code quality raw score (33) is below merge floor (40)

Comment thread .env
_APP_MAINTENANCE_RETENTION_AUDIT=1209600
_APP_USAGE_AGGREGATION_INTERVAL=30
_APP_STATS_RESOURCES_INTERVAL=3600
_APP_STATS_RESOURCES_INTERVAL=15
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performance Critical

_APP_STATS_RESOURCES_INTERVAL was changed from 3600 (1 hour) to 15 (15 seconds). This is clearly a debug value that was not reverted before merging. In production, the StatsResources worker will now run every 15 seconds instead of every hour, causing a massive and continuous load on every project database. The CI workflow correctly overrides this to 5 for tests, but that override does not affect production deployments which read from this file.

Suggested change
_APP_STATS_RESOURCES_INTERVAL=15
_APP_STATS_RESOURCES_INTERVAL=3600
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert ini developer with deep knowledge of security, performance, and best practices.

### Context

File: .env
Lines: 90-90
Issue Type: performance-critical
Severity: critical

Issue Description:
`_APP_STATS_RESOURCES_INTERVAL` was changed from `3600` (1 hour) to `15` (15 seconds). This is clearly a debug value that was not reverted before merging. In production, the `StatsResources` worker will now run every 15 seconds instead of every hour, causing a massive and continuous load on every project database. The CI workflow correctly overrides this to `5` for tests, but that override does not affect production deployments which read from this file.

Current Code:
_APP_STATS_RESOURCES_INTERVAL=15

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow ini best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue

Comment on lines 142 to 148
$dbForLogs->createOrUpdateDocumentsWithIncrease(
'stats',
'value',
[$document]
$documents
);
Console::success('Usage logs pushed to Logs DB');
} catch (\Throwable $th) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robustness Medium

The previous implementation of writeToLogsDB filtered out resource-level metrics (databases, collections, documents, buckets, files, deployments, builds, storage) before writing to logsDB, because those were handled by the periodic StatsResources worker. This PR removes all filtering, meaning any residual metric from the queue (e.g. leftover keys from in-flight messages during a rolling deploy) will now be double-written to logsDB, potentially corrupting cumulative counts. The skip-list was a deliberate guard and should either be retained or replaced with an explicit allowlist.

Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: src/Appwrite/Platform/Workers/StatsUsageDump.php
Lines: 142-148
Issue Type: robustness-medium
Severity: medium

Issue Description:
The previous implementation of `writeToLogsDB` filtered out resource-level metrics (databases, collections, documents, buckets, files, deployments, builds, storage) before writing to logsDB, because those were handled by the periodic `StatsResources` worker. This PR removes all filtering, meaning any residual metric from the queue (e.g. leftover keys from in-flight messages during a rolling deploy) will now be double-written to logsDB, potentially corrupting cumulative counts. The skip-list was a deliberate guard and should either be retained or replaced with an explicit allowlist.

Current Code:
        /** @var \Utopia\Database\Database $dbForLogs*/
        $dbForLogs = call_user_func($this->getLogsDB, $project);

        try {
            $dbForLogs->createOrUpdateDocumentsWithIncrease(
                'stats',
                'value',
                $documents
            );
            Console::success('Usage logs pushed to Logs DB');

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional High

In the per-function usage response, 'builds' is mapped to $usage[$metrics[2]]['data'] and 'buildsStorage' to $usage[$metrics[3]]['data']. After the refactor, $metrics only contains compute/execution metrics: [0]=BUILDS_COMPUTE, [1]=EXECUTIONS, [2]=EXECUTIONS_COMPUTE, [3]=BUILDS_MB_SECONDS. So $metrics[2] is execution-compute data and $metrics[3] is builds-MB-seconds data — both completely wrong fields. The build count and build storage time-series data should be sourced from $logsDBMetrics[2] (METRIC_RESOURCE_TYPE_ID_BUILDS) and $logsDBMetrics[3] (METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE) respectively, exactly as the *Total counterparts above them correctly do.

Suggested fix
            'builds' => $usage[$logsDBMetrics[2]]['data'],
            'buildsStorage' => $usage[$logsDBMetrics[3]]['data'],
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: app/controllers/api/functions.php
Lines: 734-735
Issue Type: functional-high
Severity: high

Issue Description:
In the per-function usage response, `'builds'` is mapped to `$usage[$metrics[2]]['data']` and `'buildsStorage'` to `$usage[$metrics[3]]['data']`. After the refactor, `$metrics` only contains compute/execution metrics: `[0]=BUILDS_COMPUTE, [1]=EXECUTIONS, [2]=EXECUTIONS_COMPUTE, [3]=BUILDS_MB_SECONDS`. So `$metrics[2]` is execution-compute data and `$metrics[3]` is builds-MB-seconds data — both completely wrong fields. The build count and build storage time-series data should be sourced from `$logsDBMetrics[2]` (`METRIC_RESOURCE_TYPE_ID_BUILDS`) and `$logsDBMetrics[3]` (`METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE`) respectively, exactly as the `*Total` counterparts above them correctly do.

Current Code:
            'builds' => $usage[$metrics[2]]['data'],
            'buildsStorage' => $usage[$metrics[3]]['data'],

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional Medium

The per-function deployment and build storage breakdown still reads from $dbForProject via getDocument. However, $metricsFromLogsDB explicitly lists METRIC_DEPLOYMENTS_STORAGE and METRIC_BUILDS_STORAGE as metrics that now live in $dbForLogs, and StatsResources::countForFunctions had its $dbForLogs parameter removed — suggesting these per-function storage metrics are now written to logsDB by the periodic worker. If that is the case, reading them from $dbForProject will always return 0, silently producing a broken breakdown table.

Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: app/controllers/api/project.php
Lines: 225-232
Issue Type: functional-medium
Severity: medium

Issue Description:
The per-function deployment and build storage breakdown still reads from `$dbForProject` via `getDocument`. However, `$metricsFromLogsDB` explicitly lists `METRIC_DEPLOYMENTS_STORAGE` and `METRIC_BUILDS_STORAGE` as metrics that now live in `$dbForLogs`, and `StatsResources::countForFunctions` had its `$dbForLogs` parameter removed — suggesting these per-function storage metrics are now written to logsDB by the periodic worker. If that is the case, reading them from `$dbForProject` will always return 0, silently producing a broken breakdown table.

Current Code:
            $deploymentValue  = $dbForProject->getDocument('stats', md5('_inf_' . $deploymentMetric));

            $buildMetric = str_replace(['{functionInternalId}'], [$function->getInternalId()], METRIC_FUNCTION_ID_BUILDS_STORAGE);
            $buildValue = $dbForProject->getDocument('stats', md5('_inf_' . $buildMetric));

            $value = ($buildValue['value'] ?? 0) + ($deploymentValue['value'] ?? 0);

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 24, 2026

Security Scan Summary

Metric Value
Vulnerabilities Critical: 0
Overall Risk Clean
Files Scanned 14

No critical security issues detected

Scan completed in 46.1s

Security scan powered by Codity.ai

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 24, 2026

Dependency vulnerability scanning

Metric Value
Vulnerabilities Found 13
Scanner composer audit
Top 10 Vulnerabilities (13 total found)

1. google/protobuf 4.29.3

CVE: GHSA-p2gh-cfq4-4wjc
Severity: HIGH
Fixed in: 4.33.6

Protobuf: Denial of Service issue through malicious messages containing negative varints or deep recursion


2. phpseclib/phpseclib 3.0.43

CVE: GHSA-3qpq-r242-jqj7
Severity: CRITICAL
Fixed in: 1.0.29

phpseclib has a CVE-2024-27355 mitigation bypass — OID amplification DoS in ASN1::decodeOID()


3. phpseclib/phpseclib 3.0.43

CVE: GHSA-94g3-g5v7-q4jg
Severity: MEDIUM
Fixed in: 3.0.50

phpseclib's AES-CBC unpadding susceptible to padding oracle timing attack


4. phpseclib/phpseclib 3.0.43

CVE: GHSA-r854-jrxh-36qx
Severity: MEDIUM
Fixed in: 1.0.28

phpseclib has a variable-time HMAC comparison in SSH2::get_binary_packet() using != instead of hash_equals()


5. webonyx/graphql-php 14.11.10

CVE: GHSA-68jq-c3rv-pcrr
Severity: MEDIUM
Fixed in: 15.31.5

graphql-php is affected by a Denial of Service via quadratic complexity in OverlappingFieldsCanBeMerged validation


6. webonyx/graphql-php 14.11.10

CVE: GHSA-fc86-6rv6-2jpm
Severity: CRITICAL
Fixed in: 15.32.2

webonyx/graphql-php has quadratic validation cost in OverlappingFieldsCanBeMerged via inline fragments


7. webonyx/graphql-php 14.11.10

CVE: GHSA-r7cg-qjjm-xhqq
Severity: CRITICAL
Fixed in: 15.32.3

webonyx/graphql-php has unbounded recursion in parser that causes stack overflow on crafted nested input


8. phpunit/phpunit 9.6.22

CVE: GHSA-vvj3-c3rp-c85p
Severity: HIGH
Fixed in: 8.5.52

PHPUnit Vulnerable to Unsafe Deserialization in PHPT Code Coverage Handling


9. twig/twig 3.14.2

CVE: GHSA-24x9-r6q4-q93w
Severity: HIGH
Fixed in: 3.26.0

Twig: template_from_string() escapes a SourcePolicy-driven sandbox via synthesized template name


10. twig/twig 3.14.2

CVE: GHSA-4j38-f5cw-54h7
Severity: MEDIUM
Fixed in: 3.26.0

Twig: The spaceless filter implicitly marks its output as safe


3 more vulnerabilities not shown. Update dependencies to fix these issues.

Powered by Codity.ai · Docs

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 24, 2026

License Compliance Scan

Metric Value
Packages Scanned 132
High Risk (Strong Copyleft) 0
Medium Risk (Weak Copyleft) 3
Low Risk (Permissive) 129
Unknown License 0

All licenses are low-risk and compliant

Medium Risk Licenses - 3 packages

LGPL-2.1-only (1 packages):

  • phpmailer/phpmailer 6.9.1

LGPL-2.1-or-later (1 packages):

  • php-amqplib/php-amqplib 3.7.3

LGPL-3.0-or-later (1 packages):

  • matomo/device-detector 6.1.6

Powered by Codity.ai · Docs

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 24, 2026

Code Quality Report — test-org-codity/appwrite · PR #1

Scanned: 2026-05-24 10:34 UTC | Score: 33/100 | Provider: github

Executive Summary

Severity Count
Critical 0
High 2
Medium 3
Low 51
Top Findings

[CQ-LLM-002] app/controllers/api/databases.php:4245 (Duplication · HIGH)

Issue: There are multiple instances of similar code blocks for handling metrics which can be refactored to avoid duplication.
Suggestion: Extract the repeated logic into a separate function to adhere to the DRY principle.

foreach ([...$logsDBMetrics,...$metrics] as $metric) { ... }

[CQ-LLM-003] app/controllers/api/databases.php:4293 (Error_Handling · HIGH)

Issue: The code does not handle potential null values returned from the database queries, which could lead to runtime errors.
Suggestion: Add null checks after database calls to ensure that the code handles unexpected null values gracefully.

$result = $dbForProject->getDocument('stats', md5('_inf_' . $metric));

[CQ-LLM-001] app/controllers/api/databases.php:4186 (Complexity · MEDIUM)

Issue: The function 'updateAttribute' has deep nesting due to multiple nested loops and conditionals.
Suggestion: Consider refactoring the function to reduce nesting and improve readability.

foreach ($logsDBMetrics as $metric) { ... }

[CQ-LLM-004] app/controllers/api/databases.php:4186 (Performance · MEDIUM)

Issue: The use of multiple database queries in loops can lead to performance issues, especially if the number of metrics increases.
Suggestion: Consider batching database queries or optimizing the data retrieval process to reduce the number of queries.

foreach ($logsDBMetrics as $metric) { ... }

[CQ-LLM-006] app/controllers/api/databases.php:4186 (Maintainability · MEDIUM)

Issue: The use of magic strings for metric names can lead to maintainability issues.
Suggestion: Define constants for metric names to improve readability and maintainability.

md5('_inf_' . $metric)

[CQ-008] .env:90 (Maintainability · LOW)

Issue: Magic number 15 in code
Suggestion: Extract to a named constant

_APP_STATS_RESOURCES_INTERVAL=15

[CQ-009] app/controllers/api/databases.php:3352 (Style · LOW)

Issue: Line exceeds 120 characters (140 chars)
Suggestion: Break long lines into multiple lines for readability

            ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WR...

[CQ-009] app/controllers/api/databases.php:4136 (Style · LOW)

Issue: Line exceeds 120 characters (130 chars)
Suggestion: Break long lines into multiple lines for readability

            ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WR...

[CQ-LLM-005] app/controllers/api/databases.php:4186 (Documentation · LOW)

Issue: Missing docstrings for the new parameters added to the action function.
Suggestion: Add docstrings to describe the purpose and expected types of the new parameters.

->action(function (string $range, Response $response, Database $dbForProject, Database $dbForLogs) { ... }

[CQ-002] app/controllers/api/databases.php:4201 (Complexity · LOW)

Issue: Deep nesting detected (depth ~5)
Suggestion: Extract nested blocks into helper functions

Query::equal('metric', [$metric]),

Per-File Breakdown

File Critical High Medium Low Total
.env 0 0 0 1 1
app/controllers/api/databases.php 0 2 3 19 24
app/controllers/api/functions.php 0 0 0 19 19
app/controllers/api/project.php 0 0 0 2 2
app/controllers/api/storage.php 0 0 0 1 1
src/Appwrite/Platform/Workers/StatsResources.php 0 0 0 2 2
src/Appwrite/Platform/Workers/StatsUsageDump.php 0 0 0 6 6
src/Appwrite/Utopia/Response/Model/File.php 0 0 0 1 1

Recommendations

  1. Resolve High severity issues, especially error handling gaps and performance bottlenecks.
  • Run automated tests after applying fixes to verify no regressions.

@DhirenMhatre
Copy link
Copy Markdown
Author

@codity review

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 24, 2026

Policy Check Failed

✗ 3/3 policy checks failed:

• Need 2 more approval(s) (0/2) — comment LGTM or approve via review
• Missing ticket reference (expected: JIRA-, ENG-, #*)
• 12 code file(s) changed but no test files added


To merge this PR:

  1. Address the failed checks listed above
  2. Ensure branch protection requires the codity/policy-check status

Configure policies in your dashboard

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 24, 2026

PR Summary

What Changed

  • Separated metrics into two databases: dbForLogs for resource counts (databases, collections, storage) and dbForProject for operation metrics (reads/writes).
  • Removed duplicate metric tracking from real-time event handlers and consolidated stats collection into the StatsResources worker.
  • Simplified storage calculation logic and added sizeActual field to File responses.

Key Changes by Area

Stats System: Replaced scattered metric increments with centralized collection in StatsResources worker. Removed handleDatabaseStorage method and filtering logic from StatsUsageDump.

Database API: Updated usage endpoints to query correct database per metric type. Removed inline storage metric tracking from create/delete operations.

Functions API: Separated deployment/builds/storage metrics (logs DB) from compute/execution metrics (project DB).

File Model: Added sizeActual field to expose actual storage size alongside original size.

Configuration: Reduced _APP_STATS_RESOURCES_INTERVAL to 15 seconds (5 seconds in tests) for faster aggregation.

Files Changed

File Changes Summary
.env Reduced _APP_STATS_RESOURCES_INTERVAL from 3600 to 15 seconds
.github/workflows/tests.yml Set _APP_STATS_RESOURCES_INTERVAL=5 for faster test execution
app/controllers/api/databases.php Removed inline storage metrics; updated usage endpoints to use separate DBs
app/controllers/api/functions.php Separated metric queries between logs and project DBs
app/controllers/api/project.php Updated metric key patterns to METRIC_RESOURCE_TYPE_ID_* format
app/controllers/api/storage.php Updated to read metrics from dbForLogs
app/controllers/shared/api.php Removed duplicate metric increments for all resource types
app/init.php Added dbForLogs resource for direct injection
src/Appwrite/Platform/Workers/Builds.php Removed per-resource metrics (now handled by StatsResources)
src/Appwrite/Platform/Workers/Messaging.php Removed per-resource metrics (now handled by StatsResources)
src/Appwrite/Platform/Workers/StatsResources.php Added per-function deployment/builds storage tracking; updated metric naming
src/Appwrite/Platform/Workers/StatsUsageDump.php Removed storage calculation and filtering; simplified batch processing
src/Appwrite/Utopia/Response/Model/File.php Added sizeActual field
tests/e2e/General/UsageTest.php Updated to use sizeActual; added sleep calls for stability
tests/e2e/Services/Databases/DatabasesConsoleClientTest.php Added documentsTotal assertions
tests/e2e/Services/Health/HealthCustomServerTest.php Added health checks for stats queues

Review Focus Areas

  • Verify dbForLogs vs dbForProject query separation in usage endpoints handles all metric types correctly.
  • Check that removed inline metrics in shared/api.php are fully covered by StatsResources worker.
  • Confirm sizeActual field population matches expected storage calculation behavior.

Architecture

Design Decisions: The split between dbForLogs (resource counts) and dbForProject (operation metrics) eliminates write conflicts from concurrent updates. Centralizing in StatsResources trades immediate consistency for eventual consistency with simpler code. The sizeActual addition exposes implementation detail (actual vs original size) that was previously hidden.

Scalability & Extensibility: Batch processing in StatsUsageDump reduces DB round trips. Out of scope: horizontal scaling of stats workers or retention policies.

Risks (Intentional): Eventual consistency for resource counts (acceptable for stats). Risks (Unintentional): Missing metric coverage if StatsResources worker fails or lags; verify monitoring exists for worker queue depth.

Merge Status

NOT MERGEABLE — PR Score 21/100, below threshold (50)

  • [H2] 3 critical dependency CVEs detected
  • [H4] PR quality score (21) is below merge floor (50)
  • [H5] 7 HIGH-severity inline review findings need resolution (threshold: 3)
  • [H6] Code quality raw score (35) is below merge floor (40)

Comment thread .env
_APP_USAGE_AGGREGATION_INTERVAL=30
_APP_STATS_RESOURCES_INTERVAL=3600
_APP_STATS_RESOURCES_INTERVAL=15
_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional High

_APP_STATS_RESOURCES_INTERVAL was changed from 3600 (1 hour) to 15 seconds in the default .env shipped with the repository. The CI workflow correctly overrides this to 5 for tests, but any deployment that sources the bundled .env as a base will run the resource-counting worker every 15 seconds, causing severe unnecessary database load in production. The original value of 3600 should be restored.

Suggested change
_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000
_APP_STATS_RESOURCES_INTERVAL=3600
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert bash developer with deep knowledge of security, performance, and best practices.

### Context

File: .env
Lines: 91-91
Issue Type: functional-high
Severity: high

Issue Description:
`_APP_STATS_RESOURCES_INTERVAL` was changed from `3600` (1 hour) to `15` seconds in the default `.env` shipped with the repository. The CI workflow correctly overrides this to `5` for tests, but any deployment that sources the bundled `.env` as a base will run the resource-counting worker every 15 seconds, causing severe unnecessary database load in production. The original value of `3600` should be restored.

Current Code:
_APP_STATS_RESOURCES_INTERVAL=15

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow bash best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue

Comment on lines +722 to 723
'deploymentsStorage' => $usage[$logsDBMetrics[1]]['data'],
'builds' => $usage[$metrics[2]]['data'],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional Critical

In the per-function usage endpoint the 'builds' and 'buildsStorage' data fields were not updated to reference $logsDBMetrics after the metric arrays were split. They still reference $metrics[2] (now METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE) and $metrics[3] (now METRIC_FUNCTION_ID_BUILDS_MB_SECONDS) respectively, so the API returns execution-compute time series where callers expect build-count data, and MB-seconds time series where callers expect build-storage data. Both fields will silently return completely unrelated numbers.

Suggested fix
            'builds' => $usage[$logsDBMetrics[2]]['data'],
            'buildsStorage' => $usage[$logsDBMetrics[3]]['data'],
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: app/controllers/api/functions.php
Lines: 722-723
Issue Type: functional-critical
Severity: critical

Issue Description:
In the per-function usage endpoint the `'builds'` and `'buildsStorage'` data fields were not updated to reference `$logsDBMetrics` after the metric arrays were split. They still reference `$metrics[2]` (now `METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE`) and `$metrics[3]` (now `METRIC_FUNCTION_ID_BUILDS_MB_SECONDS`) respectively, so the API returns execution-compute time series where callers expect build-count data, and MB-seconds time series where callers expect build-storage data. Both fields will silently return completely unrelated numbers.

Current Code:
            'builds' => $usage[$metrics[2]]['data'],
            'buildsStorage' => $usage[$metrics[3]]['data'],

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue

Comment on lines 221 to 230
$functionsStorageBreakdown = array_map(function ($function) use ($dbForProject) {
$id = $function->getId();
$name = $function->getAttribute('name');
$deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $function->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE);
$deploymentValue = $dbForProject->findOne('stats', [
Query::equal('metric', [$deploymentMetric]),
Query::equal('period', ['inf'])
]);
$deploymentValue = $dbForProject->getDocument('stats', md5('_inf_' . $deploymentMetric));

$buildMetric = str_replace(['{functionInternalId}'], [$function->getInternalId()], METRIC_FUNCTION_ID_BUILDS_STORAGE);
$buildValue = $dbForProject->findOne('stats', [
Query::equal('metric', [$buildMetric]),
Query::equal('period', ['inf'])
]);
$buildValue = $dbForProject->getDocument('stats', md5('_inf_' . $buildMetric));

$value = ($buildValue['value'] ?? 0) + ($deploymentValue['value'] ?? 0);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional High

The per-function deployment+build storage breakdown reads both METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE and METRIC_FUNCTION_ID_BUILDS_STORAGE from $dbForProject. These are storage metrics that the rest of the PR migrates to $dbForLogs (the functions usage endpoint moves them to $logsDBMetrics). Additionally, the value is computed with raw array access $buildValue['value'] ?? 0 on Document objects that now come from getDocument — while Document's ArrayAccess implementation does delegate to getAttribute, the pattern is inconsistent and masks the primary bug: both lookups should target $dbForLogs. The result is that all per-function storage totals in the project overview will be 0.

Suggested fix
            $deploymentValue  = $dbForLogs->getDocument('stats', md5('_inf_' . $deploymentMetric));

            $buildMetric = str_replace(['{functionInternalId}'], [$function->getInternalId()], METRIC_FUNCTION_ID_BUILDS_STORAGE);
            $buildValue = $dbForLogs->getDocument('stats', md5('_inf_' . $buildMetric));

            $value = $buildValue->getAttribute('value', 0) + $deploymentValue->getAttribute('value', 0);
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: app/controllers/api/project.php
Lines: 221-230
Issue Type: functional-high
Severity: high

Issue Description:
The per-function deployment+build storage breakdown reads both `METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE` and `METRIC_FUNCTION_ID_BUILDS_STORAGE` from `$dbForProject`. These are storage metrics that the rest of the PR migrates to `$dbForLogs` (the functions usage endpoint moves them to `$logsDBMetrics`). Additionally, the value is computed with raw array access `$buildValue['value'] ?? 0` on Document objects that now come from `getDocument` — while Document's `ArrayAccess` implementation does delegate to `getAttribute`, the pattern is inconsistent and masks the primary bug: both lookups should target `$dbForLogs`. The result is that all per-function storage totals in the project overview will be `0`.

Current Code:
            $deploymentValue  = $dbForProject->getDocument('stats', md5('_inf_' . $deploymentMetric));

            $buildMetric = str_replace(['{functionInternalId}'], [$function->getInternalId()], METRIC_FUNCTION_ID_BUILDS_STORAGE);
            $buildValue = $dbForProject->getDocument('stats', md5('_inf_' . $buildMetric));

            $value = ($buildValue['value'] ?? 0) + ($deploymentValue['value'] ?? 0);

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional High

The per-database storage breakdown in the project usage action still queries $dbForProject for METRIC_DATABASE_ID_STORAGE, but this metric was migrated to $dbForLogs throughout this PR (e.g. the databases usage endpoint now reads it exclusively from $dbForLogs). Querying the wrong database will always return an empty Document, so every database's storage contribution is reported as 0 in the project-level storage breakdown.

Suggested fix
            $result = $dbForLogs->getDocument('stats', md5('_inf_' . $metric));

            return [
                'resourceId' => $id,
                'name' => $name,
                'value' => $result->getAttribute('value', 0),
            ];
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert php developer with deep knowledge of security, performance, and best practices.

### Context

File: app/controllers/api/project.php
Lines: 207-212
Issue Type: functional-high
Severity: high

Issue Description:
The per-database storage breakdown in the project usage action still queries `$dbForProject` for `METRIC_DATABASE_ID_STORAGE`, but this metric was migrated to `$dbForLogs` throughout this PR (e.g. the databases usage endpoint now reads it exclusively from `$dbForLogs`). Querying the wrong database will always return an empty Document, so every database's storage contribution is reported as `0` in the project-level storage breakdown.

Current Code:
            $result = $dbForProject->getDocument('stats', md5('_inf_' . $metric));

            return [
                'resourceId' => $id,
                'name' => $name,
                'value' => $result->getAttribute('value', 0),
            ];

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow php best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 24, 2026

Security Scan Summary

Metric Value
Vulnerabilities Critical: 0
Overall Risk Clean
Files Scanned 14

No critical security issues detected

Scan completed in 38.9s

Security scan powered by Codity.ai

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 24, 2026

Dependency vulnerability scanning

Metric Value
Vulnerabilities Found 13
Scanner composer audit
Top 10 Vulnerabilities (13 total found)

1. google/protobuf 4.29.3

CVE: GHSA-p2gh-cfq4-4wjc
Severity: HIGH
Fixed in: 4.33.6

Protobuf: Denial of Service issue through malicious messages containing negative varints or deep recursion


2. phpseclib/phpseclib 3.0.43

CVE: GHSA-3qpq-r242-jqj7
Severity: CRITICAL
Fixed in: 1.0.29

phpseclib has a CVE-2024-27355 mitigation bypass — OID amplification DoS in ASN1::decodeOID()


3. phpseclib/phpseclib 3.0.43

CVE: GHSA-94g3-g5v7-q4jg
Severity: MEDIUM
Fixed in: 3.0.50

phpseclib's AES-CBC unpadding susceptible to padding oracle timing attack


4. phpseclib/phpseclib 3.0.43

CVE: GHSA-r854-jrxh-36qx
Severity: MEDIUM
Fixed in: 1.0.28

phpseclib has a variable-time HMAC comparison in SSH2::get_binary_packet() using != instead of hash_equals()


5. webonyx/graphql-php 14.11.10

CVE: GHSA-68jq-c3rv-pcrr
Severity: MEDIUM
Fixed in: 15.31.5

graphql-php is affected by a Denial of Service via quadratic complexity in OverlappingFieldsCanBeMerged validation


6. webonyx/graphql-php 14.11.10

CVE: GHSA-fc86-6rv6-2jpm
Severity: CRITICAL
Fixed in: 15.32.2

webonyx/graphql-php has quadratic validation cost in OverlappingFieldsCanBeMerged via inline fragments


7. webonyx/graphql-php 14.11.10

CVE: GHSA-r7cg-qjjm-xhqq
Severity: CRITICAL
Fixed in: 15.32.3

webonyx/graphql-php has unbounded recursion in parser that causes stack overflow on crafted nested input


8. phpunit/phpunit 9.6.22

CVE: GHSA-vvj3-c3rp-c85p
Severity: HIGH
Fixed in: 8.5.52

PHPUnit Vulnerable to Unsafe Deserialization in PHPT Code Coverage Handling


9. twig/twig 3.14.2

CVE: GHSA-24x9-r6q4-q93w
Severity: HIGH
Fixed in: 3.26.0

Twig: template_from_string() escapes a SourcePolicy-driven sandbox via synthesized template name


10. twig/twig 3.14.2

CVE: GHSA-4j38-f5cw-54h7
Severity: MEDIUM
Fixed in: 3.26.0

Twig: The spaceless filter implicitly marks its output as safe


3 more vulnerabilities not shown. Update dependencies to fix these issues.

Powered by Codity.ai · Docs

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 24, 2026

License Compliance Scan

Metric Value
Packages Scanned 132
High Risk (Strong Copyleft) 0
Medium Risk (Weak Copyleft) 3
Low Risk (Permissive) 129
Unknown License 0

All licenses are low-risk and compliant

Medium Risk Licenses - 3 packages

LGPL-2.1-only (1 packages):

  • phpmailer/phpmailer 6.9.1

LGPL-2.1-or-later (1 packages):

  • php-amqplib/php-amqplib 3.7.3

LGPL-3.0-or-later (1 packages):

  • matomo/device-detector 6.1.6

Powered by Codity.ai · Docs

@codity-dm
Copy link
Copy Markdown

codity-dm Bot commented May 24, 2026

Code Quality Report — test-org-codity/appwrite · PR #1

Scanned: 2026-05-24 10:51 UTC | Score: 35/100 | Provider: github

Executive Summary

Severity Count
Critical 0
High 1
Medium 3
Low 51
Top Findings

[CQ-LLM-002] app/controllers/api/databases.php:4245 (Duplication · HIGH)

Issue: There are multiple instances of similar code for handling metrics which could be abstracted into a separate function.
Suggestion: Create a helper function to handle metric processing to adhere to DRY principles.

foreach ([...$logsDBMetrics,...$metrics] as $metric) { ... }

[CQ-LLM-001] app/controllers/api/databases.php:4186 (Complexity · MEDIUM)

Issue: The function 'updateAttribute' has deep nesting due to multiple nested loops and conditionals.
Suggestion: Consider refactoring the function to reduce nesting and improve readability.

foreach ($logsDBMetrics as $metric) { ... }

[CQ-LLM-004] app/controllers/api/databases.php:4186 (Performance · MEDIUM)

Issue: The use of multiple database calls in loops can lead to performance issues, especially if the number of metrics is large.
Suggestion: Consider batching database calls or optimizing the queries to reduce the number of calls made.

foreach ($logsDBMetrics as $metric) { ... }

[CQ-LLM-003] app/controllers/api/databases.php:4293 (Error_Handling · MEDIUM)

Issue: The code does not handle potential null values returned from database queries, which could lead to runtime errors.
Suggestion: Add null checks after database calls to ensure that the code handles unexpected null values gracefully.

$result = $dbForProject->getDocument('stats', md5('_inf_' . $metric));

[CQ-008] .env:90 (Maintainability · LOW)

Issue: Magic number 15 in code
Suggestion: Extract to a named constant

_APP_STATS_RESOURCES_INTERVAL=15

[CQ-009] app/controllers/api/databases.php:3352 (Style · LOW)

Issue: Line exceeds 120 characters (140 chars)
Suggestion: Break long lines into multiple lines for readability

            ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WR...

[CQ-009] app/controllers/api/databases.php:4136 (Style · LOW)

Issue: Line exceeds 120 characters (130 chars)
Suggestion: Break long lines into multiple lines for readability

            ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WR...

[CQ-LLM-005] app/controllers/api/databases.php:4186 (Documentation · LOW)

Issue: Missing docstring for the action function which makes it hard to understand its purpose.
Suggestion: Add a docstring to describe the function's purpose, parameters, and return values.

->action(function (string $range, Response $response, Database $dbForProject, Database $dbForLogs) { ... }

[CQ-002] app/controllers/api/databases.php:4201 (Complexity · LOW)

Issue: Deep nesting detected (depth ~5)
Suggestion: Extract nested blocks into helper functions

Query::equal('metric', [$metric]),

[CQ-002] app/controllers/api/databases.php:4202 (Complexity · LOW)

Issue: Deep nesting detected (depth ~5)
Suggestion: Extract nested blocks into helper functions

Query::equal('period', [$period]),

Per-File Breakdown

File Critical High Medium Low Total
.env 0 0 0 1 1
app/controllers/api/databases.php 0 1 3 19 23
app/controllers/api/functions.php 0 0 0 19 19
app/controllers/api/project.php 0 0 0 2 2
app/controllers/api/storage.php 0 0 0 1 1
src/Appwrite/Platform/Workers/StatsResources.php 0 0 0 2 2
src/Appwrite/Platform/Workers/StatsUsageDump.php 0 0 0 6 6
src/Appwrite/Utopia/Response/Model/File.php 0 0 0 1 1

Recommendations

  1. Resolve High severity issues, especially error handling gaps and performance bottlenecks.
  • Run automated tests after applying fixes to verify no regressions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants