Skip to content

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.

Changelog: added

Part of #454310

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.

image

How to set up and validate locally

Numbered steps to set up and validate the change are strongly suggested.

  1. Go to the shell in your GDK gitlab directory and run bundle exec rake "gitlab:seed:runner_fleet". This will seed your GDK with some pipelines and jobs required for testing this MR.

  2. Open http://gdk.test:3000/-/graphql-explorer

  3. 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

Merge request reports