railwatch 0.1.4 → 0.2.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 +4 -4
- data/CHANGELOG.md +212 -0
- data/README.md +10 -0
- data/app/channels/railwatch/environment_channel.rb +28 -0
- data/app/controllers/concerns/railwatch/telemetry_identity.rb +25 -0
- data/app/controllers/railwatch/alerts_controller.rb +48 -0
- data/app/controllers/railwatch/anomaly_rules_controller.rb +31 -0
- data/app/controllers/railwatch/attachments_controller.rb +22 -0
- data/app/controllers/railwatch/beacon_controller.rb +67 -7
- data/app/controllers/railwatch/broadcasts_controller.rb +15 -0
- data/app/controllers/railwatch/cache_events_controller.rb +30 -0
- data/app/controllers/railwatch/commands_controller.rb +16 -0
- data/app/controllers/railwatch/comments_controller.rb +11 -0
- data/app/controllers/railwatch/dashboard_controller.rb +69 -0
- data/app/controllers/railwatch/deploys_controller.rb +34 -0
- data/app/controllers/railwatch/deprecations_controller.rb +54 -0
- data/app/controllers/railwatch/environment_scoped.rb +99 -0
- data/app/controllers/railwatch/exceptions_controller.rb +53 -0
- data/app/controllers/railwatch/executions_controller.rb +13 -0
- data/app/controllers/railwatch/issues_controller.rb +258 -0
- data/app/controllers/railwatch/jobs_controller.rb +63 -0
- data/app/controllers/railwatch/llm_calls_controller.rb +124 -0
- data/app/controllers/railwatch/logs_controller.rb +40 -0
- data/app/controllers/railwatch/mails_controller.rb +19 -0
- data/app/controllers/railwatch/notifications_controller.rb +11 -0
- data/app/controllers/railwatch/outgoing_requests_controller.rb +19 -0
- data/app/controllers/railwatch/overview_controller.rb +38 -0
- data/app/controllers/railwatch/people_controller.rb +25 -0
- data/app/controllers/railwatch/processes_controller.rb +33 -0
- data/app/controllers/railwatch/profiles_controller.rb +50 -0
- data/app/controllers/railwatch/queries_controller.rb +59 -0
- data/app/controllers/railwatch/releases_controller.rb +75 -0
- data/app/controllers/railwatch/requests_controller.rb +55 -0
- data/app/controllers/railwatch/saved_views_controller.rb +53 -0
- data/app/controllers/railwatch/scheduled_tasks_controller.rb +45 -0
- data/app/controllers/railwatch/spans_controller.rb +47 -0
- data/app/controllers/railwatch/storage_ops_controller.rb +15 -0
- data/app/controllers/railwatch/tenants_controller.rb +44 -0
- data/app/controllers/railwatch/thresholds_controller.rb +40 -0
- data/app/controllers/railwatch/traces_controller.rb +72 -0
- data/app/controllers/railwatch/transactions_controller.rb +21 -0
- data/app/controllers/railwatch/view_renders_controller.rb +28 -0
- data/app/controllers/railwatch/visits_controller.rb +53 -0
- data/app/helpers/railwatch/assets_helper.rb +52 -0
- data/app/jobs/railwatch/anomaly_scan_job.rb +11 -0
- data/app/jobs/railwatch/application_job.rb +7 -0
- data/app/jobs/railwatch/auto_resolve_issues_job.rb +19 -0
- data/app/jobs/railwatch/check_scheduled_tasks_job.rb +113 -0
- data/app/jobs/railwatch/detect_anomalies_job.rb +171 -0
- data/app/jobs/railwatch/detect_performance_issues_job.rb +85 -0
- data/app/jobs/railwatch/group_exceptions_job.rb +91 -0
- data/app/jobs/railwatch/optimize_telemetry_job.rb +23 -0
- data/app/jobs/railwatch/performance_scan_job.rb +11 -0
- data/app/jobs/railwatch/prune_telemetry_job.rb +110 -0
- data/app/jobs/railwatch/release_health_rollup_job.rb +64 -0
- data/app/jobs/railwatch/rollup_catchup_job.rb +21 -0
- data/app/jobs/railwatch/rollup_job.rb +130 -0
- data/app/jobs/railwatch/scheduled_task_scan_job.rb +11 -0
- data/app/models/concerns/railwatch/detection_snapshotting.rb +20 -0
- data/app/models/railwatch/alert.rb +229 -0
- data/app/models/railwatch/alert_rule.rb +121 -0
- data/app/models/railwatch/anomaly_rule.rb +33 -0
- data/app/models/railwatch/application.rb +44 -0
- data/app/models/railwatch/application_record.rb +33 -0
- data/app/models/railwatch/comment.rb +36 -0
- data/app/models/railwatch/deploy.rb +67 -0
- data/app/models/railwatch/environment.rb +54 -0
- data/app/models/railwatch/execution_presenter.rb +185 -0
- data/app/models/railwatch/filter_query.rb +143 -0
- data/app/models/railwatch/followup_receipt.rb +27 -0
- data/app/models/railwatch/ingest/batch.rb +305 -0
- data/app/models/railwatch/ingest/mapper.rb +575 -0
- data/app/models/railwatch/ingest/payload.rb +96 -0
- data/app/models/railwatch/ingest/rollup_absorber.rb +170 -0
- data/app/models/railwatch/ingest/writer.rb +137 -0
- data/app/models/railwatch/issue.rb +277 -0
- data/app/models/railwatch/issue_activity.rb +23 -0
- data/app/models/railwatch/issue_detection_presenter.rb +309 -0
- data/app/models/railwatch/issue_detection_snapshot.rb +77 -0
- data/app/models/railwatch/maintenance_task.rb +53 -0
- data/app/models/railwatch/saved_view.rb +63 -0
- data/app/models/railwatch/telemetry/aggregations.rb +116 -0
- data/app/models/railwatch/telemetry/attachment.rb +31 -0
- data/app/models/railwatch/telemetry/bounded_gzip.rb +101 -0
- data/app/models/railwatch/telemetry/broadcast.rb +13 -0
- data/app/models/railwatch/telemetry/cache_event.rb +16 -0
- data/app/models/railwatch/telemetry/child.rb +53 -0
- data/app/models/railwatch/telemetry/cursor_page.rb +99 -0
- data/app/models/railwatch/telemetry/deprecation.rb +13 -0
- data/app/models/railwatch/telemetry/enqueued_job.rb +13 -0
- data/app/models/railwatch/telemetry/exception.rb +21 -0
- data/app/models/railwatch/telemetry/execution.rb +71 -0
- data/app/models/railwatch/telemetry/health_sample.rb +72 -0
- data/app/models/railwatch/telemetry/ingest_batch.rb +31 -0
- data/app/models/railwatch/telemetry/llm_call.rb +37 -0
- data/app/models/railwatch/telemetry/log.rb +85 -0
- data/app/models/railwatch/telemetry/mail.rb +13 -0
- data/app/models/railwatch/telemetry/n_plus_one.rb +92 -0
- data/app/models/railwatch/telemetry/notification.rb +13 -0
- data/app/models/railwatch/telemetry/outgoing_request.rb +13 -0
- data/app/models/railwatch/telemetry/person.rb +50 -0
- data/app/models/railwatch/telemetry/process.rb +10 -0
- data/app/models/railwatch/telemetry/profile.rb +37 -0
- data/app/models/railwatch/telemetry/query.rb +50 -0
- data/app/models/railwatch/telemetry/query_shape.rb +45 -0
- data/app/models/railwatch/telemetry/release_health.rb +63 -0
- data/app/models/railwatch/telemetry/rollup.rb +78 -0
- data/app/models/railwatch/telemetry/session.rb +24 -0
- data/app/models/railwatch/telemetry/span.rb +19 -0
- data/app/models/railwatch/telemetry/storage_op.rb +13 -0
- data/app/models/railwatch/telemetry/tenant.rb +221 -0
- data/app/models/railwatch/telemetry/transaction.rb +13 -0
- data/app/models/railwatch/telemetry/view_render.rb +13 -0
- data/app/models/railwatch/telemetry/visit.rb +24 -0
- data/app/models/railwatch/telemetry_record.rb +57 -0
- data/app/models/railwatch/threshold.rb +29 -0
- data/app/models/railwatch/user.rb +47 -0
- data/app/models/railwatch/viewer.rb +13 -0
- data/app/views/layouts/railwatch/dashboard.html.erb +25 -0
- data/config/routes.rb +59 -0
- data/db/railwatch_migrate/20260916000000_create_railwatch_tables.rb +151 -0
- data/db/railwatch_migrate/20260917000000_create_railwatch_maintenance_tasks.rb +18 -0
- data/db/railwatch_migrate/20260917120000_create_railwatch_followup_receipts.rb +20 -0
- data/db/railwatch_migrate/20260918120000_widen_host_user_ids.rb +71 -0
- data/db/railwatch_telemetry_migrate/20260903000001_create_telemetry.rb +481 -0
- data/db/railwatch_telemetry_migrate/20260903000002_rename_tenant_to_app_tenant.rb +14 -0
- data/db/railwatch_telemetry_migrate/20260903000003_add_statement_count_to_transactions.rb +9 -0
- data/db/railwatch_telemetry_migrate/20260903000004_add_role_and_channel.rb +10 -0
- data/db/railwatch_telemetry_migrate/20260903000005_add_locals_to_exceptions.rb +9 -0
- data/db/railwatch_telemetry_migrate/20260903000006_add_spans_health_vitals_and_fts.rb +82 -0
- data/db/railwatch_telemetry_migrate/20260903000007_rename_span_attributes_to_payload.rb +10 -0
- data/db/railwatch_telemetry_migrate/20260903000008_add_profiles_and_attachments.rb +60 -0
- data/db/railwatch_telemetry_migrate/20260903000009_add_truncated_to_attachments.rb +9 -0
- data/db/railwatch_telemetry_migrate/20260903000010_create_sessions_and_release_health.rb +51 -0
- data/db/railwatch_telemetry_migrate/20260903000011_add_fingerprint_to_exceptions.rb +11 -0
- data/db/railwatch_telemetry_migrate/20260904000012_add_failed_to_broadcasts.rb +10 -0
- data/db/railwatch_telemetry_migrate/20260904010000_add_filter_cursor_indexes.rb +37 -0
- data/db/railwatch_telemetry_migrate/20260904020000_add_n_plus_ones_execution_id_index.rb +11 -0
- data/db/railwatch_telemetry_migrate/20260904120000_create_query_shapes.rb +15 -0
- data/db/railwatch_telemetry_migrate/20260906120000_add_backpressure_factor_to_ingest_batches.rb +9 -0
- data/db/railwatch_telemetry_migrate/20260907000000_rename_lantern_version_on_processes.rb +10 -0
- data/db/railwatch_telemetry_migrate/20260913000000_rename_nightrail_version_on_processes.rb +9 -0
- data/db/railwatch_telemetry_migrate/20260914000000_drop_orphan_durable_ingest_tables.rb +18 -0
- data/db/railwatch_telemetry_migrate/20260914010000_drop_orphan_durable_ingest_columns.rb +25 -0
- data/db/railwatch_telemetry_migrate/20260915000000_create_llm_calls.rb +55 -0
- data/db/railwatch_telemetry_migrate/20260915120000_add_detail_to_llm_calls.rb +21 -0
- data/db/railwatch_telemetry_migrate/20260915200000_add_explained_index_to_queries.rb +16 -0
- data/db/railwatch_telemetry_migrate/20260915210000_add_slowest_index_to_queries.rb +18 -0
- data/db/railwatch_telemetry_migrate/20260917010000_add_batch_ledger_to_ingest_batches.rb +16 -0
- data/docs/configuration.md +26 -0
- data/docs/embedded.md +352 -0
- data/docs/getting-started.md +5 -0
- data/lib/generators/railwatch/install/install_generator.rb +222 -1
- data/lib/generators/railwatch/install/templates/{initializer.rb → initializer.rb.tt} +39 -0
- data/lib/generators/railwatch/install/templates/post-deploy +8 -0
- data/lib/puma/plugin/railwatch.rb +170 -0
- data/lib/railwatch/authentication.rb +83 -0
- data/lib/railwatch/configuration.rb +134 -3
- data/lib/railwatch/dashboard_assets.rb +45 -0
- data/lib/railwatch/embedded.rb +54 -0
- data/lib/railwatch/engine.rb +89 -1
- data/lib/railwatch/ingest_request_body_limit.rb +10 -0
- data/lib/railwatch/json_compat.rb +60 -0
- data/lib/railwatch/maintenance.rb +183 -0
- data/lib/railwatch/patches/runner_command.rb +21 -1
- data/lib/railwatch/record.rb +33 -8
- data/lib/railwatch/reporter.rb +16 -0
- data/lib/railwatch/subscribers/process_info.rb +2 -1
- data/lib/railwatch/transport/local.rb +78 -0
- data/lib/railwatch/transport/socket.rb +183 -0
- data/lib/railwatch/version.rb +1 -1
- data/lib/railwatch/writer.rb +370 -0
- data/lib/railwatch.rb +38 -1
- data/lib/tasks/railwatch_tasks.rake +128 -0
- data/public/railwatch/assets/CommitMono-Bold-D6h61ieg.woff2 +0 -0
- data/public/railwatch/assets/CommitMono-Regular-zr8w7Obm.woff2 +0 -0
- data/public/railwatch/assets/Roboto-Black-auA4GeOK.woff2 +0 -0
- data/public/railwatch/assets/Roboto-Bold-CJLnO8j1.woff2 +0 -0
- data/public/railwatch/assets/Roboto-Medium-Cm2bwKpj.woff2 +0 -0
- data/public/railwatch/assets/Roboto-Regular-Chaq1-PV.woff2 +0 -0
- data/public/railwatch/assets/app-layout-yh-sPWgK.js +1 -0
- data/public/railwatch/assets/app-wordmark-nbjkzxwQ.js +1 -0
- data/public/railwatch/assets/appearance-CDuRvQTB.js +1 -0
- data/public/railwatch/assets/application-C_kpBdnf.css +1 -0
- data/public/railwatch/assets/arrow-up-DVtOGdVA.js +1 -0
- data/public/railwatch/assets/auth-layout-TCwPpS1K.js +1 -0
- data/public/railwatch/assets/badge-Daw4Hvr8.js +1 -0
- data/public/railwatch/assets/braces-DhFbHPsz.js +1 -0
- data/public/railwatch/assets/card-BX_3HXcJ.js +1 -0
- data/public/railwatch/assets/chart-B14-N9g7.js +39 -0
- data/public/railwatch/assets/chart-hover-Vy52H4uD.js +1 -0
- data/public/railwatch/assets/chart-panel-Cb4S_ej_.js +1 -0
- data/public/railwatch/assets/checkbox-D3aRSsBj.js +1 -0
- data/public/railwatch/assets/code-KvW8k7Jr.js +1 -0
- data/public/railwatch/assets/copy-DaQMJWoT.js +1 -0
- data/public/railwatch/assets/copy-block-BKFGd11J.js +1 -0
- data/public/railwatch/assets/copy-id-Djks1fXB.js +1 -0
- data/public/railwatch/assets/cursor-load-more-BXV0f1D_.js +1 -0
- data/public/railwatch/assets/data-table-iv1bdF6u.js +1 -0
- data/public/railwatch/assets/edit-BZc_Iawe.js +1 -0
- data/public/railwatch/assets/edit-DMKUF8Zi.js +8 -0
- data/public/railwatch/assets/edit-__9yJlO3.js +1 -0
- data/public/railwatch/assets/empty-state-6j_0AaQQ.js +1 -0
- data/public/railwatch/assets/env-layout-DrT8rO6P.js +1 -0
- data/public/railwatch/assets/execution-path-CzgBUi5e.js +1 -0
- data/public/railwatch/assets/filter-bar-9SU5NrzX.js +1 -0
- data/public/railwatch/assets/flamegraph-qcekju8V.js +2 -0
- data/public/railwatch/assets/format-B9SDkrWj.js +1 -0
- data/public/railwatch/assets/frames-Cyu7KMxZ.js +1 -0
- data/public/railwatch/assets/google-sign-in-button-DsTSfmzY.js +1 -0
- data/public/railwatch/assets/index-1ol1-QWI.js +1 -0
- data/public/railwatch/assets/index-5jI4aFzC.js +1 -0
- data/public/railwatch/assets/index-9KTrVnrc.js +1 -0
- data/public/railwatch/assets/index-B0-8lcTp.js +1 -0
- data/public/railwatch/assets/index-B7jjfNfO.js +1 -0
- data/public/railwatch/assets/index-BBchRy0M.js +1 -0
- data/public/railwatch/assets/index-BRiq3SNR.js +1 -0
- data/public/railwatch/assets/index-BgKj9xhr.js +1 -0
- data/public/railwatch/assets/index-BkTZqqOu.js +1 -0
- data/public/railwatch/assets/index-BprKx8QO.js +1 -0
- data/public/railwatch/assets/index-C3jzvPs3.js +1 -0
- data/public/railwatch/assets/index-Cbs6gGyQ.js +1 -0
- data/public/railwatch/assets/index-CdRZ6AWF.js +1 -0
- data/public/railwatch/assets/index-CeYKnapu.js +1 -0
- data/public/railwatch/assets/index-Cmlwy1-V.js +1 -0
- data/public/railwatch/assets/index-Cwx6058d.js +1 -0
- data/public/railwatch/assets/index-D4CSdbHv.js +1 -0
- data/public/railwatch/assets/index-DEFMSkdG.js +1 -0
- data/public/railwatch/assets/index-DFiHEBSh.js +1 -0
- data/public/railwatch/assets/index-DL4vWdWJ.js +1 -0
- data/public/railwatch/assets/index-DU9F5b5d.js +1 -0
- data/public/railwatch/assets/index-DaXgPcGL.js +1 -0
- data/public/railwatch/assets/index-DbtaU-EE.js +1 -0
- data/public/railwatch/assets/index-DeOe83F4.js +1 -0
- data/public/railwatch/assets/index-DiucHN4B.js +1 -0
- data/public/railwatch/assets/index-DlnR_l9o.js +1 -0
- data/public/railwatch/assets/index-DlumCsWY.js +2 -0
- data/public/railwatch/assets/index-DmRd7aIG.js +1 -0
- data/public/railwatch/assets/index-DxSh2UpM.js +1 -0
- data/public/railwatch/assets/index-MIMGuFNt.js +1 -0
- data/public/railwatch/assets/index-OqI59zPb.js +1 -0
- data/public/railwatch/assets/index-P4rC7IlX.js +1 -0
- data/public/railwatch/assets/index-gpPOcFWq.js +1 -0
- data/public/railwatch/assets/index-oVkururr.js +1 -0
- data/public/railwatch/assets/index-p9puqVge.js +1 -0
- data/public/railwatch/assets/inertia-TViv6kNv.js +97 -0
- data/public/railwatch/assets/input-error-LxImUkxv.js +1 -0
- data/public/railwatch/assets/json-viewer-Ar4cjPDW.js +1 -0
- data/public/railwatch/assets/klass-CJ-J4INB.js +1 -0
- data/public/railwatch/assets/label-COUKWqE_.js +1 -0
- data/public/railwatch/assets/layout-DNSLAkw_.js +1 -0
- data/public/railwatch/assets/live-dot-ChfUtY3p.js +41 -0
- data/public/railwatch/assets/nav-CNnDqPlm.js +1 -0
- data/public/railwatch/assets/new-84S8ZJq9.js +1 -0
- data/public/railwatch/assets/new-Be55nmt9.js +1 -0
- data/public/railwatch/assets/new-Bi_xQiIb.js +1 -0
- data/public/railwatch/assets/new-BvCT8TMg.js +1 -0
- data/public/railwatch/assets/new-D05SajFR.js +1 -0
- data/public/railwatch/assets/new-D4uewYC8.js +1 -0
- data/public/railwatch/assets/onboarding-CYZi5Cqc.js +1 -0
- data/public/railwatch/assets/origin-identity-6q1-CBts.js +1 -0
- data/public/railwatch/assets/percentile-picker-gFZCXtdb.js +1 -0
- data/public/railwatch/assets/relative-time-IOOgl5n2.js +1 -0
- data/public/railwatch/assets/release-health-DC8oc7uw.js +1 -0
- data/public/railwatch/assets/route-Dv6LAWvT.js +1 -0
- data/public/railwatch/assets/segmented-h1VdDTqE.js +1 -0
- data/public/railwatch/assets/select-_AJsUa7X.js +1 -0
- data/public/railwatch/assets/separator-BwwTYtCF.js +1 -0
- data/public/railwatch/assets/series-chart-DaFPefku.js +1 -0
- data/public/railwatch/assets/show-B7NCgkEo.js +1 -0
- data/public/railwatch/assets/show-BKqyKjBK.js +1 -0
- data/public/railwatch/assets/show-BM6X2Mpo.js +1 -0
- data/public/railwatch/assets/show-BNw4tN5q.js +1 -0
- data/public/railwatch/assets/show-BO3bnG5h.js +1 -0
- data/public/railwatch/assets/show-BhrAVAEA.js +1 -0
- data/public/railwatch/assets/show-C4Ltf5i9.js +2 -0
- data/public/railwatch/assets/show-C8sHalnw.js +1 -0
- data/public/railwatch/assets/show-CeTL4B37.js +2 -0
- data/public/railwatch/assets/show-CpfgV1jP.js +1 -0
- data/public/railwatch/assets/show-DACku6AD.js +3 -0
- data/public/railwatch/assets/show-DIOSGcXV.js +6 -0
- data/public/railwatch/assets/show-DQp_1n-B.js +1 -0
- data/public/railwatch/assets/show-DVNz46RI.js +1 -0
- data/public/railwatch/assets/show-DYteoYWW.js +1 -0
- data/public/railwatch/assets/show-DgSIoRvA.js +1 -0
- data/public/railwatch/assets/show-JxFtB4eK.js +2 -0
- data/public/railwatch/assets/sort-header-DpFzXblu.js +1 -0
- data/public/railwatch/assets/source-link-B2183i2-.js +1 -0
- data/public/railwatch/assets/sparkline-cell-C3-5vFkP.js +1 -0
- data/public/railwatch/assets/stat-s4RpOS9w.js +1 -0
- data/public/railwatch/assets/status-badge-8jVV-LA4.js +1 -0
- data/public/railwatch/assets/tenant-path-G-6u9A-o.js +1 -0
- data/public/railwatch/assets/text-link-DfsiaCcP.js +1 -0
- data/public/railwatch/assets/textarea-Dye72uP7.js +1 -0
- data/public/railwatch/assets/timeline-CD7WHnbo.js +1 -0
- data/public/railwatch/assets/transition-B_AW8rMK.js +5 -0
- data/public/railwatch/assets/use-clipboard-ColgLyQ2.js +1 -0
- data/public/railwatch/icon.png +0 -0
- data/public/railwatch/icon.svg +5 -0
- data/public/railwatch/manifest.json +2171 -0
- data/public/railwatch/rails-vite.json +1 -0
- metadata +314 -4
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# The embedded install's maintenance lease table: one row per task in
|
|
4
|
+
# Railwatch::Maintenance::TASKS, recording when it last ran and which process
|
|
5
|
+
# holds it now. Lives in the railwatch database with the other permanent,
|
|
6
|
+
# operator-facing state rather than in the pruned telemetry file.
|
|
7
|
+
class CreateRailwatchMaintenanceTasks < ActiveRecord::Migration[8.1]
|
|
8
|
+
def change
|
|
9
|
+
create_table :railwatch_maintenance_tasks do |t|
|
|
10
|
+
t.string :name, null: false
|
|
11
|
+
t.datetime :last_run_at
|
|
12
|
+
t.string :lease_owner
|
|
13
|
+
t.datetime :lease_expires_at
|
|
14
|
+
t.timestamps
|
|
15
|
+
end
|
|
16
|
+
add_index :railwatch_maintenance_tasks, :name, unique: true
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# What makes replaying a batch's follow-ups safe. Exception grouping bumps an
|
|
4
|
+
# issue's occurrence count in this database, but the "done" mark lives on the
|
|
5
|
+
# batch's ledger row in the OTHER database, so a crash between the two (or
|
|
6
|
+
# the inline drain racing the maintenance drain) would count the same
|
|
7
|
+
# exceptions twice. A receipt per (batch, group) is inserted in the same
|
|
8
|
+
# transaction as the issue update; the unique index turns a second attempt
|
|
9
|
+
# into a no-op.
|
|
10
|
+
class CreateRailwatchFollowupReceipts < ActiveRecord::Migration[8.1]
|
|
11
|
+
def change
|
|
12
|
+
create_table :railwatch_followup_receipts do |t|
|
|
13
|
+
t.string :batch_id, limit: 36, null: false
|
|
14
|
+
t.string :group_hash, limit: 32, null: false
|
|
15
|
+
t.datetime :created_at, null: false
|
|
16
|
+
end
|
|
17
|
+
add_index :railwatch_followup_receipts, [ :batch_id, :group_hash ], unique: true
|
|
18
|
+
add_index :railwatch_followup_receipts, :created_at
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# The ids on comments, issue activity, saved views and issue assignment are
|
|
4
|
+
# whatever the host's `dashboard_user` resolver returned. They were integer
|
|
5
|
+
# columns, which quietly assumed every application numbers its users. An app
|
|
6
|
+
# with UUID primary keys could not store a comment at all, and one with ids
|
|
7
|
+
# past the signed range could not either.
|
|
8
|
+
#
|
|
9
|
+
# Nothing joins on these columns and nothing indexes them; they are an opaque
|
|
10
|
+
# handle the host gave us and hands back. A string says that, and costs
|
|
11
|
+
# nothing in a database that is a few thousand rows of authored content.
|
|
12
|
+
#
|
|
13
|
+
# Existing values convert cleanly: SQLite rewrites 7 as "7", and the models
|
|
14
|
+
# compare with to_s on both sides, so a row written before this migration
|
|
15
|
+
# still matches the same viewer after it.
|
|
16
|
+
class WidenHostUserIds < ActiveRecord::Migration[8.1]
|
|
17
|
+
COLUMNS = {
|
|
18
|
+
railwatch_issues: :assignee_id,
|
|
19
|
+
railwatch_comments: :viewer_id,
|
|
20
|
+
railwatch_issue_activities: :viewer_id,
|
|
21
|
+
railwatch_saved_views: :viewer_id
|
|
22
|
+
}.freeze
|
|
23
|
+
|
|
24
|
+
# SQLite rebuilds a table to change a column type, and a rebuild inside a
|
|
25
|
+
# transaction ignores `PRAGMA foreign_keys = OFF`. This database declares no
|
|
26
|
+
# foreign keys, so there is nothing to cascade, but the rebuild is kept out
|
|
27
|
+
# of the migrator's transaction anyway: it is the cheap half of a habit
|
|
28
|
+
# whose expensive half is deleted rows.
|
|
29
|
+
disable_ddl_transaction!
|
|
30
|
+
|
|
31
|
+
def up
|
|
32
|
+
COLUMNS.each do |table, column|
|
|
33
|
+
null = column == :viewer_id && table == :railwatch_saved_views ? false : true
|
|
34
|
+
change_column table, column, :string, limit: 255, null: null
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Reversible only while every stored id still looks like a number. Once a
|
|
39
|
+
# host with UUIDs (or emails, or anything else) has written one, there is
|
|
40
|
+
# no integer to go back to: the column would either refuse the value or
|
|
41
|
+
# quietly coerce it to something that is no longer that person. Say so and
|
|
42
|
+
# stop, rather than losing the identity on the way down. These tables are
|
|
43
|
+
# authored content, a few thousand rows at most, so reading them is cheap.
|
|
44
|
+
INTEGERISH = /\A-?\d+\z/
|
|
45
|
+
MAX_REPORTED = 3
|
|
46
|
+
|
|
47
|
+
def down
|
|
48
|
+
blocking = COLUMNS.filter_map do |table, column|
|
|
49
|
+
next unless connection.table_exists?(table)
|
|
50
|
+
|
|
51
|
+
values = connection.select_values(
|
|
52
|
+
"SELECT DISTINCT #{connection.quote_column_name(column)} FROM #{connection.quote_table_name(table)} " \
|
|
53
|
+
"WHERE #{connection.quote_column_name(column)} IS NOT NULL"
|
|
54
|
+
)
|
|
55
|
+
offenders = values.reject { |value| INTEGERISH.match?(value.to_s) }
|
|
56
|
+
"#{table}.#{column} (#{offenders.first(MAX_REPORTED).join(', ')}#{"..." if offenders.size > MAX_REPORTED})" if offenders.any?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
if blocking.any?
|
|
60
|
+
raise ActiveRecord::IrreversibleMigration,
|
|
61
|
+
"cannot narrow host user ids back to integers: #{blocking.join('; ')}. " \
|
|
62
|
+
"Those ids came from this application's own dashboard_user resolver and have no integer form; " \
|
|
63
|
+
"rolling back would discard them."
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
COLUMNS.each do |table, column|
|
|
67
|
+
null = column == :viewer_id && table == :railwatch_saved_views ? false : true
|
|
68
|
+
change_column table, column, :integer, null: null
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# One table per record type, matching the gem's wire types one to one.
|
|
4
|
+
# Every table starts with the shared envelope. JSON columns hold the
|
|
5
|
+
# variable parts; hot filter columns are real columns with indexes.
|
|
6
|
+
class CreateTelemetry < ActiveRecord::Migration[8.1]
|
|
7
|
+
def change
|
|
8
|
+
create_table :executions do |t|
|
|
9
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
10
|
+
# the history never calls a model that has since changed.
|
|
11
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
12
|
+
t.string :deploy, limit: 128
|
|
13
|
+
t.string :server, limit: 255
|
|
14
|
+
t.string :group_hash, limit: 32
|
|
15
|
+
t.string :trace_id, limit: 36
|
|
16
|
+
t.string :execution_source, limit: 20
|
|
17
|
+
t.string :execution_id, limit: 36
|
|
18
|
+
t.string :execution_preview, limit: 255
|
|
19
|
+
t.string :execution_stage, limit: 32
|
|
20
|
+
t.string :user_ref, limit: 255
|
|
21
|
+
t.string :tenant, limit: 255
|
|
22
|
+
t.string :kind, null: false, limit: 20 # request, job_attempt, scheduled_task, command
|
|
23
|
+
t.string :name, null: false, limit: 255 # "GET /widgets/:id", "WidgetJob", "rake db:migrate"
|
|
24
|
+
t.integer :duration, null: false # microseconds
|
|
25
|
+
t.integer :status # http status, or exit code
|
|
26
|
+
t.string :outcome, limit: 20 # processed, failed, aborted
|
|
27
|
+
t.string :method, limit: 10
|
|
28
|
+
t.string :route, limit: 255
|
|
29
|
+
t.string :controller, limit: 255
|
|
30
|
+
t.string :action, limit: 128
|
|
31
|
+
t.string :queue, limit: 128
|
|
32
|
+
t.integer :attempt
|
|
33
|
+
t.integer :queue_latency
|
|
34
|
+
t.string :job_id, limit: 36
|
|
35
|
+
t.string :task_key, limit: 128
|
|
36
|
+
t.string :inertia_component, limit: 255
|
|
37
|
+
t.boolean :inertia_partial, default: false
|
|
38
|
+
t.integer :allocations
|
|
39
|
+
t.bigint :peak_memory
|
|
40
|
+
t.string :exception_preview, limit: 255
|
|
41
|
+
t.json :stages, null: false, default: {}
|
|
42
|
+
t.json :counters, null: false, default: {}
|
|
43
|
+
t.json :detail, null: false, default: {} # headers, payload, url, ip, user agent, context, extras
|
|
44
|
+
end
|
|
45
|
+
add_index :executions, [ :kind, :occurred_at ]
|
|
46
|
+
add_index :executions, [ :group_hash, :occurred_at ]
|
|
47
|
+
add_index :executions, :execution_id, unique: true
|
|
48
|
+
add_index :executions, :trace_id
|
|
49
|
+
add_index :executions, [ :user_ref, :occurred_at ]
|
|
50
|
+
add_index :executions, [ :deploy, :occurred_at ]
|
|
51
|
+
add_index :executions, [ :tenant, :occurred_at ]
|
|
52
|
+
|
|
53
|
+
create_table :queries do |t|
|
|
54
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
55
|
+
# the history never calls a model that has since changed.
|
|
56
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
57
|
+
t.string :deploy, limit: 128
|
|
58
|
+
t.string :server, limit: 255
|
|
59
|
+
t.string :group_hash, limit: 32
|
|
60
|
+
t.string :trace_id, limit: 36
|
|
61
|
+
t.string :execution_source, limit: 20
|
|
62
|
+
t.string :execution_id, limit: 36
|
|
63
|
+
t.string :execution_preview, limit: 255
|
|
64
|
+
t.string :execution_stage, limit: 32
|
|
65
|
+
t.string :user_ref, limit: 255
|
|
66
|
+
t.string :tenant, limit: 255
|
|
67
|
+
t.text :sql, null: false
|
|
68
|
+
t.string :name, limit: 255
|
|
69
|
+
t.integer :duration, null: false
|
|
70
|
+
t.string :connection, limit: 64
|
|
71
|
+
t.string :adapter, limit: 32
|
|
72
|
+
t.boolean :async, default: false
|
|
73
|
+
t.boolean :in_transaction, default: false
|
|
74
|
+
t.integer :row_count
|
|
75
|
+
t.string :source, limit: 255
|
|
76
|
+
t.integer :allocations
|
|
77
|
+
end
|
|
78
|
+
add_index :queries, [ :group_hash, :occurred_at ]
|
|
79
|
+
add_index :queries, [ :execution_id, :occurred_at ]
|
|
80
|
+
add_index :queries, [ :occurred_at, :duration ]
|
|
81
|
+
|
|
82
|
+
create_table :exceptions do |t|
|
|
83
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
84
|
+
# the history never calls a model that has since changed.
|
|
85
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
86
|
+
t.string :deploy, limit: 128
|
|
87
|
+
t.string :server, limit: 255
|
|
88
|
+
t.string :group_hash, limit: 32
|
|
89
|
+
t.string :trace_id, limit: 36
|
|
90
|
+
t.string :execution_source, limit: 20
|
|
91
|
+
t.string :execution_id, limit: 36
|
|
92
|
+
t.string :execution_preview, limit: 255
|
|
93
|
+
t.string :execution_stage, limit: 32
|
|
94
|
+
t.string :user_ref, limit: 255
|
|
95
|
+
t.string :tenant, limit: 255
|
|
96
|
+
t.string :class_name, null: false, limit: 255
|
|
97
|
+
t.text :message, null: false
|
|
98
|
+
t.boolean :handled, null: false, default: false
|
|
99
|
+
t.string :severity, limit: 16
|
|
100
|
+
t.string :source, limit: 128
|
|
101
|
+
t.string :file, limit: 255
|
|
102
|
+
t.integer :line
|
|
103
|
+
t.json :frames, null: false, default: []
|
|
104
|
+
t.json :cause
|
|
105
|
+
t.text :context
|
|
106
|
+
t.string :ruby_version, limit: 16
|
|
107
|
+
t.string :rails_version, limit: 16
|
|
108
|
+
end
|
|
109
|
+
add_index :exceptions, [ :group_hash, :occurred_at ]
|
|
110
|
+
add_index :exceptions, [ :execution_id ]
|
|
111
|
+
add_index :exceptions, [ :occurred_at ]
|
|
112
|
+
|
|
113
|
+
create_table :cache_events do |t|
|
|
114
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
115
|
+
# the history never calls a model that has since changed.
|
|
116
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
117
|
+
t.string :deploy, limit: 128
|
|
118
|
+
t.string :server, limit: 255
|
|
119
|
+
t.string :group_hash, limit: 32
|
|
120
|
+
t.string :trace_id, limit: 36
|
|
121
|
+
t.string :execution_source, limit: 20
|
|
122
|
+
t.string :execution_id, limit: 36
|
|
123
|
+
t.string :execution_preview, limit: 255
|
|
124
|
+
t.string :execution_stage, limit: 32
|
|
125
|
+
t.string :user_ref, limit: 255
|
|
126
|
+
t.string :tenant, limit: 255
|
|
127
|
+
t.string :store, limit: 64
|
|
128
|
+
t.string :key, limit: 255
|
|
129
|
+
t.string :type, null: false, limit: 20
|
|
130
|
+
t.integer :duration, null: false
|
|
131
|
+
t.integer :ttl
|
|
132
|
+
t.integer :hits
|
|
133
|
+
end
|
|
134
|
+
add_index :cache_events, [ :group_hash, :occurred_at ]
|
|
135
|
+
add_index :cache_events, [ :execution_id ]
|
|
136
|
+
|
|
137
|
+
create_table :mails do |t|
|
|
138
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
139
|
+
# the history never calls a model that has since changed.
|
|
140
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
141
|
+
t.string :deploy, limit: 128
|
|
142
|
+
t.string :server, limit: 255
|
|
143
|
+
t.string :group_hash, limit: 32
|
|
144
|
+
t.string :trace_id, limit: 36
|
|
145
|
+
t.string :execution_source, limit: 20
|
|
146
|
+
t.string :execution_id, limit: 36
|
|
147
|
+
t.string :execution_preview, limit: 255
|
|
148
|
+
t.string :execution_stage, limit: 32
|
|
149
|
+
t.string :user_ref, limit: 255
|
|
150
|
+
t.string :tenant, limit: 255
|
|
151
|
+
t.string :mailer, null: false, limit: 255
|
|
152
|
+
t.string :subject, limit: 255
|
|
153
|
+
t.integer :to, default: 0
|
|
154
|
+
t.integer :cc, default: 0
|
|
155
|
+
t.integer :bcc, default: 0
|
|
156
|
+
t.integer :attachments, default: 0
|
|
157
|
+
t.string :delivery_method, limit: 64
|
|
158
|
+
t.boolean :perform_deliveries, default: true
|
|
159
|
+
t.integer :duration, null: false
|
|
160
|
+
t.boolean :failed, default: false
|
|
161
|
+
t.string :message_id, limit: 255
|
|
162
|
+
end
|
|
163
|
+
add_index :mails, [ :group_hash, :occurred_at ]
|
|
164
|
+
add_index :mails, [ :execution_id ]
|
|
165
|
+
|
|
166
|
+
create_table :broadcasts do |t|
|
|
167
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
168
|
+
# the history never calls a model that has since changed.
|
|
169
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
170
|
+
t.string :deploy, limit: 128
|
|
171
|
+
t.string :server, limit: 255
|
|
172
|
+
t.string :group_hash, limit: 32
|
|
173
|
+
t.string :trace_id, limit: 36
|
|
174
|
+
t.string :execution_source, limit: 20
|
|
175
|
+
t.string :execution_id, limit: 36
|
|
176
|
+
t.string :execution_preview, limit: 255
|
|
177
|
+
t.string :execution_stage, limit: 32
|
|
178
|
+
t.string :user_ref, limit: 255
|
|
179
|
+
t.string :tenant, limit: 255
|
|
180
|
+
t.string :kind, null: false, limit: 20
|
|
181
|
+
t.string :stream, limit: 255
|
|
182
|
+
t.string :channel, limit: 255
|
|
183
|
+
t.string :action, limit: 128
|
|
184
|
+
t.integer :bytes
|
|
185
|
+
t.integer :duration, null: false
|
|
186
|
+
end
|
|
187
|
+
add_index :broadcasts, [ :group_hash, :occurred_at ]
|
|
188
|
+
add_index :broadcasts, [ :execution_id ]
|
|
189
|
+
|
|
190
|
+
create_table :notifications do |t|
|
|
191
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
192
|
+
# the history never calls a model that has since changed.
|
|
193
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
194
|
+
t.string :deploy, limit: 128
|
|
195
|
+
t.string :server, limit: 255
|
|
196
|
+
t.string :group_hash, limit: 32
|
|
197
|
+
t.string :trace_id, limit: 36
|
|
198
|
+
t.string :execution_source, limit: 20
|
|
199
|
+
t.string :execution_id, limit: 36
|
|
200
|
+
t.string :execution_preview, limit: 255
|
|
201
|
+
t.string :execution_stage, limit: 32
|
|
202
|
+
t.string :user_ref, limit: 255
|
|
203
|
+
t.string :tenant, limit: 255
|
|
204
|
+
t.string :notifier, limit: 255
|
|
205
|
+
t.string :delivery_method, limit: 128
|
|
206
|
+
t.integer :duration, null: false
|
|
207
|
+
t.boolean :failed, default: false
|
|
208
|
+
end
|
|
209
|
+
add_index :notifications, [ :group_hash, :occurred_at ]
|
|
210
|
+
|
|
211
|
+
create_table :outgoing_requests do |t|
|
|
212
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
213
|
+
# the history never calls a model that has since changed.
|
|
214
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
215
|
+
t.string :deploy, limit: 128
|
|
216
|
+
t.string :server, limit: 255
|
|
217
|
+
t.string :group_hash, limit: 32
|
|
218
|
+
t.string :trace_id, limit: 36
|
|
219
|
+
t.string :execution_source, limit: 20
|
|
220
|
+
t.string :execution_id, limit: 36
|
|
221
|
+
t.string :execution_preview, limit: 255
|
|
222
|
+
t.string :execution_stage, limit: 32
|
|
223
|
+
t.string :user_ref, limit: 255
|
|
224
|
+
t.string :tenant, limit: 255
|
|
225
|
+
t.string :host, null: false, limit: 255
|
|
226
|
+
t.string :method, null: false, limit: 10
|
|
227
|
+
t.string :url, limit: 2048
|
|
228
|
+
t.integer :duration, null: false
|
|
229
|
+
t.integer :status_code
|
|
230
|
+
t.integer :request_size
|
|
231
|
+
t.integer :response_size
|
|
232
|
+
t.string :error, limit: 255
|
|
233
|
+
t.string :source, limit: 255
|
|
234
|
+
end
|
|
235
|
+
add_index :outgoing_requests, [ :group_hash, :occurred_at ]
|
|
236
|
+
add_index :outgoing_requests, [ :execution_id ]
|
|
237
|
+
|
|
238
|
+
create_table :storage_ops do |t|
|
|
239
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
240
|
+
# the history never calls a model that has since changed.
|
|
241
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
242
|
+
t.string :deploy, limit: 128
|
|
243
|
+
t.string :server, limit: 255
|
|
244
|
+
t.string :group_hash, limit: 32
|
|
245
|
+
t.string :trace_id, limit: 36
|
|
246
|
+
t.string :execution_source, limit: 20
|
|
247
|
+
t.string :execution_id, limit: 36
|
|
248
|
+
t.string :execution_preview, limit: 255
|
|
249
|
+
t.string :execution_stage, limit: 32
|
|
250
|
+
t.string :user_ref, limit: 255
|
|
251
|
+
t.string :tenant, limit: 255
|
|
252
|
+
t.string :service, limit: 64
|
|
253
|
+
t.string :op, null: false, limit: 32
|
|
254
|
+
t.string :key, limit: 255
|
|
255
|
+
t.integer :duration, null: false
|
|
256
|
+
end
|
|
257
|
+
add_index :storage_ops, [ :group_hash, :occurred_at ]
|
|
258
|
+
|
|
259
|
+
create_table :view_renders do |t|
|
|
260
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
261
|
+
# the history never calls a model that has since changed.
|
|
262
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
263
|
+
t.string :deploy, limit: 128
|
|
264
|
+
t.string :server, limit: 255
|
|
265
|
+
t.string :group_hash, limit: 32
|
|
266
|
+
t.string :trace_id, limit: 36
|
|
267
|
+
t.string :execution_source, limit: 20
|
|
268
|
+
t.string :execution_id, limit: 36
|
|
269
|
+
t.string :execution_preview, limit: 255
|
|
270
|
+
t.string :execution_stage, limit: 32
|
|
271
|
+
t.string :user_ref, limit: 255
|
|
272
|
+
t.string :tenant, limit: 255
|
|
273
|
+
t.string :identifier, null: false, limit: 255
|
|
274
|
+
t.string :kind, limit: 20
|
|
275
|
+
t.string :layout, limit: 255
|
|
276
|
+
t.integer :count
|
|
277
|
+
t.integer :cache_hits
|
|
278
|
+
t.integer :duration, null: false
|
|
279
|
+
end
|
|
280
|
+
add_index :view_renders, [ :group_hash, :occurred_at ]
|
|
281
|
+
add_index :view_renders, [ :execution_id ]
|
|
282
|
+
|
|
283
|
+
create_table :logs do |t|
|
|
284
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
285
|
+
# the history never calls a model that has since changed.
|
|
286
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
287
|
+
t.string :deploy, limit: 128
|
|
288
|
+
t.string :server, limit: 255
|
|
289
|
+
t.string :group_hash, limit: 32
|
|
290
|
+
t.string :trace_id, limit: 36
|
|
291
|
+
t.string :execution_source, limit: 20
|
|
292
|
+
t.string :execution_id, limit: 36
|
|
293
|
+
t.string :execution_preview, limit: 255
|
|
294
|
+
t.string :execution_stage, limit: 32
|
|
295
|
+
t.string :user_ref, limit: 255
|
|
296
|
+
t.string :tenant, limit: 255
|
|
297
|
+
t.string :level, null: false, limit: 10
|
|
298
|
+
t.text :message, null: false
|
|
299
|
+
t.json :tags, null: false, default: []
|
|
300
|
+
t.text :context
|
|
301
|
+
t.string :source, limit: 255
|
|
302
|
+
end
|
|
303
|
+
add_index :logs, [ :level, :occurred_at ]
|
|
304
|
+
add_index :logs, [ :execution_id ]
|
|
305
|
+
add_index :logs, [ :occurred_at ]
|
|
306
|
+
|
|
307
|
+
create_table :enqueued_jobs do |t|
|
|
308
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
309
|
+
# the history never calls a model that has since changed.
|
|
310
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
311
|
+
t.string :deploy, limit: 128
|
|
312
|
+
t.string :server, limit: 255
|
|
313
|
+
t.string :group_hash, limit: 32
|
|
314
|
+
t.string :trace_id, limit: 36
|
|
315
|
+
t.string :execution_source, limit: 20
|
|
316
|
+
t.string :execution_id, limit: 36
|
|
317
|
+
t.string :execution_preview, limit: 255
|
|
318
|
+
t.string :execution_stage, limit: 32
|
|
319
|
+
t.string :user_ref, limit: 255
|
|
320
|
+
t.string :tenant, limit: 255
|
|
321
|
+
t.string :job_id, limit: 36
|
|
322
|
+
t.string :name, null: false, limit: 255
|
|
323
|
+
t.string :queue, limit: 128
|
|
324
|
+
t.string :adapter, limit: 64
|
|
325
|
+
t.integer :priority
|
|
326
|
+
t.datetime :scheduled_at, precision: 6
|
|
327
|
+
t.integer :duration, null: false
|
|
328
|
+
t.boolean :failed, default: false
|
|
329
|
+
end
|
|
330
|
+
add_index :enqueued_jobs, [ :group_hash, :occurred_at ]
|
|
331
|
+
add_index :enqueued_jobs, [ :execution_id ]
|
|
332
|
+
add_index :enqueued_jobs, :job_id
|
|
333
|
+
|
|
334
|
+
create_table :transactions do |t|
|
|
335
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
336
|
+
# the history never calls a model that has since changed.
|
|
337
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
338
|
+
t.string :deploy, limit: 128
|
|
339
|
+
t.string :server, limit: 255
|
|
340
|
+
t.string :group_hash, limit: 32
|
|
341
|
+
t.string :trace_id, limit: 36
|
|
342
|
+
t.string :execution_source, limit: 20
|
|
343
|
+
t.string :execution_id, limit: 36
|
|
344
|
+
t.string :execution_preview, limit: 255
|
|
345
|
+
t.string :execution_stage, limit: 32
|
|
346
|
+
t.string :user_ref, limit: 255
|
|
347
|
+
t.string :tenant, limit: 255
|
|
348
|
+
t.integer :duration, null: false
|
|
349
|
+
t.string :outcome, limit: 20
|
|
350
|
+
t.string :connection, limit: 64
|
|
351
|
+
end
|
|
352
|
+
add_index :transactions, [ :execution_id ]
|
|
353
|
+
|
|
354
|
+
create_table :n_plus_ones do |t|
|
|
355
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
356
|
+
# the history never calls a model that has since changed.
|
|
357
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
358
|
+
t.string :deploy, limit: 128
|
|
359
|
+
t.string :server, limit: 255
|
|
360
|
+
t.string :group_hash, limit: 32
|
|
361
|
+
t.string :trace_id, limit: 36
|
|
362
|
+
t.string :execution_source, limit: 20
|
|
363
|
+
t.string :execution_id, limit: 36
|
|
364
|
+
t.string :execution_preview, limit: 255
|
|
365
|
+
t.string :execution_stage, limit: 32
|
|
366
|
+
t.string :user_ref, limit: 255
|
|
367
|
+
t.string :tenant, limit: 255
|
|
368
|
+
t.text :sql, null: false
|
|
369
|
+
t.integer :count, null: false
|
|
370
|
+
t.string :source, limit: 255
|
|
371
|
+
end
|
|
372
|
+
add_index :n_plus_ones, [ :group_hash, :occurred_at ]
|
|
373
|
+
|
|
374
|
+
create_table :deprecations do |t|
|
|
375
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
376
|
+
# the history never calls a model that has since changed.
|
|
377
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
378
|
+
t.string :deploy, limit: 128
|
|
379
|
+
t.string :server, limit: 255
|
|
380
|
+
t.string :group_hash, limit: 32
|
|
381
|
+
t.string :trace_id, limit: 36
|
|
382
|
+
t.string :execution_source, limit: 20
|
|
383
|
+
t.string :execution_id, limit: 36
|
|
384
|
+
t.string :execution_preview, limit: 255
|
|
385
|
+
t.string :execution_stage, limit: 32
|
|
386
|
+
t.string :user_ref, limit: 255
|
|
387
|
+
t.string :tenant, limit: 255
|
|
388
|
+
t.text :message, null: false
|
|
389
|
+
t.string :gem_name, limit: 128
|
|
390
|
+
t.string :horizon, limit: 32
|
|
391
|
+
t.string :source, limit: 255
|
|
392
|
+
end
|
|
393
|
+
add_index :deprecations, [ :group_hash, :occurred_at ]
|
|
394
|
+
|
|
395
|
+
create_table :visits do |t|
|
|
396
|
+
# The record envelope as it was when this migration shipped; inlined so
|
|
397
|
+
# the history never calls a model that has since changed.
|
|
398
|
+
t.datetime :occurred_at, null: false, precision: 6
|
|
399
|
+
t.string :deploy, limit: 128
|
|
400
|
+
t.string :server, limit: 255
|
|
401
|
+
t.string :group_hash, limit: 32
|
|
402
|
+
t.string :trace_id, limit: 36
|
|
403
|
+
t.string :execution_source, limit: 20
|
|
404
|
+
t.string :execution_id, limit: 36
|
|
405
|
+
t.string :execution_preview, limit: 255
|
|
406
|
+
t.string :execution_stage, limit: 32
|
|
407
|
+
t.string :user_ref, limit: 255
|
|
408
|
+
t.string :tenant, limit: 255
|
|
409
|
+
t.string :component, limit: 255
|
|
410
|
+
t.string :url, limit: 2048
|
|
411
|
+
t.string :method, limit: 10
|
|
412
|
+
t.integer :duration, null: false
|
|
413
|
+
t.string :status, limit: 20
|
|
414
|
+
t.boolean :partial, default: false
|
|
415
|
+
t.json :only, null: false, default: []
|
|
416
|
+
t.integer :props_bytes
|
|
417
|
+
t.string :user_agent, limit: 255
|
|
418
|
+
end
|
|
419
|
+
add_index :visits, [ :group_hash, :occurred_at ]
|
|
420
|
+
|
|
421
|
+
create_table :people do |t|
|
|
422
|
+
t.string :ref, null: false, limit: 255 # tenant:id or id
|
|
423
|
+
t.string :name, limit: 255
|
|
424
|
+
t.string :email, limit: 255
|
|
425
|
+
t.string :tenant, limit: 255
|
|
426
|
+
t.datetime :first_seen_at, precision: 6
|
|
427
|
+
t.datetime :last_seen_at, precision: 6
|
|
428
|
+
t.integer :requests_count, null: false, default: 0
|
|
429
|
+
t.integer :exceptions_count, null: false, default: 0
|
|
430
|
+
end
|
|
431
|
+
add_index :people, :ref, unique: true
|
|
432
|
+
add_index :people, :last_seen_at
|
|
433
|
+
|
|
434
|
+
create_table :processes do |t|
|
|
435
|
+
t.datetime :booted_at, null: false, precision: 6
|
|
436
|
+
t.integer :pid
|
|
437
|
+
t.string :role, limit: 20
|
|
438
|
+
t.string :server, limit: 255
|
|
439
|
+
t.string :deploy, limit: 128
|
|
440
|
+
t.string :ruby_version, limit: 16
|
|
441
|
+
t.string :rails_version, limit: 16
|
|
442
|
+
t.string :lantern_version, limit: 16
|
|
443
|
+
t.float :boot_seconds
|
|
444
|
+
t.json :detail, null: false, default: {}
|
|
445
|
+
end
|
|
446
|
+
add_index :processes, :booted_at
|
|
447
|
+
|
|
448
|
+
# Hourly aggregates per record type and group. Percentiles come from a
|
|
449
|
+
# t-digest blob so they merge across hours without the raw rows.
|
|
450
|
+
create_table :rollups do |t|
|
|
451
|
+
t.datetime :bucket, null: false # start of the hour, UTC
|
|
452
|
+
t.string :record_type, null: false, limit: 32 # request, job_attempt, query, ...
|
|
453
|
+
t.string :group_hash, null: false, limit: 32
|
|
454
|
+
t.string :name, null: false, limit: 255
|
|
455
|
+
t.bigint :count, null: false, default: 0
|
|
456
|
+
t.bigint :error_count, null: false, default: 0 # 5xx, failed, exceptions
|
|
457
|
+
t.bigint :client_error_count, null: false, default: 0
|
|
458
|
+
t.bigint :duration_sum, null: false, default: 0
|
|
459
|
+
t.integer :duration_max, null: false, default: 0
|
|
460
|
+
t.integer :p50, null: false, default: 0
|
|
461
|
+
t.integer :p95, null: false, default: 0
|
|
462
|
+
t.integer :p99, null: false, default: 0
|
|
463
|
+
t.binary :digest
|
|
464
|
+
t.json :extra, null: false, default: {}
|
|
465
|
+
end
|
|
466
|
+
add_index :rollups, [ :record_type, :group_hash, :bucket ], unique: true
|
|
467
|
+
add_index :rollups, [ :record_type, :bucket ]
|
|
468
|
+
|
|
469
|
+
create_table :ingest_batches do |t|
|
|
470
|
+
t.datetime :received_at, null: false, precision: 6
|
|
471
|
+
t.integer :accepted, null: false, default: 0
|
|
472
|
+
t.integer :rejected, null: false, default: 0
|
|
473
|
+
t.integer :dropped_by_client, null: false, default: 0
|
|
474
|
+
t.integer :bytes, null: false, default: 0
|
|
475
|
+
t.string :gem_version, limit: 16
|
|
476
|
+
t.json :counts_by_type, null: false, default: {}
|
|
477
|
+
t.json :rejections, null: false, default: []
|
|
478
|
+
end
|
|
479
|
+
add_index :ingest_batches, :received_at
|
|
480
|
+
end
|
|
481
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# activerecord-tenanted defines `#tenant` on every tenanted model (the DB the
|
|
4
|
+
# row lives in), which shadowed the wire record's own tenant column. The
|
|
5
|
+
# monitored app's tenant is a different thing, so it gets its own name.
|
|
6
|
+
class RenameTenantToAppTenant < ActiveRecord::Migration[8.1]
|
|
7
|
+
TABLES = %i[executions queries exceptions cache_events mails broadcasts notifications outgoing_requests
|
|
8
|
+
storage_ops view_renders logs enqueued_jobs transactions n_plus_ones deprecations visits].freeze
|
|
9
|
+
|
|
10
|
+
def change
|
|
11
|
+
TABLES.each { |t| rename_column t, :tenant, :app_tenant }
|
|
12
|
+
rename_column :people, :tenant, :app_tenant
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# The gem reports how many statements ran inside each transaction; the
|
|
4
|
+
# ingest mapper dropped it because the column never existed.
|
|
5
|
+
class AddStatementCountToTransactions < ActiveRecord::Migration[8.1]
|
|
6
|
+
def change
|
|
7
|
+
add_column :transactions, :statement_count, :integer
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Nightwatch parity: a query's multi-DB role (writing/reading) and a
|
|
4
|
+
# notification's channel (email/slack/...) alongside the delivery class.
|
|
5
|
+
class AddRoleAndChannel < ActiveRecord::Migration[8.1]
|
|
6
|
+
def change
|
|
7
|
+
add_column :queries, :role, :string, limit: 16
|
|
8
|
+
add_column :notifications, :channel, :string, limit: 64
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Redacted local variables at the raise site, when the gem is configured to
|
|
4
|
+
# capture them (NIGHTRAIL_CAPTURE_EXCEPTION_LOCALS).
|
|
5
|
+
class AddLocalsToExceptions < ActiveRecord::Migration[8.1]
|
|
6
|
+
def change
|
|
7
|
+
add_column :exceptions, :locals, :json
|
|
8
|
+
end
|
|
9
|
+
end
|