railwatch 0.1.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 +7 -0
- data/AGENTS.md +122 -0
- data/CHANGELOG.md +462 -0
- data/MIT-LICENSE +20 -0
- data/README.md +226 -0
- data/app/controllers/railwatch/beacon_controller.rb +254 -0
- data/config/routes.rb +5 -0
- data/docs/ai-and-mcp.md +227 -0
- data/docs/configuration.md +931 -0
- data/docs/faq.md +230 -0
- data/docs/getting-started.md +279 -0
- data/docs/records.md +834 -0
- data/docs/replacing-nightwatch.md +216 -0
- data/docs/replacing-sentry.md +573 -0
- data/docs/security.md +94 -0
- data/docs/self-hosting.md +60 -0
- data/docs/source-maps.md +60 -0
- data/docs/testing.md +175 -0
- data/docs/troubleshooting.md +319 -0
- data/lib/generators/railwatch/install/install_generator.rb +280 -0
- data/lib/generators/railwatch/install/templates/initializer.rb +54 -0
- data/lib/generators/railwatch/install/templates/post-deploy +98 -0
- data/lib/generators/railwatch/install/templates/railwatch.ts +658 -0
- data/lib/railwatch/attachments.rb +83 -0
- data/lib/railwatch/backtrace.rb +158 -0
- data/lib/railwatch/buffer.rb +122 -0
- data/lib/railwatch/clock.rb +25 -0
- data/lib/railwatch/configuration.rb +334 -0
- data/lib/railwatch/console.rb +48 -0
- data/lib/railwatch/context.rb +125 -0
- data/lib/railwatch/controller_helpers.rb +21 -0
- data/lib/railwatch/current.rb +32 -0
- data/lib/railwatch/engine.rb +144 -0
- data/lib/railwatch/execution.rb +367 -0
- data/lib/railwatch/faraday.rb +73 -0
- data/lib/railwatch/health.rb +188 -0
- data/lib/railwatch/job_tracing.rb +49 -0
- data/lib/railwatch/middleware/request.rb +289 -0
- data/lib/railwatch/minitest.rb +43 -0
- data/lib/railwatch/patches/inertia.rb +34 -0
- data/lib/railwatch/patches/net_http.rb +102 -0
- data/lib/railwatch/patches/rake_task.rb +88 -0
- data/lib/railwatch/patches/runner_command.rb +120 -0
- data/lib/railwatch/patches.rb +43 -0
- data/lib/railwatch/profiler.rb +270 -0
- data/lib/railwatch/record.rb +119 -0
- data/lib/railwatch/redactor.rb +67 -0
- data/lib/railwatch/release_detector.rb +97 -0
- data/lib/railwatch/reporter.rb +539 -0
- data/lib/railwatch/rspec.rb +139 -0
- data/lib/railwatch/sampler.rb +17 -0
- data/lib/railwatch/secret_safety.rb +62 -0
- data/lib/railwatch/sessions.rb +162 -0
- data/lib/railwatch/source_maps.rb +59 -0
- data/lib/railwatch/spec_helper.rb +147 -0
- data/lib/railwatch/sql_normalizer.rb +398 -0
- data/lib/railwatch/subscribers/base.rb +54 -0
- data/lib/railwatch/subscribers/broadcasts.rb +107 -0
- data/lib/railwatch/subscribers/cache.rb +107 -0
- data/lib/railwatch/subscribers/deprecations.rb +26 -0
- data/lib/railwatch/subscribers/exceptions.rb +304 -0
- data/lib/railwatch/subscribers/jobs.rb +282 -0
- data/lib/railwatch/subscribers/logs.rb +137 -0
- data/lib/railwatch/subscribers/mail.rb +42 -0
- data/lib/railwatch/subscribers/notifications.rb +36 -0
- data/lib/railwatch/subscribers/process_info.rb +98 -0
- data/lib/railwatch/subscribers/queries.rb +183 -0
- data/lib/railwatch/subscribers/requests.rb +94 -0
- data/lib/railwatch/subscribers/storage.rb +35 -0
- data/lib/railwatch/subscribers/users.rb +159 -0
- data/lib/railwatch/subscribers/views.rb +54 -0
- data/lib/railwatch/subscribers.rb +34 -0
- data/lib/railwatch/transport/http.rb +208 -0
- data/lib/railwatch/version.rb +5 -0
- data/lib/railwatch.rb +550 -0
- data/lib/tasks/railwatch_tasks.rake +289 -0
- data/llms.txt +38 -0
- metadata +157 -0
data/docs/ai-and-mcp.md
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# AI assistants and MCP
|
|
2
|
+
|
|
3
|
+
Railwatch Cloud is an [MCP](https://modelcontextprotocol.io) server. Point
|
|
4
|
+
Claude Code, Claude Desktop, Cursor, VS Code, or Zed at it and the assistant
|
|
5
|
+
sitting in your editor can read the same production data your dashboards
|
|
6
|
+
show: issues and their stack traces, slow routes, the queries and N+1s
|
|
7
|
+
behind them, stored query plans, stack profiles, logs, deploys, and
|
|
8
|
+
crash-free rates per release. It can also write — resolve an issue, set a
|
|
9
|
+
priority, leave a comment — and every write is signed with your user and the
|
|
10
|
+
agent's name in the issue's activity feed.
|
|
11
|
+
|
|
12
|
+
The endpoint is `<your ingest host>/mcp`. For the hosted platform that's
|
|
13
|
+
`https://railwatch.rebulk.com/mcp`; if you self-host, it is your own host (see
|
|
14
|
+
[`self-hosting.md`](self-hosting.md)). The gem knows which one you're on:
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
bin/rails railwatch:mcp
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
prints every block below with your platform's host already filled in.
|
|
21
|
+
|
|
22
|
+
## 1. Get a token
|
|
23
|
+
|
|
24
|
+
MCP tokens are **per person**, not per application: sign in to the platform,
|
|
25
|
+
go to **Settings → Profile → "API & MCP token"**, and press *Generate token*.
|
|
26
|
+
The token starts with `lnt_` and is shown once. It can reach every account
|
|
27
|
+
your user belongs to, and nothing else.
|
|
28
|
+
|
|
29
|
+
This is a different token from the `lt_...` ingest token the gem uses. The
|
|
30
|
+
ingest token writes telemetry for one environment; the MCP token reads it
|
|
31
|
+
back as you.
|
|
32
|
+
|
|
33
|
+
That page also renders the blocks below with the real token substituted in,
|
|
34
|
+
each with a copy button — so the fastest path is: generate, copy, paste.
|
|
35
|
+
|
|
36
|
+
## 2. Connect a client
|
|
37
|
+
|
|
38
|
+
Everything below uses `https://railwatch.rebulk.com/mcp`; substitute your own
|
|
39
|
+
host if you self-host, and `lnt_your_token_here` for the token.
|
|
40
|
+
|
|
41
|
+
### Claude Code
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
claude mcp add railwatch --transport http https://railwatch.rebulk.com/mcp \
|
|
45
|
+
--header "Authorization: Bearer lnt_your_token_here"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Claude Desktop
|
|
49
|
+
|
|
50
|
+
Claude Desktop speaks stdio, so it needs the `mcp-remote` bridge. In
|
|
51
|
+
`claude_desktop_config.json`:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"mcpServers": {
|
|
56
|
+
"railwatch": {
|
|
57
|
+
"command": "npx",
|
|
58
|
+
"args": [
|
|
59
|
+
"-y",
|
|
60
|
+
"mcp-remote",
|
|
61
|
+
"https://railwatch.rebulk.com/mcp",
|
|
62
|
+
"--header",
|
|
63
|
+
"Authorization: Bearer lnt_your_token_here"
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Cursor
|
|
71
|
+
|
|
72
|
+
`.cursor/mcp.json` in the project, or `~/.cursor/mcp.json` for every project:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"mcpServers": {
|
|
77
|
+
"railwatch": {
|
|
78
|
+
"url": "https://railwatch.rebulk.com/mcp",
|
|
79
|
+
"headers": { "Authorization": "Bearer lnt_your_token_here" }
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### VS Code
|
|
86
|
+
|
|
87
|
+
`.vscode/mcp.json` in the workspace:
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"servers": {
|
|
92
|
+
"railwatch": {
|
|
93
|
+
"type": "http",
|
|
94
|
+
"url": "https://railwatch.rebulk.com/mcp",
|
|
95
|
+
"headers": { "Authorization": "Bearer lnt_your_token_here" }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Zed
|
|
102
|
+
|
|
103
|
+
`settings.json`, also through the `mcp-remote` bridge:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"context_servers": {
|
|
108
|
+
"railwatch": {
|
|
109
|
+
"source": "custom",
|
|
110
|
+
"command": "npx",
|
|
111
|
+
"args": [
|
|
112
|
+
"-y",
|
|
113
|
+
"mcp-remote",
|
|
114
|
+
"https://railwatch.rebulk.com/mcp",
|
|
115
|
+
"--header",
|
|
116
|
+
"Authorization: Bearer lnt_your_token_here"
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Check it without a client
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
curl -sS https://railwatch.rebulk.com/mcp \
|
|
127
|
+
-H "Authorization: Bearer lnt_your_token_here" \
|
|
128
|
+
-H "Content-Type: application/json" \
|
|
129
|
+
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
A JSON body listing tools means the token works. A `401` means it doesn't.
|
|
133
|
+
|
|
134
|
+
`GET https://railwatch.rebulk.com/mcp` and
|
|
135
|
+
`GET https://railwatch.rebulk.com/.well-known/mcp.json` describe the server —
|
|
136
|
+
name, version, protocol version, transport, tool and prompt names, and how
|
|
137
|
+
to authenticate — with no token at all, for clients that probe a host before
|
|
138
|
+
they're configured.
|
|
139
|
+
|
|
140
|
+
## 3. Tools
|
|
141
|
+
|
|
142
|
+
Every tool returns JSON as the text body of a single content block. **All
|
|
143
|
+
durations are milliseconds.** Every `window` argument takes `1h`, `6h`,
|
|
144
|
+
`24h`, `7d`, or `30d`, and defaults to `24h`.
|
|
145
|
+
|
|
146
|
+
| Tool | Arguments | Returns |
|
|
147
|
+
|---|---|---|
|
|
148
|
+
| `list_applications` | — | applications, their account, and their environments. Start here — everything else takes the `application_slug` and `environment` this returns. |
|
|
149
|
+
| `list_issues` | `application_slug?`, `environment?`, `status?` (`open`/`resolved`/`ignored`, default `open`), `limit?` | issues with key, title, kind, status, priority, occurrence and affected-user counts, culprit, first/last seen. |
|
|
150
|
+
| `get_issue` | `key` | one issue plus the sample occurrence: exception class, message, stack frames, and the execution it happened inside. |
|
|
151
|
+
| `update_issue` | `key`, `status?`, `priority?`, `assignee_email?`, `agent?` | the updated issue. Writes an activity entry attributed to your user and `agent`. |
|
|
152
|
+
| `add_comment` | `key`, `body`, `agent?` | the created comment, attributed the same way. |
|
|
153
|
+
| `list_slow_routes` | `application_slug`, `environment`, `window?` | the 20 slowest routes by p95, each with `group_hash`, count, errors, `p95_ms`. |
|
|
154
|
+
| `get_route` | `application_slug`, `environment`, `route` or `group_hash`, `window?` | one route's count/errors, p50/p95/p99/max, its slowest individual requests, the slowest queries those requests ran, and each N+1 with a concrete Active Record fix. |
|
|
155
|
+
| `search_requests` | `application_slug`, `environment`, `q?`, `window?`, `limit?` | individual requests. `q` is the dashboard's filter grammar: `method:GET`, `route:/checkout`, `status:500` or `status:5xx`, `deploy:…`, `tenant:…`, `user:…`, `min_ms:250`; bare words match the route name. |
|
|
156
|
+
| `get_execution` | `application_slug`, `environment`, `execution_id` | one execution and its full child timeline — every query, cache read, log line, outgoing request, view render, and exception, each offset in ms from the start. |
|
|
157
|
+
| `explain_query` | `application_slug`, `environment`, `group_hash`, `window?` | the stored query plan for a query group, with the SQL and the sample's duration. `explain` is null unless the app sets `RAILWATCH_CAPTURE_QUERY_EXPLAIN`. `sql` is the normalized shape unless the app also sets `RAILWATCH_CAPTURE_SQL_VALUES`. |
|
|
158
|
+
| `get_profile` | `application_slug`, `environment`, `profile_id?`, `execution_id?`, `limit?` | the hottest frames of a stack profile — self and total samples, each with a percentage. |
|
|
159
|
+
| `search_logs` | `application_slug`, `environment`, `q`, `level?`, `limit?` | matching log lines, each with the `execution_id` to expand with `get_execution`. |
|
|
160
|
+
| `list_tenants` | `application_slug`, `environment`, `window?`, `q?` | your app's own tenants (whatever it passes to `Railwatch.context(tenant:)`) with request, error, job, exception, and user counts. |
|
|
161
|
+
| `recent_deploys` | `application_slug`, `environment` | the 20 most recent deploys with ref, name, time, and link. |
|
|
162
|
+
| `release_health` | `application_slug`, `environment`, `window?` | crash-free session rate, crash-free user rate, and adoption per release. |
|
|
163
|
+
| `list_alerts` | `application_slug?`, `event?`, `status?`, `limit?` | fired alerts: which rule, which issue, which integration, and whether delivery succeeded. |
|
|
164
|
+
|
|
165
|
+
## 4. Prompts
|
|
166
|
+
|
|
167
|
+
Three canned workflows. A prompt is a plan, not an answer: it tells the
|
|
168
|
+
assistant which tools to call in which order and what to do with each
|
|
169
|
+
result, so its first turn is spent working rather than asking you which tool
|
|
170
|
+
exists.
|
|
171
|
+
|
|
172
|
+
| Prompt | Arguments | What it does |
|
|
173
|
+
|---|---|---|
|
|
174
|
+
| `triage_issue` | `key` | Reads the issue and its sample, pulls the execution timeline around the failure, searches the logs for the same failure elsewhere, lines `first_seen_at` up against recent deploys, then reports what breaks, for whom, how often, and the smallest fix. It will comment and set a priority; it is told not to resolve. |
|
|
175
|
+
| `slow_route` | `application_slug`, `environment`, `route`, `window?` | Pulls the route summary, its slow queries and N+1s, the stored plan for each query group, and a stack profile if one exists, then reports the indexes and `includes` to add, ordered by expected saving, quoting measured milliseconds. |
|
|
176
|
+
| `daily_summary` | `application_slug`, `environment`, `window?` | New issues, spiking issues, deploys, release-health movement, the worst routes, and what already alerted — leading with the one thing worth acting on. |
|
|
177
|
+
|
|
178
|
+
In Claude Code these appear as slash commands once the server is connected.
|
|
179
|
+
|
|
180
|
+
## 5. Resources
|
|
181
|
+
|
|
182
|
+
The server also publishes documents an assistant can read without a tool
|
|
183
|
+
call:
|
|
184
|
+
|
|
185
|
+
| URI | Contents |
|
|
186
|
+
|---|---|
|
|
187
|
+
| `railwatch://applications` | Every application and environment the token can see. |
|
|
188
|
+
| `railwatch://applications/<slug>/environments/<name>/summary` | Request and job volume, p95, errors, open issue count, last-seen time, and deploys, over the last 24 hours, with the previous 24 hours alongside for comparison. |
|
|
189
|
+
| `railwatch://docs/<name>` | Railwatch's own documentation — `readme`, `getting-started`, `configuration`, `records`, `testing`, `replacing-sentry`, `troubleshooting`, `faq`, and the rest. An assistant that doesn't know an option can look it up instead of guessing. |
|
|
190
|
+
|
|
191
|
+
## 6. What an assistant can and can't do
|
|
192
|
+
|
|
193
|
+
- **Scope.** A token reaches exactly the accounts its user belongs to.
|
|
194
|
+
Revoke it by regenerating: Settings → Profile → *Regenerate token*
|
|
195
|
+
invalidates the old one immediately.
|
|
196
|
+
- **Writes.** Only three things write: `update_issue`, `add_comment`, and
|
|
197
|
+
the activity entries they create. There is no tool that deletes anything,
|
|
198
|
+
changes billing, or touches your Rails app.
|
|
199
|
+
- **Attribution.** Every write records your user *and* the `agent` name the
|
|
200
|
+
client sent, so "who resolved this" has an honest answer in the UI.
|
|
201
|
+
- **Payloads.** Tools return what the dashboards show, which is what the gem
|
|
202
|
+
shipped. If you don't want request parameters or job arguments leaving
|
|
203
|
+
your app, they never arrive here in the first place — see the redaction
|
|
204
|
+
and opt-in capture settings in
|
|
205
|
+
[`configuration.md`](configuration.md).
|
|
206
|
+
|
|
207
|
+
## 7. Agents working on your app
|
|
208
|
+
|
|
209
|
+
Separately from the MCP server, the gem ships two files for coding agents
|
|
210
|
+
working *in a Rails app that uses Railwatch*:
|
|
211
|
+
|
|
212
|
+
- [`../llms.txt`](../llms.txt) — the [llmstxt.org](https://llmstxt.org)
|
|
213
|
+
index: one paragraph on what Railwatch is, then every document with a
|
|
214
|
+
one-line description.
|
|
215
|
+
- [`../AGENTS.md`](../AGENTS.md) — how to install it, the facade methods,
|
|
216
|
+
the spec matchers, `railwatch:doctor`, and this MCP hookup, in under 120
|
|
217
|
+
lines.
|
|
218
|
+
|
|
219
|
+
Copy either into your own app's repo to give its agent the same context.
|
|
220
|
+
|
|
221
|
+
## See also
|
|
222
|
+
|
|
223
|
+
- [`getting-started.md`](getting-started.md) — install, token, first request.
|
|
224
|
+
- [`self-hosting.md`](self-hosting.md) — pointing the gem, and this endpoint,
|
|
225
|
+
at your own platform.
|
|
226
|
+
- [`troubleshooting.md`](troubleshooting.md) — when something isn't
|
|
227
|
+
reporting.
|