Skip to content

Commit f90f92f

Browse files
committed
Fixed Graylog alerts
Graylog changed API call for quering alerts and events. Added graph for showing alerts and events. Signed-off-by: Sven Rueß <[email protected]>
1 parent e688886 commit f90f92f

File tree

5 files changed

+175
-77
lines changed

5 files changed

+175
-77
lines changed

Diff for: cmk/base/plugins/agent_based/graylog_alerts.py

+21-26
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,43 @@
33
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
44
# conditions defined in the file COPYING, which is part of this source code package.
55

6+
"""
7+
Kuhn & Rueß GmbH
8+
Consulting and Development
9+
https://kuhn-ruess.de
10+
"""
11+
12+
613
import json
714
from collections.abc import Mapping
8-
from dataclasses import dataclass
9-
from typing import Any
15+
from typing import Any, NamedTuple
1016

11-
from .agent_based_api.v1 import check_levels, register, render, Service
17+
from .agent_based_api.v1 import check_levels, register, Service
1218
from .agent_based_api.v1.type_defs import CheckResult, DiscoveryResult, StringTable
1319

1420
# <<<graylog_alerts>>>
15-
# {"alerts": {"num_of_alerts": 0, "has_since_argument": false, "alerts_since": null, "num_of_alerts_in_range": 0}}
21+
# {"alerts": {"num_of_events": 947, "num_of_alerts": 174}}
1622

1723
# <<<graylog_alerts>>>
18-
# {"alerts": {"num_of_alerts": 5, "has_since_argument": true, "alerts_since": 1800, "num_of_alerts_in_range": 2}}
24+
# {"alerts": {"num_of_events": 543, "num_of_alerts": 0}}
1925

2026

21-
@dataclass
22-
class AlertsInfo:
27+
class AlertsInfo(NamedTuple):
28+
num_of_events: int
2329
num_of_alerts: int
24-
has_since_argument: bool
25-
alerts_since: int | None
26-
num_of_alerts_in_range: int
2730

2831

2932
def parse_graylog_alerts(string_table: StringTable) -> AlertsInfo | None:
3033
alerts_section = json.loads(string_table[0][0])
34+
3135
if len(alerts_section) != 1:
3236
return None
3337

3438
alerts_data = alerts_section.get("alerts")
3539

3640
return AlertsInfo(
41+
num_of_events=alerts_data.get("num_of_events"),
3742
num_of_alerts=alerts_data.get("num_of_alerts"),
38-
has_since_argument=alerts_data.get("has_since_argument"),
39-
alerts_since=alerts_data.get("alerts_since"),
40-
num_of_alerts_in_range=alerts_data.get("num_of_alerts_in_range"),
4143
)
4244

4345

@@ -53,21 +55,14 @@ def discover_graylog_alerts(section: AlertsInfo) -> DiscoveryResult:
5355

5456

5557
def check_graylog_alerts(params: Mapping[str, Any], section: AlertsInfo) -> CheckResult:
56-
yield from check_levels(
57-
value=section.num_of_alerts,
58-
levels_upper=params.get("alerts_upper", (None, None)),
59-
levels_lower=params.get("alerts_lower", (None, None)),
60-
render_func=lambda x: str(int(x)),
61-
label="Total number of alerts",
62-
)
63-
64-
if section.has_since_argument and section.alerts_since:
58+
for which in ["alerts", "events"]:
6559
yield from check_levels(
66-
value=section.num_of_alerts_in_range,
67-
levels_upper=params.get("alerts_in_range_upper", (None, None)),
68-
levels_lower=params.get("alerts_in_range_lower", (None, None)),
60+
value=(section._asdict())[f"num_of_{which}"],
61+
levels_upper=params.get(f"{which}_upper", (None, None)),
62+
levels_lower=params.get(f"{which}_lower", (None, None)),
63+
metric_name=f"graylog_{which}",
6964
render_func=lambda x: str(int(x)),
70-
label=f"Total number of alerts in the last {render.timespan(section.alerts_since)}",
65+
label=f"Total number of {which}",
7166
)
7267

7368

