Skip to content

Commit e7f46c2

Browse files
authored
feat: tb endpoints for new widgets (#3667)
Signed-off-by: Gašper Grom <[email protected]>
1 parent 3efbbbe commit e7f46c2

File tree

4 files changed

+362
-1
lines changed

4 files changed

+362
-1
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
DESCRIPTION >
2+
- `median_time_to_merge.pipe` serves the "Median time to merge" widget in the Development tab.
3+
- Calculates the median time in seconds from PR opening to merge for the selected time period.
4+
- **When `granularity` is NOT provided, returns a single KPI value** (median) across the entire time range.
5+
- **When `granularity` is provided, returns time-series data** showing median time to merge aggregated by different time periods (daily, weekly, monthly, quarterly, yearly).
6+
- Uses `generate_timeseries` pipe to create consistent time periods and left joins PR data to handle periods with no merged PRs.
7+
- Only includes PRs that have been merged (`isNotNull(pra.mergedAt)`) to ensure accurate merge time calculations.
8+
- Replaces the deprecated `averageTimeToMerge` widget with more robust median-based statistics.
9+
- Available for projects connected with Gerrit, GitHub, or GitLab platforms.
10+
- Primary use case: monitoring code review and merge cycle time, identifying bottlenecks in the merge process.
11+
- Parameters:
12+
- `project`: Required string for project slug (e.g., 'k8s', 'tensorflow') - inherited from `segments_filtered`
13+
- `repos`: Optional array of repository URLs for filtering (e.g., ['https://github.com/kubernetes/kubernetes'])
14+
- `startDate`: Optional DateTime filter for PRs opened after timestamp (e.g., '2024-01-01 00:00:00')
15+
- `endDate`: Optional DateTime filter for PRs opened before timestamp (e.g., '2024-12-31 23:59:59')
16+
- `platform`: Optional string filter for source platform (e.g., 'gerrit', 'github', 'gitlab')
17+
- `granularity`: Optional string for time aggregation ('daily', 'weekly', 'monthly', 'quarterly', 'yearly')
18+
- Response:
19+
- Without granularity: `medianTimeToMergeSeconds` (median value in seconds)
20+
- With granularity: `startDate`, `endDate`, and `medianTimeToMergeSeconds` for each time period
21+
22+
TAGS "Widget", "Pull requests", "Development metrics", "Merge time"
23+
24+
NODE timeseries_generation_for_median_time_to_merge
25+
SQL >
26+
%
27+
{% if defined(granularity) %}
28+
SELECT
29+
ds."startDate",
30+
ds."endDate",
31+
ifNull(round(median(prf.mergedInSeconds)), 0) AS "medianTimeToMergeSeconds"
32+
FROM generate_timeseries ds
33+
LEFT JOIN
34+
pull_requests_filtered prf
35+
ON CASE
36+
WHEN {{ granularity }} = 'daily'
37+
THEN toDate(prf.openedAt)
38+
WHEN {{ granularity }} = 'weekly'
39+
THEN toStartOfWeek(prf.openedAt)
40+
WHEN {{ granularity }} = 'monthly'
41+
THEN toStartOfMonth(prf.openedAt)
42+
WHEN {{ granularity }} = 'quarterly'
43+
THEN toStartOfQuarter(prf.openedAt)
44+
WHEN {{ granularity }} = 'yearly'
45+
THEN toStartOfYear(prf.openedAt)
46+
END
47+
= ds."startDate"
48+
AND isNotNull(prf.mergedAt)
49+
AND isNotNull(prf.mergedInSeconds)
50+
{% if defined(platform) %}
51+
AND prf.platform
52+
= {{
53+
String(
54+
platform,
55+
description="Filter by platform (e.g., 'gerrit', 'github', 'gitlab')",
56+
required=False,
57+
)
58+
}}
59+
{% end %}
60+
{% if defined(startDate) %}
61+
AND prf.openedAt
62+
>= {{
63+
DateTime(
64+
startDate,
65+
description="Filter PRs opened after this timestamp",
66+
required=False,
67+
)
68+
}}
69+
{% end %}
70+
{% if defined(endDate) %}
71+
AND prf.openedAt
72+
<= {{
73+
DateTime(
74+
endDate,
75+
description="Filter PRs opened before this timestamp",
76+
required=False,
77+
)
78+
}}
79+
{% end %}
80+
GROUP BY ds."startDate", ds."endDate"
81+
ORDER BY ds."startDate"
82+
{% else %} SELECT 1
83+
{% end %}
84+
85+
NODE median_time_to_merge_merged
86+
SQL >
87+
%
88+
{% if not defined(granularity) %}
89+
SELECT round(median(prf.mergedInSeconds)) AS "medianTimeToMergeSeconds"
90+
FROM pull_requests_filtered prf
91+
WHERE
92+
isNotNull(prf.mergedAt) AND isNotNull(prf.mergedInSeconds)
93+
{% if defined(platform) %}
94+
AND prf.platform
95+
= {{
96+
String(
97+
platform,
98+
description="Filter by platform (e.g., 'gerrit', 'github', 'gitlab')",
99+
required=False,
100+
)
101+
}}
102+
{% end %}
103+
{% if defined(startDate) %}
104+
AND prf.openedAt
105+
>= {{
106+
DateTime(
107+
startDate,
108+
description="Filter PRs opened after this timestamp",
109+
required=False,
110+
)
111+
}}
112+
{% end %}
113+
{% if defined(endDate) %}
114+
AND prf.openedAt
115+
<= {{
116+
DateTime(
117+
endDate,
118+
description="Filter PRs opened before this timestamp",
119+
required=False,
120+
)
121+
}}
122+
{% end %}
123+
{% else %} SELECT * FROM timeseries_generation_for_median_time_to_merge
124+
{% end %}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
DESCRIPTION >
2+
- `median_time_to_review.pipe` serves the "Median time to review" widget in the Development tab.
3+
- Calculates the median time in seconds from PR opening to first review for the selected time period.
4+
- **When `granularity` is NOT provided, returns a single KPI value** (median) across the entire time range.
5+
- **When `granularity` is provided, returns time-series data** showing median time to review aggregated by different time periods (daily, weekly, monthly, quarterly, yearly).
6+
- Uses `generate_timeseries` pipe to create consistent time periods and left joins PR data to handle periods with no reviewed PRs.
7+
- Only includes PRs that have been reviewed (`isNotNull(pra.reviewedAt)`) to ensure accurate review time calculations.
8+
- Replaces the deprecated `waitTimeFor1stReview` widget with more robust median-based statistics.
9+
- Available for projects connected with Gerrit, GitHub, or GitLab platforms.
10+
- Primary use case: monitoring code review responsiveness and identifying delays in the review process.
11+
- Parameters:
12+
- `project`: Required string for project slug (e.g., 'k8s', 'tensorflow') - inherited from `segments_filtered`
13+
- `repos`: Optional array of repository URLs for filtering (e.g., ['https://github.com/kubernetes/kubernetes'])
14+
- `startDate`: Optional DateTime filter for PRs opened after timestamp (e.g., '2024-01-01 00:00:00')
15+
- `endDate`: Optional DateTime filter for PRs opened before timestamp (e.g., '2024-12-31 23:59:59')
16+
- `platform`: Optional string filter for source platform (e.g., 'gerrit', 'github', 'gitlab')
17+
- `granularity`: Optional string for time aggregation ('daily', 'weekly', 'monthly', 'quarterly', 'yearly')
18+
- Response:
19+
- Without granularity: `medianTimeToReviewSeconds` (median value in seconds)
20+
- With granularity: `startDate`, `endDate`, and `medianTimeToReviewSeconds` for each time period
21+
22+
TAGS "Widget", "Pull requests", "Development metrics", "Review time"
23+
24+
NODE timeseries_generation_for_median_time_to_review
25+
SQL >
26+
%
27+
{% if defined(granularity) %}
28+
SELECT
29+
ds."startDate",
30+
ds."endDate",
31+
ifNull(round(median(prf.reviewedInSeconds)), 0) AS "medianTimeToReviewSeconds"
32+
FROM generate_timeseries ds
33+
LEFT JOIN
34+
pull_requests_filtered prf
35+
ON CASE
36+
WHEN {{ granularity }} = 'daily'
37+
THEN toDate(prf.openedAt)
38+
WHEN {{ granularity }} = 'weekly'
39+
THEN toStartOfWeek(prf.openedAt)
40+
WHEN {{ granularity }} = 'monthly'
41+
THEN toStartOfMonth(prf.openedAt)
42+
WHEN {{ granularity }} = 'quarterly'
43+
THEN toStartOfQuarter(prf.openedAt)
44+
WHEN {{ granularity }} = 'yearly'
45+
THEN toStartOfYear(prf.openedAt)
46+
END
47+
= ds."startDate"
48+
AND isNotNull(prf.reviewedAt)
49+
AND isNotNull(prf.reviewedInSeconds)
50+
{% if defined(platform) %}
51+
AND prf.platform
52+
= {{
53+
String(
54+
platform,
55+
description="Filter by platform (e.g., 'gerrit', 'github', 'gitlab')",
56+
required=False,
57+
)
58+
}}
59+
{% end %}
60+
{% if defined(startDate) %}
61+
AND prf.openedAt
62+
>= {{
63+
DateTime(
64+
startDate,
65+
description="Filter PRs opened after this timestamp",
66+
required=False,
67+
)
68+
}}
69+
{% end %}
70+
{% if defined(endDate) %}
71+
AND prf.openedAt
72+
<= {{
73+
DateTime(
74+
endDate,
75+
description="Filter PRs opened before this timestamp",
76+
required=False,
77+
)
78+
}}
79+
{% end %}
80+
GROUP BY ds."startDate", ds."endDate"
81+
ORDER BY ds."startDate"
82+
{% else %} SELECT 1
83+
{% end %}
84+
85+
NODE median_time_to_review_merged
86+
SQL >
87+
%
88+
{% if not defined(granularity) %}
89+
SELECT round(median(prf.reviewedInSeconds)) AS "medianTimeToReviewSeconds"
90+
FROM pull_requests_filtered prf
91+
WHERE
92+
isNotNull(prf.reviewedAt) AND isNotNull(prf.reviewedInSeconds)
93+
{% if defined(platform) %}
94+
AND prf.platform
95+
= {{
96+
String(
97+
platform,
98+
description="Filter by platform (e.g., 'gerrit', 'github', 'gitlab')",
99+
required=False,
100+
)
101+
}}
102+
{% end %}
103+
{% if defined(startDate) %}
104+
AND prf.openedAt
105+
>= {{
106+
DateTime(
107+
startDate,
108+
description="Filter PRs opened after this timestamp",
109+
required=False,
110+
)
111+
}}
112+
{% end %}
113+
{% if defined(endDate) %}
114+
AND prf.openedAt
115+
<= {{
116+
DateTime(
117+
endDate,
118+
description="Filter PRs opened before this timestamp",
119+
required=False,
120+
)
121+
}}
122+
{% end %}
123+
{% else %} SELECT * FROM timeseries_generation_for_median_time_to_review
124+
{% end %}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
DESCRIPTION >
2+
- `patchsets_per_review.pipe` serves the "Patchsets per review" widget in the Development tab.
3+
- Calculates median or average number of patchsets per review for Gerrit changesets in the selected time period.
4+
- **When `granularity` is NOT provided, returns a single KPI value** (median or average) across the entire time range.
5+
- **When `granularity` is provided, returns time-series data** showing patchsets per review aggregated by different time periods (daily, weekly, monthly, quarterly, yearly).
6+
- Uses `generate_timeseries` pipe to create consistent time periods and left joins PR data to handle periods with no data.
7+
- Only includes Gerrit changesets with patchset data (`platform = 'gerrit'` and `isNotNull(numberOfPatchsets)`) to ensure accurate calculations.
8+
- Primary use case: analyzing code review iteration patterns and review efficiency specifically for Gerrit changesets.
9+
- Parameters:
10+
- `project`: Required string for project slug (e.g., 'k8s', 'tensorflow') - inherited from `segments_filtered`
11+
- `repos`: Optional array of repository URLs for filtering (e.g., ['https://gerrit.example.com/repo'])
12+
- `startDate`: Optional DateTime filter for changesets opened after timestamp (e.g., '2024-01-01 00:00:00')
13+
- `endDate`: Optional DateTime filter for changesets opened before timestamp (e.g., '2024-12-31 23:59:59')
14+
- `granularity`: Optional string for time aggregation ('daily', 'weekly', 'monthly', 'quarterly', 'yearly')
15+
- `dataType`: Optional string to select calculation method ('median' or 'average'), defaults to 'median'
16+
- Response:
17+
- Without granularity: `patchsetsPerReview` (median or average value)
18+
- With granularity: `startDate`, `endDate`, and `patchsetsPerReview` for each time period
19+
20+
TAGS "Widget", "Pull requests", "Development metrics", "Code review", "Gerrit"
21+
22+
NODE timeseries_generation_for_patchsets_per_review
23+
SQL >
24+
%
25+
{% if defined(granularity) %}
26+
{% set dataType_val = 'median' %}
27+
{% if defined(dataType) %} {% set dataType_val = dataType %} {% end %}
28+
SELECT
29+
ds."startDate",
30+
ds."endDate",
31+
{% if dataType_val == 'average' %}
32+
ifNull(round(avg(prf.numberOfPatchsets), 2), 0) AS "patchsetsPerReview"
33+
{% else %} ifNull(round(median(prf.numberOfPatchsets), 2), 0) AS "patchsetsPerReview"
34+
{% end %}
35+
FROM generate_timeseries ds
36+
LEFT JOIN
37+
pull_requests_filtered prf
38+
ON CASE
39+
WHEN {{ granularity }} = 'daily'
40+
THEN toDate(prf.openedAt)
41+
WHEN {{ granularity }} = 'weekly'
42+
THEN toStartOfWeek(prf.openedAt)
43+
WHEN {{ granularity }} = 'monthly'
44+
THEN toStartOfMonth(prf.openedAt)
45+
WHEN {{ granularity }} = 'quarterly'
46+
THEN toStartOfQuarter(prf.openedAt)
47+
WHEN {{ granularity }} = 'yearly'
48+
THEN toStartOfYear(prf.openedAt)
49+
END
50+
= ds."startDate"
51+
AND prf.platform = 'gerrit'
52+
AND isNotNull(prf.numberOfPatchsets)
53+
{% if defined(startDate) %}
54+
AND prf.openedAt
55+
>= {{
56+
DateTime(
57+
startDate,
58+
description="Filter changesets opened after this timestamp",
59+
required=False,
60+
)
61+
}}
62+
{% end %}
63+
{% if defined(endDate) %}
64+
AND prf.openedAt
65+
<= {{
66+
DateTime(
67+
endDate,
68+
description="Filter changesets opened before this timestamp",
69+
required=False,
70+
)
71+
}}
72+
{% end %}
73+
GROUP BY ds."startDate", ds."endDate"
74+
ORDER BY ds."startDate"
75+
{% else %} SELECT 1
76+
{% end %}
77+
78+
NODE patchsets_per_review_merged
79+
SQL >
80+
%
81+
{% if not defined(granularity) %}
82+
{% set dataType_val = 'median' %}
83+
{% if defined(dataType) %} {% set dataType_val = dataType %} {% end %}
84+
SELECT
85+
{% if dataType_val == 'average' %}
86+
round(avg(prf.numberOfPatchsets), 2) AS "patchsetsPerReview"
87+
{% else %} round(median(prf.numberOfPatchsets), 2) AS "patchsetsPerReview"
88+
{% end %}
89+
FROM pull_requests_filtered prf
90+
WHERE
91+
prf.platform = 'gerrit' AND isNotNull(prf.numberOfPatchsets)
92+
{% if defined(startDate) %}
93+
AND prf.openedAt
94+
>= {{
95+
DateTime(
96+
startDate,
97+
description="Filter changesets opened after this timestamp",
98+
required=False,
99+
)
100+
}}
101+
{% end %}
102+
{% if defined(endDate) %}
103+
AND prf.openedAt
104+
<= {{
105+
DateTime(
106+
endDate,
107+
description="Filter changesets opened before this timestamp",
108+
required=False,
109+
)
110+
}}
111+
{% end %}
112+
{% else %} SELECT * FROM timeseries_generation_for_patchsets_per_review
113+
{% end %}

services/libs/tinybird/pipes/review_efficiency.pipe

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ DESCRIPTION >
1717
- Without granularity: `openedCount` and `mergedCount` (single values)
1818
- With granularity: `startDate`, `endDate`, `openedCount`, and `mergedCount` for each time period
1919

20-
TAGS "" Development metrics", Widget", "Pull requests", "Review efficiency"
20+
TAGS "Widget", "Pull requests", "Development metrics", "Review efficiency"
2121

2222
NODE review_efficiency_timeseries
2323
SQL >

0 commit comments

Comments
 (0)