fastlane-plugin-sentry_api 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e998c3813e2bc19b0bfa6e76e1a102cfb546dbf4bce827f7bc4a6605417af6b8
|
|
4
|
+
data.tar.gz: 3f614ff5d0b6f8e3bcb0091d6fa4e13444114aea9517521f2ebc03eee95f49c8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0b33aa8f31b3fcb6678f232129a57b3cc610c0eefd72bb6fb1bcd0d82454483540ce86834b2d48f366d9262043637ac82be68851d105faa1befe5ff172c1b579
|
|
7
|
+
data.tar.gz: d4cfdf3c7bf563ee2c407da39b6a4ef7dd8d3e5fc7d022d2b08def70f736f1b34ac56f4209bf34cdc9ee861ff5f5ad8e30b4a9ea33e11012e3746767d60292dd
|
data/README.md
CHANGED
|
@@ -89,7 +89,7 @@ Query crash-free session and user rates from the Sentry Sessions API. Supports a
|
|
|
89
89
|
| `per_page` | `Integer` | No | `10` | Number of groups to return (max 100) |
|
|
90
90
|
| `order_by` | `String` | No | `-sum(session)` | Sort order for grouped results |
|
|
91
91
|
|
|
92
|
-
**Output (SharedValues):** `SENTRY_CRASH_FREE_SESSION_RATE`, `SENTRY_CRASH_FREE_USER_RATE`, `SENTRY_TOTAL_SESSIONS`, `SENTRY_TOTAL_USERS`, `SENTRY_SESSION_GROUPS`
|
|
92
|
+
**Output (SharedValues):** `SENTRY_CRASH_FREE_SESSION_RATE`, `SENTRY_CRASH_FREE_USER_RATE`, `SENTRY_TOTAL_SESSIONS`, `SENTRY_TOTAL_USERS`, `SENTRY_SESSION_GROUPS`, `SENTRY_CRASH_FREE_SESSIONS_STATUS_CODE`, `SENTRY_CRASH_FREE_SESSIONS_JSON`
|
|
93
93
|
|
|
94
94
|
**Examples:**
|
|
95
95
|
|
|
@@ -130,7 +130,7 @@ Convenience action for fetching user-centric crash-free metrics. For full sessio
|
|
|
130
130
|
| `start_date` | `String` | No | — | ISO 8601 start date |
|
|
131
131
|
| `end_date` | `String` | No | — | ISO 8601 end date |
|
|
132
132
|
|
|
133
|
-
**Output (SharedValues):** `SENTRY_CRASH_FREE_USER_RATE_ONLY`, `SENTRY_TOTAL_USERS_ONLY`
|
|
133
|
+
**Output (SharedValues):** `SENTRY_CRASH_FREE_USER_RATE_ONLY`, `SENTRY_TOTAL_USERS_ONLY`, `SENTRY_CRASH_FREE_USERS_STATUS_CODE`, `SENTRY_CRASH_FREE_USERS_JSON`
|
|
134
134
|
|
|
135
135
|
**Example:**
|
|
136
136
|
|
|
@@ -163,7 +163,7 @@ Query TTID (Time to Initial Display) percentiles per screen from the Sentry Even
|
|
|
163
163
|
| `sort` | `String` | No | `-count()` | Sort order |
|
|
164
164
|
| `include_overall` | `Boolean` | No | `false` | Also fetch overall/aggregate TTID percentiles across all screens |
|
|
165
165
|
|
|
166
|
-
**Output (SharedValues):** `SENTRY_TTID_DATA` (array of `{ transaction:, p50:, p75:, p95:, count: }`), `SENTRY_TTID_OVERALL` (hash with `{ p50:, p75:, p95:, count: }` when `include_overall` is true)
|
|
166
|
+
**Output (SharedValues):** `SENTRY_TTID_DATA` (array of `{ transaction:, p50:, p75:, p95:, count: }`), `SENTRY_TTID_OVERALL` (hash with `{ p50:, p75:, p95:, count: }` when `include_overall` is true), `SENTRY_TTID_STATUS_CODE`, `SENTRY_TTID_JSON`
|
|
167
167
|
|
|
168
168
|
**Examples:**
|
|
169
169
|
|
|
@@ -171,7 +171,7 @@ Query TTID (Time to Initial Display) percentiles per screen from the Sentry Even
|
|
|
171
171
|
# Top 10 screens by load count
|
|
172
172
|
screens = sentry_ttid_percentiles(stats_period: "7d", per_page: 10)
|
|
173
173
|
screens.each do |s|
|
|
174
|
-
UI.message("#{s[:transaction]}: p50=#{s[:p50]}ms p95=#{s[:p95]}ms (#{s[:count]} loads)")
|
|
174
|
+
UI.message("#{s[:transaction]}: p50=#{s[:p50]}ms p75=#{s[:p75]}ms p95=#{s[:p95]}ms (#{s[:count]} loads)")
|
|
175
175
|
end
|
|
176
176
|
|
|
177
177
|
# With overall aggregate TTID
|
|
@@ -208,7 +208,7 @@ Query app launch latency (cold start & warm start) percentiles from the Sentry E
|
|
|
208
208
|
| `end_date` | `String` | No | — | ISO 8601 end date |
|
|
209
209
|
| `release` | `String` | No | — | Filter by release version |
|
|
210
210
|
|
|
211
|
-
**Output (SharedValues):** `SENTRY_APP_LAUNCH_DATA` (hash with `:cold_start` and `:warm_start`, each containing `{ p50:, p75:, p95:, count: }`)
|
|
211
|
+
**Output (SharedValues):** `SENTRY_APP_LAUNCH_DATA` (hash with `:cold_start` and `:warm_start`, each containing `{ p50:, p75:, p95:, count: }`), `SENTRY_APP_LAUNCH_STATUS_CODE`, `SENTRY_APP_LAUNCH_JSON`
|
|
212
212
|
|
|
213
213
|
**Examples:**
|
|
214
214
|
|
|
@@ -249,7 +249,7 @@ Fetch issues from a Sentry project. Supports filtering by release version, query
|
|
|
249
249
|
| `per_page` | `Integer` | No | `25` | Number of issues to return (max 100) |
|
|
250
250
|
| `cursor` | `String` | No | — | Pagination cursor |
|
|
251
251
|
|
|
252
|
-
**Output (SharedValues):** `SENTRY_ISSUES` (array of issue hashes), `SENTRY_ISSUE_COUNT`
|
|
252
|
+
**Output (SharedValues):** `SENTRY_ISSUES` (array of issue hashes with `:id`, `:short_id`, `:title`, `:culprit`, `:level`, `:status`, `:event_count`, `:user_count`, `:first_seen`, `:last_seen`, `:permalink`, `:metadata`), `SENTRY_ISSUE_COUNT`, `SENTRY_ISSUES_STATUS_CODE`, `SENTRY_ISSUES_JSON`
|
|
253
253
|
|
|
254
254
|
**Examples:**
|
|
255
255
|
|
|
@@ -303,13 +303,14 @@ Includes target checking with ✅/⚠️ indicators and optional JSON file outpu
|
|
|
303
303
|
| `ttid_screen_count` | `Integer` | No | `10` | Number of top screens in TTID report |
|
|
304
304
|
| `issue_count` | `Integer` | No | `10` | Number of top issues per release |
|
|
305
305
|
| `crash_issue_count` | `Integer` | No | `5` | Number of top crash (unhandled error) issues to include |
|
|
306
|
+
| `crash_query` | `String` | No | `is:unresolved issue.category:error error.unhandled:true` | Custom Sentry search query for top crash issues |
|
|
306
307
|
| `output_json` | `String` | No | — | Path to write JSON report file |
|
|
307
308
|
|
|
308
309
|
**Output (SharedValues):** `SENTRY_SLO_REPORT` (complete hash with `:availability`, `:latency`, `:issues`)
|
|
309
310
|
|
|
310
311
|
The `:latency` section includes:
|
|
311
312
|
- `:current` — array of per-screen TTID data
|
|
312
|
-
- `:overall` — aggregate TTID `{ p50:, p75:, p95:, count: }` across all screens
|
|
313
|
+
- `:overall` — aggregate TTID `{ avg:, p50:, p75:, p95:, count: }` across all screens
|
|
313
314
|
- `:app_launch` — `{ cold: { p50:, p75:, p95:, count: }, warm: { ... } }`
|
|
314
315
|
- `:previous`, `:overall_previous`, `:app_launch_previous` — week-over-week counterparts (when `compare_weeks` is true)
|
|
315
316
|
|
|
@@ -338,7 +339,7 @@ report = lane_context[SharedValues::SENTRY_SLO_REPORT]
|
|
|
338
339
|
|
|
339
340
|
# Overall TTID
|
|
340
341
|
overall = report[:latency][:overall]
|
|
341
|
-
UI.message("Overall TTID p95: #{overall[:p95]}ms")
|
|
342
|
+
UI.message("Overall TTID avg: #{overall[:avg]}ms p95: #{overall[:p95]}ms")
|
|
342
343
|
|
|
343
344
|
# App launch
|
|
344
345
|
cold = report[:latency][:app_launch][:cold]
|
|
@@ -375,11 +376,11 @@ end
|
|
|
375
376
|
lane :ttid_check do
|
|
376
377
|
screens = sentry_ttid_percentiles(stats_period: "7d", per_page: 10, include_overall: true)
|
|
377
378
|
screens.each do |s|
|
|
378
|
-
UI.message("#{s[:transaction]}: p50=#{s[:p50]}ms p95=#{s[:p95]}ms (#{s[:count]} loads)")
|
|
379
|
+
UI.message("#{s[:transaction]}: p50=#{s[:p50]}ms p75=#{s[:p75]}ms p95=#{s[:p95]}ms (#{s[:count]} loads)")
|
|
379
380
|
end
|
|
380
381
|
|
|
381
382
|
overall = lane_context[SharedValues::SENTRY_TTID_OVERALL]
|
|
382
|
-
UI.important("Overall TTID: p50=#{overall[:p50]}ms p95=#{overall[:p95]}ms") if overall
|
|
383
|
+
UI.important("Overall TTID: p50=#{overall[:p50]}ms p75=#{overall[:p75]}ms p95=#{overall[:p95]}ms") if overall
|
|
383
384
|
end
|
|
384
385
|
|
|
385
386
|
lane :app_launch_check do
|
|
@@ -133,7 +133,8 @@ module Fastlane
|
|
|
133
133
|
|
|
134
134
|
report[:issues][:top_crashes] = fetch_top_crash_issues(
|
|
135
135
|
auth_token: auth_token, org_slug: org_slug, project_slug: project_slug,
|
|
136
|
-
stats_period: stats_period, per_page: params[:crash_issue_count]
|
|
136
|
+
stats_period: stats_period, per_page: params[:crash_issue_count],
|
|
137
|
+
query: params[:crash_query]
|
|
137
138
|
)
|
|
138
139
|
log_top_crashes(report[:issues][:top_crashes])
|
|
139
140
|
|
|
@@ -286,6 +287,11 @@ module Fastlane
|
|
|
286
287
|
optional: true,
|
|
287
288
|
default_value: 5,
|
|
288
289
|
type: Integer),
|
|
290
|
+
FastlaneCore::ConfigItem.new(key: :crash_query,
|
|
291
|
+
description: "Custom Sentry search query for top crash issues",
|
|
292
|
+
optional: true,
|
|
293
|
+
default_value: "is:unresolved issue.category:error error.unhandled:true",
|
|
294
|
+
type: String),
|
|
289
295
|
# ── Output ──
|
|
290
296
|
FastlaneCore::ConfigItem.new(key: :output_json,
|
|
291
297
|
description: "Path to write JSON report file (optional)",
|
|
@@ -410,6 +416,7 @@ module Fastlane
|
|
|
410
416
|
def fetch_ttid(auth_token:, org_slug:, project_id:, environment:, stats_period: nil, start_date: nil, end_date: nil, per_page: 10)
|
|
411
417
|
fields = [
|
|
412
418
|
'transaction',
|
|
419
|
+
'avg(measurements.time_to_initial_display)',
|
|
413
420
|
'p50(measurements.time_to_initial_display)',
|
|
414
421
|
'p75(measurements.time_to_initial_display)',
|
|
415
422
|
'p95(measurements.time_to_initial_display)',
|
|
@@ -445,6 +452,7 @@ module Fastlane
|
|
|
445
452
|
data.map do |row|
|
|
446
453
|
{
|
|
447
454
|
transaction: row['transaction'],
|
|
455
|
+
avg: round_ms(row['avg(measurements.time_to_initial_display)']),
|
|
448
456
|
p50: round_ms(row['p50(measurements.time_to_initial_display)']),
|
|
449
457
|
p75: round_ms(row['p75(measurements.time_to_initial_display)']),
|
|
450
458
|
p95: round_ms(row['p95(measurements.time_to_initial_display)']),
|
|
@@ -455,6 +463,7 @@ module Fastlane
|
|
|
455
463
|
|
|
456
464
|
def fetch_ttid_overall(auth_token:, org_slug:, project_id:, environment:, stats_period: nil, start_date: nil, end_date: nil)
|
|
457
465
|
fields = [
|
|
466
|
+
'avg(measurements.time_to_initial_display)',
|
|
458
467
|
'p50(measurements.time_to_initial_display)',
|
|
459
468
|
'p75(measurements.time_to_initial_display)',
|
|
460
469
|
'p95(measurements.time_to_initial_display)',
|
|
@@ -487,6 +496,7 @@ module Fastlane
|
|
|
487
496
|
|
|
488
497
|
row = response[:json]&.dig('data', 0) || {}
|
|
489
498
|
{
|
|
499
|
+
avg: round_ms(row['avg(measurements.time_to_initial_display)']),
|
|
490
500
|
p50: round_ms(row['p50(measurements.time_to_initial_display)']),
|
|
491
501
|
p75: round_ms(row['p75(measurements.time_to_initial_display)']),
|
|
492
502
|
p95: round_ms(row['p95(measurements.time_to_initial_display)']),
|
|
@@ -551,13 +561,13 @@ module Fastlane
|
|
|
551
561
|
'14d'
|
|
552
562
|
end
|
|
553
563
|
|
|
554
|
-
def fetch_top_crash_issues(auth_token:, org_slug:, project_slug:, stats_period:, per_page:)
|
|
564
|
+
def fetch_top_crash_issues(auth_token:, org_slug:, project_slug:, stats_period:, per_page:, query:)
|
|
555
565
|
response = Helper::SentryApiHelper.get_issues(
|
|
556
566
|
auth_token: auth_token,
|
|
557
567
|
org_slug: org_slug,
|
|
558
568
|
project_slug: project_slug,
|
|
559
569
|
params: {
|
|
560
|
-
query:
|
|
570
|
+
query: query,
|
|
561
571
|
sort: 'freq',
|
|
562
572
|
statsPeriod: issues_api_stats_period(stats_period),
|
|
563
573
|
per_page: per_page.to_s
|
|
@@ -666,7 +676,7 @@ module Fastlane
|
|
|
666
676
|
end
|
|
667
677
|
|
|
668
678
|
def empty_ttid_overall
|
|
669
|
-
{ p50: nil, p75: nil, p95: nil, count: nil }
|
|
679
|
+
{ avg: nil, p50: nil, p75: nil, p95: nil, count: nil }
|
|
670
680
|
end
|
|
671
681
|
|
|
672
682
|
def round_ms(value)
|
|
@@ -815,19 +825,8 @@ module Fastlane
|
|
|
815
825
|
cold = app_launch[:cold]
|
|
816
826
|
warm = app_launch[:warm]
|
|
817
827
|
launch_target = params[:app_launch_p95_target_ms]
|
|
818
|
-
|
|
819
|
-
if
|
|
820
|
-
indicator = if launch_target
|
|
821
|
-
cold[:p95] <= launch_target ? "✅" : "⚠️"
|
|
822
|
-
else
|
|
823
|
-
""
|
|
824
|
-
end
|
|
825
|
-
UI.message("Cold start p95: #{cold[:p95]}ms #{indicator} (target: #{launch_target}ms)")
|
|
826
|
-
end
|
|
827
|
-
|
|
828
|
-
if warm && warm[:p95]
|
|
829
|
-
UI.message("Warm start p95: #{warm[:p95]}ms")
|
|
830
|
-
end
|
|
828
|
+
log_cold_start(cold, launch_target)
|
|
829
|
+
UI.message("Warm start p95: #{warm[:p95]}ms") if warm && warm[:p95]
|
|
831
830
|
end
|
|
832
831
|
|
|
833
832
|
# Top Crash Issues
|
|
@@ -852,6 +851,19 @@ module Fastlane
|
|
|
852
851
|
UI.success("SLO report generated at #{report[:generated_at]}")
|
|
853
852
|
end
|
|
854
853
|
|
|
854
|
+
def log_cold_start(cold, launch_target)
|
|
855
|
+
return unless cold && cold[:p95]
|
|
856
|
+
|
|
857
|
+
indicator = target_indicator(cold[:p95], launch_target)
|
|
858
|
+
UI.message("Cold start p95: #{cold[:p95]}ms #{indicator} (target: #{launch_target}ms)")
|
|
859
|
+
end
|
|
860
|
+
|
|
861
|
+
def target_indicator(value, target)
|
|
862
|
+
return "" unless target
|
|
863
|
+
|
|
864
|
+
value <= target ? "✅" : "⚠️"
|
|
865
|
+
end
|
|
866
|
+
|
|
855
867
|
def format_pct(value)
|
|
856
868
|
return "N/A" if value.nil?
|
|
857
869
|
|