Diff for: cmk/gui/plugins/metrics/graylog.py

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
Kuhn & Rueß GmbH
5+
Consulting and Development
6+
https://kuhn-ruess.de
7+
"""
8+
9+
10+
from cmk.gui.i18n import _
11+
from cmk.gui.plugins.metrics.utils import graph_info, metric_info
12+
13+
# .
14+
# .--Metrics-------------------------------------------------------------.
15+
# | __ __ _ _ |
16+
# | | \/ | ___| |_ _ __(_) ___ ___ |
17+
# | | |\/| |/ _ \ __| '__| |/ __/ __| |
18+
# | | | | | __/ |_| | | | (__\__ \ |
19+
# | |_| |_|\___|\__|_| |_|\___|___/ |
20+
# | |
21+
# +----------------------------------------------------------------------+
22+
# | Definitions of metrics |
23+
# '----------------------------------------------------------------------'
24+
25+
metric_info["graylog_alerts"] = {
26+
"title": "Total amount of alerts",
27+
"unit": "count",
28+
"color": "blue",
29+
}
30+
metric_info["graylog_events"] = {
31+
"title": "Total amount of events",
32+
"unit": "count",
33+
"color": "green",
34+
}
35+
36+
# .
37+
# .--Graphs--------------------------------------------------------------.
38+
# | ____ _ |
39+
# | / ___|_ __ __ _ _ __ | |__ ___ |
40+
# | | | _| '__/ _` | '_ \| '_ \/ __| |
41+
# | | |_| | | | (_| | |_) | | | \__ \ |
42+
# | \____|_| \__,_| .__/|_| |_|___/ |
43+
# | |_| |
44+
# +----------------------------------------------------------------------+
45+
# | Definitions of time series graphs |
46+
# '----------------------------------------------------------------------'
47+
48+
graph_info["graylog_alerts"] = {
49+
"title": _("Graylog alerts and events"),
50+
"metrics": [
51+
("graylog_alerts", "line"),
52+
("graylog_events", "line"),
53+
],
54+
}

Diff for: cmk/gui/plugins/wato/check_parameters/graylog_alerts.py

+19-12
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
44
# conditions defined in the file COPYING, which is part of this source code package.
55

6+
"""
7+
Kuhn & Rueß GmbH
8+
Consulting and Development
9+
https://kuhn-ruess.de
10+
"""
11+
12+
613
from cmk.gui.i18n import _
714
from cmk.gui.plugins.wato.utils import (
815
CheckParameterRulespecWithoutItem,
@@ -20,8 +27,8 @@ def _parameter_valuespec_graylog_alerts():
2027
Tuple(
2128
title=_("Total alerts count upper levels"),
2229
elements=[
23-
Integer(title=_("Warning at")),
24-
Integer(title=_("Critical at")),
30+
Integer(title=_("Warning at"), unit="alerts"),
31+
Integer(title=_("Critical at"), unit="alerts"),
2532
],
2633
),
2734
),
@@ -30,28 +37,28 @@ def _parameter_valuespec_graylog_alerts():
3037
Tuple(
3138
title=_("Total alerts count lower levels"),
3239
elements=[
33-
Integer(title=_("Warning below")),
34-
Integer(title=_("Critical below")),
40+
Integer(title=_("Warning below"), unit="alerts"),
41+
Integer(title=_("Critical below"), unit="alerts"),
3542
],
3643
),
3744
),
3845
(
39-
"alerts_in_range_upper",
46+
"events_upper",
4047
Tuple(
41-
title=_("Number of alerts in defined timespan upper level"),
48+
title=_("Total events count upper levesl"),
4249
elements=[
43-
Integer(title=_("Warning below"), unit="alerts"),
44-
Integer(title=_("Critical below"), unit="alerts"),
50+
Integer(title=_("Warning at"), unit="events"),
51+
Integer(title=_("Critical at"), unit="events"),
4552
],
4653
),
4754
),
4855
(
49-
"alerts_in_range_lower",
56+
"events_lower",
5057
Tuple(
51-
title=_("Number of alerts in defined timespan lower level"),
58+
title=_("Total event count lower levels"),
5259
elements=[
53-
Integer(title=_("Warning at"), unit="alerts"),
54-
Integer(title=_("Critical at"), unit="alerts"),
60+
Integer(title=_("Warning below"), unit="events"),
61+
Integer(title=_("Critical below"), unit="events"),
5562
],
5663
),
5764
),

Diff for: cmk/special_agents/agent_graylog.py

+50-24
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
44
# conditions defined in the file COPYING, which is part of this source code package.
55

6+
"""
7+
Kuhn & Rueß GmbH
8+
Consulting and Development
9+
https://kuhn-ruess.de
10+
"""
11+
12+
613
import argparse
714
import json
815
import sys
@@ -34,7 +41,7 @@ def main(argv=None):
3441

3542
# Add new queries here
3643
sections = [
37-
GraylogSection(name="alerts", uri="/streams/alerts?limit=300"),
44+
GraylogSection(name="alerts", uri="/events/search"),
3845
GraylogSection(name="cluster_health", uri="/system/indexer/cluster/health"),
3946
GraylogSection(name="cluster_inputstates", uri="/cluster/inputstates"),
4047
GraylogSection(name="cluster_stats", uri="/system/cluster/stats"),
@@ -70,6 +77,14 @@ def handle_request(args, sections): # pylint: disable=too-many-branches
7077

7178
if section.name == "events":
7279
value = handle_response(url, args, "POST").json()
80+
81+
elif section.name == "alerts":
82+
content = {
83+
"filter": {"alerts": "include"},
84+
"timerange": {"type": "relative", "range": args.alerts_since},
85+
}
86+
value = handle_response(url, args, "POST", args.alerts_since, content).json()
87+
7388
else:
7489
value = handle_response(url, args).json()
7590

@@ -157,24 +172,24 @@ def handle_request(args, sections): # pylint: disable=too-many-branches
157172
handle_output([events], section.name, args)
158173

159174
if section.name == "alerts":
160-
num_of_alerts = value.get("total", 0)
161-
num_of_alerts_in_range = 0
162-
alerts_since_argument = args.alerts_since
163-
164-
if alerts_since_argument:
165-
url_alerts_in_range = f"{url}%since={str(alerts_since_argument)}"
166-
num_of_alerts_in_range = (
167-
handle_response(url_alerts_in_range, args).json().get("total", 0)
168-
)
175+
num_of_events = value.get("total_events", 0)
176+
177+
content = {
178+
"filter": {"alerts": "only"},
179+
"timerange": {"type": "relative", "range": args.alerts_since},
180+
}
181+
value = handle_response(url, args, "POST", args.alerts_since, content).json()
182+
183+
num_of_alerts = value.get("total_events", 0)
184+
num_of_events -= num_of_alerts
169185

170186
alerts = {
171187
"alerts": {
188+
"num_of_events": num_of_events,
172189
"num_of_alerts": num_of_alerts,
173-
"has_since_argument": bool(alerts_since_argument),
174-
"alerts_since": alerts_since_argument if alerts_since_argument else None,
175-
"num_of_alerts_in_range": num_of_alerts_in_range,
176190
}
177191
}
192+
178193
handle_output([alerts], section.name, args)
179194

180195
if section.name == "sources":
@@ -219,18 +234,29 @@ def handle_request(args, sections): # pylint: disable=too-many-branches
219234
handle_output(value, section.name, args)
220235

221236

222-
def handle_response(url, args, method="GET", events_since=86400):
237+
def handle_response(url, args, method="GET", events_since=86400, content=None):
223238
if method == "POST":
224239
try:
225-
response = requests.post(
226-
url,
227-
auth=(args.user, args.password),
228-
headers={
229-
"Content-Type": "application/json",
230-
"X-Requested-By": args.user,
231-
},
232-
json={"timerange": {"type": "relative", "range": events_since}},
233-
)
240+
if content:
241+
response = requests.post(
242+
url,
243+
auth=(args.user, args.password),
244+
headers={
245+
"Content-Type": "application/json",
246+
"X-Requested-By": args.user,
247+
},
248+
json=content,
249+
)
250+
else:
251+
response = requests.post(
252+
url,
253+
auth=(args.user, args.password),
254+
headers={
255+
"Content-Type": "application/json",
256+
"X-Requested-By": args.user,
257+
},
258+
json={"timerange": {"type": "relative", "range": events_since}},
259+
)
234260
except requests.exceptions.RequestException as e:
235261
sys.stderr.write("Error: %s\n" % e)
236262
if args.debug:
@@ -330,7 +356,7 @@ def parse_arguments(argv):
330356
"-m",
331357
"--sections",
332358
default=sections,
333-
help="""Comma separated list of data to query. Possible values: %s (default: all)"""
359+
help="""Comma seperated list of data to query. Possible values: %s (default: all)"""
334360
% ", ".join(sections),
335361
)
336362
parser.add_argument(

0 commit comments

Comments
 (0)