GraphQL: Add durationStatistics to ProjectPipelineAnalyticsResolver
What does this MR do and why?
This MR adds a durationStatistics
field to ProjectPipelineAnalyticsResolver
as an alpha field. This will allow computing the mean duration of pipelines in #454310 (closed).
Changelog: added
Part of #454310 (closed)
MR acceptance checklist
Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Screenshots or screen recordings
Screenshots are required for UI changes, and strongly recommended for all other merge requests.
How to set up and validate locally
Numbered steps to set up and validate the change are strongly suggested.
-
Go to the shell in your GDK
gitlab
directory and runbundle exec rake "gitlab:seed:runner_fleet"
. This will seed your GDK with some pipelines and jobs required for testing this MR. -
Execute the following query:
{ project(fullPath: "rf-top-level-group-1/rf-group-1.1/rf-group-1.1.1/rf-project-1-1-1-1") { pipelineAnalytics { durationStatistics { p50 p75 p90 p95 p99 } } } }
You should obtain the requested statistics from the pipelines in the specified group, as demonstrated in the screenshot above.
Database query plan
Percentile query for gitlab-org/gitlab project's latest 1000 pipelines
https://console.postgres.ai/gitlab/gitlab-production-ci/sessions/29369/commands/91384
SELECT PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY pipelines.duration) AS p50, PERCENTILE_CONT(0.75) WITHIN GROUP
(ORDER BY pipelines.duration) AS p75, PERCENTILE_CONT(0.9) WITHIN GROUP (ORDER BY pipelines.duration) AS p90,
PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY pipelines.duration) AS p95,
PERCENTILE_CONT(0.99) WITHIN GROUP (ORDER BY pipelines.duration) AS p99
FROM (
SELECT "ci_pipelines"."duration"
FROM "ci_pipelines"
WHERE "ci_pipelines"."project_id" = 278964
AND ("ci_pipelines"."source" IN (1, 2, 3, 4, 5, 6, 7, 8, 10, 11)
OR "ci_pipelines"."source" IS NULL)
AND ("ci_pipelines"."status" IN ('success', 'failed', 'canceled', 'skipped'))
ORDER BY "ci_pipelines"."id" DESC
LIMIT 1000) pipelines
Aggregate (cost=1501.69..1501.70 rows=1 width=40) (actual time=3640.279..3640.281 rows=1 loops=1)
Buffers: shared hit=432 read=3978 dirtied=2254
I/O Timings: read=3447.488 write=0.000
-> Limit (cost=0.60..1486.67 rows=1000 width=12) (actual time=28.630..3638.537 rows=1000 loops=1)
Buffers: shared hit=424 read=3977 dirtied=2254
I/O Timings: read=3447.427 write=0.000
-> Index Scan using index_ci_pipelines_on_project_id_and_id_desc on public.ci_pipelines (cost=0.60..3341804.22 rows=2248749 width=12) (actual time=28.627..3637.871 rows=1000 loops=1)
Index Cond: (ci_pipelines.project_id = 278964)
Filter: (((ci_pipelines.source = ANY ('{1,2,3,4,5,6,7,8,10,11}'::integer[])) OR (ci_pipelines.source IS NULL)) AND ((ci_pipelines.status)::text = ANY ('{success,failed,canceled,skipped}'::text[])))
Rows Removed by Filter: 2466
Buffers: shared hit=424 read=3977 dirtied=2254
I/O Timings: read=3447.427 write=0.000