@dipseth/opensearch-logs 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.
Files changed (91) hide show
  1. package/.env.example +14 -0
  2. package/alerts/langfuse-usage.yaml +142 -0
  3. package/alerts/production-incidents.yaml +280 -0
  4. package/alerts/service-health.yaml +98 -0
  5. package/dashboards/langfuse-usage.yaml +57 -0
  6. package/dist/create-dashboards.d.ts +10 -0
  7. package/dist/create-dashboards.js +38 -0
  8. package/dist/create-dashboards.js.map +1 -0
  9. package/dist/interfaces/alert.interfaces.d.ts +323 -0
  10. package/dist/interfaces/alert.interfaces.js +6 -0
  11. package/dist/interfaces/alert.interfaces.js.map +1 -0
  12. package/dist/interfaces/dashboard-gen.interfaces.d.ts +33 -0
  13. package/dist/interfaces/dashboard-gen.interfaces.js +3 -0
  14. package/dist/interfaces/dashboard-gen.interfaces.js.map +1 -0
  15. package/dist/interfaces/interfaces.d.ts +312 -0
  16. package/dist/interfaces/interfaces.js +3 -0
  17. package/dist/interfaces/interfaces.js.map +1 -0
  18. package/dist/interfaces/playbook.interfaces.d.ts +140 -0
  19. package/dist/interfaces/playbook.interfaces.js +3 -0
  20. package/dist/interfaces/playbook.interfaces.js.map +1 -0
  21. package/dist/os-alert.d.ts +17 -0
  22. package/dist/os-alert.js +245 -0
  23. package/dist/os-alert.js.map +1 -0
  24. package/dist/os-dash.d.ts +9 -0
  25. package/dist/os-dash.js +53 -0
  26. package/dist/os-dash.js.map +1 -0
  27. package/dist/os-monitor.d.ts +12 -0
  28. package/dist/os-monitor.js +59 -0
  29. package/dist/os-monitor.js.map +1 -0
  30. package/dist/os-playbook.d.ts +9 -0
  31. package/dist/os-playbook.js +71 -0
  32. package/dist/os-playbook.js.map +1 -0
  33. package/dist/os-search.d.ts +11 -0
  34. package/dist/os-search.js +84 -0
  35. package/dist/os-search.js.map +1 -0
  36. package/dist/repositories/index.d.ts +1 -0
  37. package/dist/repositories/index.js +2 -0
  38. package/dist/repositories/index.js.map +1 -0
  39. package/dist/repositories/opensearch.repository.d.ts +51 -0
  40. package/dist/repositories/opensearch.repository.js +167 -0
  41. package/dist/repositories/opensearch.repository.js.map +1 -0
  42. package/dist/services/alert.service.d.ts +73 -0
  43. package/dist/services/alert.service.js +503 -0
  44. package/dist/services/alert.service.js.map +1 -0
  45. package/dist/services/dashboard-gen.service.d.ts +36 -0
  46. package/dist/services/dashboard-gen.service.js +162 -0
  47. package/dist/services/dashboard-gen.service.js.map +1 -0
  48. package/dist/services/dashboard.service.d.ts +33 -0
  49. package/dist/services/dashboard.service.js +428 -0
  50. package/dist/services/dashboard.service.js.map +1 -0
  51. package/dist/services/gchat.service.d.ts +45 -0
  52. package/dist/services/gchat.service.js +228 -0
  53. package/dist/services/gchat.service.js.map +1 -0
  54. package/dist/services/index.d.ts +8 -0
  55. package/dist/services/index.js +9 -0
  56. package/dist/services/index.js.map +1 -0
  57. package/dist/services/monitor.service.d.ts +18 -0
  58. package/dist/services/monitor.service.js +342 -0
  59. package/dist/services/monitor.service.js.map +1 -0
  60. package/dist/services/panel-layout.d.ts +21 -0
  61. package/dist/services/panel-layout.js +33 -0
  62. package/dist/services/panel-layout.js.map +1 -0
  63. package/dist/services/playbook-dashboard.service.d.ts +19 -0
  64. package/dist/services/playbook-dashboard.service.js +434 -0
  65. package/dist/services/playbook-dashboard.service.js.map +1 -0
  66. package/dist/services/playbook.service.d.ts +13 -0
  67. package/dist/services/playbook.service.js +621 -0
  68. package/dist/services/playbook.service.js.map +1 -0
  69. package/dist/services/search.service.d.ts +30 -0
  70. package/dist/services/search.service.js +885 -0
  71. package/dist/services/search.service.js.map +1 -0
  72. package/dist/utils/cli.d.ts +14 -0
  73. package/dist/utils/cli.js +90 -0
  74. package/dist/utils/cli.js.map +1 -0
  75. package/dist/utils/config.d.ts +20 -0
  76. package/dist/utils/config.js +104 -0
  77. package/dist/utils/config.js.map +1 -0
  78. package/dist/utils/index.d.ts +5 -0
  79. package/dist/utils/index.js +5 -0
  80. package/dist/utils/index.js.map +1 -0
  81. package/dist/utils/service-registry.d.ts +15 -0
  82. package/dist/utils/service-registry.js +56 -0
  83. package/dist/utils/service-registry.js.map +1 -0
  84. package/dist/utils/template.d.ts +18 -0
  85. package/dist/utils/template.js +66 -0
  86. package/dist/utils/template.js.map +1 -0
  87. package/package.json +76 -0
  88. package/playbooks/error-investigation.yaml +45 -0
  89. package/playbooks/incident-triage.yaml +32 -0
  90. package/playbooks/post-deploy-validation.yaml +24 -0
  91. package/playbooks/service-deep-dive.yaml +42 -0
