@pranshulsoni/flowwatch 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.
- package/README.md +442 -0
- package/dist/ai/groqInsightService.d.ts +39 -0
- package/dist/ai/groqInsightService.js +230 -0
- package/dist/createFlowwatch.d.ts +17 -0
- package/dist/createFlowwatch.js +90 -0
- package/dist/dashboard/routes/dashboardResponse.d.ts +204 -0
- package/dist/dashboard/routes/dashboardResponse.js +248 -0
- package/dist/dashboard/routes/router.d.ts +13 -0
- package/dist/dashboard/routes/router.js +708 -0
- package/dist/dashboard/static/dashboard.html +6061 -0
- package/dist/engine/background/queues/workflowQueue.d.ts +6 -0
- package/dist/engine/background/queues/workflowQueue.js +14 -0
- package/dist/engine/background/workers/workflowWorker.d.ts +15 -0
- package/dist/engine/background/workers/workflowWorker.js +98 -0
- package/dist/engine/errors/errorEngine.d.ts +27 -0
- package/dist/engine/errors/errorEngine.js +115 -0
- package/dist/engine/flags/evaluateFlag.d.ts +3 -0
- package/dist/engine/flags/evaluateFlag.js +50 -0
- package/dist/engine/flags/flagEngine.d.ts +9 -0
- package/dist/engine/flags/flagEngine.js +52 -0
- package/dist/engine/flags/hashRollout.d.ts +1 -0
- package/dist/engine/flags/hashRollout.js +9 -0
- package/dist/engine/flags/types.d.ts +7 -0
- package/dist/engine/flags/types.js +1 -0
- package/dist/engine/trace/traceEngine.d.ts +26 -0
- package/dist/engine/trace/traceEngine.js +76 -0
- package/dist/engine/workflows/types.d.ts +28 -0
- package/dist/engine/workflows/types.js +1 -0
- package/dist/engine/workflows/workflowEngine.d.ts +15 -0
- package/dist/engine/workflows/workflowEngine.js +112 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +3 -0
- package/dist/persistence/cache/redisClient.d.ts +2 -0
- package/dist/persistence/cache/redisClient.js +4 -0
- package/dist/persistence/db/postgres.d.ts +3 -0
- package/dist/persistence/db/postgres.js +4 -0
- package/dist/persistence/migrations/migrationRunner.d.ts +3 -0
- package/dist/persistence/migrations/migrationRunner.js +46 -0
- package/dist/persistence/migrations/migrations.d.ts +5 -0
- package/dist/persistence/migrations/migrations.js +191 -0
- package/dist/persistence/repositories/errors/errorRepository.d.ts +38 -0
- package/dist/persistence/repositories/errors/errorRepository.js +63 -0
- package/dist/persistence/repositories/flags/flagRepository.d.ts +72 -0
- package/dist/persistence/repositories/flags/flagRepository.js +245 -0
- package/dist/persistence/repositories/traces/traceRepository.d.ts +64 -0
- package/dist/persistence/repositories/traces/traceRepository.js +110 -0
- package/dist/persistence/repositories/workflows/workflowRepository.d.ts +93 -0
- package/dist/persistence/repositories/workflows/workflowRepository.js +260 -0
- package/dist/persistence/transaction.d.ts +2 -0
- package/dist/persistence/transaction.js +16 -0
- package/dist/runtime/config/normalizeConfig.d.ts +2 -0
- package/dist/runtime/config/normalizeConfig.js +46 -0
- package/dist/runtime/config/validationConfig.d.ts +2 -0
- package/dist/runtime/config/validationConfig.js +119 -0
- package/dist/runtime/health/healthService.d.ts +30 -0
- package/dist/runtime/health/healthService.js +54 -0
- package/dist/runtime/tracing/traceContext.d.ts +12 -0
- package/dist/runtime/tracing/traceContext.js +28 -0
- package/dist/runtime/tracing/tracingMiddleware.d.ts +3 -0
- package/dist/runtime/tracing/tracingMiddleware.js +46 -0
- package/dist/search/elasticsearch/client.d.ts +2 -0
- package/dist/search/elasticsearch/client.js +4 -0
- package/dist/search/elasticsearch/indexSetup.d.ts +3 -0
- package/dist/search/elasticsearch/indexSetup.js +43 -0
- package/dist/search/elasticsearch/indexer.d.ts +9 -0
- package/dist/search/elasticsearch/indexer.js +86 -0
- package/dist/search/elasticsearch/mappingChecker.d.ts +2 -0
- package/dist/search/elasticsearch/mappingChecker.js +28 -0
- package/dist/types/index.d.ts +48 -0
- package/dist/types/index.js +1 -0
- package/dist/utils/flowwatchEnvStore.d.ts +27 -0
- package/dist/utils/flowwatchEnvStore.js +145 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
# FlowWatch
|
|
2
|
+
|
|
3
|
+
**The world's first npm package that gives you durable workflows, feature flags, request tracing, and error reporting — all in one, completely free, and running entirely inside your own Express app.**
|
|
4
|
+
|
|
5
|
+
No SaaS. No monthly bill. No third-party cloud. Your Postgres, your Redis, your data.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Why I built this](#why-i-built-this) ← skip this if you just want the code
|
|
12
|
+
- [What you get with one install](#what-you-get-with-one-install)
|
|
13
|
+
- [Getting started](#getting-started)
|
|
14
|
+
- [Durable Workflows](#durable-workflows)
|
|
15
|
+
- [Feature Flags](#feature-flags)
|
|
16
|
+
- [Request Tracing](#request-tracing)
|
|
17
|
+
- [Error Reporting](#error-reporting)
|
|
18
|
+
- [AI Insights and Chat](#ai-insights-and-chat)
|
|
19
|
+
- [Infrastructure](#infrastructure)
|
|
20
|
+
- [The Dashboard](#the-dashboard)
|
|
21
|
+
- [Quick Reference](#quick-reference)
|
|
22
|
+
- [Database Schema](#database-schema)
|
|
23
|
+
- [License](#license)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Why I built this
|
|
28
|
+
|
|
29
|
+
When I was first learning backend development, I thought building an API was simple. You write an Express route, connect to a database, query some data, and return a JSON response. It felt clean, fast, and empowering.
|
|
30
|
+
|
|
31
|
+
Then, my first real-world project went live.
|
|
32
|
+
|
|
33
|
+
Within weeks, marketing wanted to hide new checkout pages behind a feature flag. The product manager wanted a complex user-onboarding sequence that sent emails, charged cards, and created database records — all guaranteed never to fail midway. Users started complaining about occasional timeouts, and I spent hours staring at thousands of lines of scrambled console logs.
|
|
34
|
+
|
|
35
|
+
To solve these basic production problems, I was forced to stitch together a monster of external SaaS tools:
|
|
36
|
+
1. **LaunchDarkly** (or Split) for Feature Flags ($$$)
|
|
37
|
+
2. **Sentry** (or Rollbar) for Error Tracking ($$)
|
|
38
|
+
3. **Datadog** (or Jaeger) for Distributed Tracing ($$$$)
|
|
39
|
+
4. **Temporal** (or BullMQ with custom state machines) for Durable Workflows
|
|
40
|
+
|
|
41
|
+
Suddenly, I wasn't just a backend developer writing code; I was a systems integrator managing five different SDKs, logging into five different dashboards, paying five monthly subscriptions, and writing hundreds of lines of glue code. Worst of all, **none of these tools talked to each other**. My Sentry error had no idea about the Temporal workflow step that failed, and my Datadog traces didn't show which LaunchDarkly feature flags were enabled.
|
|
42
|
+
|
|
43
|
+
**FlowWatch is the tool I always wished I had.** It embeds all four pillars of backend operations directly into your Express application as a single npm package. It uses the infrastructure you already have (Postgres, Redis, Elasticsearch) and serves a beautiful, unified admin dashboard directly from your app.
|
|
44
|
+
|
|
45
|
+
And because all your operations data lives in the same database, we added **Groq-powered AI insights and support chat** that can correlate logs, flags, errors, and traces to diagnose your bugs in seconds.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## What you get with one install
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npm install @pranshulsoni/flowwatch
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
- **Durable Workflows** — define multi-step processes that survive server crashes and retry failed steps automatically
|
|
56
|
+
- **Feature Flags** — toggle features and do percentage rollouts from a dashboard, no redeploys needed
|
|
57
|
+
- **Request Tracing** — see exactly what every request did, how long each part took, and which parts were slow
|
|
58
|
+
- **Error Reporting** — capture, group, and search errors with full stack traces and context
|
|
59
|
+
- **AI Diagnostics** — connect a Groq API key and get automated incident analysis and a chat interface that knows your actual data
|
|
60
|
+
- **Built-in Dashboard** — a 10-page admin UI served directly from your Express app at whatever path you choose
|
|
61
|
+
|
|
62
|
+
Everything stores in your own Postgres database. Redis is optional (but recommended). Elasticsearch is optional. The Groq API key is optional. Postgres is the only hard requirement.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Getting started
|
|
67
|
+
|
|
68
|
+
### Minimum setup
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import express from "express";
|
|
72
|
+
import { createFlowwatch } from "@pranshulsoni/flowwatch";
|
|
73
|
+
|
|
74
|
+
const app = express();
|
|
75
|
+
app.use(express.json());
|
|
76
|
+
|
|
77
|
+
const fw = await createFlowwatch({
|
|
78
|
+
db: {
|
|
79
|
+
connectionString: process.env.DATABASE_URL
|
|
80
|
+
},
|
|
81
|
+
migrations: {
|
|
82
|
+
autoRun: true
|
|
83
|
+
},
|
|
84
|
+
runtime: {
|
|
85
|
+
serviceName: "my-api",
|
|
86
|
+
environment: "production"
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
app.use(fw.requestTracer); // goes first
|
|
91
|
+
app.use("/ops", fw.dashboard);
|
|
92
|
+
|
|
93
|
+
// your routes go here
|
|
94
|
+
|
|
95
|
+
app.use(fw.errorHandler); // goes last
|
|
96
|
+
|
|
97
|
+
app.listen(3000);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Visit `http://localhost:3000/ops` and the dashboard is live.
|
|
101
|
+
|
|
102
|
+
### Full setup with Redis and Elasticsearch
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
const fw = await createFlowwatch({
|
|
106
|
+
db: {
|
|
107
|
+
connectionString: process.env.DATABASE_URL
|
|
108
|
+
},
|
|
109
|
+
redis: {
|
|
110
|
+
url: process.env.REDIS_URL
|
|
111
|
+
},
|
|
112
|
+
elasticsearch: {
|
|
113
|
+
node: process.env.ELASTICSEARCH_URL
|
|
114
|
+
},
|
|
115
|
+
migrations: {
|
|
116
|
+
autoRun: true
|
|
117
|
+
},
|
|
118
|
+
runtime: {
|
|
119
|
+
serviceName: "my-api",
|
|
120
|
+
environment: "production"
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Durable Workflows
|
|
128
|
+
|
|
129
|
+
### The problem
|
|
130
|
+
|
|
131
|
+
You have a checkout flow. Charge card → deduct inventory → send email → generate invoice. You write it as four sequential awaits in a route handler. It works in development. In production, the email server goes down between step 2 and step 3. The card was charged, inventory was deducted, but the process died halfway.
|
|
132
|
+
|
|
133
|
+
Now you have inconsistent data and no visibility into what happened.
|
|
134
|
+
|
|
135
|
+
### Without FlowWatch
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
app.post("/checkout", async (req, res) => {
|
|
139
|
+
try {
|
|
140
|
+
await chargeCard(req.body);
|
|
141
|
+
await deductInventory(req.body); // server crashes here
|
|
142
|
+
await sendEmail(req.body); // never runs
|
|
143
|
+
await generateInvoice(req.body);
|
|
144
|
+
res.json({ ok: true });
|
|
145
|
+
} catch (err) {
|
|
146
|
+
// what do you roll back? what already ran?
|
|
147
|
+
res.status(500).json({ error: "something failed" });
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### With FlowWatch
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
fw.workflow("checkout", [
|
|
156
|
+
{ name: "charge-card", run: async (input) => chargeCard(input), maxRetries: 3 },
|
|
157
|
+
{ name: "deduct-inventory", run: async (input) => deductInventory(input), maxRetries: 2 },
|
|
158
|
+
{ name: "send-email", run: async (input) => sendEmail(input), maxRetries: 5 },
|
|
159
|
+
{ name: "generate-invoice", run: async (input) => generateInvoice(input), maxRetries: 2 }
|
|
160
|
+
]);
|
|
161
|
+
|
|
162
|
+
app.post("/checkout", async (req, res) => {
|
|
163
|
+
const { executionId } = await fw.trigger("checkout", req.body);
|
|
164
|
+
res.json({ executionId });
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Each step's result is saved to Postgres immediately after it completes. If the server crashes on step 2, the next time it starts up the workflow engine picks up the execution and resumes from step 2. No double charges. No lost orders. No cron jobs.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Feature Flags
|
|
173
|
+
|
|
174
|
+
### The problem
|
|
175
|
+
|
|
176
|
+
You want to test a new feature with 10% of your users. You hardcode an env variable — now toggling it requires a redeploy. You move it to the database — now every request hits the DB just to read a boolean. You add Redis caching — now you have cache invalidation bugs.
|
|
177
|
+
|
|
178
|
+
### Without FlowWatch
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
// requires a redeploy to change anything
|
|
182
|
+
if (process.env.NEW_SEARCH === "true") {
|
|
183
|
+
return runNewSearch(query);
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### With FlowWatch
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
const useNewSearch = await fw.flag("new-search-v2", {
|
|
191
|
+
userId: req.user.id,
|
|
192
|
+
email: req.user.email,
|
|
193
|
+
plan: req.user.plan
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
if (useNewSearch) return runNewSearch(req.query.q);
|
|
197
|
+
return runOldSearch(req.query.q);
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Toggle flags, adjust rollout percentages, and define targeting rules from the dashboard — no redeploys needed. Evaluations use Redis caching with a 60-second TTL and consistent SHA-256 hashing so the same user always gets the same result.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Request Tracing
|
|
205
|
+
|
|
206
|
+
### The problem
|
|
207
|
+
|
|
208
|
+
An endpoint is slow. You open your terminal and see 150 log lines from 30 concurrent requests all mixed together. You have no idea which log line belongs to which request or which database call caused the slowdown.
|
|
209
|
+
|
|
210
|
+
### Without FlowWatch
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
// passing requestId through every function in the codebase
|
|
214
|
+
async function getUser(id: number, requestId: string) {
|
|
215
|
+
console.log(`[${requestId}] fetching user ${id}`);
|
|
216
|
+
return db.query("SELECT * FROM users WHERE id = $1", [id]);
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### With FlowWatch
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
app.use(fw.requestTracer);
|
|
224
|
+
|
|
225
|
+
app.get("/api/dashboard", async (req, res) => {
|
|
226
|
+
const user = await fw.trace("fetch-user", "database", () =>
|
|
227
|
+
db.query("SELECT * FROM users WHERE id = $1", [req.user.id])
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
const rates = await fw.trace("fetch-shipping-api", "http", () =>
|
|
231
|
+
axios.get("https://api.shipping.com/rates")
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
res.json({ user, rates });
|
|
235
|
+
});
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
FlowWatch uses `AsyncLocalStorage` to carry trace context automatically through every async operation. In the dashboard you get an interactive trace graph:
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
GET /api/dashboard (4800ms)
|
|
242
|
+
├── fetch-user database 42ms
|
|
243
|
+
└── fetch-shipping-api http 4720ms ← there's your problem
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Error Reporting
|
|
249
|
+
|
|
250
|
+
### The problem
|
|
251
|
+
|
|
252
|
+
Something crashes in production. pm2 restarts the server. The stack trace is gone. A user emails support. The same database timeout fires 3,000 times and fills your log file. You have no context about what request or workflow step triggered it.
|
|
253
|
+
|
|
254
|
+
### Without FlowWatch
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
app.use((err, req, res, next) => {
|
|
258
|
+
console.error(err.stack); // gets lost or floods the log file
|
|
259
|
+
res.status(500).json({ error: "Internal server error" });
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### With FlowWatch
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
// automatically catches all unhandled errors — register last
|
|
267
|
+
app.use(fw.errorHandler);
|
|
268
|
+
|
|
269
|
+
// or capture specific errors manually
|
|
270
|
+
try {
|
|
271
|
+
await processPayment(data);
|
|
272
|
+
} catch (err) {
|
|
273
|
+
await fw.captureError(err, {
|
|
274
|
+
source: "payment_processor",
|
|
275
|
+
level: "fatal",
|
|
276
|
+
category: "dependency"
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
FlowWatch fingerprints each error using SHA-256 so identical errors are grouped with a frequency count instead of thousands of duplicates. Each error links back to the exact request trace where it happened.
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## AI Insights and Chat
|
|
286
|
+
|
|
287
|
+
Because FlowWatch holds all four pillars of observability in the same Postgres database, it has a complete picture of your application's state.
|
|
288
|
+
|
|
289
|
+
Connect a **Groq API key** in the Settings page and you get two features:
|
|
290
|
+
|
|
291
|
+
**AI Insights** — one click pulls recent errors, failing workflows, toggled feature flags, and infrastructure health, then returns a structured diagnosis. It can say things like: *"database errors spiked 4 minutes after feature flag 'new-billing-v2' was rolled out to 50%, suggesting the new code path is hitting an unindexed column."*
|
|
292
|
+
|
|
293
|
+
**Ask AI** — a full chat interface where you can ask in plain English:
|
|
294
|
+
- "Which workflow has the most failures this week?"
|
|
295
|
+
- "What's in the stack trace for the checkout error from an hour ago?"
|
|
296
|
+
- "List the feature flags that were toggled today"
|
|
297
|
+
|
|
298
|
+
Both features are optional. Everything else works without a Groq key.
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## Infrastructure
|
|
303
|
+
|
|
304
|
+
### Version requirements
|
|
305
|
+
|
|
306
|
+
| Service | Minimum Version | Notes |
|
|
307
|
+
| :--- | :--- | :--- |
|
|
308
|
+
| Postgres | Any modern version (v11+) | No version-specific features used |
|
|
309
|
+
| Redis | **v5+** for workflow queues | Older Redis disables workflows but everything else still works |
|
|
310
|
+
| Elasticsearch | **v8.x** | Built against the v8 API — v7 is not supported |
|
|
311
|
+
|
|
312
|
+
### Graceful degradation
|
|
313
|
+
|
|
314
|
+
| Service | Required | What breaks without it |
|
|
315
|
+
| :--- | :--- | :--- |
|
|
316
|
+
| Postgres | **Yes** | Nothing works without it |
|
|
317
|
+
| Redis | No | Workflow queues are disabled. Flag evaluations hit Postgres directly |
|
|
318
|
+
| Elasticsearch | No | Search falls back to Postgres queries |
|
|
319
|
+
| Groq API key | No | AI Insights and Ask AI are locked |
|
|
320
|
+
|
|
321
|
+
### Option 1 — Bring your own URLs
|
|
322
|
+
|
|
323
|
+
```ts
|
|
324
|
+
const fw = await createFlowwatch({
|
|
325
|
+
db: { connectionString: "postgresql://user:password@your-host:5432/dbname" },
|
|
326
|
+
redis: { url: "redis://your-redis-host:6379" },
|
|
327
|
+
elasticsearch: { node: "https://your-es-host:9200" }
|
|
328
|
+
});
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Option 2 — Spin up locally with Docker Compose
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
docker-compose up -d
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Starts Postgres 16, Redis 7, and Elasticsearch 8.13 locally, then connect with:
|
|
338
|
+
|
|
339
|
+
```ts
|
|
340
|
+
const fw = await createFlowwatch({
|
|
341
|
+
db: { connectionString: "postgresql://postgres:postgres@localhost:5432/flowwatch" },
|
|
342
|
+
redis: { url: "redis://localhost:6379" },
|
|
343
|
+
elasticsearch: { node: "http://localhost:9200" }
|
|
344
|
+
});
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## The Dashboard
|
|
350
|
+
|
|
351
|
+
Once mounted, the dashboard is a 10-page single-page application served directly by your Express router — no React, no build step, no CDN.
|
|
352
|
+
|
|
353
|
+
| Page | What it shows |
|
|
354
|
+
| :--- | :--- |
|
|
355
|
+
| Overview | Summary metrics, recent executions, recent errors, infrastructure health |
|
|
356
|
+
| Workflows | Registered workflow definitions with step counts |
|
|
357
|
+
| Executions | Every workflow run with status, step timeline, input/output |
|
|
358
|
+
| Feature Flags | All flags with toggle switches, rollout percentage bars, rule counts |
|
|
359
|
+
| Errors | Error list with grouping, frequency, category filters, and full-text search |
|
|
360
|
+
| Traces | Interactive SVG trace graph, span inspector, filterable trace table |
|
|
361
|
+
| AI Insights | Automated diagnosis panel (requires Groq key) |
|
|
362
|
+
| Ask AI | Full chat interface with conversation history (requires Groq key) |
|
|
363
|
+
| Health | Live health cards for Postgres, Redis, Elasticsearch |
|
|
364
|
+
| Settings | Environment name, Groq API key, model selection |
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## Quick Reference
|
|
369
|
+
|
|
370
|
+
```ts
|
|
371
|
+
// Factory — call once at startup
|
|
372
|
+
const fw = await createFlowwatch(config);
|
|
373
|
+
|
|
374
|
+
// Middleware
|
|
375
|
+
app.use(fw.requestTracer); // mount first
|
|
376
|
+
app.use(fw.errorHandler); // mount last
|
|
377
|
+
|
|
378
|
+
// Dashboard
|
|
379
|
+
app.use("/ops", fw.dashboard);
|
|
380
|
+
|
|
381
|
+
// Workflows
|
|
382
|
+
fw.workflow(name, steps[]);
|
|
383
|
+
await fw.trigger(name, input?); // returns { executionId }
|
|
384
|
+
|
|
385
|
+
// Feature flags
|
|
386
|
+
await fw.flag(key, context?); // returns boolean
|
|
387
|
+
|
|
388
|
+
// Tracing
|
|
389
|
+
await fw.trace(name, type, fn, metadata?);
|
|
390
|
+
|
|
391
|
+
// Error capture
|
|
392
|
+
await fw.captureError(error, options?);
|
|
393
|
+
|
|
394
|
+
// Context helpers (usable anywhere in async call chain)
|
|
395
|
+
getCurrentTraceId();
|
|
396
|
+
getCurrentSpanId();
|
|
397
|
+
getCurrentClientIp();
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## Database Schema
|
|
403
|
+
|
|
404
|
+
When you set `migrations: { autoRun: true }`, FlowWatch creates these tables automatically. All table names are prefixed with `flowwatch_` so they never conflict with your own tables.
|
|
405
|
+
|
|
406
|
+
### Workflows
|
|
407
|
+
|
|
408
|
+
```
|
|
409
|
+
flowwatch_workflows — id, name, version, timestamps
|
|
410
|
+
flowwatch_workflow_steps — id, workflow_id, step_index, name, max_retries
|
|
411
|
+
flowwatch_workflow_executions — id, workflow_id, status, input, output, error, timestamps
|
|
412
|
+
flowwatch_workflow_step_executions — id, execution_id, step_index, status, input, output, attempt_count, next_retry_at
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### Feature Flags
|
|
416
|
+
|
|
417
|
+
```
|
|
418
|
+
flowwatch_feature_flags — id, key (unique), enabled, rollout_percentage, timestamps
|
|
419
|
+
flowwatch_feature_flag_rules — id, flag_id, attribute, operator, value, enabled
|
|
420
|
+
flowwatch_feature_flag_audit_logs — id, flag_id, action, before, after, changed_by, created_at
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Traces and Errors
|
|
424
|
+
|
|
425
|
+
```
|
|
426
|
+
flowwatch_request_traces — id, method, path, status_code, duration_ms, ip, user_agent, metadata
|
|
427
|
+
flowwatch_trace_spans — id, trace_id, parent_span_id (self-ref), name, type, status, duration_ms
|
|
428
|
+
flowwatch_errors — id, trace_id, span_id, category, level, message, stack, fingerprint (SHA-256)
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### Elasticsearch Indices (optional)
|
|
432
|
+
|
|
433
|
+
| Index | Contents |
|
|
434
|
+
| :--- | :--- |
|
|
435
|
+
| `flowwatch_errors` | All captured errors, mirrored from Postgres for full-text search |
|
|
436
|
+
| `flowwatch_trace_spans` | All trace spans, mirrored from Postgres for fast filtering |
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
## License
|
|
441
|
+
|
|
442
|
+
ISC — free to use, modify, and distribute.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface FlowwatchAiInsightContext {
|
|
2
|
+
serviceName: string;
|
|
3
|
+
environment: string;
|
|
4
|
+
generatedAt: string;
|
|
5
|
+
workflows: unknown[];
|
|
6
|
+
executions: unknown[];
|
|
7
|
+
errors: unknown[];
|
|
8
|
+
traces: unknown[];
|
|
9
|
+
flags: unknown[];
|
|
10
|
+
health: unknown[];
|
|
11
|
+
}
|
|
12
|
+
export interface FlowwatchAiInsight {
|
|
13
|
+
summary: string;
|
|
14
|
+
likelyCause: string;
|
|
15
|
+
impact: string;
|
|
16
|
+
evidence: string[];
|
|
17
|
+
recommendedActions: string[];
|
|
18
|
+
confidence: number;
|
|
19
|
+
sourceCounts: {
|
|
20
|
+
workflows: number;
|
|
21
|
+
executions: number;
|
|
22
|
+
errors: number;
|
|
23
|
+
traces: number;
|
|
24
|
+
flags: number;
|
|
25
|
+
health: number;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export interface GroqModelOption {
|
|
29
|
+
id: string;
|
|
30
|
+
ownedBy?: string;
|
|
31
|
+
}
|
|
32
|
+
export declare function isServerObservabilityQuestion(message: string): boolean;
|
|
33
|
+
export declare function outOfScopeFlowwatchResponse(): string;
|
|
34
|
+
export declare function listGroqModels(): Promise<GroqModelOption[]>;
|
|
35
|
+
export declare function generateGroqInsight(context: FlowwatchAiInsightContext, model?: string): Promise<FlowwatchAiInsight>;
|
|
36
|
+
export declare function askGroqAi(context: FlowwatchAiInsightContext, message: string, history: Array<{
|
|
37
|
+
role: string;
|
|
38
|
+
content: string;
|
|
39
|
+
}>, model?: string): Promise<string>;
|