@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,71 @@
1
+ /**
2
+ * CLI entry point — DAG-based playbook runner for OpenSearch queries.
3
+ *
4
+ * Usage:
5
+ * node dist/os-playbook.js --playbook incident-triage --hours 1
6
+ * node dist/os-playbook.js --playbook service-deep-dive --service deal_structure --hours 2
7
+ * node dist/os-playbook.js --playbook post-deploy-validation --json
8
+ */
9
+ import { loadConfig, resolveIndex, parseTimeRange, parseArgs } from "./utils/index.js";
10
+ import { createOpenSearchRepository } from "./repositories/index.js";
11
+ import { loadPlaybook, runPlaybook, renderResults } from "./services/playbook.service.js";
12
+ import { PlaybookDashboardService } from "./services/playbook-dashboard.service.js";
13
+ async function main() {
14
+ const args = parseArgs({
15
+ playbook: { short: "p", type: "string", required: true },
16
+ env: { short: "e", type: "string", default: "production", choices: ["production", "staging"] },
17
+ hours: { short: "h", type: "number", default: 1 },
18
+ service: { short: "s", type: "string" },
19
+ limit: { short: "n", type: "number", default: 20 },
20
+ concurrency: { short: "c", type: "number", default: 4 },
21
+ json: { type: "boolean" },
22
+ dashboard: { short: "d", type: "boolean" },
23
+ });
24
+ const playbook = loadPlaybook(args.playbook);
25
+ const config = loadConfig();
26
+ const repo = createOpenSearchRepository(config);
27
+ const [fromDt, toDt] = parseTimeRange({ hours: args.hours });
28
+ const index = resolveIndex(args.env, fromDt, toDt);
29
+ // CLI args override playbook defaults
30
+ const defaults = {
31
+ ...playbook.defaults,
32
+ env: args.env,
33
+ ...(args.hours !== 1 && { hours: args.hours }),
34
+ ...(args.service && { service: args.service }),
35
+ ...(args.limit !== 20 && { limit: args.limit }),
36
+ };
37
+ const ctx = {
38
+ results: new Map(),
39
+ index,
40
+ fromDt,
41
+ toDt,
42
+ defaults,
43
+ };
44
+ process.stderr.write(`\n Running playbook: ${playbook.name}\n`);
45
+ process.stderr.write(` Steps: ${Object.keys(playbook.steps).length}\n`);
46
+ process.stderr.write(` Index: ${index}\n`);
47
+ process.stderr.write(` Window: ${fromDt.toISOString()} → ${toDt.toISOString()}\n\n`);
48
+ try {
49
+ const results = await runPlaybook(playbook, repo, ctx, args.concurrency);
50
+ renderResults(playbook, results, args.json);
51
+ if (args.dashboard) {
52
+ const dashSvc = new PlaybookDashboardService(repo);
53
+ const url = await dashSvc.generate(playbook, results, ctx);
54
+ // Dashboard URL is the primary stdout output when --dashboard is used
55
+ console.log(url);
56
+ }
57
+ }
58
+ catch (err) {
59
+ const msg = err instanceof Error ? err.message : String(err);
60
+ console.error(`\n Pipeline failed: ${msg}`);
61
+ // Still render partial results
62
+ if (ctx.results.size > 0) {
63
+ renderResults(playbook, ctx.results, args.json);
64
+ }
65
+ process.exit(1);
66
+ }
67
+ }
68
+ if (import.meta.url === `file://${process.argv[1]}`) {
69
+ main();
70
+ }
71
+ //# sourceMappingURL=os-playbook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"os-playbook.js","sourceRoot":"","sources":["../src/os-playbook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * CLI entry point — OpenSearch log search & analysis.
3
+ *
4
+ * 9 modes: search, count, histogram, timeline, dashboard, latency, errors, services, report
5
+ *
6
+ * Usage:
7
+ * node dist/os-search.js --mode dashboard --hours 1
8
+ * node dist/os-search.js --service deal_structure --level ERROR --hours 2
9
+ * node dist/os-search.js --mode latency --hours 4
10
+ */
11
+ export {};
@@ -0,0 +1,84 @@
1
+ /**
2
+ * CLI entry point — OpenSearch log search & analysis.
3
+ *
4
+ * 9 modes: search, count, histogram, timeline, dashboard, latency, errors, services, report
5
+ *
6
+ * Usage:
7
+ * node dist/os-search.js --mode dashboard --hours 1
8
+ * node dist/os-search.js --service deal_structure --level ERROR --hours 2
9
+ * node dist/os-search.js --mode latency --hours 4
10
+ */
11
+ import { loadConfig, resolveIndex, parseTimeRange, parseArgs, resolveServiceName } from "./utils/index.js";
12
+ import { createOpenSearchRepository } from "./repositories/index.js";
13
+ import { SearchService } from "./services/index.js";
14
+ async function main() {
15
+ const args = parseArgs({
16
+ env: { type: "string", default: "production", choices: ["production", "staging"] },
17
+ query: { short: "q", type: "string" },
18
+ service: { short: "s", type: "string" },
19
+ level: { short: "l", type: "string" },
20
+ status: { type: "string" },
21
+ correlationId: { type: "string" },
22
+ hours: { type: "number" },
23
+ timeFrom: { type: "string" }, // --time-from or --from
24
+ timeTo: { type: "string" }, // --time-to or --to
25
+ mode: { short: "m", type: "string", default: "search", choices: ["search", "count", "histogram", "timeline", "dashboard", "latency", "errors", "services", "report"] },
26
+ limit: { short: "n", type: "number", default: 20 },
27
+ interval: { type: "string" },
28
+ asc: { type: "boolean" },
29
+ ids: { type: "boolean" },
30
+ full: { type: "boolean" },
31
+ json: { type: "boolean" },
32
+ link: { type: "boolean" },
33
+ });
34
+ // Handle --from / --to as aliases for --time-from / --time-to
35
+ const rawArgs = process.argv.slice(2);
36
+ for (let i = 0; i < rawArgs.length; i++) {
37
+ if (rawArgs[i] === "--from" && i + 1 < rawArgs.length)
38
+ args.timeFrom = rawArgs[++i];
39
+ else if (rawArgs[i] === "--to" && i + 1 < rawArgs.length)
40
+ args.timeTo = rawArgs[++i];
41
+ }
42
+ const config = loadConfig();
43
+ const repo = createOpenSearchRepository(config);
44
+ const service = new SearchService(repo);
45
+ const [fromDt, toDt] = parseTimeRange(args);
46
+ const index = resolveIndex(args.env, fromDt, toDt);
47
+ // Modes that manage their own queries
48
+ if (args.mode === "dashboard")
49
+ return service.modeDashboard(index, fromDt, toDt);
50
+ if (args.mode === "latency")
51
+ return service.modeLatency(index, fromDt, toDt, args);
52
+ if (args.mode === "errors")
53
+ return service.modeErrors(index, fromDt, toDt, args);
54
+ if (args.mode === "services")
55
+ return service.modeServices(index, fromDt, toDt);
56
+ if (args.mode === "report")
57
+ return service.modeReport(index, fromDt, toDt, args);
58
+ // Modes that require at least one filter
59
+ const hasFilters = !!(args.query || args.service || args.level || args.status || args.correlationId);
60
+ if (!hasFilters) {
61
+ console.error("ERROR: At least one filter is required: --query, --service, --level, --status, or --correlation-id");
62
+ process.exit(1);
63
+ }
64
+ const query = service.buildQuery(args, fromDt, toDt);
65
+ if (args.link) {
66
+ let linkQuery = args.query ?? "";
67
+ if (args.service)
68
+ linkQuery += ` AND service:"${resolveServiceName(args.service)}"`;
69
+ console.log(service.buildDashboardLink(linkQuery, fromDt, toDt));
70
+ return;
71
+ }
72
+ if (args.mode === "search")
73
+ await service.modeSearch(index, query, args);
74
+ else if (args.mode === "count")
75
+ await service.modeCount(index, query);
76
+ else if (args.mode === "histogram")
77
+ await service.modeHistogram(index, query, args);
78
+ else if (args.mode === "timeline")
79
+ await service.modeTimeline(index, query, args);
80
+ }
81
+ if (import.meta.url === `file://${process.argv[1]}`) {
82
+ main();
83
+ }
84
+ //# sourceMappingURL=os-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"os-search.js","sourceRoot":"","sources":["../src/os-search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { OpenSearchRepository, createOpenSearchRepository } from "./opensearch.repository.js";
@@ -0,0 +1,2 @@
1
+ export { OpenSearchRepository, createOpenSearchRepository } from "./opensearch.repository.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/repositories/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * OpenSearch repository — data access layer for both APIs.
3
+ *
4
+ * - Data API (port 25060): index search, mappings, cluster health. No tenant header.
5
+ * - Dashboards API (port 443): saved objects, settings. Uses global tenant + osd-xsrf.
6
+ *
7
+ * Uses Node 22 native fetch. No external dependencies.
8
+ */
9
+ import type { OpenSearchConfig, ApiResponse, SearchResult } from "../interfaces/interfaces.js";
10
+ import type { OsdMonitorPayload, OsdMonitorResponse, OsdSearchMonitorsResponse, OsdExecuteResponse, NotificationChannelPayload, NotificationChannelResponse, NotificationChannelListResponse } from "../interfaces/alert.interfaces.js";
11
+ export declare class OpenSearchRepository {
12
+ readonly config: OpenSearchConfig;
13
+ private readonly dataPort;
14
+ private readonly dashboardsPort;
15
+ private readonly tenant;
16
+ constructor(config: OpenSearchConfig);
17
+ private basicAuth;
18
+ private request;
19
+ /** Request to OpenSearch data API. No tenant header. */
20
+ dataApi(method: string, path: string, body?: unknown): Promise<ApiResponse>;
21
+ /** Search — POST /{index}/_search. Exits on error. Generic TAggs for typed aggregations. */
22
+ search<TAggs = Record<string, unknown>>(index: string, body: unknown): Promise<SearchResult<TAggs>>;
23
+ /** Count — POST /{index}/_count. Returns -1 on error. */
24
+ count(index: string, body: unknown): Promise<number>;
25
+ /** Request to OpenSearch Dashboards API (configured tenant). */
26
+ dashboardsApi(method: string, path: string, body?: unknown): Promise<ApiResponse>;
27
+ /** Create or update a saved object. Returns [action, success]. */
28
+ upsertSavedObject(objType: string, objId: string, body: unknown): Promise<[string, boolean]>;
29
+ /** Delete a saved object. */
30
+ deleteSavedObject(objType: string, objId: string): Promise<void>;
31
+ /** Get a saved object. Returns the response or null if not found. */
32
+ getSavedObject(objType: string, objId: string): Promise<ApiResponse | null>;
33
+ /** Create a monitor. Returns the created monitor response. */
34
+ createMonitor(body: OsdMonitorPayload): Promise<OsdMonitorResponse | null>;
35
+ /** Update a monitor by ID. */
36
+ updateMonitor(monitorId: string, body: OsdMonitorPayload): Promise<OsdMonitorResponse | null>;
37
+ /** Delete a monitor by ID. */
38
+ deleteMonitor(monitorId: string): Promise<boolean>;
39
+ /** Execute (dry-run) a monitor by ID. */
40
+ executeMonitor(monitorId: string): Promise<OsdExecuteResponse | null>;
41
+ /** Search monitors using an OpenSearch query. */
42
+ searchMonitors(query: Record<string, unknown>): Promise<OsdSearchMonitorsResponse | null>;
43
+ /** Create a notification channel. Returns the config_id or null. */
44
+ createNotificationChannel(body: NotificationChannelPayload): Promise<NotificationChannelResponse | null>;
45
+ /** List notification channels. */
46
+ listNotificationChannels(): Promise<NotificationChannelListResponse | null>;
47
+ /** Delete a notification channel by config_id. */
48
+ deleteNotificationChannel(configId: string): Promise<boolean>;
49
+ }
50
+ /** Factory — create a repository instance with the given config. */
51
+ export declare function createOpenSearchRepository(config: OpenSearchConfig): OpenSearchRepository;
@@ -0,0 +1,167 @@
1
+ /**
2
+ * OpenSearch repository — data access layer for both APIs.
3
+ *
4
+ * - Data API (port 25060): index search, mappings, cluster health. No tenant header.
5
+ * - Dashboards API (port 443): saved objects, settings. Uses global tenant + osd-xsrf.
6
+ *
7
+ * Uses Node 22 native fetch. No external dependencies.
8
+ */
9
+ const DEFAULT_DATA_API_PORT = 25060;
10
+ const DEFAULT_DASHBOARDS_API_PORT = 443;
11
+ const DEFAULT_TENANT = "global";
12
+ const TIMEOUT_MS = 30_000;
13
+ export class OpenSearchRepository {
14
+ config;
15
+ dataPort;
16
+ dashboardsPort;
17
+ tenant;
18
+ constructor(config) {
19
+ this.config = config;
20
+ this.dataPort = config.dataPort ?? DEFAULT_DATA_API_PORT;
21
+ this.dashboardsPort = config.dashboardsPort ?? DEFAULT_DASHBOARDS_API_PORT;
22
+ this.tenant = config.tenant ?? DEFAULT_TENANT;
23
+ }
24
+ basicAuth() {
25
+ return Buffer.from(`${this.config.username}:${this.config.password}`).toString("base64");
26
+ }
27
+ async request(port, method, path, body, tenant) {
28
+ const url = `https://${this.config.host}:${port}${path}`;
29
+ const headers = {
30
+ Authorization: `Basic ${this.basicAuth()}`,
31
+ "Content-Type": "application/json",
32
+ };
33
+ if (tenant) {
34
+ headers["securitytenant"] = tenant;
35
+ headers["osd-xsrf"] = "true";
36
+ }
37
+ const init = {
38
+ method,
39
+ headers,
40
+ signal: AbortSignal.timeout(TIMEOUT_MS),
41
+ };
42
+ if (body !== undefined) {
43
+ init.body = JSON.stringify(body);
44
+ }
45
+ try {
46
+ const resp = await fetch(url, init);
47
+ const text = await resp.text();
48
+ if (!resp.ok) {
49
+ if (resp.status === 409)
50
+ return { _conflict: true };
51
+ if (resp.status === 404)
52
+ return { _not_found: true };
53
+ return { _error: true, _code: resp.status, _body: text.slice(0, 300) };
54
+ }
55
+ return JSON.parse(text);
56
+ }
57
+ catch (err) {
58
+ const msg = err instanceof Error ? err.message : String(err);
59
+ return { _error: true, _reason: msg };
60
+ }
61
+ }
62
+ // ── Data API (port 25060) ────────────────────────────────────────────
63
+ /** Request to OpenSearch data API. No tenant header. */
64
+ async dataApi(method, path, body) {
65
+ return this.request(this.dataPort, method, path, body);
66
+ }
67
+ /** Search — POST /{index}/_search. Exits on error. Generic TAggs for typed aggregations. */
68
+ async search(index, body) {
69
+ const result = await this.dataApi("POST", `/${index}/_search`, body);
70
+ if (result._error) {
71
+ console.error(`ERROR: OpenSearch search failed: ${result._body ?? result._reason}`);
72
+ process.exit(1);
73
+ }
74
+ return result;
75
+ }
76
+ /** Count — POST /{index}/_count. Returns -1 on error. */
77
+ async count(index, body) {
78
+ const result = await this.dataApi("POST", `/${index}/_count`, body);
79
+ if (result._error)
80
+ return -1;
81
+ return result.count;
82
+ }
83
+ // ── Dashboards API (port 443) ────────────────────────────────────────
84
+ /** Request to OpenSearch Dashboards API (configured tenant). */
85
+ async dashboardsApi(method, path, body) {
86
+ return this.request(this.dashboardsPort, method, path, body, this.tenant);
87
+ }
88
+ /** Create or update a saved object. Returns [action, success]. */
89
+ async upsertSavedObject(objType, objId, body) {
90
+ let result = await this.dashboardsApi("POST", `/api/saved_objects/${objType}/${objId}`, body);
91
+ if (result?._conflict) {
92
+ result = await this.dashboardsApi("PUT", `/api/saved_objects/${objType}/${objId}`, body);
93
+ return ["updated", !!result && !result._error];
94
+ }
95
+ return ["created", !!result && !result._error];
96
+ }
97
+ /** Delete a saved object. */
98
+ async deleteSavedObject(objType, objId) {
99
+ await this.dashboardsApi("DELETE", `/api/saved_objects/${objType}/${objId}`);
100
+ }
101
+ /** Get a saved object. Returns the response or null if not found. */
102
+ async getSavedObject(objType, objId) {
103
+ const result = await this.dashboardsApi("GET", `/api/saved_objects/${objType}/${objId}`);
104
+ if (result._not_found || result._error)
105
+ return null;
106
+ return result;
107
+ }
108
+ // ── Alerting API (_plugins/_alerting) ─────────────────────────────────
109
+ /** Create a monitor. Returns the created monitor response. */
110
+ async createMonitor(body) {
111
+ const result = await this.dataApi("POST", "/_plugins/_alerting/monitors", body);
112
+ if (result._error)
113
+ return null;
114
+ return result;
115
+ }
116
+ /** Update a monitor by ID. */
117
+ async updateMonitor(monitorId, body) {
118
+ const result = await this.dataApi("PUT", `/_plugins/_alerting/monitors/${monitorId}`, body);
119
+ if (result._error)
120
+ return null;
121
+ return result;
122
+ }
123
+ /** Delete a monitor by ID. */
124
+ async deleteMonitor(monitorId) {
125
+ const result = await this.dataApi("DELETE", `/_plugins/_alerting/monitors/${monitorId}`);
126
+ return !result._error;
127
+ }
128
+ /** Execute (dry-run) a monitor by ID. */
129
+ async executeMonitor(monitorId) {
130
+ const result = await this.dataApi("POST", `/_plugins/_alerting/monitors/${monitorId}/_execute`);
131
+ if (result._error)
132
+ return null;
133
+ return result;
134
+ }
135
+ /** Search monitors using an OpenSearch query. */
136
+ async searchMonitors(query) {
137
+ const result = await this.dataApi("POST", "/_plugins/_alerting/monitors/_search", query);
138
+ if (result._error || result._not_found)
139
+ return null;
140
+ return result;
141
+ }
142
+ // ── Notifications API (_plugins/_notifications) ─────────────────────
143
+ /** Create a notification channel. Returns the config_id or null. */
144
+ async createNotificationChannel(body) {
145
+ const result = await this.dataApi("POST", "/_plugins/_notifications/configs", body);
146
+ if (result._error)
147
+ return null;
148
+ return result;
149
+ }
150
+ /** List notification channels. */
151
+ async listNotificationChannels() {
152
+ const result = await this.dataApi("GET", "/_plugins/_notifications/configs");
153
+ if (result._error || result._not_found)
154
+ return null;
155
+ return result;
156
+ }
157
+ /** Delete a notification channel by config_id. */
158
+ async deleteNotificationChannel(configId) {
159
+ const result = await this.dataApi("DELETE", `/_plugins/_notifications/configs/${configId}`);
160
+ return !result._error;
161
+ }
162
+ }
163
+ /** Factory — create a repository instance with the given config. */
164
+ export function createOpenSearchRepository(config) {
165
+ return new OpenSearchRepository(config);
166
+ }
167
+ //# sourceMappingURL=opensearch.repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opensearch.repository.js","sourceRoot":"","sources":["../../src/repositories/opensearch.repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Alert service — load YAML alert profiles, resolve templates,
3
+ * and CRUD monitors/destinations on OSD.
4
+ */
5
+ import type { OpenSearchRepository } from "../repositories/opensearch.repository.js";
6
+ import type { AlertProfile, MonitorDef, TemplateContext, HealthReport, MonitorListItem, OsdMonitorPayload, OsdExecuteResponse } from "../interfaces/alert.interfaces.js";
7
+ export declare class AlertService {
8
+ private repo;
9
+ constructor(repo: OpenSearchRepository);
10
+ /** Load and parse an alert profile YAML. */
11
+ loadProfile(profileName: string): AlertProfile;
12
+ /**
13
+ * Build flat context from profile thresholds, defaults, and CLI overrides.
14
+ * This context resolves {{thresholds.*}} and {{defaults.*}} expressions.
15
+ */
16
+ buildContext(profile: AlertProfile, overrides?: {
17
+ service?: string;
18
+ dashboardUrl?: string;
19
+ env?: string;
20
+ }): TemplateContext;
21
+ /**
22
+ * Resolve all pre-flight templates in a string.
23
+ * {{thresholds.*}}, {{defaults.*}} are resolved.
24
+ * {{ctx.*}} expressions are passed through for OSD Mustache.
25
+ */
26
+ resolveString(value: string, context: TemplateContext): string;
27
+ /**
28
+ * Ensure a notification channel exists. Searches by name first; creates if missing.
29
+ * Returns the channel config_id (used as destination_id in monitor actions).
30
+ */
31
+ ensureNotificationChannel(channelName: string, webhookUrl: string): Promise<string>;
32
+ /**
33
+ * Build an OSD monitor payload from a profile monitor definition.
34
+ */
35
+ buildMonitorPayload(profileName: string, monitorKey: string, monitorDef: MonitorDef, destinationId: string, cardTemplate: string, context: TemplateContext, env: string): OsdMonitorPayload;
36
+ /**
37
+ * Wrap a user query in a bool+filter with a relative time range
38
+ * so the monitor scans recent data each period.
39
+ * If the query contains an `aggs` key, hoist it to the top level.
40
+ */
41
+ private buildSearchQuery;
42
+ /**
43
+ * Create all monitors for a profile (or a single monitor if monitorKey is specified).
44
+ * Returns array of [monitorKey, monitorId, created] tuples.
45
+ */
46
+ createMonitors(profile: AlertProfile, webhookUrl: string, context: TemplateContext, env: string, monitorKey?: string): Promise<Array<[string, string, boolean]>>;
47
+ /**
48
+ * Generate payloads for all monitors without calling the API (dry-run).
49
+ */
50
+ dryRunMonitors(profile: AlertProfile, webhookUrl: string, context: TemplateContext, env: string, monitorKey?: string): Array<[string, OsdMonitorPayload]>;
51
+ /** Find a monitor ID by exact name. Returns ID or null. */
52
+ findMonitorByName(name: string): Promise<string | null>;
53
+ /**
54
+ * List monitors, optionally filtered by profile prefix.
55
+ */
56
+ listMonitors(profileName?: string): Promise<MonitorListItem[]>;
57
+ /**
58
+ * Delete all monitors for a profile.
59
+ * Returns array of [name, deleted] tuples.
60
+ */
61
+ deleteMonitors(profileName: string): Promise<Array<[string, boolean]>>;
62
+ /**
63
+ * Execute (dry-run) a single monitor by profile + monitor key.
64
+ */
65
+ executeMonitor(profileName: string, monitorKey: string): Promise<OsdExecuteResponse | null>;
66
+ /**
67
+ * Gather a live production health report by querying OpenSearch.
68
+ * Returns structured data suitable for building a Google Chat card.
69
+ */
70
+ gatherHealthReport(index: string, fromDt: Date, toDt: Date, env: string, _service?: string): Promise<HealthReport>;
71
+ private serviceFilter;
72
+ private latencyScriptedMetric;
73
+ }