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: cee8dc5203226fee972dc466c125f43e872f655f4776dc703feb349a638a8ea1
4
- data.tar.gz: 8d4f199b0714184b9475043557c0150da47fa83881b09de8e1ebe4b4866187e8
3
+ metadata.gz: e998c3813e2bc19b0bfa6e76e1a102cfb546dbf4bce827f7bc4a6605417af6b8
4
+ data.tar.gz: 3f614ff5d0b6f8e3bcb0091d6fa4e13444114aea9517521f2ebc03eee95f49c8
5
5
  SHA512:
6
- metadata.gz: dbbb4b57bf4a3fa1530489172d9c40024e04f2b2c54ceb59ae2c79bc1f63488749528d708c7e31353212fbabf5e16c5a6ed26b893c5a2a96b9c7affed0d920e1
7
- data.tar.gz: 1ef24556a924fd1a372e56e8693d8eac3c25295d4a30608cd3c72a5f064c6cc34d0ff8b96739da6cc88495858560cdc570d5fe97148ca9eb8982dde9178f2c62
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: 'is:unresolved issue.category:error error.unhandled:true',
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 cold && cold[:p95]
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
 
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module SentryApi
3
- VERSION = "0.2.0"
3
+ VERSION = "0.4.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-sentry_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - crazymanish