@@ -0,0 +1,503 @@
1
+ /**
2
+ * Alert service — load YAML alert profiles, resolve templates,
3
+ * and CRUD monitors/destinations on OSD.
4
+ */
5
+ import { readFileSync, existsSync } from "node:fs";
6
+ import { dirname, join } from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+ import { parse as parseYaml } from "yaml";
9
+ import { resolveFlat } from "../utils/template.js";
10
+ import { SERVICE_REGISTRY } from "../utils/service-registry.js";
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = dirname(__filename);
13
+ const ALERTS_DIR = join(__dirname, "..", "..", "alerts");
14
+ /** Naming convention: oslog-{profile}-{monitor} */
15
+ function monitorName(profileName, monitorKey) {
16
+ return `oslog-${profileName}-${monitorKey}`;
17
+ }
18
+ export class AlertService {
19
+ repo;
20
+ constructor(repo) {
21
+ this.repo = repo;
22
+ }
23
+ // ── Profile Loading ─────────────────────────────────────────────────
24
+ /** Load and parse an alert profile YAML. */
25
+ loadProfile(profileName) {
26
+ const filePath = join(ALERTS_DIR, `${profileName}.yaml`);
27
+ if (!existsSync(filePath)) {
28
+ throw new Error(`Alert profile not found: ${filePath}`);
29
+ }
30
+ const raw = readFileSync(filePath, "utf-8");
31
+ return parseYaml(raw);
32
+ }
33
+ // ── Template Resolution ─────────────────────────────────────────────
34
+ /**
35
+ * Build flat context from profile thresholds, defaults, and CLI overrides.
36
+ * This context resolves {{thresholds.*}} and {{defaults.*}} expressions.
37
+ */
38
+ buildContext(profile, overrides) {
39
+ const ctx = {
40
+ thresholds: { ...profile.thresholds },
41
+ defaults: { ...profile.defaults },
42
+ };
43
+ if (overrides?.env) {
44
+ ctx.defaults.env = overrides.env;
45
+ }
46
+ if (overrides?.dashboardUrl) {
47
+ ctx.defaults.dashboard_url = overrides.dashboardUrl;
48
+ }
49
+ if (overrides?.service) {
50
+ ctx.defaults.service = overrides.service;
51
+ }
52
+ return ctx;
53
+ }
54
+ /**
55
+ * Resolve all pre-flight templates in a string.
56
+ * {{thresholds.*}}, {{defaults.*}} are resolved.
57
+ * {{ctx.*}} expressions are passed through for OSD Mustache.
58
+ */
59
+ resolveString(value, context) {
60
+ return resolveFlat(value, context);
61
+ }
62
+ // ── Destination Management ──────────────────────────────────────────
63
+ /**
64
+ * Ensure a notification channel exists. Searches by name first; creates if missing.
65
+ * Returns the channel config_id (used as destination_id in monitor actions).
66
+ */
67
+ async ensureNotificationChannel(channelName, webhookUrl) {
68
+ // Search for existing channel by name
69
+ const existing = await this.repo.listNotificationChannels();
70
+ if (existing) {
71
+ const found = existing.config_list.find(c => c.config.name === channelName);
72
+ if (found)
73
+ return found.config_id;
74
+ }
75
+ // Create new notification channel
76
+ const result = await this.repo.createNotificationChannel({
77
+ config_id: channelName,
78
+ config: {
79
+ name: channelName,
80
+ description: `Webhook channel for ${channelName}`,
81
+ config_type: "webhook",
82
+ is_enabled: true,
83
+ webhook: {
84
+ url: webhookUrl,
85
+ header_params: { "Content-Type": "application/json; charset=UTF-8" },
86
+ method: "POST",
87
+ },
88
+ },
89
+ });
90
+ if (!result) {
91
+ throw new Error(`Failed to create notification channel: ${channelName}`);
92
+ }
93
+ return result.config_id;
94
+ }
95
+ // ── Monitor CRUD ────────────────────────────────────────────────────
96
+ /**
97
+ * Build an OSD monitor payload from a profile monitor definition.
98
+ */
99
+ buildMonitorPayload(profileName, monitorKey, monitorDef, destinationId, cardTemplate, context, env) {
100
+ const name = monitorName(profileName, monitorKey);
101
+ const indexPrefix = this.repo.config.indexPrefix ?? "python-services";
102
+ const indexPattern = monitorDef.index_pattern
103
+ ? this.resolveString(monitorDef.index_pattern, context)
104
+ : `${indexPrefix}-${env}-*`;
105
+ const resolvedCondition = this.resolveString(monitorDef.trigger.condition, context);
106
+ const resolvedCardTemplate = this.resolveString(cardTemplate, context);
107
+ const action = {
108
+ name: `notify-${monitorDef.trigger.name}`,
109
+ destination_id: destinationId,
110
+ message_template: { source: resolvedCardTemplate, lang: "mustache" },
111
+ throttle_enabled: !!monitorDef.throttle,
112
+ };
113
+ if (monitorDef.throttle) {
114
+ action.throttle = { value: monitorDef.throttle.value, unit: monitorDef.throttle.unit };
115
+ }
116
+ const searchQuery = this.buildSearchQuery(monitorDef.query, monitorDef.schedule);
117
+ const trigger = {
118
+ name: monitorDef.trigger.name,
119
+ severity: String(monitorDef.trigger.severity),
120
+ condition: { script: { source: resolvedCondition, lang: "painless" } },
121
+ actions: [action],
122
+ };
123
+ const input = {
124
+ search: {
125
+ indices: [indexPattern],
126
+ query: searchQuery,
127
+ },
128
+ };
129
+ return {
130
+ type: "monitor",
131
+ name,
132
+ monitor_type: "query_level_monitor",
133
+ enabled: true,
134
+ schedule: {
135
+ period: {
136
+ interval: monitorDef.schedule.interval,
137
+ unit: monitorDef.schedule.unit,
138
+ },
139
+ },
140
+ inputs: [input],
141
+ triggers: [trigger],
142
+ };
143
+ }
144
+ /**
145
+ * Wrap a user query in a bool+filter with a relative time range
146
+ * so the monitor scans recent data each period.
147
+ * If the query contains an `aggs` key, hoist it to the top level.
148
+ */
149
+ buildSearchQuery(userQuery, schedule) {
150
+ // Extract aggs from top level or from inside bool (YAML allows either)
151
+ let aggs;
152
+ let queryPart;
153
+ if (userQuery.aggs) {
154
+ const { aggs: topAggs, ...rest } = userQuery;
155
+ aggs = topAggs;
156
+ queryPart = rest;
157
+ }
158
+ else if (userQuery.bool &&
159
+ typeof userQuery.bool === "object" &&
160
+ userQuery.bool.aggs) {
161
+ const boolObj = { ...userQuery.bool };
162
+ aggs = boolObj.aggs;
163
+ delete boolObj.aggs;
164
+ queryPart = { bool: boolObj };
165
+ }
166
+ else {
167
+ queryPart = userQuery;
168
+ }
169
+ // Lookback matches the schedule interval so each run covers its full period
170
+ const unitMap = { MINUTES: "m", HOURS: "h", DAYS: "d" };
171
+ const lookback = `${schedule.interval}${unitMap[schedule.unit] ?? "m"}`;
172
+ const result = {
173
+ size: 0,
174
+ query: {
175
+ bool: {
176
+ must: [queryPart],
177
+ filter: [
178
+ { range: { "@timestamp": { gte: `{{period_end}}||-${lookback}`, lte: "{{period_end}}", format: "epoch_millis" } } },
179
+ ],
180
+ },
181
+ },
182
+ };
183
+ if (aggs) {
184
+ result.aggs = aggs;
185
+ }
186
+ return result;
187
+ }
188
+ /**
189
+ * Create all monitors for a profile (or a single monitor if monitorKey is specified).
190
+ * Returns array of [monitorKey, monitorId, created] tuples.
191
+ */
192
+ async createMonitors(profile, webhookUrl, context, env, monitorKey) {
193
+ const destId = await this.ensureNotificationChannel(profile.destination.name, webhookUrl);
194
+ const results = [];
195
+ const entries = monitorKey
196
+ ? [[monitorKey, profile.monitors[monitorKey]]]
197
+ : Object.entries(profile.monitors);
198
+ for (const [key, def] of entries) {
199
+ if (!def) {
200
+ results.push([key, "", false]);
201
+ continue;
202
+ }
203
+ const cardTemplate = profile.card_templates[def.card_template] ?? "";
204
+ const payload = this.buildMonitorPayload(profile.name, key, def, destId, cardTemplate, context, env);
205
+ const existing = await this.findMonitorByName(payload.name);
206
+ if (existing) {
207
+ const updated = await this.repo.updateMonitor(existing, payload);
208
+ results.push([key, existing, !!updated]);
209
+ }
210
+ else {
211
+ const created = await this.repo.createMonitor(payload);
212
+ results.push([key, created?._id ?? "", !!created]);
213
+ }
214
+ }
215
+ return results;
216
+ }
217
+ /**
218
+ * Generate payloads for all monitors without calling the API (dry-run).
219
+ */
220
+ dryRunMonitors(profile, webhookUrl, context, env, monitorKey) {
221
+ const entries = monitorKey
222
+ ? [[monitorKey, profile.monitors[monitorKey]]]
223
+ : Object.entries(profile.monitors);
224
+ const results = [];
225
+ for (const [key, def] of entries) {
226
+ if (!def)
227
+ continue;
228
+ const cardTemplate = profile.card_templates[def.card_template] ?? "";
229
+ const payload = this.buildMonitorPayload(profile.name, key, def, "DRY_RUN_DEST_ID", cardTemplate, context, env);
230
+ results.push([key, payload]);
231
+ }
232
+ return results;
233
+ }
234
+ // ── List / Search ───────────────────────────────────────────────────
235
+ /** Find a monitor ID by exact name. Returns ID or null. */
236
+ async findMonitorByName(name) {
237
+ // Alerting system index only supports match_all; filter in app code
238
+ const result = await this.repo.searchMonitors({
239
+ query: { match_all: {} }, size: 200,
240
+ });
241
+ if (!result)
242
+ return null;
243
+ const hit = result.hits.hits.find(h => h._source.name === name);
244
+ return hit?._id ?? null;
245
+ }
246
+ /**
247
+ * List monitors, optionally filtered by profile prefix.
248
+ */
249
+ async listMonitors(profileName) {
250
+ const result = await this.repo.searchMonitors({
251
+ query: { match_all: {} }, size: 200,
252
+ });
253
+ if (!result)
254
+ return [];
255
+ const prefix = profileName ? `oslog-${profileName}-` : "oslog-";
256
+ return result.hits.hits
257
+ .filter(hit => hit._source.name.startsWith(prefix))
258
+ .map(hit => ({
259
+ id: hit._id,
260
+ name: hit._source.name,
261
+ enabled: hit._source.enabled,
262
+ }));
263
+ }
264
+ // ── Delete ──────────────────────────────────────────────────────────
265
+ /**
266
+ * Delete all monitors for a profile.
267
+ * Returns array of [name, deleted] tuples.
268
+ */
269
+ async deleteMonitors(profileName) {
270
+ const monitors = await this.listMonitors(profileName);
271
+ const results = [];
272
+ for (const mon of monitors) {
273
+ const ok = await this.repo.deleteMonitor(mon.id);
274
+ results.push([mon.name, ok]);
275
+ }
276
+ return results;
277
+ }
278
+ // ── Test / Execute ──────────────────────────────────────────────────
279
+ /**
280
+ * Execute (dry-run) a single monitor by profile + monitor key.
281
+ */
282
+ async executeMonitor(profileName, monitorKey) {
283
+ const name = monitorName(profileName, monitorKey);
284
+ const monitorId = await this.findMonitorByName(name);
285
+ if (!monitorId) {
286
+ throw new Error(`Monitor not found: ${name}`);
287
+ }
288
+ return this.repo.executeMonitor(monitorId);
289
+ }
290
+ // ── Health Report ───────────────────────────────────────────────────
291
+ /**
292
+ * Gather a live production health report by querying OpenSearch.
293
+ * Returns structured data suitable for building a Google Chat card.
294
+ */
295
+ async gatherHealthReport(index, fromDt, toDt, env, _service) {
296
+ const timeFilter = {
297
+ range: { "@timestamp": { gte: fromDt.toISOString(), lte: toDt.toISOString() } },
298
+ };
299
+ const aggs = {};
300
+ // ── Global health-check patterns ───────────────────────────────────
301
+ const TEXT_CHECKS = {
302
+ "HTTP 500s": '"500 Internal Server Error"',
303
+ "HTTP 503s": 'log:"status=503"',
304
+ "Connection Refused": '"Connection refused"',
305
+ "Worker Shutdowns": '"Shutting down"',
306
+ "Worker Startups": '"Application startup complete"',
307
+ "Max Request Limit": '"Maximum request limit"',
308
+ "Playwright Failures": '"Failed to launch browser"',
309
+ "OOM / Memory": 'OOM OR "Cannot allocate memory"',
310
+ };
311
+ for (const [name, q] of Object.entries(TEXT_CHECKS)) {
312
+ const safe = name.replace(/[^a-zA-Z0-9]/g, "_");
313
+ aggs[safe] = {
314
+ filter: { bool: { must: [{ query_string: { query: q } }], filter: [timeFilter] } },
315
+ };
316
+ }
317
+ // ── Per-service 5xx errors ─────────────────────────────────────────
318
+ for (const [alias, info] of SERVICE_REGISTRY) {
319
+ aggs[`svc_5xx_${alias}`] = {
320
+ filter: {
321
+ bool: {
322
+ must: [
323
+ this.serviceFilter(info.logName),
324
+ {
325
+ bool: {
326
+ should: [
327
+ { range: { status_code: { gte: 500 } } },
328
+ { term: { "level.keyword": "ERROR" } },
329
+ { query_string: { query: '"500 Internal Server Error" OR log:"status=503" OR log:"status=502"' } },
330
+ ],
331
+ minimum_should_match: 1,
332
+ },
333
+ },
334
+ ],
335
+ filter: [timeFilter],
336
+ },
337
+ },
338
+ };
339
+ }
340
+ // ── Latency from correlation middleware ─────────────────────────────
341
+ aggs.latency_stats = {
342
+ filter: { bool: { filter: [timeFilter], must: [{ term: { "name.keyword": "common.middleware.correlation" } }] } },
343
+ aggs: { parsed: this.latencyScriptedMetric() },
344
+ };
345
+ // ── Total requests ─────────────────────────────────────────────────
346
+ aggs.total_requests = { filter: { bool: { filter: [timeFilter] } } };
347
+ // ── Error trend (1h buckets) ───────────────────────────────────────
348
+ aggs.error_trend = {
349
+ filter: {
350
+ bool: {
351
+ must: [{
352
+ bool: {
353
+ should: [
354
+ { range: { status_code: { gte: 400 } } },
355
+ { term: { "level.keyword": "ERROR" } },
356
+ ],
357
+ minimum_should_match: 1,
358
+ },
359
+ }],
360
+ filter: [timeFilter],
361
+ },
362
+ },
363
+ aggs: {
364
+ over_time: { date_histogram: { field: "@timestamp", fixed_interval: "1h" } },
365
+ },
366
+ };
367
+ // ── Recent error samples ───────────────────────────────────────────
368
+ aggs.recent_errors = {
369
+ filter: {
370
+ bool: {
371
+ must: [{
372
+ bool: {
373
+ should: [
374
+ { term: { "level.keyword": "ERROR" } },
375
+ { range: { status_code: { gte: 500 } } },
376
+ ],
377
+ minimum_should_match: 1,
378
+ },
379
+ }],
380
+ filter: [timeFilter],
381
+ },
382
+ },
383
+ aggs: {
384
+ samples: {
385
+ top_hits: {
386
+ size: 5,
387
+ sort: [{ "@timestamp": "desc" }],
388
+ _source: ["@timestamp", "log", "service", "level", "message"],
389
+ },
390
+ },
391
+ },
392
+ };
393
+ const result = await this.repo.search(index, { size: 0, aggs });
394
+ const aggData = result.aggregations;
395
+ // ── Extract patterns ───────────────────────────────────────────────
396
+ const patterns = [];
397
+ for (const name of Object.keys(TEXT_CHECKS)) {
398
+ const safe = name.replace(/[^a-zA-Z0-9]/g, "_");
399
+ const count = aggData[safe]?.doc_count ?? 0;
400
+ if (count > 0)
401
+ patterns.push({ name, count });
402
+ }
403
+ patterns.sort((a, b) => b.count - a.count);
404
+ // ── Extract service errors ─────────────────────────────────────────
405
+ const serviceErrors = [];
406
+ for (const [alias, info] of SERVICE_REGISTRY) {
407
+ const count = aggData[`svc_5xx_${alias}`]?.doc_count ?? 0;
408
+ if (count > 0)
409
+ serviceErrors.push({ service: alias, count, description: info.description });
410
+ }
411
+ serviceErrors.sort((a, b) => b.count - a.count);
412
+ // ── Extract latency ────────────────────────────────────────────────
413
+ const latAgg = aggData.latency_stats;
414
+ const latency = latAgg.doc_count > 0
415
+ ? {
416
+ tracked: latAgg.parsed.value.count,
417
+ avg: Math.round(latAgg.parsed.value.avg),
418
+ p50: Math.round(latAgg.parsed.value.p50),
419
+ p95: Math.round(latAgg.parsed.value.p95),
420
+ p99: Math.round(latAgg.parsed.value.p99),
421
+ }
422
+ : null;
423
+ // ── Extract error trend ────────────────────────────────────────────
424
+ const trendAgg = aggData.error_trend;
425
+ const totalErrors = trendAgg.doc_count;
426
+ const errorTrend = trendAgg.over_time.buckets.map(b => ({
427
+ time: b.key_as_string,
428
+ count: b.doc_count,
429
+ }));
430
+ // ── Extract recent errors ──────────────────────────────────────────
431
+ const recentAgg = aggData.recent_errors;
432
+ const recentErrors = recentAgg.samples.hits.hits.map(h => ({
433
+ timestamp: String(h._source["@timestamp"] ?? ""),
434
+ service: String(h._source.service ?? "unknown"),
435
+ message: String(h._source.message ?? h._source.log ?? "").slice(0, 200),
436
+ }));
437
+ // ── Determine status ───────────────────────────────────────────────
438
+ const totalLogs = aggData.total_requests.doc_count;
439
+ let status = "HEALTHY";
440
+ if (patterns.length > 3 || totalErrors > 1000 || serviceErrors.some(s => s.count > 500)) {
441
+ status = "DEGRADED";
442
+ }
443
+ else if (patterns.length > 0 || totalErrors > 100) {
444
+ status = "WARNING";
445
+ }
446
+ // ── Dashboard URLs ─────────────────────────────────────────────────
447
+ const host = this.repo.config.host;
448
+ const tenant = this.repo.config.tenant ?? "global";
449
+ const timeG = `_g=(time:(from:'${fromDt.toISOString()}',to:'${toDt.toISOString()}'))`;
450
+ const dashboardUrl = `https://${host}/app/dashboards?security_tenant=${tenant}#/view/python-services-production-health-v2?${timeG}`;
451
+ const discoverUrl = `https://${host}/app/discover?security_tenant=${tenant}#/?${timeG}&_a=(query:(language:kuery,query:'level:ERROR'))`;
452
+ return {
453
+ env,
454
+ periodStart: fromDt.toISOString(),
455
+ periodEnd: toDt.toISOString(),
456
+ totalLogs,
457
+ totalErrors,
458
+ status,
459
+ patterns,
460
+ serviceErrors,
461
+ latency,
462
+ errorTrend,
463
+ recentErrors,
464
+ dashboardUrl,
465
+ discoverUrl,
466
+ };
467
+ }
468
+ // ── Private Query Helpers ───────────────────────────────────────────
469
+ serviceFilter(svcName) {
470
+ return {
471
+ bool: {
472
+ should: [
473
+ { term: { "service.keyword": svcName } },
474
+ { match_phrase: { log: svcName } },
475
+ ],
476
+ minimum_should_match: 1,
477
+ },
478
+ };
479
+ }
480
+ latencyScriptedMetric() {
481
+ return {
482
+ scripted_metric: {
483
+ init_script: "state.values = []",
484
+ map_script: String.raw `def msg = doc["message.keyword"].value; if (msg != null) { def m = /\d+(?=ms)/.matcher(msg); if (m.find()) { state.values.add(Integer.parseInt(m.group())); } }`,
485
+ combine_script: "return state.values",
486
+ reduce_script: [
487
+ 'List all = new ArrayList();',
488
+ 'for (s in states) { if (s instanceof List) { all.addAll(s); } }',
489
+ 'Map result = new HashMap();',
490
+ 'if (all.isEmpty()) { result.put("count", 0); result.put("avg", 0); result.put("p50", 0); result.put("p95", 0); result.put("p99", 0); return result; }',
491
+ 'Collections.sort(all); long sum = 0; for (def v : all) { sum += v; }',
492
+ 'int sz = all.size();',
493
+ 'int p50i = sz / 2; int p95i = sz * 95 / 100; if (p95i >= sz) { p95i = sz - 1; }',
494
+ 'int p99i = sz * 99 / 100; if (p99i >= sz) { p99i = sz - 1; }',
495
+ 'result.put("count", sz); result.put("avg", sum / sz);',
496
+ 'result.put("p50", all.get(p50i)); result.put("p95", all.get(p95i)); result.put("p99", all.get(p99i));',
497
+ 'return result;',
498
+ ].join(" "),
499
+ },
500
+ };
501
+ }
502
+ }
503
+ //# sourceMappingURL=alert.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alert.service.js","sourceRoot":"","sources":["../../src/services/alert.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * YAML-driven dashboard generator — creates OSD saved dashboards
3
+ * from a declarative config file. No code required.
4
+ *
5
+ * Supports: header markdown, metric tiles, line charts, markdown sections.
6
+ * Layout is automatic: metrics fill rows of 6, charts pair half-width,
7
+ * full-width charts get their own row.
8
+ */
9
+ import type { OpenSearchRepository } from "../repositories/opensearch.repository.js";
10
+ import type { SavedObjectRef, DashboardPanel, VisDef } from "../interfaces/interfaces.js";
11
+ import type { DashboardConfig } from "../interfaces/dashboard-gen.interfaces.js";
12
+ export declare class DashboardGenService {
13
+ private repo;
14
+ constructor(repo: OpenSearchRepository);
15
+ /** Load and parse a dashboard config YAML. */
16
+ loadConfig(configPath: string): DashboardConfig;
17
+ /**
18
+ * Build all visualizations and the dashboard layout from config.
19
+ * Returns the vis list, panel layout, and references — ready for upsert.
20
+ */
21
+ build(config: DashboardConfig): {
22
+ vizList: VisDef[];
23
+ panels: DashboardPanel[];
24
+ refs: SavedObjectRef[];
25
+ dashId: string;
26
+ };
27
+ /** Create or update the dashboard on OSD. */
28
+ create(config: DashboardConfig): Promise<{
29
+ url: string;
30
+ vizOk: number;
31
+ vizTotal: number;
32
+ dashOk: boolean;
33
+ }>;
34
+ /** Delete a dashboard and its visualizations. */
35
+ delete(config: DashboardConfig): Promise<number>;
36
+ }