Description
When quota_per_project_enable is set to false in Harbor's configuration, no rows are created in the quota or quota_usage tables for new projects. The Prometheus exporter's projectBasicSQL uses INNER JOIN on both tables, silently excluding every project without quota records from the in-memory project map built on each scrape.
The three subsequent collector functions (updateProjectMemberInfo, updateProjectRepoInfo, updateProjectArtifactInfo) query those same projects independently and call log.Errorf("project not found, ID %d") for each project ID absent from the map. With a large number of affected projects this produces hundreds of error log writes per scrape, increasing scrape latency and risking Prometheus scrape timeouts that drop all Harbor metrics. Affected projects also have no metrics emitted for quota, member, repo, or artifact dimensions.
Steps to Reproduce
- Set
quota_per_project_enable=false in Harbor configuration.
- Create one or more projects — no rows are inserted into
quota or quota_usage.
- Observe the exporter logs: a
project not found error is logged for each affected project on every Prometheus scrape.
- With enough affected projects, Prometheus scrapes begin to time out intermittently.
Expected Behavior
All non-deleted projects appear in the collector map regardless of whether quota records exist. Projects without quota records should emit 0 for storage quota/usage metrics.
Actual Behavior
Projects without quota records are silently dropped from the map. The exporter floods logs with project not found errors on every scrape and Prometheus metrics are incomplete or missing.
Environment
- Harbor version: v2.13.1
quota_per_project_enable: false
Fix
PR #23520 switches projectBasicSQL from INNER JOIN to LEFT JOIN on quota, quota_usage, and project_metadata, with COALESCE defaults so projects without quota records emit {} (storage = 0) rather than being dropped.
Description
When
quota_per_project_enableis set tofalsein Harbor's configuration, no rows are created in thequotaorquota_usagetables for new projects. The Prometheus exporter'sprojectBasicSQLusesINNER JOINon both tables, silently excluding every project without quota records from the in-memory project map built on each scrape.The three subsequent collector functions (
updateProjectMemberInfo,updateProjectRepoInfo,updateProjectArtifactInfo) query those same projects independently and calllog.Errorf("project not found, ID %d")for each project ID absent from the map. With a large number of affected projects this produces hundreds of error log writes per scrape, increasing scrape latency and risking Prometheus scrape timeouts that drop all Harbor metrics. Affected projects also have no metrics emitted for quota, member, repo, or artifact dimensions.Steps to Reproduce
quota_per_project_enable=falsein Harbor configuration.quotaorquota_usage.project not founderror is logged for each affected project on every Prometheus scrape.Expected Behavior
All non-deleted projects appear in the collector map regardless of whether quota records exist. Projects without quota records should emit
0for storage quota/usage metrics.Actual Behavior
Projects without quota records are silently dropped from the map. The exporter floods logs with
project not founderrors on every scrape and Prometheus metrics are incomplete or missing.Environment
quota_per_project_enable:falseFix
PR #23520 switches
projectBasicSQLfromINNER JOINtoLEFT JOINonquota,quota_usage, andproject_metadata, withCOALESCEdefaults so projects without quota records emit{}(storage = 0) rather than being dropped.