railwatch 0.9.3 → 1.0.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/AGENTS.md +37 -33
- data/CHANGELOG.md +66 -0
- data/README.md +51 -60
- data/config/routes.rb +0 -59
- data/docs/ai-and-mcp.md +9 -8
- data/docs/configuration.md +57 -71
- data/docs/faq.md +17 -25
- data/docs/getting-started.md +105 -117
- data/docs/replacing-nightwatch.md +8 -7
- data/docs/replacing-sentry.md +12 -16
- data/docs/security.md +14 -20
- data/docs/self-hosting.md +24 -22
- data/docs/testing.md +6 -14
- data/docs/troubleshooting.md +12 -46
- data/lib/generators/railwatch/install/install_generator.rb +12 -240
- data/lib/generators/railwatch/install/templates/initializer.rb.tt +10 -40
- data/lib/generators/railwatch/install/templates/post-deploy +0 -7
- data/lib/railwatch/authentication.rb +6 -5
- data/lib/railwatch/buffer.rb +9 -0
- data/lib/railwatch/configuration.rb +21 -151
- data/lib/railwatch/engine.rb +9 -118
- data/lib/railwatch/patches.rb +0 -11
- data/lib/railwatch/reporter.rb +92 -21
- data/lib/railwatch/sampler.rb +10 -2
- data/lib/railwatch/subscribers/process_info.rb +1 -2
- data/lib/railwatch/version.rb +1 -1
- data/lib/railwatch.rb +8 -64
- data/lib/tasks/railwatch_tasks.rake +3 -325
- data/llms.txt +23 -25
- metadata +3 -453
- data/app/channels/railwatch/environment_channel.rb +0 -62
- data/app/controllers/concerns/railwatch/telemetry_identity.rb +0 -25
- data/app/controllers/railwatch/alerts_controller.rb +0 -48
- data/app/controllers/railwatch/anomaly_rules_controller.rb +0 -31
- data/app/controllers/railwatch/attachments_controller.rb +0 -22
- data/app/controllers/railwatch/broadcasts_controller.rb +0 -15
- data/app/controllers/railwatch/cache_events_controller.rb +0 -30
- data/app/controllers/railwatch/commands_controller.rb +0 -16
- data/app/controllers/railwatch/comments_controller.rb +0 -11
- data/app/controllers/railwatch/dashboard_controller.rb +0 -70
- data/app/controllers/railwatch/deploys_controller.rb +0 -34
- data/app/controllers/railwatch/deprecations_controller.rb +0 -54
- data/app/controllers/railwatch/environment_scoped.rb +0 -81
- data/app/controllers/railwatch/exceptions_controller.rb +0 -52
- data/app/controllers/railwatch/executions_controller.rb +0 -13
- data/app/controllers/railwatch/issues_controller.rb +0 -258
- data/app/controllers/railwatch/jobs_controller.rb +0 -63
- data/app/controllers/railwatch/llm_calls_controller.rb +0 -124
- data/app/controllers/railwatch/logs_controller.rb +0 -40
- data/app/controllers/railwatch/mails_controller.rb +0 -19
- data/app/controllers/railwatch/notifications_controller.rb +0 -11
- data/app/controllers/railwatch/outgoing_requests_controller.rb +0 -19
- data/app/controllers/railwatch/overview_controller.rb +0 -38
- data/app/controllers/railwatch/people_controller.rb +0 -25
- data/app/controllers/railwatch/processes_controller.rb +0 -33
- data/app/controllers/railwatch/profiles_controller.rb +0 -65
- data/app/controllers/railwatch/queries_controller.rb +0 -59
- data/app/controllers/railwatch/releases_controller.rb +0 -75
- data/app/controllers/railwatch/requests_controller.rb +0 -37
- data/app/controllers/railwatch/saved_views_controller.rb +0 -53
- data/app/controllers/railwatch/scheduled_tasks_controller.rb +0 -45
- data/app/controllers/railwatch/spans_controller.rb +0 -47
- data/app/controllers/railwatch/storage_ops_controller.rb +0 -15
- data/app/controllers/railwatch/tenants_controller.rb +0 -44
- data/app/controllers/railwatch/thresholds_controller.rb +0 -47
- data/app/controllers/railwatch/traces_controller.rb +0 -72
- data/app/controllers/railwatch/transactions_controller.rb +0 -21
- data/app/controllers/railwatch/view_renders_controller.rb +0 -28
- data/app/controllers/railwatch/visits_controller.rb +0 -53
- data/app/frontend/components/app-content.tsx +0 -26
- data/app/frontend/components/app-logo-icon.tsx +0 -23
- data/app/frontend/components/app-logo.tsx +0 -14
- data/app/frontend/components/app-shell.tsx +0 -38
- data/app/frontend/components/app-sidebar-header.tsx +0 -54
- data/app/frontend/components/app-sidebar.tsx +0 -94
- data/app/frontend/components/app-wordmark.tsx +0 -29
- data/app/frontend/components/breadcrumbs.tsx +0 -46
- data/app/frontend/components/icon.tsx +0 -16
- data/app/frontend/components/input-error.tsx +0 -18
- data/app/frontend/components/nav-footer.tsx +0 -46
- data/app/frontend/components/nav-main.tsx +0 -41
- data/app/frontend/components/nav-user.tsx +0 -50
- data/app/frontend/components/railwatch/chart-hover.tsx +0 -34
- data/app/frontend/components/railwatch/chart-panel.tsx +0 -170
- data/app/frontend/components/railwatch/code.tsx +0 -28
- data/app/frontend/components/railwatch/command-palette.tsx +0 -132
- data/app/frontend/components/railwatch/copy-block.tsx +0 -52
- data/app/frontend/components/railwatch/copy-id.tsx +0 -49
- data/app/frontend/components/railwatch/cursor-load-more.tsx +0 -39
- data/app/frontend/components/railwatch/data-table.tsx +0 -195
- data/app/frontend/components/railwatch/digit-roll.tsx +0 -312
- data/app/frontend/components/railwatch/empty-state.tsx +0 -159
- data/app/frontend/components/railwatch/env-nav.tsx +0 -130
- data/app/frontend/components/railwatch/env-switcher.tsx +0 -145
- data/app/frontend/components/railwatch/filter-bar.tsx +0 -153
- data/app/frontend/components/railwatch/flamegraph.tsx +0 -324
- data/app/frontend/components/railwatch/frames.tsx +0 -295
- data/app/frontend/components/railwatch/json-viewer.tsx +0 -159
- data/app/frontend/components/railwatch/live-dot.tsx +0 -78
- data/app/frontend/components/railwatch/live-toggle.tsx +0 -76
- data/app/frontend/components/railwatch/metric-chart.tsx +0 -112
- data/app/frontend/components/railwatch/mobile-page-switcher.tsx +0 -89
- data/app/frontend/components/railwatch/onboarding.tsx +0 -91
- data/app/frontend/components/railwatch/origin-identity.tsx +0 -84
- data/app/frontend/components/railwatch/page-header.tsx +0 -42
- data/app/frontend/components/railwatch/percentile-picker.tsx +0 -18
- data/app/frontend/components/railwatch/relative-time.tsx +0 -18
- data/app/frontend/components/railwatch/saved-views.tsx +0 -232
- data/app/frontend/components/railwatch/segmented.tsx +0 -64
- data/app/frontend/components/railwatch/series-chart.tsx +0 -400
- data/app/frontend/components/railwatch/shortcuts-dialog.tsx +0 -89
- data/app/frontend/components/railwatch/signal-toast.tsx +0 -121
- data/app/frontend/components/railwatch/sort-header.tsx +0 -37
- data/app/frontend/components/railwatch/source-link.tsx +0 -57
- data/app/frontend/components/railwatch/sparkline-cell.tsx +0 -14
- data/app/frontend/components/railwatch/sql-block.tsx +0 -116
- data/app/frontend/components/railwatch/stat.tsx +0 -185
- data/app/frontend/components/railwatch/status-badge.tsx +0 -79
- data/app/frontend/components/railwatch/step-picker.tsx +0 -57
- data/app/frontend/components/railwatch/timeline.tsx +0 -405
- data/app/frontend/components/railwatch/utilisation-bar.tsx +0 -44
- data/app/frontend/components/railwatch/window-picker.tsx +0 -147
- data/app/frontend/components/ui/avatar.tsx +0 -51
- data/app/frontend/components/ui/badge.tsx +0 -46
- data/app/frontend/components/ui/breadcrumb.tsx +0 -109
- data/app/frontend/components/ui/button.tsx +0 -60
- data/app/frontend/components/ui/card.tsx +0 -92
- data/app/frontend/components/ui/chart.tsx +0 -374
- data/app/frontend/components/ui/checkbox.tsx +0 -32
- data/app/frontend/components/ui/collapsible.tsx +0 -31
- data/app/frontend/components/ui/command.tsx +0 -182
- data/app/frontend/components/ui/dialog.tsx +0 -158
- data/app/frontend/components/ui/dropdown-menu.tsx +0 -255
- data/app/frontend/components/ui/hover-card.tsx +0 -42
- data/app/frontend/components/ui/input.tsx +0 -21
- data/app/frontend/components/ui/label.tsx +0 -24
- data/app/frontend/components/ui/popover.tsx +0 -87
- data/app/frontend/components/ui/select.tsx +0 -185
- data/app/frontend/components/ui/separator.tsx +0 -28
- data/app/frontend/components/ui/sheet.tsx +0 -137
- data/app/frontend/components/ui/sidebar.tsx +0 -726
- data/app/frontend/components/ui/skeleton.tsx +0 -13
- data/app/frontend/components/ui/sonner.tsx +0 -41
- data/app/frontend/components/ui/table.tsx +0 -114
- data/app/frontend/components/ui/tabs.tsx +0 -91
- data/app/frontend/components/ui/textarea.tsx +0 -18
- data/app/frontend/components/ui/tooltip.tsx +0 -61
- data/app/frontend/components/user-info.tsx +0 -32
- data/app/frontend/components/user-menu-content.tsx +0 -94
- data/app/frontend/entrypoints/application.css +0 -244
- data/app/frontend/entrypoints/inertia.tsx +0 -92
- data/app/frontend/fonts/CommitMono-Bold.woff2 +0 -0
- data/app/frontend/fonts/CommitMono-Regular.woff2 +0 -0
- data/app/frontend/fonts/Roboto-Black.woff2 +0 -0
- data/app/frontend/fonts/Roboto-Bold.woff2 +0 -0
- data/app/frontend/fonts/Roboto-Medium.woff2 +0 -0
- data/app/frontend/fonts/Roboto-Regular.woff2 +0 -0
- data/app/frontend/hooks/use-appearance.tsx +0 -67
- data/app/frontend/hooks/use-clipboard.ts +0 -32
- data/app/frontend/hooks/use-flash.tsx +0 -23
- data/app/frontend/hooks/use-hotkeys.ts +0 -63
- data/app/frontend/hooks/use-initials.tsx +0 -15
- data/app/frontend/hooks/use-live.ts +0 -205
- data/app/frontend/hooks/use-mobile-navigation.ts +0 -8
- data/app/frontend/hooks/use-mobile.ts +0 -21
- data/app/frontend/hooks/use-percentile.ts +0 -24
- data/app/frontend/hooks/use-reduced-motion.ts +0 -25
- data/app/frontend/hooks/use-row-nav.ts +0 -106
- data/app/frontend/hooks/use-step.ts +0 -27
- data/app/frontend/hooks/use-ticker.ts +0 -12
- data/app/frontend/hooks/use-window.ts +0 -58
- data/app/frontend/layouts/app/app-sidebar-layout.tsx +0 -107
- data/app/frontend/layouts/app-layout.tsx +0 -21
- data/app/frontend/layouts/env-layout.tsx +0 -53
- data/app/frontend/layouts/persistent-layout.tsx +0 -18
- data/app/frontend/lib/cable.ts +0 -10
- data/app/frontend/lib/env-pages.ts +0 -236
- data/app/frontend/lib/execution-path.ts +0 -55
- data/app/frontend/lib/explain.ts +0 -50
- data/app/frontend/lib/filter.ts +0 -25
- data/app/frontend/lib/flamegraph.ts +0 -155
- data/app/frontend/lib/format.ts +0 -71
- data/app/frontend/lib/keyboard.ts +0 -18
- data/app/frontend/lib/mount.ts +0 -23
- data/app/frontend/lib/source-link.ts +0 -217
- data/app/frontend/lib/utils.ts +0 -6
- data/app/frontend/pages/alerts/index.tsx +0 -171
- data/app/frontend/pages/broadcasts/index.tsx +0 -171
- data/app/frontend/pages/cache_events/index.tsx +0 -127
- data/app/frontend/pages/commands/index.tsx +0 -143
- data/app/frontend/pages/deploys/index.tsx +0 -94
- data/app/frontend/pages/deploys/show.tsx +0 -309
- data/app/frontend/pages/deprecations/index.tsx +0 -176
- data/app/frontend/pages/exceptions/index.tsx +0 -271
- data/app/frontend/pages/executions/show.tsx +0 -821
- data/app/frontend/pages/issues/index.tsx +0 -399
- data/app/frontend/pages/issues/show.tsx +0 -1367
- data/app/frontend/pages/jobs/index.tsx +0 -381
- data/app/frontend/pages/jobs/klass.tsx +0 -215
- data/app/frontend/pages/llm_calls/index.tsx +0 -664
- data/app/frontend/pages/logs/index.tsx +0 -303
- data/app/frontend/pages/mails/index.tsx +0 -218
- data/app/frontend/pages/notifications/index.tsx +0 -161
- data/app/frontend/pages/outgoing_requests/index.tsx +0 -309
- data/app/frontend/pages/overview/show.tsx +0 -333
- data/app/frontend/pages/people/index.tsx +0 -102
- data/app/frontend/pages/people/show.tsx +0 -149
- data/app/frontend/pages/processes/index.tsx +0 -335
- data/app/frontend/pages/profiles/index.tsx +0 -110
- data/app/frontend/pages/profiles/show.tsx +0 -105
- data/app/frontend/pages/queries/index.tsx +0 -492
- data/app/frontend/pages/queries/show.tsx +0 -276
- data/app/frontend/pages/releases/index.tsx +0 -190
- data/app/frontend/pages/releases/release-health.tsx +0 -68
- data/app/frontend/pages/releases/release-path.ts +0 -25
- data/app/frontend/pages/releases/show.tsx +0 -262
- data/app/frontend/pages/requests/index.tsx +0 -235
- data/app/frontend/pages/requests/route.tsx +0 -159
- data/app/frontend/pages/scheduled_tasks/index.tsx +0 -220
- data/app/frontend/pages/spans/index.tsx +0 -229
- data/app/frontend/pages/spans/show.tsx +0 -220
- data/app/frontend/pages/storage_ops/index.tsx +0 -150
- data/app/frontend/pages/tenants/index.tsx +0 -236
- data/app/frontend/pages/tenants/show.tsx +0 -477
- data/app/frontend/pages/tenants/tenant-path.ts +0 -26
- data/app/frontend/pages/thresholds/index.tsx +0 -414
- data/app/frontend/pages/traces/show.tsx +0 -208
- data/app/frontend/pages/transactions/index.tsx +0 -220
- data/app/frontend/pages/view_renders/index.tsx +0 -241
- data/app/frontend/pages/visits/index.tsx +0 -321
- data/app/frontend/public/icon.png +0 -0
- data/app/frontend/public/icon.svg +0 -5
- data/app/frontend/routes/index.d.ts +0 -2136
- data/app/frontend/routes/index.js +0 -2112
- data/app/frontend/types/globals.d.ts +0 -9
- data/app/frontend/types/index.ts +0 -288
- data/app/frontend/types/vite-env.d.ts +0 -9
- data/app/helpers/railwatch/assets_helper.rb +0 -52
- data/app/jobs/railwatch/anomaly_scan_job.rb +0 -11
- data/app/jobs/railwatch/application_job.rb +0 -7
- data/app/jobs/railwatch/auto_resolve_issues_job.rb +0 -19
- data/app/jobs/railwatch/check_scheduled_tasks_job.rb +0 -113
- data/app/jobs/railwatch/detect_anomalies_job.rb +0 -171
- data/app/jobs/railwatch/detect_performance_issues_job.rb +0 -95
- data/app/jobs/railwatch/group_exceptions_job.rb +0 -91
- data/app/jobs/railwatch/optimize_telemetry_job.rb +0 -23
- data/app/jobs/railwatch/performance_scan_job.rb +0 -11
- data/app/jobs/railwatch/prune_telemetry_job.rb +0 -129
- data/app/jobs/railwatch/release_health_rollup_job.rb +0 -64
- data/app/jobs/railwatch/rollup_catchup_job.rb +0 -21
- data/app/jobs/railwatch/rollup_job.rb +0 -132
- data/app/jobs/railwatch/scheduled_task_scan_job.rb +0 -11
- data/app/models/concerns/railwatch/detection_snapshotting.rb +0 -20
- data/app/models/railwatch/alert.rb +0 -229
- data/app/models/railwatch/alert_rule.rb +0 -121
- data/app/models/railwatch/anomaly_rule.rb +0 -51
- data/app/models/railwatch/application.rb +0 -44
- data/app/models/railwatch/application_record.rb +0 -33
- data/app/models/railwatch/comment.rb +0 -36
- data/app/models/railwatch/deploy.rb +0 -67
- data/app/models/railwatch/environment.rb +0 -68
- data/app/models/railwatch/execution_presenter.rb +0 -185
- data/app/models/railwatch/filter_query.rb +0 -184
- data/app/models/railwatch/followup_receipt.rb +0 -27
- data/app/models/railwatch/ingest/batch.rb +0 -355
- data/app/models/railwatch/ingest/mapper.rb +0 -585
- data/app/models/railwatch/ingest/payload.rb +0 -96
- data/app/models/railwatch/ingest/rollup_absorber.rb +0 -170
- data/app/models/railwatch/ingest/writer.rb +0 -137
- data/app/models/railwatch/issue.rb +0 -277
- data/app/models/railwatch/issue_activity.rb +0 -23
- data/app/models/railwatch/issue_detection_presenter.rb +0 -309
- data/app/models/railwatch/issue_detection_snapshot.rb +0 -77
- data/app/models/railwatch/maintenance_task.rb +0 -53
- data/app/models/railwatch/saved_view.rb +0 -63
- data/app/models/railwatch/telemetry/aggregations.rb +0 -251
- data/app/models/railwatch/telemetry/attachment.rb +0 -31
- data/app/models/railwatch/telemetry/bounded_gzip.rb +0 -101
- data/app/models/railwatch/telemetry/broadcast.rb +0 -13
- data/app/models/railwatch/telemetry/cache_event.rb +0 -16
- data/app/models/railwatch/telemetry/child.rb +0 -53
- data/app/models/railwatch/telemetry/cursor_page.rb +0 -99
- data/app/models/railwatch/telemetry/deprecation.rb +0 -13
- data/app/models/railwatch/telemetry/enqueued_job.rb +0 -13
- data/app/models/railwatch/telemetry/exception.rb +0 -28
- data/app/models/railwatch/telemetry/execution.rb +0 -152
- data/app/models/railwatch/telemetry/export_delivery.rb +0 -32
- data/app/models/railwatch/telemetry/export_destination.rb +0 -66
- data/app/models/railwatch/telemetry/health_sample.rb +0 -72
- data/app/models/railwatch/telemetry/ingest_batch.rb +0 -31
- data/app/models/railwatch/telemetry/llm_call.rb +0 -37
- data/app/models/railwatch/telemetry/log.rb +0 -91
- data/app/models/railwatch/telemetry/mail.rb +0 -13
- data/app/models/railwatch/telemetry/n_plus_one.rb +0 -92
- data/app/models/railwatch/telemetry/notification.rb +0 -13
- data/app/models/railwatch/telemetry/outgoing_request.rb +0 -13
- data/app/models/railwatch/telemetry/person.rb +0 -50
- data/app/models/railwatch/telemetry/process.rb +0 -10
- data/app/models/railwatch/telemetry/profile.rb +0 -37
- data/app/models/railwatch/telemetry/query.rb +0 -57
- data/app/models/railwatch/telemetry/query_shape.rb +0 -45
- data/app/models/railwatch/telemetry/release_health.rb +0 -69
- data/app/models/railwatch/telemetry/rollup.rb +0 -157
- data/app/models/railwatch/telemetry/session.rb +0 -24
- data/app/models/railwatch/telemetry/span.rb +0 -19
- data/app/models/railwatch/telemetry/storage_op.rb +0 -13
- data/app/models/railwatch/telemetry/tenant.rb +0 -240
- data/app/models/railwatch/telemetry/transaction.rb +0 -13
- data/app/models/railwatch/telemetry/view_render.rb +0 -13
- data/app/models/railwatch/telemetry/visit.rb +0 -24
- data/app/models/railwatch/telemetry_record.rb +0 -107
- data/app/models/railwatch/threshold.rb +0 -66
- data/app/models/railwatch/user.rb +0 -47
- data/app/models/railwatch/viewer.rb +0 -13
- data/app/models/railwatch/window.rb +0 -66
- data/app/views/layouts/railwatch/dashboard.html.erb +0 -25
- data/db/railwatch_migrate/20260916000000_create_railwatch_tables.rb +0 -151
- data/db/railwatch_migrate/20260917000000_create_railwatch_maintenance_tasks.rb +0 -18
- data/db/railwatch_migrate/20260917120000_create_railwatch_followup_receipts.rb +0 -20
- data/db/railwatch_migrate/20260918120000_widen_host_user_ids.rb +0 -71
- data/db/railwatch_telemetry_migrate/20260903000000_enable_incremental_vacuum.rb +0 -62
- data/db/railwatch_telemetry_migrate/20260903000001_create_telemetry.rb +0 -481
- data/db/railwatch_telemetry_migrate/20260903000002_rename_tenant_to_app_tenant.rb +0 -14
- data/db/railwatch_telemetry_migrate/20260903000003_add_statement_count_to_transactions.rb +0 -9
- data/db/railwatch_telemetry_migrate/20260903000004_add_role_and_channel.rb +0 -10
- data/db/railwatch_telemetry_migrate/20260903000005_add_locals_to_exceptions.rb +0 -9
- data/db/railwatch_telemetry_migrate/20260903000006_add_spans_health_vitals_and_fts.rb +0 -82
- data/db/railwatch_telemetry_migrate/20260903000007_rename_span_attributes_to_payload.rb +0 -10
- data/db/railwatch_telemetry_migrate/20260903000008_add_profiles_and_attachments.rb +0 -60
- data/db/railwatch_telemetry_migrate/20260903000009_add_truncated_to_attachments.rb +0 -9
- data/db/railwatch_telemetry_migrate/20260903000010_create_sessions_and_release_health.rb +0 -51
- data/db/railwatch_telemetry_migrate/20260903000011_add_fingerprint_to_exceptions.rb +0 -11
- data/db/railwatch_telemetry_migrate/20260904000012_add_failed_to_broadcasts.rb +0 -10
- data/db/railwatch_telemetry_migrate/20260904010000_add_filter_cursor_indexes.rb +0 -37
- data/db/railwatch_telemetry_migrate/20260904020000_add_n_plus_ones_execution_id_index.rb +0 -11
- data/db/railwatch_telemetry_migrate/20260904120000_create_query_shapes.rb +0 -15
- data/db/railwatch_telemetry_migrate/20260906120000_add_backpressure_factor_to_ingest_batches.rb +0 -9
- data/db/railwatch_telemetry_migrate/20260907000000_rename_lantern_version_on_processes.rb +0 -10
- data/db/railwatch_telemetry_migrate/20260913000000_rename_nightrail_version_on_processes.rb +0 -9
- data/db/railwatch_telemetry_migrate/20260914000000_drop_orphan_durable_ingest_tables.rb +0 -18
- data/db/railwatch_telemetry_migrate/20260914010000_drop_orphan_durable_ingest_columns.rb +0 -25
- data/db/railwatch_telemetry_migrate/20260915000000_create_llm_calls.rb +0 -55
- data/db/railwatch_telemetry_migrate/20260915120000_add_detail_to_llm_calls.rb +0 -21
- data/db/railwatch_telemetry_migrate/20260915200000_add_explained_index_to_queries.rb +0 -16
- data/db/railwatch_telemetry_migrate/20260915210000_add_slowest_index_to_queries.rb +0 -18
- data/db/railwatch_telemetry_migrate/20260917010000_add_batch_ledger_to_ingest_batches.rb +0 -16
- data/db/railwatch_telemetry_migrate/20260919000100_create_export_queue.rb +0 -146
- data/db/railwatch_telemetry_migrate/20260922000000_add_covering_indexes_for_dashboard_aggregates.rb +0 -34
- data/db/railwatch_telemetry_migrate/20260923000000_add_people_index.rb +0 -15
- data/db/railwatch_telemetry_migrate/20260925000000_add_tenant_summary_index.rb +0 -17
- data/db/railwatch_telemetry_migrate/20261008000000_add_in_transaction_to_outgoing_requests.rb +0 -10
- data/docs/embedded.md +0 -503
- data/lib/puma/plugin/railwatch.rb +0 -215
- data/lib/railwatch/dashboard_assets.rb +0 -45
- data/lib/railwatch/embedded.rb +0 -50
- data/lib/railwatch/export/client.rb +0 -124
- data/lib/railwatch/export/lease.rb +0 -56
- data/lib/railwatch/export/outbox.rb +0 -361
- data/lib/railwatch/export/policy.rb +0 -79
- data/lib/railwatch/export/sender.rb +0 -130
- data/lib/railwatch/ingest_request_body_limit.rb +0 -10
- data/lib/railwatch/maintenance.rb +0 -194
- data/lib/railwatch/patches/migration_busy_timeout.rb +0 -73
- data/lib/railwatch/transport/local.rb +0 -78
- data/lib/railwatch/transport/socket.rb +0 -183
- data/lib/railwatch/writer.rb +0 -370
- 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-by7G3sa1.js +0 -41
- data/public/railwatch/assets/application-Cc5v_Vk9.css +0 -1
- data/public/railwatch/assets/arrow-up-DCZ7emux.js +0 -1
- data/public/railwatch/assets/braces-CykT5_5u.js +0 -1
- data/public/railwatch/assets/card-C-PPSA0g.js +0 -1
- data/public/railwatch/assets/chart-Cov79YC5.js +0 -39
- data/public/railwatch/assets/chart-hover-DdK4E-2h.js +0 -1
- data/public/railwatch/assets/chart-panel-BPaYRXJB.js +0 -1
- data/public/railwatch/assets/code-BYjC4YZ_.js +0 -1
- data/public/railwatch/assets/copy-id-LPfoj9cC.js +0 -1
- data/public/railwatch/assets/cursor-load-more-DSdhgpGl.js +0 -1
- data/public/railwatch/assets/data-table-CQ_YRWQs.js +0 -1
- data/public/railwatch/assets/env-layout-CdMWbUkm.js +0 -1
- data/public/railwatch/assets/execution-path-7MYt-Qbn.js +0 -1
- data/public/railwatch/assets/filter-bar-CrzpQ_vD.js +0 -1
- data/public/railwatch/assets/flamegraph-BIFEdTAg.js +0 -2
- data/public/railwatch/assets/format-B9SDkrWj.js +0 -1
- data/public/railwatch/assets/frames-C5t-x4f0.js +0 -1
- data/public/railwatch/assets/index--NQ7us-L.js +0 -1
- data/public/railwatch/assets/index-2kgYe_99.js +0 -1
- data/public/railwatch/assets/index-4YEPHxtO.js +0 -1
- data/public/railwatch/assets/index-AOCC1GDJ.js +0 -1
- data/public/railwatch/assets/index-BEo-u0eO.js +0 -1
- data/public/railwatch/assets/index-BJ1V3w2N.js +0 -1
- data/public/railwatch/assets/index-BPoHsBKb.js +0 -1
- data/public/railwatch/assets/index-BZzyGUM3.js +0 -1
- data/public/railwatch/assets/index-BgVq7yKL.js +0 -1
- data/public/railwatch/assets/index-BqFGEZvW.js +0 -1
- data/public/railwatch/assets/index-ByuHJ1CH.js +0 -1
- data/public/railwatch/assets/index-C2j50AL2.js +0 -1
- data/public/railwatch/assets/index-CLEdTkvW.js +0 -1
- data/public/railwatch/assets/index-CWgq8qBu.js +0 -1
- data/public/railwatch/assets/index-CXQ7_oVj.js +0 -2
- data/public/railwatch/assets/index-CmyYrjS2.js +0 -1
- data/public/railwatch/assets/index-Cn9_HjDo.js +0 -1
- data/public/railwatch/assets/index-CsMAm9UK.js +0 -1
- data/public/railwatch/assets/index-D0Kk_oGY.js +0 -1
- data/public/railwatch/assets/index-DC9ZptJh.js +0 -1
- data/public/railwatch/assets/index-DNzg7jmV.js +0 -1
- data/public/railwatch/assets/index-DQ8uJO5f.js +0 -1
- data/public/railwatch/assets/index-Deq14BxB.js +0 -1
- data/public/railwatch/assets/index-IaV3Blzp.js +0 -1
- data/public/railwatch/assets/index-TYNWcJQs.js +0 -1
- data/public/railwatch/assets/index-WonH2fcZ.js +0 -1
- data/public/railwatch/assets/index-WxWUaH_d.js +0 -1
- data/public/railwatch/assets/index-mUNrl4ky.js +0 -1
- data/public/railwatch/assets/inertia-DfNRARuA.js +0 -97
- data/public/railwatch/assets/json-viewer-DMsF5glp.js +0 -1
- data/public/railwatch/assets/klass-CmHYk5rz.js +0 -1
- data/public/railwatch/assets/origin-identity-1R3bqa3R.js +0 -1
- data/public/railwatch/assets/percentile-picker-73z5PAps.js +0 -1
- data/public/railwatch/assets/relative-time-Dsc_cCdX.js +0 -1
- data/public/railwatch/assets/release-health-BV5OaOWd.js +0 -1
- data/public/railwatch/assets/route-CWh58C7K.js +0 -1
- data/public/railwatch/assets/segmented-DB4zh-Am.js +0 -1
- data/public/railwatch/assets/select-DBKjFlOX.js +0 -1
- data/public/railwatch/assets/series-chart-BaiDG795.js +0 -1
- data/public/railwatch/assets/show-B4ICCFGh.js +0 -1
- data/public/railwatch/assets/show-B5lOU9Gv.js +0 -1
- data/public/railwatch/assets/show-BYPB74t4.js +0 -2
- data/public/railwatch/assets/show-C7A0m2M8.js +0 -1
- data/public/railwatch/assets/show-DT5X1zqE.js +0 -1
- data/public/railwatch/assets/show-D_NBdXsn.js +0 -2
- data/public/railwatch/assets/show-DgPCnRg8.js +0 -1
- data/public/railwatch/assets/show-Yl69HF0x.js +0 -1
- data/public/railwatch/assets/show-_QxuUQCm.js +0 -3
- data/public/railwatch/assets/show-g__jnN36.js +0 -1
- data/public/railwatch/assets/show-l4ztfjl9.js +0 -1
- data/public/railwatch/assets/sort-header-BcG8ulEH.js +0 -1
- data/public/railwatch/assets/source-link-B2183i2-.js +0 -1
- data/public/railwatch/assets/sparkline-cell-B47ipscB.js +0 -1
- data/public/railwatch/assets/stat-DT2hhsqS.js +0 -1
- data/public/railwatch/assets/status-badge-CmbRKlY7.js +0 -1
- data/public/railwatch/assets/tenant-path-C4rNGauE.js +0 -1
- data/public/railwatch/assets/use-clipboard-oTNeP4ax.js +0 -1
- data/public/railwatch/assets/use-live-CLZZj245.js +0 -1
- data/public/railwatch/icon.png +0 -0
- data/public/railwatch/icon.svg +0 -5
- data/public/railwatch/manifest.json +0 -1245
- data/public/railwatch/rails-vite.json +0 -1
- /data/{app/frontend/lib → lib/generators/railwatch/install/templates}/railwatch.ts +0 -0
data/docs/configuration.md
CHANGED
|
@@ -11,9 +11,9 @@ values set in the initializer always win over the env var.
|
|
|
11
11
|
|
|
12
12
|
| Attribute | Env var | Default | Meaning |
|
|
13
13
|
|---|---|---|---|
|
|
14
|
-
| `enabled` | `RAILWATCH_ENABLED` | `true` | Master switch.
|
|
15
|
-
| `token` | `RAILWATCH_TOKEN` | nil | Bearer token for `/ingest`. Required with
|
|
16
|
-
| `ingest_url` | `RAILWATCH_INGEST_URL` | `https://railwatch.rebulk.com` |
|
|
14
|
+
| `enabled` | `RAILWATCH_ENABLED` | `true` | Master switch. `Railwatch.enabled?` is also `false` whenever `token` is blank, so setting only `RAILWATCH_TOKEN` is enough to turn an install on. |
|
|
15
|
+
| `token` | `RAILWATCH_TOKEN` | nil | Bearer token for `/ingest`. Required; with railwatch-server installed it is set for you. |
|
|
16
|
+
| `ingest_url` | `RAILWATCH_INGEST_URL` | `https://railwatch.rebulk.com` | Server base URL. Point at a self-hosted railwatch-rs to override. |
|
|
17
17
|
| `allow_http` | `RAILWATCH_ALLOW_HTTP` | `false` | Permit a non-loopback plain HTTP ingest URL. HTTPS is required by default; `localhost`, `127.0.0.1`, and `::1` remain available for local self-hosted development. |
|
|
18
18
|
| `deploy` | `RAILWATCH_DEPLOY` | auto-detected (order below), then nil | Version tag stamped on every record and used by `railwatch:deploy`. Full 40-character SHAs are shortened to 12 characters. |
|
|
19
19
|
| `detect_deploy` | `RAILWATCH_DETECT_DEPLOY` | `true` | Detect deploys beyond `RAILWATCH_DEPLOY` and `KAMAL_VERSION`. Set false when the app deliberately reports no inferred deploy. |
|
|
@@ -25,7 +25,7 @@ values set in the initializer always win over the env var.
|
|
|
25
25
|
| `beacon_rate_limit` | `RAILWATCH_BEACON_RATE_LIMIT` | `120` | Beacon POSTs accepted per client IP per minute before `POST /railwatch/beacon` answers 429. The beacon is unauthenticated and keeps every browser error it is sent, so this is what stops a script from spending the app's event quota. Counted in the app's cache store; `0` turns it off. |
|
|
26
26
|
|
|
27
27
|
`Railwatch.enabled?` delegates to `config.enabled?`, which is `@enabled &&
|
|
28
|
-
|
|
28
|
+
token.present?`. There is no separate "is configured" check
|
|
29
29
|
elsewhere.
|
|
30
30
|
|
|
31
31
|
Deploy detection stops at the first value found: `RAILWATCH_DEPLOY`,
|
|
@@ -411,7 +411,12 @@ result without inserting the payload twice. Records written while a request is i
|
|
|
411
411
|
separate bounded buffer, so they never change the retained request's
|
|
412
412
|
identity. At most one retained batch plus one live buffer are held in
|
|
413
413
|
memory. The reporter retries with jittered exponential backoff, from one
|
|
414
|
-
second up to 60 seconds. It does not busy-loop. A
|
|
414
|
+
second up to 60 seconds. It does not busy-loop. A response with a
|
|
415
|
+
`Retry-After` (a 503 for a full disk or busy database, a 429 rate limit) is a
|
|
416
|
+
refusal: the next attempt waits for its `Retry-After` instead, but never
|
|
417
|
+
less than the backoff rung and never more than 15 seconds (jittered down to
|
|
418
|
+
7.5), because Railwatch's receivers send a fixed 60 there, not a forecast.
|
|
419
|
+
A 401 marks the transport
|
|
415
420
|
permanently unauthorized: no further HTTP attempts for the process's
|
|
416
421
|
lifetime. It and other permanent client rejections are reported through
|
|
417
422
|
`on_unrecoverable`. Delivery never raises into app code.
|
|
@@ -433,6 +438,15 @@ affects one probabilistic decision. Set `backpressure` false to keep the
|
|
|
433
438
|
factor at 1. The current value is sent as
|
|
434
439
|
`X-Railwatch-Backpressure-Factor` whenever it is greater than 1.
|
|
435
440
|
|
|
441
|
+
A refusal from ingest (see above) sets the factor straight to 8x, and the
|
|
442
|
+
first delivery accepted after it sets it straight back to 1x, so sampling
|
|
443
|
+
recovers within one retry of the receiver recovering. Each refusal prints
|
|
444
|
+
two `[railwatch]` lines, the same way lost records do (see
|
|
445
|
+
`warn_on_data_loss`): one when it starts, and one when ingest accepts
|
|
446
|
+
again, with how long it lasted, how many executions backpressure sampled
|
|
447
|
+
out that the configured rates would have kept, and how many records were
|
|
448
|
+
dropped.
|
|
449
|
+
|
|
436
450
|
`Railwatch.flush` forces an immediate flush, on the calling thread and
|
|
437
451
|
without a time limit, so it is yours to call when you know you want to
|
|
438
452
|
wait. Nothing in the gem calls it for you: a short-lived process keeps its
|
|
@@ -571,7 +585,7 @@ Rake tasks and Solid Queue jobs are never interactive.
|
|
|
571
585
|
|
|
572
586
|
| Attribute | Env var | Default | Meaning |
|
|
573
587
|
|---|---|---|---|
|
|
574
|
-
| `capture_exception_source` | `RAILWATCH_CAPTURE_EXCEPTION_SOURCE_CODE` | `true` | Record source snippet lines surrounding each in-application exception frame (sent to
|
|
588
|
+
| `capture_exception_source` | `RAILWATCH_CAPTURE_EXCEPTION_SOURCE_CODE` | `true` | Record source snippet lines surrounding each in-application exception frame (sent to whichever server the app reports to). This is on by default for crash context; disable it when source disclosure is outside the application's telemetry policy. |
|
|
575
589
|
| `capture_exception_locals` | `RAILWATCH_CAPTURE_EXCEPTION_LOCALS` | `false` | Snapshot the raising frame's local variables (up to 25, values truncated to 200 chars, run through the same filter as request params) onto each exception, like Sentry's locals panel. Installs a `TracePoint(:raise)`; opt in per environment. |
|
|
576
590
|
| `capture_request_payload` | `RAILWATCH_CAPTURE_REQUEST_PAYLOAD` | `false` | Capture (redacted) request params — only for a request that raised, never otherwise. |
|
|
577
591
|
| `capture_job_arguments` | `RAILWATCH_CAPTURE_JOB_ARGUMENTS` | `false` | Add the job's real arguments (`job.serialize["arguments"]`) to each `job_attempt`/`scheduled_task` record, capped at 8 KiB of JSON. Hash arguments run through the same filter as request params. Off by default because job arguments routinely carry PII; `arguments_preview` (argument *shapes* only) is always on regardless. |
|
|
@@ -827,16 +841,19 @@ Railwatch.on_unrecoverable { |error| Rails.error.report(error, handled: true) }
|
|
|
827
841
|
```
|
|
828
842
|
|
|
829
843
|
Called whenever Railwatch rescues one of its own internal errors, ingest
|
|
830
|
-
permanently rejects a batch, or
|
|
831
|
-
that could not be sent. Retryable
|
|
832
|
-
|
|
844
|
+
permanently rejects a batch, ingest starts or stops refusing deliveries, or
|
|
845
|
+
shutdown expires with retained records that could not be sent. Retryable
|
|
846
|
+
delivery failures stay buffered and do not fire the callback on every
|
|
847
|
+
attempt. With no callback registered, a
|
|
833
848
|
recovered internal error falls back to `Railwatch.debug`, gated on
|
|
834
849
|
`RAILWATCH_DEBUG` — the gem carried on and there is nothing to do about it.
|
|
835
850
|
|
|
836
851
|
**Lost records are different, and are reported by default.** A batch
|
|
837
852
|
dropped after its retry ladder, one the receiver permanently refused, or
|
|
838
853
|
records still unsent when the bounded shutdown ran out of time each print
|
|
839
|
-
one `[railwatch]` stderr line.
|
|
854
|
+
one `[railwatch]` stderr line. So do the start and end of an ingest
|
|
855
|
+
refusal, which samples down until it is over (see backpressure above).
|
|
856
|
+
Telemetry that vanishes silently looks
|
|
840
857
|
exactly like having nothing to report, and a short-lived process — a rake
|
|
841
858
|
task, a `rails runner`, a cron job — gets one bounded shutdown and no
|
|
842
859
|
second chance to mention it.
|
|
@@ -883,72 +900,50 @@ in `lib/railwatch.rb`, unless noted:
|
|
|
883
900
|
`instrument_outgoing`, `flush`, `debug { }`. `pause`/`resume` are the
|
|
884
901
|
ignore block's building blocks, and are nestable.
|
|
885
902
|
|
|
886
|
-
##
|
|
903
|
+
## Dashboard gate (railwatch-server)
|
|
904
|
+
|
|
905
|
+
These settings do nothing on their own. They gate the dashboard that the
|
|
906
|
+
[`railwatch-server`](https://github.com/Rebulk/railwatch-server) gem
|
|
907
|
+
serves at `/railwatch` inside the app, so one setting covers it whichever
|
|
908
|
+
way it is installed.
|
|
887
909
|
|
|
888
910
|
```ruby
|
|
889
|
-
c.transport = :local # RAILWATCH_TRANSPORT; runtime default "http", but the installer writes :local
|
|
890
|
-
c.issue_prefix = "SHOP" # RAILWATCH_ISSUE_PREFIX; default from the app name
|
|
891
|
-
c.repository_url = "..." # RAILWATCH_REPOSITORY_URL
|
|
892
|
-
c.retention_days = 7 # RAILWATCH_RETENTION_DAYS
|
|
893
911
|
c.http_basic_auth_enabled = true # RAILWATCH_HTTP_BASIC_AUTH_ENABLED; on, and closed outside development until credentials exist
|
|
894
912
|
c.http_basic_auth_user = "ops" # RAILWATCH_HTTP_BASIC_AUTH_USER, or credentials railwatch.http_basic_auth_user
|
|
895
913
|
c.http_basic_auth_password = "..." # RAILWATCH_HTTP_BASIC_AUTH_PASSWORD, or credentials railwatch.http_basic_auth_password
|
|
896
914
|
c.base_controller_class = "AdminController" # RAILWATCH_BASE_CONTROLLER_CLASS; default ActionController::Base
|
|
897
|
-
c.dashboard_open = false # RAILWATCH_DASHBOARD_OPEN; default false, true makes it public on purpose
|
|
898
|
-
c.dashboard_user = ->(request) { { id:, name:, email: } or nil }
|
|
899
|
-
c.writer_socket = "tmp/sockets/railwatch-writer.sock" # RAILWATCH_WRITER_SOCKET
|
|
900
915
|
```
|
|
901
916
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
railwatch:authentication:configure` has written credentials; a host with
|
|
908
|
-
its own admin auth turns Basic off and sets `base_controller_class` or a
|
|
909
|
-
routes constraint. Full walkthrough: [Embedded mode](embedded.md).
|
|
910
|
-
|
|
911
|
-
### Export to Railwatch Cloud
|
|
912
|
-
|
|
913
|
-
An embedded install can also mirror every record to Railwatch Cloud.
|
|
914
|
-
Off unless `export_enabled` is set; a configured token alone sends
|
|
915
|
-
nothing. Only meaningful with `transport = :local`.
|
|
916
|
-
|
|
917
|
-
| Attribute | Env var | Default | Meaning |
|
|
918
|
-
|---|---|---|---|
|
|
919
|
-
| `export_enabled` | `RAILWATCH_EXPORT_ENABLED` | `false` | Mirror every record to the cloud as well as storing it locally. |
|
|
920
|
-
| `export_token` | `RAILWATCH_EXPORT_TOKEN` | `token` | Cloud environment token to send with. |
|
|
921
|
-
| `export_url` | `RAILWATCH_EXPORT_URL` | `{ingest_url}/ingest` | Where to send. |
|
|
922
|
-
| `export_max_bytes` | `RAILWATCH_EXPORT_MAX_BYTES` | `268435456` (256 MiB) | Queue ceiling in bytes. At capacity new work is refused and counted, not swapped for old. |
|
|
923
|
-
| `export_max_deliveries` | `RAILWATCH_EXPORT_MAX_DELIVERIES` | `100000` | Queue ceiling in deliveries. |
|
|
924
|
-
| `export_max_age` | `RAILWATCH_EXPORT_MAX_AGE_SECONDS` | `86400` | How long a queued delivery is kept. At most seven days, past which the receiver no longer recognises it. |
|
|
917
|
+
HTTP Basic is on by default and, outside development, answers 401 until
|
|
918
|
+
credentials exist: `bin/rails railwatch:authentication:configure` writes
|
|
919
|
+
them to the current environment's Rails credentials, or set the env vars.
|
|
920
|
+
In development with no credentials configured, it is open. An initializer
|
|
921
|
+
or env var that sets them wins over credentials.
|
|
925
922
|
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
923
|
+
An app with its own admin authentication turns Basic off and names a
|
|
924
|
+
base controller. railwatch-server's proxy controller inherits from
|
|
925
|
+
`base_controller_class`, so the app's own `before_action`s (require an
|
|
926
|
+
admin, redirect to sign-in) run in front of every dashboard request.
|
|
929
927
|
|
|
930
928
|
## Rake tasks
|
|
931
929
|
|
|
932
930
|
Ship with the gem via Rails::Engine's default `lib/tasks` convention, in
|
|
933
931
|
`lib/tasks/railwatch_tasks.rake`:
|
|
934
932
|
|
|
935
|
-
- **`railwatch:status`**
|
|
936
|
-
|
|
937
|
-
|
|
933
|
+
- **`railwatch:status`** pings `{ingest_url}/ingest/ping` with the
|
|
934
|
+
configured token, and aborts if `RAILWATCH_TOKEN` is unset or the ping
|
|
935
|
+
fails.
|
|
938
936
|
- **`railwatch:doctor`** prints a ✓/✗ checklist of the whole install.
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
stored, the ingest URL and its transport security, and
|
|
943
|
-
`GET /ingest/ping`. Then, either way: `Railwatch::Middleware::Request`
|
|
937
|
+
It checks the token, where the token is stored, the ingest URL and its
|
|
938
|
+
transport security, and `GET /ingest/ping`. Then
|
|
939
|
+
`Railwatch::Middleware::Request`
|
|
944
940
|
in the middleware stack, the mounted engine's beacon route,
|
|
945
941
|
`config.deploy` and its source, sample rates, ignored record types, the
|
|
946
942
|
Kamal `post-deploy` hook, the browser client and whether an entrypoint
|
|
947
943
|
calls it, the profiler backend, and the test matchers. It exits
|
|
948
944
|
non-zero only on the lines marked fatal in
|
|
949
945
|
[Troubleshooting](troubleshooting.md).
|
|
950
|
-
- **`railwatch:deploy[ref,name,url]`**
|
|
951
|
-
to the app's `railwatch` database. Cloud: POSTs `{deploy, ref, name,
|
|
946
|
+
- **`railwatch:deploy[ref,name,url]`** POSTs `{deploy, ref, name,
|
|
952
947
|
url, server, timestamp, performer, destination, service, commits}` to
|
|
953
948
|
`{ingest_url}/ingest/deploys`. `deploy` comes from `config.deploy`. It
|
|
954
949
|
aborts if that's unset. `ref` defaults to `git rev-parse HEAD` when not
|
|
@@ -957,29 +952,20 @@ Ship with the gem via Rails::Engine's default `lib/tasks` convention, in
|
|
|
957
952
|
`{sha, author, message, at}` objects, newest first, from `git log`. It
|
|
958
953
|
is empty inside an app container, which has no `.git`. That is why the
|
|
959
954
|
hook below posts from the deployer instead.
|
|
960
|
-
- **`railwatch:authentication:configure`** writes the
|
|
961
|
-
dashboard's HTTP Basic
|
|
962
|
-
credentials.
|
|
963
|
-
- **`railwatch:
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
abandon everything queued.
|
|
967
|
-
- **`railwatch:vacuum:status`** and **`railwatch:vacuum`** report and
|
|
968
|
-
reclaim the telemetry database's disk
|
|
969
|
-
([Embedded mode](embedded.md#giving-the-disk-back)).
|
|
970
|
-
- **`railwatch:token`** and **`railwatch:mcp`** print where to create a
|
|
971
|
-
cloud ingest token and paste-ready MCP client configuration.
|
|
955
|
+
- **`railwatch:authentication:configure`** writes the
|
|
956
|
+
[dashboard gate](#dashboard-gate-railwatch-server)'s HTTP Basic
|
|
957
|
+
credentials to the current environment's Rails credentials.
|
|
958
|
+
- **`railwatch:token`** and **`railwatch:mcp`** print where to create an
|
|
959
|
+
ingest token and paste-ready MCP client configuration for the server
|
|
960
|
+
`ingest_url` points at.
|
|
972
961
|
- **`railwatch:sourcemaps[directory,delete]`** uploads browser source
|
|
973
962
|
maps ([Source maps](source-maps.md)).
|
|
974
963
|
|
|
975
964
|
## Kamal integration
|
|
976
965
|
|
|
977
966
|
`bin/rails generate railwatch:install` writes `.kamal/hooks/post-deploy`,
|
|
978
|
-
but only if `config/deploy.yml` already exists.
|
|
979
|
-
`
|
|
980
|
-
`bin/rails railwatch:deploy[$KAMAL_VERSION]` in the primary container,
|
|
981
|
-
which records the marker in the embedded database, and stops. Otherwise
|
|
982
|
-
it no-ops when `RAILWATCH_TOKEN` isn't set. It never fails a deploy.
|
|
967
|
+
but only if `config/deploy.yml` already exists. It no-ops when
|
|
968
|
+
`RAILWATCH_TOKEN` isn't set. It never fails a deploy.
|
|
983
969
|
Every network call ends in `|| true`.
|
|
984
970
|
|
|
985
971
|
The hook runs on the **deployer machine**, not in a container, which is
|
data/docs/faq.md
CHANGED
|
@@ -51,26 +51,25 @@ A second gate, `bench/no_db_writes.rb`, drives 200 requests and a job with
|
|
|
51
51
|
a `sql.active_record` subscriber watching for any `INSERT`/`UPDATE`/
|
|
52
52
|
`DELETE` issued from a frame inside `lib/railwatch`, and fails if it finds
|
|
53
53
|
one. **Railwatch never writes to your application's database.** Records
|
|
54
|
-
live in memory and are delivered by a background thread
|
|
55
|
-
|
|
54
|
+
live in memory and are delivered by a background thread over HTTP to the
|
|
55
|
+
Railwatch server, which owns its own storage. That
|
|
56
56
|
is not a nicety: instrumentation that takes a write lock is what turns a
|
|
57
57
|
single-writer SQLite app into a "database is locked" incident.
|
|
58
58
|
|
|
59
59
|
## Where does the data go, and how long is it kept?
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
hourly rollups back the charts. Nothing leaves the machine unless you
|
|
65
|
-
turn on export. See [Embedded mode](embedded.md).
|
|
61
|
+
One gzip-NDJSON POST to `{ingest_url}/ingest` per batch, to Railwatch
|
|
62
|
+
Cloud, a self-hosted railwatch-rs, or the server the `railwatch-server`
|
|
63
|
+
gem runs next to the app. The gem keeps nothing on disk itself.
|
|
66
64
|
|
|
67
|
-
Railwatch Cloud
|
|
68
|
-
batch. The platform stores each monitored environment's telemetry in its
|
|
65
|
+
Railwatch Cloud stores each monitored environment's telemetry in its
|
|
69
66
|
own database, prunes raw rows on a retention window, and keeps hourly
|
|
70
67
|
rollups for the charts. Retention there is set by the account's plan
|
|
71
|
-
tier, not by the gem — 7, 30, or 90 days depending on the plan. For
|
|
72
|
-
self-hosted
|
|
73
|
-
|
|
68
|
+
tier, not by the gem — 7, 30, or 90 days depending on the plan. For
|
|
69
|
+
railwatch-rs, self-hosted or through railwatch-server, retention and
|
|
70
|
+
backups are server settings
|
|
71
|
+
([railwatch-rs SELF-HOST.md](https://github.com/Rebulk/railwatch-rs/blob/main/docs/SELF-HOST.md),
|
|
72
|
+
[railwatch-server README](https://github.com/Rebulk/railwatch-server#readme)).
|
|
74
73
|
|
|
75
74
|
## What about PII?
|
|
76
75
|
|
|
@@ -125,15 +124,13 @@ Yes, on both sides, and it's the first-class target.
|
|
|
125
124
|
|
|
126
125
|
**In your app:** the gem does no I/O on the request path and never writes
|
|
127
126
|
to the app database, so there is no contention with SQLite's single
|
|
128
|
-
writer.
|
|
129
|
-
whatever the app runs on. SQL normalization is per adapter, so SQLite,
|
|
127
|
+
writer. SQL normalization is per adapter, so SQLite,
|
|
130
128
|
Postgres, MySQL, and Trilogy all group correctly.
|
|
131
129
|
|
|
132
|
-
**On the
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
runs unchanged on Postgres if that's what's configured.
|
|
130
|
+
**On the server:** telemetry is stored in SQLite per monitored
|
|
131
|
+
environment. That is what makes retention pruning, backup, and restore
|
|
132
|
+
per-environment operations rather than one enormous table, and it's why
|
|
133
|
+
log search gets FTS5 with snippet highlighting.
|
|
137
134
|
|
|
138
135
|
## One database per environment — what does that mean for me?
|
|
139
136
|
|
|
@@ -168,12 +165,7 @@ Two features are Solid Queue-specific, because they read its tables:
|
|
|
168
165
|
with `task_key`, `schedule`, and `drift`) and the queue depth and
|
|
169
166
|
oldest-job age on `health` records.
|
|
170
167
|
|
|
171
|
-
## What happens when the
|
|
172
|
-
|
|
173
|
-
This section is about the cloud transport. In embedded mode the
|
|
174
|
-
equivalent is the writer process being down, covered in
|
|
175
|
-
[Embedded mode](embedded.md#the-writer-process), and export keeps its
|
|
176
|
-
own durable queue.
|
|
168
|
+
## What happens when the server is unreachable?
|
|
177
169
|
|
|
178
170
|
Nothing, from your app's point of view. This is the property everything
|
|
179
171
|
else is built around: **delivery never raises into application code.**
|
data/docs/getting-started.md
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
# Getting started
|
|
2
2
|
|
|
3
|
-
Two commands on a Rails 8 app,
|
|
4
|
-
Everything below is the gem's own generator and rake tasks;
|
|
5
|
-
has to be wired by hand.
|
|
3
|
+
Two commands on a Rails 8 app, a token, and the app reports to
|
|
4
|
+
Railwatch. Everything below is the gem's own generator and rake tasks;
|
|
5
|
+
nothing else has to be wired by hand.
|
|
6
|
+
|
|
7
|
+
The `railwatch` gem is the agent: it instruments the app and sends what
|
|
8
|
+
it records over HTTPS to a Railwatch server. The server is one of:
|
|
9
|
+
|
|
10
|
+
- **Railwatch Cloud** at <https://railwatch.rebulk.com>, the default.
|
|
11
|
+
- **Your own [railwatch-rs](https://github.com/Rebulk/railwatch-rs)**,
|
|
12
|
+
one static binary that serves many apps
|
|
13
|
+
([Self-hosting](self-hosting.md)).
|
|
14
|
+
- **The [`railwatch-server`](https://github.com/Rebulk/railwatch-server)
|
|
15
|
+
gem**, which runs railwatch-rs next to Puma for this one app and serves
|
|
16
|
+
the dashboard at `/railwatch` ([below](#embedded-railwatch-server)).
|
|
6
17
|
|
|
7
18
|
## Install
|
|
8
19
|
|
|
@@ -14,89 +25,6 @@ bin/rails generate railwatch:install
|
|
|
14
25
|
The gem, its Ruby namespace, and its require path share one name:
|
|
15
26
|
`railwatch`, `Railwatch::*`, `require "railwatch"`.
|
|
16
27
|
|
|
17
|
-
With no flags the install is [embedded](embedded.md): telemetry stays in
|
|
18
|
-
two SQLite databases the app owns, Puma forks one writer process for
|
|
19
|
-
them (`plugin :railwatch` in `config/puma.rb`), and the dashboard is
|
|
20
|
-
served from the app. No token, no cloud, no job worker. The generator
|
|
21
|
-
creates and migrates both databases before it returns. On a PostgreSQL
|
|
22
|
-
or MySQL app without the `sqlite3` gem it adds the gem instead; run
|
|
23
|
-
`bundle install` and `bin/rails db:prepare` to finish.
|
|
24
|
-
|
|
25
|
-
Restart the app and open `/railwatch`. In development it is open; every
|
|
26
|
-
other environment answers 401 until you give it a password:
|
|
27
|
-
|
|
28
|
-
```sh
|
|
29
|
-
RAILS_ENV=production bin/rails railwatch:authentication:configure
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
[Embedded mode](embedded.md#authentication) covers using your own
|
|
33
|
-
admin authentication instead.
|
|
34
|
-
|
|
35
|
-
### What the generator writes
|
|
36
|
-
|
|
37
|
-
In every mode:
|
|
38
|
-
|
|
39
|
-
- `config/initializers/railwatch.rb`, with every option commented out at
|
|
40
|
-
its default (embedded: `c.transport = :local`).
|
|
41
|
-
- `mount Railwatch::Engine, at: "/railwatch"` in `config/routes.rb`: the
|
|
42
|
-
embedded dashboard and the beacon endpoint the browser client posts to.
|
|
43
|
-
- `.kamal/hooks/post-deploy` — only if `config/deploy.yml` already
|
|
44
|
-
exists.
|
|
45
|
-
- `app/frontend/lib/railwatch.ts` plus the `startRailwatch()` call in your
|
|
46
|
-
Inertia entrypoint — only if `app/frontend/` exists. If it can't find
|
|
47
|
-
an entrypoint it prints the two lines to add.
|
|
48
|
-
- `require "railwatch/rspec"` in `spec/rails_helper.rb`, or
|
|
49
|
-
`require "railwatch/minitest"` in `test/test_helper.rb`.
|
|
50
|
-
|
|
51
|
-
Embedded adds the two databases to `config/database.yml` and the Puma
|
|
52
|
-
plugin line; see [Embedded mode](embedded.md#your-applications-own-database).
|
|
53
|
-
|
|
54
|
-
### Check the wiring
|
|
55
|
-
|
|
56
|
-
```sh
|
|
57
|
-
bin/rails railwatch:doctor
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
With the app running, the embedded checklist starts like this:
|
|
61
|
-
|
|
62
|
-
```
|
|
63
|
-
✓ transport: local (telemetry stays in this app; dashboard at the engine mount)
|
|
64
|
-
✓ railwatch database: storage/development_railwatch.sqlite3
|
|
65
|
-
✓ railwatch_telemetry database: storage/development_railwatch_telemetry.sqlite3
|
|
66
|
-
✓ railwatch_telemetry migrations: up to date
|
|
67
|
-
✓ railwatch migrations: up to date
|
|
68
|
-
✓ telemetry disk: auto_vacuum=incremental; the nightly prune returns freed pages
|
|
69
|
-
✓ writer process: listening at /app/tmp/sockets/railwatch-writer.sock
|
|
70
|
-
✓ last write: 12 seconds ago
|
|
71
|
-
✓ dashboard access: open in development. Production stays closed until you run `RAILS_ENV=production bin/rails railwatch:authentication:configure`
|
|
72
|
-
✓ request middleware: Railwatch::Middleware::Request at position 0
|
|
73
|
-
✓ engine mounted: POST /railwatch/beacon -> railwatch/beacon#create
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
With the app stopped, `writer process` and `maintenance` are `✗`, and say
|
|
77
|
-
so. Every line and what to do about a `✗` is in
|
|
78
|
-
[`troubleshooting.md`](troubleshooting.md).
|
|
79
|
-
|
|
80
|
-
### Adding Railwatch Cloud
|
|
81
|
-
|
|
82
|
-
Railwatch Cloud delivers alerts to Slack, email, webhooks or Linear
|
|
83
|
-
(embedded mode only records them), serves the [MCP server](ai-and-mcp.md)
|
|
84
|
-
to your AI assistant, and puts many apps and servers in one place. An
|
|
85
|
-
embedded install can mirror every record to it and keep `/railwatch`:
|
|
86
|
-
set a token ([below](#where-the-token-comes-from)) and
|
|
87
|
-
`c.export_enabled = true`. See
|
|
88
|
-
[Embedded mode](embedded.md#three-ways-to-run-it).
|
|
89
|
-
|
|
90
|
-
## Railwatch Cloud instead
|
|
91
|
-
|
|
92
|
-
To send telemetry only to Railwatch Cloud, with no local databases, run
|
|
93
|
-
the same generator with `--cloud`:
|
|
94
|
-
|
|
95
|
-
```sh
|
|
96
|
-
bundle add railwatch
|
|
97
|
-
bin/rails generate railwatch:install --cloud
|
|
98
|
-
```
|
|
99
|
-
|
|
100
28
|
With the token already in hand, let the generator read it without placing the
|
|
101
29
|
secret in shell history or process arguments:
|
|
102
30
|
|
|
@@ -109,25 +37,34 @@ bin/rails generate railwatch:install \
|
|
|
109
37
|
|
|
110
38
|
- `--prompt-token` reads without echo. `--token-stdin` is available for a
|
|
111
39
|
secret-manager pipe; an already exported `RAILWATCH_TOKEN` is also detected.
|
|
112
|
-
- Any of `--prompt-token`, `--token-stdin`, `--url=` and `--kamal-secrets`
|
|
113
|
-
means the cloud, so none of them needs `--cloud` as well. An exported
|
|
114
|
-
`RAILWATCH_TOKEN` on its own does not: without one of these flags the
|
|
115
|
-
install is embedded.
|
|
116
40
|
- A token is written to `.env` only when Git confirms that `.env` is ignored.
|
|
117
41
|
A tracked or non-ignored dotenv file is refused; use Rails credentials, a
|
|
118
42
|
deployment secret manager, or add `.env` to `.gitignore` first. Token values
|
|
119
43
|
are never printed by the generator.
|
|
120
|
-
- `--url=` sets `RAILWATCH_INGEST_URL`, for a self-hosted
|
|
44
|
+
- `--url=` sets `RAILWATCH_INGEST_URL`, for a self-hosted server. Leave
|
|
121
45
|
it off to use the default, `https://railwatch.rebulk.com`.
|
|
122
46
|
- `--kamal-secrets` appends `RAILWATCH_TOKEN=$RAILWATCH_TOKEN` to
|
|
123
47
|
`.kamal/secrets` and adds `RAILWATCH_TOKEN` under `env: secret:` in
|
|
124
48
|
`config/deploy.yml`, which is the pair of edits Kamal needs to pass a
|
|
125
49
|
secret through to the containers.
|
|
50
|
+
- `--no-doctor` skips the `railwatch:doctor` run at the end.
|
|
126
51
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
52
|
+
### What the generator writes
|
|
53
|
+
|
|
54
|
+
- `config/initializers/railwatch.rb`, with every option commented out at
|
|
55
|
+
its default.
|
|
56
|
+
- `mount Railwatch::Engine, at: "/railwatch"` in `config/routes.rb`: the
|
|
57
|
+
beacon endpoint the browser client posts to (`POST /railwatch/beacon`).
|
|
58
|
+
- `.kamal/hooks/post-deploy` — only if `config/deploy.yml` already
|
|
59
|
+
exists.
|
|
60
|
+
- `app/frontend/lib/railwatch.ts` plus the `startRailwatch()` call in your
|
|
61
|
+
Inertia entrypoint — only if `app/frontend/` exists. If it can't find
|
|
62
|
+
an entrypoint it prints the two lines to add.
|
|
63
|
+
- `require "railwatch/rspec"` in `spec/rails_helper.rb`, or
|
|
64
|
+
`require "railwatch/minitest"` in `test/test_helper.rb`.
|
|
65
|
+
|
|
66
|
+
It finishes by running `railwatch:doctor`, so the install either ends in
|
|
67
|
+
a clean checklist or tells you what is still missing.
|
|
131
68
|
|
|
132
69
|
### Where the token comes from
|
|
133
70
|
|
|
@@ -135,18 +72,18 @@ In Railwatch Cloud, create an application, then an environment inside it
|
|
|
135
72
|
(`production`, `staging`, one token each). The token is shown once, on
|
|
136
73
|
the page you land on right after creating the environment — copy it
|
|
137
74
|
then. If you lose it, rotate it from the environment's settings and
|
|
138
|
-
update `RAILWATCH_TOKEN`.
|
|
75
|
+
update `RAILWATCH_TOKEN`. A self-hosted railwatch-rs creates tokens the
|
|
76
|
+
same way (or with `railwatch env create`; see its docs).
|
|
139
77
|
|
|
140
78
|
```sh
|
|
141
79
|
bin/rails railwatch:token # prints the URL to create/copy a token
|
|
142
80
|
```
|
|
143
81
|
|
|
144
|
-
A token looks like `rw_` followed by 40 characters.
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
subscribers and ships nothing.
|
|
82
|
+
A token looks like `rw_` followed by 40 characters. The gem is inert
|
|
83
|
+
without one: `Railwatch.enabled?` is `config.enabled && token.present?`,
|
|
84
|
+
so an app with no token installs no subscribers and ships nothing.
|
|
148
85
|
|
|
149
|
-
### Check the
|
|
86
|
+
### Check the wiring
|
|
150
87
|
|
|
151
88
|
```sh
|
|
152
89
|
bin/rails railwatch:doctor
|
|
@@ -169,11 +106,67 @@ It exits non-zero on three lines: `token` (missing), `token storage`
|
|
|
169
106
|
(a plaintext token in a tracked file), and `ingest reachable`. The rest
|
|
170
107
|
of the checklist is informational. Run it after the token is in place:
|
|
171
108
|
`ingest reachable` sends the token, so a missing or wrong token makes
|
|
172
|
-
the
|
|
109
|
+
the server answer 401 and that line is `✗` as well. Every line and what
|
|
110
|
+
to do about a `✗` is in [`troubleshooting.md`](troubleshooting.md).
|
|
173
111
|
|
|
174
112
|
`bin/rails railwatch:status` is the one-line version: it pings
|
|
175
113
|
`{ingest_url}/ingest/ping` and prints the ingest URL, deploy, and server.
|
|
176
114
|
|
|
115
|
+
## Embedded: railwatch-server
|
|
116
|
+
|
|
117
|
+
To keep telemetry inside the app instead, add the
|
|
118
|
+
[`railwatch-server`](https://github.com/Rebulk/railwatch-server) gem
|
|
119
|
+
next to this one. It bundles the railwatch-rs binary for your platform,
|
|
120
|
+
runs it as its own process beside Puma, and points this agent at it:
|
|
121
|
+
|
|
122
|
+
```ruby
|
|
123
|
+
# Gemfile
|
|
124
|
+
gem "railwatch"
|
|
125
|
+
gem "railwatch-server"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
```ruby
|
|
129
|
+
# config/puma.rb
|
|
130
|
+
plugin :railwatch_server
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
On first boot it provisions `storage/railwatch/<env>` and sets the
|
|
134
|
+
agent's token and ingest URL itself, so no `RAILWATCH_TOKEN` is needed.
|
|
135
|
+
When `RAILWATCH_TOKEN` is set, it leaves the agent alone and only serves
|
|
136
|
+
the dashboard. The dashboard at `/railwatch` is behind this gem's gate
|
|
137
|
+
settings: HTTP Basic, on and closed (401) until credentials exist, except
|
|
138
|
+
in development when none are configured:
|
|
139
|
+
|
|
140
|
+
```sh
|
|
141
|
+
RAILS_ENV=production bin/rails railwatch:authentication:configure
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
To use your own admin authentication instead, turn Basic off and name a
|
|
145
|
+
base controller ([Configuration](configuration.md#dashboard-gate-railwatch-server)).
|
|
146
|
+
Everything else about it (ports, data directory, email, backups) is in
|
|
147
|
+
the [railwatch-server README](https://github.com/Rebulk/railwatch-server#readme).
|
|
148
|
+
|
|
149
|
+
### Coming from 0.x embedded mode
|
|
150
|
+
|
|
151
|
+
Railwatch 0.x could keep telemetry in two SQLite databases of the app's
|
|
152
|
+
own, written by a Puma writer process, with the dashboard served from the
|
|
153
|
+
gem. 1.0 removes that mode. To move:
|
|
154
|
+
|
|
155
|
+
1. Remove `c.transport = :local` (or `RAILWATCH_TRANSPORT=local`) from
|
|
156
|
+
the initializer and environment.
|
|
157
|
+
2. Remove `plugin :railwatch` from `config/puma.rb`. Puma refuses to boot
|
|
158
|
+
with a plugin it cannot find.
|
|
159
|
+
3. Remove the `railwatch` and `railwatch_telemetry` entries from
|
|
160
|
+
`config/database.yml`.
|
|
161
|
+
4. Add `railwatch-server` as above, or point the app at Railwatch Cloud
|
|
162
|
+
or a self-hosted railwatch-rs.
|
|
163
|
+
|
|
164
|
+
The old files (`storage/<env>_railwatch.sqlite3`,
|
|
165
|
+
`storage/<env>_railwatch_telemetry.sqlite3`) are not migrated, and
|
|
166
|
+
railwatch-rs has no import for them: its `railwatch import-rails` reads a
|
|
167
|
+
Railwatch Cloud (Rails) install, not these files. History starts again
|
|
168
|
+
in the new server. Delete the files once you no longer want them.
|
|
169
|
+
|
|
177
170
|
## Make one request
|
|
178
171
|
|
|
179
172
|
```sh
|
|
@@ -183,8 +176,9 @@ curl http://localhost:3000/
|
|
|
183
176
|
|
|
184
177
|
Records are batched in-process and flushed every `flush_interval`
|
|
185
178
|
(2 seconds by default) or every 500 records, whichever comes first, so
|
|
186
|
-
the request shows up on the **Requests** page (
|
|
187
|
-
|
|
179
|
+
the request shows up on the **Requests** page (the environment in
|
|
180
|
+
Railwatch Cloud or your own server, or `/railwatch` with
|
|
181
|
+
railwatch-server) a couple of seconds after you make it —
|
|
188
182
|
with its queries, cache reads, view renders, and log lines already
|
|
189
183
|
attached to it.
|
|
190
184
|
|
|
@@ -266,14 +260,11 @@ up, on the account.
|
|
|
266
260
|
|
|
267
261
|
## Deploying
|
|
268
262
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
from the Kamal hook, set `RAILWATCH_TRANSPORT=local` in the deployer's
|
|
275
|
-
environment ([Embedded mode](embedded.md#deploys)). The token steps
|
|
276
|
-
below are for a cloud install or export.
|
|
263
|
+
With railwatch-server, the server's data lives under
|
|
264
|
+
`storage/railwatch/<env>`, which has to be on a volume that survives
|
|
265
|
+
deploys (the Rails 8 Kamal template mounts `storage/`); its README covers
|
|
266
|
+
deploys and two containers sharing a volume. The token steps below are
|
|
267
|
+
for Railwatch Cloud or a self-hosted server.
|
|
277
268
|
|
|
278
269
|
### Kamal
|
|
279
270
|
|
|
@@ -352,12 +343,9 @@ one — the deploy is still recorded.
|
|
|
352
343
|
`sentry-rails`.
|
|
353
344
|
- [`replacing-nightwatch.md`](replacing-nightwatch.md) — for people
|
|
354
345
|
coming from Laravel.
|
|
355
|
-
- [`embedded.md`](embedded.md) — authentication, the writer process,
|
|
356
|
-
maintenance, disk, and export to the cloud.
|
|
357
346
|
- [`self-hosting.md`](self-hosting.md) — pointing the gem at your own
|
|
358
|
-
|
|
347
|
+
railwatch-rs server.
|
|
359
348
|
- [`troubleshooting.md`](troubleshooting.md) — every `railwatch:doctor`
|
|
360
349
|
line and what a failure means.
|
|
361
350
|
- [`faq.md`](faq.md) — overhead, retention, PII, unreachable platform.
|
|
362
|
-
- [`ai-and-mcp.md`](ai-and-mcp.md) — asking an AI assistant what broke
|
|
363
|
-
(Railwatch Cloud).
|
|
351
|
+
- [`ai-and-mcp.md`](ai-and-mcp.md) — asking an AI assistant what broke.
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
Railwatch is the same product shape for Rails: one package instruments the
|
|
4
4
|
framework end to end, records are grouped under the execution that
|
|
5
5
|
produced them, and a dashboard turns them into routes, jobs, queries,
|
|
6
|
-
issues, and alerts.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
issues, and alerts. Railwatch Cloud is the hosted option; unlike
|
|
7
|
+
Nightwatch, the server can also be self-hosted
|
|
8
|
+
([railwatch-rs](self-hosting.md)) or run inside your app with the
|
|
9
|
+
[`railwatch-server`](getting-started.md#embedded-railwatch-server) gem.
|
|
10
|
+
If you know Nightwatch, you already know how to read Railwatch — this page maps the vocabulary and points out the three
|
|
10
11
|
places the Rails answer is genuinely different.
|
|
11
12
|
|
|
12
13
|
Railwatch is an independent product and is not affiliated with Laravel or
|
|
@@ -21,8 +22,8 @@ separate daemon POSTs them.
|
|
|
21
22
|
Puma and Solid Queue workers *are* long-lived, so Railwatch skips that
|
|
22
23
|
tier. A single reporter thread per process holds a bounded buffer
|
|
23
24
|
(16 MiB and 10,000 records by default, oldest dropped and counted) and
|
|
24
|
-
flushes batches every 2 seconds or every 500 records
|
|
25
|
-
|
|
25
|
+
flushes batches every 2 seconds or every 500 records, as gzip-NDJSON
|
|
26
|
+
POSTs to the Railwatch server.
|
|
26
27
|
There is no daemon to install, supervise, or forget to restart.
|
|
27
28
|
|
|
28
29
|
The thread is re-armed after `fork`, so clustered Puma workers and
|
|
@@ -184,7 +185,7 @@ every setting still has an env var — `NIGHTWATCH_*` becomes `RAILWATCH_*`.
|
|
|
184
185
|
| `nightwatch:agent` | Nothing — the reporter thread lives in the app process. |
|
|
185
186
|
| `nightwatch:status` | `bin/rails railwatch:status` |
|
|
186
187
|
| `nightwatch:deploy {deploy} --ref --name --url` | `bin/rails railwatch:deploy[ref,name,url]`, or the generated `.kamal/hooks/post-deploy` |
|
|
187
|
-
| — | `bin/rails railwatch:doctor`, which checks the whole install and exits non-zero if the
|
|
188
|
+
| — | `bin/rails railwatch:doctor`, which checks the whole install and exits non-zero if the token or the ingest host is wrong |
|
|
188
189
|
|
|
189
190
|
## The three things worth knowing about Rails
|
|
190
191
|
|