log10x-mcp 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/LICENSE +21 -0
- package/README.md +148 -0
- package/build/index.d.ts +8 -0
- package/build/index.js +150 -0
- package/build/index.js.map +1 -0
- package/build/lib/api.d.ts +31 -0
- package/build/lib/api.js +89 -0
- package/build/lib/api.js.map +1 -0
- package/build/lib/cost.d.ts +14 -0
- package/build/lib/cost.js +23 -0
- package/build/lib/cost.js.map +1 -0
- package/build/lib/environments.d.ts +24 -0
- package/build/lib/environments.js +51 -0
- package/build/lib/environments.js.map +1 -0
- package/build/lib/format.d.ts +29 -0
- package/build/lib/format.js +90 -0
- package/build/lib/format.js.map +1 -0
- package/build/lib/gates.d.ts +23 -0
- package/build/lib/gates.js +29 -0
- package/build/lib/gates.js.map +1 -0
- package/build/lib/promql.d.ts +43 -0
- package/build/lib/promql.js +99 -0
- package/build/lib/promql.js.map +1 -0
- package/build/lib/resolve-env.d.ts +11 -0
- package/build/lib/resolve-env.js +35 -0
- package/build/lib/resolve-env.js.map +1 -0
- package/build/resources/status.d.ts +7 -0
- package/build/resources/status.js +37 -0
- package/build/resources/status.js.map +1 -0
- package/build/tools/cost-drivers.d.ts +28 -0
- package/build/tools/cost-drivers.js +142 -0
- package/build/tools/cost-drivers.js.map +1 -0
- package/build/tools/dependency-check.d.ts +22 -0
- package/build/tools/dependency-check.js +80 -0
- package/build/tools/dependency-check.js.map +1 -0
- package/build/tools/event-lookup.d.ts +23 -0
- package/build/tools/event-lookup.js +131 -0
- package/build/tools/event-lookup.js.map +1 -0
- package/build/tools/exclusion-filter.d.ts +21 -0
- package/build/tools/exclusion-filter.js +246 -0
- package/build/tools/exclusion-filter.js.map +1 -0
- package/build/tools/savings.d.ts +17 -0
- package/build/tools/savings.js +75 -0
- package/build/tools/savings.js.map +1 -0
- package/build/tools/services.d.ts +14 -0
- package/build/tools/services.js +53 -0
- package/build/tools/services.js.map +1 -0
- package/build/tools/trend.d.ts +20 -0
- package/build/tools/trend.js +122 -0
- package/build/tools/trend.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* log10x_dependency_check — generate a SIEM dependency scan command.
|
|
3
|
+
*
|
|
4
|
+
* Returns a bash command that downloads and runs a Python script to check
|
|
5
|
+
* if dashboards, alerts, or saved searches in the user's SIEM reference
|
|
6
|
+
* a given pattern. The command runs locally, read-only. No data sent to Log10x.
|
|
7
|
+
*
|
|
8
|
+
* Ported from GettingStarted.jsx depcheck section.
|
|
9
|
+
*/
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
export const dependencyCheckSchema = {
|
|
12
|
+
pattern: z.string().describe('Pattern name (e.g., "Payment_Gateway_Timeout")'),
|
|
13
|
+
vendor: z.enum(['datadog', 'splunk', 'elasticsearch', 'cloudwatch']).describe('SIEM vendor to scan'),
|
|
14
|
+
service: z.string().optional().describe('Service name to scope the scan'),
|
|
15
|
+
severity: z.string().optional().describe('Severity level'),
|
|
16
|
+
};
|
|
17
|
+
const VENDOR_CONFIG = {
|
|
18
|
+
datadog: {
|
|
19
|
+
label: 'Datadog',
|
|
20
|
+
script: 'siem-check-datadog.py',
|
|
21
|
+
envSetup: 'export DD_API_KEY="<YOUR_API_KEY>"\nexport DD_APP_KEY="<YOUR_APP_KEY>"',
|
|
22
|
+
envNote: 'Create an Application Key at: Organization Settings > Application Keys',
|
|
23
|
+
},
|
|
24
|
+
splunk: {
|
|
25
|
+
label: 'Splunk',
|
|
26
|
+
script: 'siem-check-splunk.py',
|
|
27
|
+
envSetup: 'export SPLUNK_URL="https://<YOUR_SPLUNK>:8089"\nexport SPLUNK_TOKEN="<YOUR_BEARER_TOKEN>"',
|
|
28
|
+
envNote: 'Create a token at: Settings > Tokens (requires user role)',
|
|
29
|
+
},
|
|
30
|
+
elasticsearch: {
|
|
31
|
+
label: 'Elasticsearch',
|
|
32
|
+
script: 'siem-check-elasticsearch.py',
|
|
33
|
+
envSetup: 'export ES_URL="https://<YOUR_ES>:9200"\nexport ES_API_KEY="<YOUR_API_KEY>"',
|
|
34
|
+
envNote: 'Create an API key at: Stack Management > API Keys',
|
|
35
|
+
},
|
|
36
|
+
cloudwatch: {
|
|
37
|
+
label: 'CloudWatch',
|
|
38
|
+
script: 'siem-check-cloudwatch.py',
|
|
39
|
+
envSetup: '# Uses standard AWS credentials (env vars, ~/.aws/credentials, or IAM role)\npip3 install boto3',
|
|
40
|
+
envNote: 'Requires: logs:Describe*, cloudwatch:Describe*, cloudwatch:GetDashboard',
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
export function executeDependencyCheck(args) {
|
|
44
|
+
const tokens = args.pattern.split('_').filter(t => t.length > 0);
|
|
45
|
+
const sev = (args.severity || '').toLowerCase();
|
|
46
|
+
const svc = args.service || '';
|
|
47
|
+
const vc = VENDOR_CONFIG[args.vendor];
|
|
48
|
+
if (!vc)
|
|
49
|
+
return `Unknown vendor: ${args.vendor}. Supported: ${Object.keys(VENDOR_CONFIG).join(', ')}`;
|
|
50
|
+
// Build script arguments
|
|
51
|
+
const scriptArgs = [];
|
|
52
|
+
if (svc)
|
|
53
|
+
scriptArgs.push(`--service "${svc}"`);
|
|
54
|
+
if (sev && sev !== 'uncl' && sev !== 'unclassified')
|
|
55
|
+
scriptArgs.push(`--severity "${sev}"`);
|
|
56
|
+
const kwTokens = tokens.filter(t => t.length > 3).slice(0, 5);
|
|
57
|
+
if (kwTokens.length > 0)
|
|
58
|
+
scriptArgs.push(`--keywords "${kwTokens.join(',')}"`);
|
|
59
|
+
const cmd = [
|
|
60
|
+
`# 1. Set credentials`,
|
|
61
|
+
vc.envSetup,
|
|
62
|
+
``,
|
|
63
|
+
`# 2. Download and run`,
|
|
64
|
+
`curl -sO https://dl.log10x.com/siem-check/${vc.script}`,
|
|
65
|
+
`python3 ${vc.script} ${scriptArgs.join(' ')}`,
|
|
66
|
+
].join('\n');
|
|
67
|
+
const lines = [];
|
|
68
|
+
lines.push(`Dependency Check — ${vc.label}`);
|
|
69
|
+
lines.push('');
|
|
70
|
+
lines.push(`Check if any dashboards, alerts, or saved searches in your ${vc.label} depend on this pattern before dropping it.`);
|
|
71
|
+
lines.push('');
|
|
72
|
+
lines.push(`Note: ${vc.envNote}`);
|
|
73
|
+
lines.push('');
|
|
74
|
+
lines.push(cmd);
|
|
75
|
+
lines.push('');
|
|
76
|
+
lines.push('Runs locally — reads your SIEM config (read-only). No data sent to Log10x.');
|
|
77
|
+
lines.push('Source: https://github.com/log-10x/siem-check');
|
|
78
|
+
return lines.join('\n');
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=dependency-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependency-check.js","sourceRoot":"","sources":["../../src/tools/dependency-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* log10x_event_lookup — analyze a specific log pattern.
|
|
3
|
+
*
|
|
4
|
+
* Finds the pattern across all services, shows cost breakdown,
|
|
5
|
+
* and requests AI analysis. Equivalent to `/log10x event {pattern}`.
|
|
6
|
+
*
|
|
7
|
+
* Ported from SlackPatternService.queryPatternAcrossServices().
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import type { EnvConfig } from '../lib/environments.js';
|
|
11
|
+
export declare const eventLookupSchema: {
|
|
12
|
+
pattern: z.ZodString;
|
|
13
|
+
service: z.ZodOptional<z.ZodString>;
|
|
14
|
+
timeRange: z.ZodDefault<z.ZodEnum<["1d", "7d", "30d"]>>;
|
|
15
|
+
analyzerCost: z.ZodOptional<z.ZodNumber>;
|
|
16
|
+
environment: z.ZodOptional<z.ZodString>;
|
|
17
|
+
};
|
|
18
|
+
export declare function executeEventLookup(args: {
|
|
19
|
+
pattern: string;
|
|
20
|
+
service?: string;
|
|
21
|
+
timeRange: string;
|
|
22
|
+
analyzerCost: number;
|
|
23
|
+
}, env: EnvConfig): Promise<string>;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* log10x_event_lookup — analyze a specific log pattern.
|
|
3
|
+
*
|
|
4
|
+
* Finds the pattern across all services, shows cost breakdown,
|
|
5
|
+
* and requests AI analysis. Equivalent to `/log10x event {pattern}`.
|
|
6
|
+
*
|
|
7
|
+
* Ported from SlackPatternService.queryPatternAcrossServices().
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { queryInstant, queryAi } from '../lib/api.js';
|
|
11
|
+
import * as pql from '../lib/promql.js';
|
|
12
|
+
import { LABELS } from '../lib/promql.js';
|
|
13
|
+
import { bytesToCost, parsePrometheusValue } from '../lib/cost.js';
|
|
14
|
+
import { resolveMetricsEnv } from '../lib/resolve-env.js';
|
|
15
|
+
import { fmtDollar, fmtPattern, fmtSeverity, fmtCount, parseTimeframe, costPeriodLabel } from '../lib/format.js';
|
|
16
|
+
export const eventLookupSchema = {
|
|
17
|
+
pattern: z.string().describe('Pattern name or search term to look up (e.g., "Payment_Gateway_Timeout")'),
|
|
18
|
+
service: z.string().optional().describe('Service to scope the lookup'),
|
|
19
|
+
timeRange: z.enum(['1d', '7d', '30d']).default('7d').describe('Time range'),
|
|
20
|
+
analyzerCost: z.number().optional().describe('SIEM ingestion cost in $/GB'),
|
|
21
|
+
environment: z.string().optional().describe('Environment nickname'),
|
|
22
|
+
};
|
|
23
|
+
export async function executeEventLookup(args, env) {
|
|
24
|
+
const tf = parseTimeframe(args.timeRange);
|
|
25
|
+
const costPerGb = args.analyzerCost;
|
|
26
|
+
const period = costPeriodLabel(tf.days);
|
|
27
|
+
const metricsEnv = await resolveMetricsEnv(env);
|
|
28
|
+
// Current window: bytes per service for this pattern
|
|
29
|
+
const currentRes = await queryInstant(env, pql.patternAcrossServices(args.pattern, metricsEnv, tf.range));
|
|
30
|
+
if (currentRes.status !== 'success' || currentRes.data.result.length === 0) {
|
|
31
|
+
// Try fuzzy match with regex
|
|
32
|
+
const fuzzyPattern = args.pattern.replace(/[_ ]+/g, '.*');
|
|
33
|
+
const fuzzyQuery = `sum by (${LABELS.service}, ${LABELS.severity}) (increase(all_events_summaryBytes_total{${LABELS.pattern}=~"${fuzzyPattern}",${LABELS.env}="${metricsEnv}"}[${tf.range}]))`;
|
|
34
|
+
const fuzzyRes = await queryInstant(env, fuzzyQuery);
|
|
35
|
+
if (fuzzyRes.status !== 'success' || fuzzyRes.data.result.length === 0) {
|
|
36
|
+
return `No data found for pattern "${args.pattern}". Check the pattern name (use underscores, e.g., Payment_Gateway_Timeout).`;
|
|
37
|
+
}
|
|
38
|
+
// Use fuzzy results
|
|
39
|
+
return formatResults(fuzzyRes.data.result, args.pattern, metricsEnv, tf, costPerGb, period, env);
|
|
40
|
+
}
|
|
41
|
+
return formatResults(currentRes.data.result, args.pattern, metricsEnv, tf, costPerGb, period, env);
|
|
42
|
+
}
|
|
43
|
+
async function formatResults(results, pattern, metricsEnv, tf, costPerGb, period, env) {
|
|
44
|
+
// Aggregate bytes per service (multiple severity levels possible)
|
|
45
|
+
const serviceBytes = new Map();
|
|
46
|
+
const serviceSev = new Map();
|
|
47
|
+
for (const r of results) {
|
|
48
|
+
const svc = r.metric[LABELS.service] || '';
|
|
49
|
+
const sev = r.metric[LABELS.severity] || '';
|
|
50
|
+
const bytes = parsePrometheusValue(r);
|
|
51
|
+
serviceBytes.set(svc, (serviceBytes.get(svc) || 0) + bytes);
|
|
52
|
+
// Keep dominant severity
|
|
53
|
+
const current = serviceSev.get(svc);
|
|
54
|
+
if (!current || bytes > current.bytes) {
|
|
55
|
+
serviceSev.set(svc, { sev, bytes });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Baseline per service
|
|
59
|
+
const baselineByService = new Map();
|
|
60
|
+
for (const offsetDays of tf.baselineOffsets) {
|
|
61
|
+
const baseRes = await queryInstant(env, pql.patternAcrossServices(pattern, metricsEnv, tf.range, offsetDays));
|
|
62
|
+
if (baseRes.status === 'success') {
|
|
63
|
+
for (const r of baseRes.data.result) {
|
|
64
|
+
const svc = r.metric[LABELS.service] || '';
|
|
65
|
+
const arr = baselineByService.get(svc) || [];
|
|
66
|
+
arr.push(parsePrometheusValue(r));
|
|
67
|
+
baselineByService.set(svc, arr);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Event counts per service
|
|
72
|
+
const eventsRes = await queryInstant(env, pql.eventsPerServiceForPattern(pattern, metricsEnv, tf.range));
|
|
73
|
+
const eventsBySvc = new Map();
|
|
74
|
+
if (eventsRes.status === 'success') {
|
|
75
|
+
for (const r of eventsRes.data.result) {
|
|
76
|
+
const svc = r.metric[LABELS.service] || '';
|
|
77
|
+
eventsBySvc.set(svc, parsePrometheusValue(r));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const rows = [];
|
|
81
|
+
let totalCostNow = 0;
|
|
82
|
+
let totalCostBase = 0;
|
|
83
|
+
let totalEvents = 0;
|
|
84
|
+
for (const [svc, bytes] of serviceBytes) {
|
|
85
|
+
const costNow = bytesToCost(bytes, costPerGb);
|
|
86
|
+
const baseWeeks = baselineByService.get(svc) || [];
|
|
87
|
+
const isNew = baseWeeks.length === 0;
|
|
88
|
+
const costBase = isNew ? 0 : bytesToCost(baseWeeks.reduce((a, b) => a + b, 0) / baseWeeks.length, costPerGb);
|
|
89
|
+
const events = eventsBySvc.get(svc) || 0;
|
|
90
|
+
rows.push({ service: svc, severity: serviceSev.get(svc)?.sev || '', costNow, costBaseline: costBase, events, isNew });
|
|
91
|
+
totalCostNow += costNow;
|
|
92
|
+
totalCostBase += costBase;
|
|
93
|
+
totalEvents += events;
|
|
94
|
+
}
|
|
95
|
+
rows.sort((a, b) => b.costNow - a.costNow);
|
|
96
|
+
// Format output
|
|
97
|
+
const lines = [];
|
|
98
|
+
lines.push(`${fmtPattern(pattern)} — ${fmtDollar(totalCostBase)} → ${fmtDollar(totalCostNow)}${period}`);
|
|
99
|
+
lines.push('');
|
|
100
|
+
lines.push('Services:');
|
|
101
|
+
for (const r of rows) {
|
|
102
|
+
const svc = r.service.padEnd(15);
|
|
103
|
+
const sev = fmtSeverity(r.severity).padEnd(6);
|
|
104
|
+
const cost = `${fmtDollar(r.costNow)}${period}`;
|
|
105
|
+
const delta = `(${fmtDollar(r.costBaseline)} → ${fmtDollar(r.costNow)})`;
|
|
106
|
+
const events = r.events > 0 ? ` ${fmtCount(r.events)} events` : '';
|
|
107
|
+
const newFlag = r.isNew ? ' NEW' : '';
|
|
108
|
+
lines.push(` ${svc} ${sev} ${cost.padEnd(12)} ${delta}${events}${newFlag}`);
|
|
109
|
+
}
|
|
110
|
+
// AI analysis
|
|
111
|
+
try {
|
|
112
|
+
const queryResultJson = JSON.stringify(results.slice(0, 5));
|
|
113
|
+
const aiPrompt = `Classify this log pattern and recommend an action. Pattern: ${pattern}. Provide: CATEGORY (error/debug/info/metric/health), CONFIDENCE (high/medium/low), ACTION (filter/keep/reduce), FILTER_PCT (% safe to filter), EXPLANATION (one line).`;
|
|
114
|
+
const aiResult = await queryAi(env, queryResultJson, aiPrompt, costPerGb);
|
|
115
|
+
if (aiResult) {
|
|
116
|
+
lines.push('');
|
|
117
|
+
lines.push('AI Analysis:');
|
|
118
|
+
for (const line of aiResult.split('\n')) {
|
|
119
|
+
if (line.trim())
|
|
120
|
+
lines.push(` ${line.trim()}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// AI analysis is optional — skip silently
|
|
126
|
+
}
|
|
127
|
+
lines.push('');
|
|
128
|
+
lines.push(`${rows.length} service${rows.length !== 1 ? 's' : ''} · ${fmtCount(totalEvents)} events`);
|
|
129
|
+
return lines.join('\n');
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=event-lookup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-lookup.js","sourceRoot":"","sources":["../../src/tools/event-lookup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* log10x_exclusion_filter — generate SIEM/forwarder config to drop a pattern.
|
|
3
|
+
*
|
|
4
|
+
* Supports 14 vendors (4 SIEMs + 10 forwarders), with config and API modes
|
|
5
|
+
* where applicable. Ported from GettingStarted.jsx exclude section.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
export declare const exclusionFilterSchema: {
|
|
9
|
+
pattern: z.ZodString;
|
|
10
|
+
vendor: z.ZodEnum<["datadog", "splunk", "elasticsearch", "cloudwatch", "datadog-agent", "fluentbit", "fluentd", "otel", "vector", "logstash", "filebeat", "rsyslog", "syslog-ng", "promtail"]>;
|
|
11
|
+
mode: z.ZodDefault<z.ZodEnum<["config", "api"]>>;
|
|
12
|
+
service: z.ZodOptional<z.ZodString>;
|
|
13
|
+
severity: z.ZodOptional<z.ZodString>;
|
|
14
|
+
};
|
|
15
|
+
export declare function executeExclusionFilter(args: {
|
|
16
|
+
pattern: string;
|
|
17
|
+
vendor: string;
|
|
18
|
+
mode: string;
|
|
19
|
+
service?: string;
|
|
20
|
+
severity?: string;
|
|
21
|
+
}): string;
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* log10x_exclusion_filter — generate SIEM/forwarder config to drop a pattern.
|
|
3
|
+
*
|
|
4
|
+
* Supports 14 vendors (4 SIEMs + 10 forwarders), with config and API modes
|
|
5
|
+
* where applicable. Ported from GettingStarted.jsx exclude section.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
export const exclusionFilterSchema = {
|
|
9
|
+
pattern: z.string().describe('Pattern name (e.g., "Payment_Gateway_Timeout")'),
|
|
10
|
+
vendor: z.enum([
|
|
11
|
+
'datadog', 'splunk', 'elasticsearch', 'cloudwatch',
|
|
12
|
+
'datadog-agent', 'fluentbit', 'fluentd', 'otel', 'vector',
|
|
13
|
+
'logstash', 'filebeat', 'rsyslog', 'syslog-ng', 'promtail',
|
|
14
|
+
]).describe('Target vendor to generate the filter for'),
|
|
15
|
+
mode: z.enum(['config', 'api']).default('config').describe('Config snippet or API command (API available for Datadog, Splunk, Elasticsearch)'),
|
|
16
|
+
service: z.string().optional().describe('Service name for scoping the filter'),
|
|
17
|
+
severity: z.string().optional().describe('Severity level (e.g., "error", "warn")'),
|
|
18
|
+
};
|
|
19
|
+
export function executeExclusionFilter(args) {
|
|
20
|
+
const tokens = args.pattern.split('_').filter(t => t.length > 0);
|
|
21
|
+
const patRegex = tokens.join('.*');
|
|
22
|
+
const svc = args.service || '';
|
|
23
|
+
const sev = (args.severity || '').toLowerCase();
|
|
24
|
+
const vk = args.vendor;
|
|
25
|
+
const mode = args.mode;
|
|
26
|
+
const { label, text } = generateFilter(vk, mode, tokens, patRegex, svc, sev, args.pattern);
|
|
27
|
+
const lines = [];
|
|
28
|
+
const vendorLabel = VENDOR_LABELS[vk] || vk;
|
|
29
|
+
lines.push(`Exclusion Filter — ${vendorLabel} (${mode})`);
|
|
30
|
+
lines.push('');
|
|
31
|
+
lines.push(label);
|
|
32
|
+
lines.push('');
|
|
33
|
+
lines.push(text);
|
|
34
|
+
return lines.join('\n');
|
|
35
|
+
}
|
|
36
|
+
const VENDOR_LABELS = {
|
|
37
|
+
'datadog': 'Datadog',
|
|
38
|
+
'splunk': 'Splunk',
|
|
39
|
+
'elasticsearch': 'Elasticsearch',
|
|
40
|
+
'cloudwatch': 'CloudWatch',
|
|
41
|
+
'datadog-agent': 'Datadog Agent',
|
|
42
|
+
'fluentbit': 'Fluent Bit',
|
|
43
|
+
'fluentd': 'Fluentd',
|
|
44
|
+
'otel': 'OTel Collector',
|
|
45
|
+
'vector': 'Vector',
|
|
46
|
+
'logstash': 'Logstash',
|
|
47
|
+
'filebeat': 'Filebeat',
|
|
48
|
+
'rsyslog': 'rsyslog',
|
|
49
|
+
'syslog-ng': 'syslog-ng',
|
|
50
|
+
'promtail': 'Promtail',
|
|
51
|
+
};
|
|
52
|
+
function generateFilter(vk, mode, tokens, patRegex, svc, sev, rawPattern) {
|
|
53
|
+
// Datadog query for SIEM filters
|
|
54
|
+
const ddQuery = (() => {
|
|
55
|
+
const parts = [];
|
|
56
|
+
if (svc)
|
|
57
|
+
parts.push(`service:${svc}`);
|
|
58
|
+
if (sev && sev !== 'uncl')
|
|
59
|
+
parts.push(`status:${sev}`);
|
|
60
|
+
parts.push(`@message:/${patRegex}/`);
|
|
61
|
+
return parts.join(' ');
|
|
62
|
+
})();
|
|
63
|
+
// ── SIEMs ──
|
|
64
|
+
if (vk === 'datadog' && mode === 'config') {
|
|
65
|
+
return { label: 'Paste this query into an exclusion filter under Logs > Configuration > Indexes.', text: ddQuery };
|
|
66
|
+
}
|
|
67
|
+
if (vk === 'datadog' && mode === 'api') {
|
|
68
|
+
const body = JSON.stringify({ name: `Drop ${rawPattern.slice(0, 40)}`, is_enabled: true, filter: { query: ddQuery } });
|
|
69
|
+
return {
|
|
70
|
+
label: 'Run this curl command to create an exclusion filter via the Datadog API.',
|
|
71
|
+
text: `curl -X POST "https://api.datadoghq.com/api/v1/logs/config/indexes/<INDEX_NAME>/exclusion_filters" \\\n -H "DD-API-KEY: <YOUR_API_KEY>" \\\n -H "DD-APPLICATION-KEY: <YOUR_APP_KEY>" \\\n -H "Content-Type: application/json" \\\n -d '${body}'`
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (vk === 'splunk' && mode === 'config') {
|
|
75
|
+
const lines = [
|
|
76
|
+
`# Add to transforms.conf on your Heavy Forwarder or Indexer`,
|
|
77
|
+
`[drop_${tokens.slice(0, 3).join('_')}]`,
|
|
78
|
+
`REGEX = ${patRegex}`,
|
|
79
|
+
`DEST_KEY = queue`,
|
|
80
|
+
`FORMAT = nullQueue`,
|
|
81
|
+
];
|
|
82
|
+
if (svc)
|
|
83
|
+
lines.push(`# Apply in props.conf under [source::${svc}]`);
|
|
84
|
+
return { label: 'Add this stanza to transforms.conf to route matching events to nullQueue.', text: lines.join('\n') };
|
|
85
|
+
}
|
|
86
|
+
if (vk === 'splunk' && mode === 'api') {
|
|
87
|
+
return {
|
|
88
|
+
label: 'Run this curl command to create a transforms extraction via the Splunk REST API.',
|
|
89
|
+
text: `curl -k -u <USERNAME>:<PASSWORD> \\\n "https://<SPLUNK_HOST>:8089/servicesNS/nobody/search/data/transforms/extractions" \\\n -d name=drop_${tokens.slice(0, 3).join('_')} \\\n -d REGEX="${patRegex}" \\\n -d DEST_KEY=queue \\\n -d FORMAT=nullQueue`
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (vk === 'elasticsearch' && mode === 'config') {
|
|
93
|
+
const condition = `ctx.message != null && ctx.message =~ /${patRegex}/`
|
|
94
|
+
+ (svc ? ` && ctx['service.name'] == '${svc}'` : '')
|
|
95
|
+
+ (sev && sev !== 'uncl' ? ` && ctx.level == '${sev.toUpperCase()}'` : '');
|
|
96
|
+
return {
|
|
97
|
+
label: 'Add this drop processor to an ingest pipeline under Stack Management > Ingest Pipelines.',
|
|
98
|
+
text: JSON.stringify({ drop: { if: condition } }, null, 2)
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (vk === 'elasticsearch' && mode === 'api') {
|
|
102
|
+
const condition = `ctx.message != null && ctx.message =~ /${patRegex}/`
|
|
103
|
+
+ (svc ? ` && ctx['service.name'] == '${svc}'` : '')
|
|
104
|
+
+ (sev && sev !== 'uncl' ? ` && ctx.level == '${sev.toUpperCase()}'` : '');
|
|
105
|
+
const body = JSON.stringify({ description: `Drop ${rawPattern.slice(0, 40)}`, processors: [{ drop: { if: condition } }] }, null, 2);
|
|
106
|
+
return {
|
|
107
|
+
label: 'Run this curl command to create an ingest pipeline with a drop processor.',
|
|
108
|
+
text: `curl -X PUT "https://<ES_HOST>:9200/_ingest/pipeline/<PIPELINE_ID>" \\\n -H "Content-Type: application/json" \\\n -u <USERNAME>:<PASSWORD> \\\n -d '${body}'`
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (vk === 'cloudwatch') {
|
|
112
|
+
return { label: 'Use this regex in a Lambda subscription filter on the matching log group.', text: patRegex };
|
|
113
|
+
}
|
|
114
|
+
// ── Forwarders ──
|
|
115
|
+
if (vk === 'datadog-agent') {
|
|
116
|
+
const lines = [
|
|
117
|
+
`# Add to your Datadog Agent log integration config`,
|
|
118
|
+
`# (e.g. conf.d/<integration>.d/conf.yaml)`,
|
|
119
|
+
`logs:`,
|
|
120
|
+
` - type: file`,
|
|
121
|
+
` path: /var/log/app.log`,
|
|
122
|
+
];
|
|
123
|
+
if (svc)
|
|
124
|
+
lines.push(` service: ${svc}`);
|
|
125
|
+
lines.push(` log_processing_rules:`, ` - type: exclude_at_match`, ` name: drop_${tokens.slice(0, 3).join('_')}`, ` pattern: '${patRegex}'`);
|
|
126
|
+
return { label: 'Add this log_processing_rules block to your Datadog Agent config to drop matching events before ingestion.', text: lines.join('\n') };
|
|
127
|
+
}
|
|
128
|
+
if (vk === 'fluentbit') {
|
|
129
|
+
const lines = [
|
|
130
|
+
`# Add to your Fluent Bit configuration`,
|
|
131
|
+
`[FILTER]`,
|
|
132
|
+
` Name grep`,
|
|
133
|
+
` Match ${svc || '*'}`,
|
|
134
|
+
` Exclude log ${patRegex}`,
|
|
135
|
+
];
|
|
136
|
+
return { label: 'Add this filter section to your Fluent Bit configuration to drop matching events.', text: lines.join('\n') };
|
|
137
|
+
}
|
|
138
|
+
if (vk === 'fluentd') {
|
|
139
|
+
const lines = [
|
|
140
|
+
`# Add to your Fluentd configuration`,
|
|
141
|
+
`<filter ${svc || '**'}>`,
|
|
142
|
+
` @type grep`,
|
|
143
|
+
` <exclude>`,
|
|
144
|
+
` key message`,
|
|
145
|
+
` pattern /${patRegex}/`,
|
|
146
|
+
` </exclude>`,
|
|
147
|
+
];
|
|
148
|
+
if (sev && sev !== 'uncl') {
|
|
149
|
+
lines.push(` <exclude>`, ` key level`, ` pattern /^${sev}$/i`, ` </exclude>`);
|
|
150
|
+
}
|
|
151
|
+
lines.push(`</filter>`);
|
|
152
|
+
return { label: 'Add this filter block to your Fluentd configuration to drop matching events.', text: lines.join('\n') };
|
|
153
|
+
}
|
|
154
|
+
if (vk === 'otel') {
|
|
155
|
+
const cond = [`IsMatch(body, "${patRegex}")`];
|
|
156
|
+
if (svc)
|
|
157
|
+
cond.push(`resource.attributes["service.name"] == "${svc}"`);
|
|
158
|
+
if (sev && sev !== 'uncl')
|
|
159
|
+
cond.push(`severity_text == "${sev.toUpperCase()}"`);
|
|
160
|
+
const lines = [
|
|
161
|
+
`# Add to your OTel Collector config under processors:`,
|
|
162
|
+
`processors:`,
|
|
163
|
+
` filter/drop_pattern:`,
|
|
164
|
+
` logs:`,
|
|
165
|
+
` log_record:`,
|
|
166
|
+
` - '${cond.join(' and ')}'`,
|
|
167
|
+
];
|
|
168
|
+
return { label: 'Add this filter processor to your OTel Collector config to drop matching events.', text: lines.join('\n') };
|
|
169
|
+
}
|
|
170
|
+
if (vk === 'vector') {
|
|
171
|
+
const conds = [`match(string!(.message), r'${patRegex}')`];
|
|
172
|
+
if (svc)
|
|
173
|
+
conds.push(`.service == "${svc}"`);
|
|
174
|
+
if (sev && sev !== 'uncl')
|
|
175
|
+
conds.push(`.level == "${sev}"`);
|
|
176
|
+
const lines = [
|
|
177
|
+
`# Add to your Vector configuration (vector.toml)`,
|
|
178
|
+
`[transforms.drop_pattern]`,
|
|
179
|
+
`type = "filter"`,
|
|
180
|
+
`inputs = ["<YOUR_SOURCE>"]`,
|
|
181
|
+
`condition = '!(${conds.join(' && ')})'`,
|
|
182
|
+
];
|
|
183
|
+
return { label: 'Add this filter transform to your Vector config to drop matching events.', text: lines.join('\n') };
|
|
184
|
+
}
|
|
185
|
+
if (vk === 'logstash') {
|
|
186
|
+
const conds = [`[message] =~ /${patRegex}/`];
|
|
187
|
+
if (svc)
|
|
188
|
+
conds.push(`[service] == "${svc}"`);
|
|
189
|
+
if (sev && sev !== 'uncl')
|
|
190
|
+
conds.push(`[level] == "${sev}"`);
|
|
191
|
+
const lines = [
|
|
192
|
+
`# Add to the filter section of your Logstash pipeline`,
|
|
193
|
+
`filter {`,
|
|
194
|
+
` if ${conds.join(' and ')} {`,
|
|
195
|
+
` drop { }`,
|
|
196
|
+
` }`,
|
|
197
|
+
`}`,
|
|
198
|
+
];
|
|
199
|
+
return { label: 'Add this filter block to your Logstash pipeline to drop matching events.', text: lines.join('\n') };
|
|
200
|
+
}
|
|
201
|
+
if (vk === 'filebeat') {
|
|
202
|
+
const lines = [`# Add to the processors section of your filebeat.yml`];
|
|
203
|
+
const conditions = [{ regexp: { message: patRegex } }];
|
|
204
|
+
if (svc)
|
|
205
|
+
conditions.push({ equals: { 'service.name': svc } });
|
|
206
|
+
if (sev && sev !== 'uncl')
|
|
207
|
+
conditions.push({ equals: { 'log.level': sev } });
|
|
208
|
+
lines.push(`processors:`, ` - drop_event:`);
|
|
209
|
+
if (conditions.length > 1) {
|
|
210
|
+
lines.push(` when:`, ` and:`);
|
|
211
|
+
for (const c of conditions)
|
|
212
|
+
lines.push(` - ${JSON.stringify(c)}`);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
lines.push(` when:`, ` regexp:`, ` message: '${patRegex}'`);
|
|
216
|
+
}
|
|
217
|
+
return { label: 'Add this processor to your filebeat.yml to drop matching events.', text: lines.join('\n') };
|
|
218
|
+
}
|
|
219
|
+
if (vk === 'rsyslog') {
|
|
220
|
+
const lines = [`# Add to your rsyslog.conf or /etc/rsyslog.d/*.conf`];
|
|
221
|
+
if (svc)
|
|
222
|
+
lines.push(`# For messages from ${svc}:`);
|
|
223
|
+
lines.push(`:msg, regex, "${patRegex}" stop`);
|
|
224
|
+
return { label: 'Add this rule to your rsyslog config to drop matching messages.', text: lines.join('\n') };
|
|
225
|
+
}
|
|
226
|
+
if (vk === 'syslog-ng') {
|
|
227
|
+
const lines = [
|
|
228
|
+
`# Add to your syslog-ng.conf`,
|
|
229
|
+
`filter f_drop_pattern {`,
|
|
230
|
+
` not match("${patRegex}" value("MESSAGE"))`,
|
|
231
|
+
`};`,
|
|
232
|
+
];
|
|
233
|
+
return { label: 'Add this filter to your syslog-ng config and apply it to your log path.', text: lines.join('\n') };
|
|
234
|
+
}
|
|
235
|
+
if (vk === 'promtail') {
|
|
236
|
+
const lines = [
|
|
237
|
+
`# Add to your Promtail config under scrape_configs > pipeline_stages`,
|
|
238
|
+
`pipeline_stages:`,
|
|
239
|
+
` - drop:`,
|
|
240
|
+
` expression: '${patRegex}'`,
|
|
241
|
+
];
|
|
242
|
+
return { label: 'Add this pipeline stage to your Promtail config to drop matching events before sending to Loki.', text: lines.join('\n') };
|
|
243
|
+
}
|
|
244
|
+
return { label: 'Regex pattern matching this log template.', text: patRegex };
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=exclusion-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exclusion-filter.js","sourceRoot":"","sources":["../../src/tools/exclusion-filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* log10x_savings — pipeline savings summary.
|
|
3
|
+
*
|
|
4
|
+
* Shows current savings from regulator (filtering), optimizer (compaction),
|
|
5
|
+
* and streamer (indexing). Projects annual savings.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import type { EnvConfig } from '../lib/environments.js';
|
|
9
|
+
export declare const savingsSchema: {
|
|
10
|
+
timeRange: z.ZodDefault<z.ZodEnum<["1d", "7d", "30d"]>>;
|
|
11
|
+
analyzerCost: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
environment: z.ZodOptional<z.ZodString>;
|
|
13
|
+
};
|
|
14
|
+
export declare function executeSavings(args: {
|
|
15
|
+
timeRange: string;
|
|
16
|
+
analyzerCost: number;
|
|
17
|
+
}, env: EnvConfig): Promise<string>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* log10x_savings — pipeline savings summary.
|
|
3
|
+
*
|
|
4
|
+
* Shows current savings from regulator (filtering), optimizer (compaction),
|
|
5
|
+
* and streamer (indexing). Projects annual savings.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { queryInstant } from '../lib/api.js';
|
|
9
|
+
import * as pql from '../lib/promql.js';
|
|
10
|
+
import { bytesToCost, parsePrometheusValue } from '../lib/cost.js';
|
|
11
|
+
import { fmtDollar, fmtBytes, parseTimeframe, costPeriodLabel } from '../lib/format.js';
|
|
12
|
+
export const savingsSchema = {
|
|
13
|
+
timeRange: z.enum(['1d', '7d', '30d']).default('7d').describe('Time range'),
|
|
14
|
+
analyzerCost: z.number().optional().describe('SIEM ingestion cost in $/GB'),
|
|
15
|
+
environment: z.string().optional().describe('Environment nickname'),
|
|
16
|
+
};
|
|
17
|
+
export async function executeSavings(args, env) {
|
|
18
|
+
const tf = parseTimeframe(args.timeRange);
|
|
19
|
+
const costPerGb = args.analyzerCost;
|
|
20
|
+
const period = costPeriodLabel(tf.days);
|
|
21
|
+
// Query all savings metrics in parallel
|
|
22
|
+
const [regInRes, regOutRes, optInRes, optOutRes, streamRes, pipeRes, svcRes] = await Promise.all([
|
|
23
|
+
queryInstant(env, pql.regulatorInput(tf.range)).catch(() => null),
|
|
24
|
+
queryInstant(env, pql.regulatorOutput(tf.range)).catch(() => null),
|
|
25
|
+
queryInstant(env, pql.optimizerInput(tf.range)).catch(() => null),
|
|
26
|
+
queryInstant(env, pql.optimizerOutput(tf.range)).catch(() => null),
|
|
27
|
+
queryInstant(env, pql.streamerIndexed(tf.range)).catch(() => null),
|
|
28
|
+
queryInstant(env, pql.pipelineUp()).catch(() => null),
|
|
29
|
+
queryInstant(env, pql.distinctServices(tf.range)).catch(() => null),
|
|
30
|
+
]);
|
|
31
|
+
const regIn = regInRes?.data?.result?.[0] ? parsePrometheusValue(regInRes.data.result[0]) : 0;
|
|
32
|
+
const regOut = regOutRes?.data?.result?.[0] ? parsePrometheusValue(regOutRes.data.result[0]) : 0;
|
|
33
|
+
const optIn = optInRes?.data?.result?.[0] ? parsePrometheusValue(optInRes.data.result[0]) : 0;
|
|
34
|
+
const optOut = optOutRes?.data?.result?.[0] ? parsePrometheusValue(optOutRes.data.result[0]) : 0;
|
|
35
|
+
const streamBytes = streamRes?.data?.result?.[0] ? parsePrometheusValue(streamRes.data.result[0]) : 0;
|
|
36
|
+
const pipeCount = pipeRes?.data?.result?.[0] ? parsePrometheusValue(pipeRes.data.result[0]) : 0;
|
|
37
|
+
const svcCount = svcRes?.data?.result?.[0] ? parsePrometheusValue(svcRes.data.result[0]) : 0;
|
|
38
|
+
const regSavedBytes = Math.max(0, regIn - regOut);
|
|
39
|
+
const optSavedBytes = Math.max(0, optIn - optOut);
|
|
40
|
+
const regSavedCost = bytesToCost(regSavedBytes, costPerGb);
|
|
41
|
+
const optSavedCost = bytesToCost(optSavedBytes, costPerGb);
|
|
42
|
+
const streamCost = bytesToCost(streamBytes, costPerGb);
|
|
43
|
+
const totalSaved = regSavedCost + optSavedCost + streamCost;
|
|
44
|
+
const annualProjection = totalSaved * (365 / tf.days);
|
|
45
|
+
const lines = [];
|
|
46
|
+
lines.push(`Pipeline Savings (${tf.label}) at ${fmtDollar(costPerGb)}/GB`);
|
|
47
|
+
lines.push('');
|
|
48
|
+
if (regSavedBytes > 0) {
|
|
49
|
+
lines.push(` Regulator: ${fmtBytes(regSavedBytes).padEnd(14)} filtered → ${fmtDollar(regSavedCost)}${period} saved`);
|
|
50
|
+
}
|
|
51
|
+
if (optSavedBytes > 0) {
|
|
52
|
+
lines.push(` Optimizer: ${fmtBytes(optSavedBytes).padEnd(14)} compacted → ${fmtDollar(optSavedCost)}${period} saved`);
|
|
53
|
+
}
|
|
54
|
+
if (streamBytes > 0) {
|
|
55
|
+
lines.push(` Streamer: ${fmtBytes(streamBytes).padEnd(14)} indexed → ${fmtDollar(streamCost)}${period} saved`);
|
|
56
|
+
}
|
|
57
|
+
if (totalSaved === 0) {
|
|
58
|
+
lines.push(' No savings data available yet. Savings appear once the pipeline processes data.');
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
lines.push('');
|
|
62
|
+
lines.push(` Total: ${fmtDollar(totalSaved)}${period} · ${fmtDollar(annualProjection)}/yr projected`);
|
|
63
|
+
}
|
|
64
|
+
if (pipeCount > 0 || svcCount > 0) {
|
|
65
|
+
lines.push('');
|
|
66
|
+
const parts = [];
|
|
67
|
+
if (pipeCount > 0)
|
|
68
|
+
parts.push(`${Math.round(pipeCount)} pipeline instance${pipeCount !== 1 ? 's' : ''}`);
|
|
69
|
+
if (svcCount > 0)
|
|
70
|
+
parts.push(`${Math.round(svcCount)} service${svcCount !== 1 ? 's' : ''} monitored`);
|
|
71
|
+
lines.push(` ${parts.join(' · ')}`);
|
|
72
|
+
}
|
|
73
|
+
return lines.join('\n');
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=savings.js.map
|