omdnotificationforwarder 4.2__tar.gz → 4.3__tar.gz
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.
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/PKG-INFO +3 -3
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/README.md +1 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/bin/notificationforwarder +2 -2
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/pyproject.toml +3 -4
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/baseclass.py +1 -1
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/nostr/formatter.py +3 -15
- omdnotificationforwarder-4.3/src/notificationforwarder/nostr/forwarder.py +130 -0
- omdnotificationforwarder-4.3/src/notificationforwarder/util.py +37 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/test_alertmanager.py +3 -2
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/test_formatter.py +58 -1
- omdnotificationforwarder-4.3/tests/test_nostr.py +355 -0
- omdnotificationforwarder-4.2/src/notificationforwarder/nostr/forwarder.py +0 -141
- omdnotificationforwarder-4.2/tests/test_nostr.py +0 -261
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/.gitignore +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/component_loader.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/email/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/email/forwarder.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/example/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/example/forwarder.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/json/__init__.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/json/logger.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/naemonlog/reporter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/nostr/__init__.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/oauth2webhook/__init__.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/oauth2webhook/forwarder.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/rabbitmq/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/rabbitmq/forwarder.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/runtime_config.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/runtime_flow.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/spool.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/syslog/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/syslog/forwarder.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/telegram/forwarder.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/text/__init__.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/text/logger.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/src/notificationforwarder/webhook/forwarder.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/lib/python/notificationforwarder/split1/forwarder.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/lib/python/notificationforwarder/split2/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/lib/python/notificationforwarder/split2/forwarder.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/lib/python/notificationforwarder/split3/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/lib/python/notificationforwarder/split3/forwarder.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/local/lib/python/notificationforwarder/alertmanager_servicenow/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/local/lib/python/notificationforwarder/bayern/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/local/lib/python/notificationforwarder/datadup/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/local/lib/python/notificationforwarder/datapost/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/local/lib/python/notificationforwarder/discard/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/local/lib/python/notificationforwarder/split1/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/local/lib/python/notificationforwarder/split2/forwarder.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/local/lib/python/notificationforwarder/split3/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/local/lib/python/notificationforwarder/split3/forwarder.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/local/lib/python/notificationforwarder/split4/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/local/lib/python/notificationforwarder/split4/forwarder.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/local/lib/python/notificationforwarder/ticketsystem/forwarder.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/local/lib/python/notificationforwarder/ticketsystem/reporter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/pythonpath/local/lib/python/notificationforwarder/vong/formatter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/test_builtin_plugins_focus.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/test_classes.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/test_delivery_resilience.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/test_discard.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/test_logger.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/test_oauth2webhook.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/test_package.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/test_paths.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/test_reporter.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/test_runtime_foundation.py +0 -0
- {omdnotificationforwarder-4.2 → omdnotificationforwarder-4.3}/tests/test_webhook.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: omdnotificationforwarder
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.3
|
|
4
4
|
Summary: A framework for notification scripts for OMD
|
|
5
5
|
Project-URL: Homepage, https://github.com/lausser/noteventificationforhandlerwarder
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/lausser/noteventificationforhandlerwarder/issues
|
|
@@ -9,10 +9,9 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
9
9
|
Classifier: Operating System :: OS Independent
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Requires-Python: >=3.6.1
|
|
12
|
-
Requires-Dist: coshsh
|
|
13
12
|
Requires-Dist: jinja2
|
|
14
13
|
Provides-Extra: nostr
|
|
15
|
-
Requires-Dist:
|
|
14
|
+
Requires-Dist: nostr-sdk; extra == 'nostr'
|
|
16
15
|
Provides-Extra: test
|
|
17
16
|
Requires-Dist: flake8; extra == 'test'
|
|
18
17
|
Requires-Dist: pytest; extra == 'test'
|
|
@@ -25,6 +24,7 @@ Description-Content-Type: text/markdown
|
|
|
25
24
|
In this framework, two aspects are in the focus. How to transport a notification to the recipient system and in which format.
|
|
26
25
|
In the beginning, Naemon or one of the other monitoring cores will execute a command line. The actual script and the individual command line parameters are defined in a command definition. Typical parameters are (i use the notation of Nagios macros) HOSTNAME, SERVICEDESC, SERVICESTATE, SERVICEOUTPUT. These snippets need to be put together to some kind of payload suitable for the receiving system. And then this payload must be transported to it. We call the two components *formatter* and *forwarder*. The formatter takes the raw input data and creates a payload and the forwarder transmits the payload to the destination.
|
|
27
26
|
What the framework does for you behind the scenes: When forwarding to a recipient fails, the event is saved in a local sqlite database for a certain time and re-sent when the script is called next time and the recipient is available again. Logging of successful and of course failed deliveries is also done automatically.
|
|
27
|
+
Logging uses the framework's native setup with the standard logfile naming and format used by the built-in tools.
|
|
28
28
|
There is also a component *reporter* which will rarely be used. It's purpose is to run additional code after a successful or failed delivery.
|
|
29
29
|
|
|
30
30
|
Let me list some of the formatter/forwarder combinations which are usually found in enterprise environments:
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
In this framework, two aspects are in the focus. How to transport a notification to the recipient system and in which format.
|
|
4
4
|
In the beginning, Naemon or one of the other monitoring cores will execute a command line. The actual script and the individual command line parameters are defined in a command definition. Typical parameters are (i use the notation of Nagios macros) HOSTNAME, SERVICEDESC, SERVICESTATE, SERVICEOUTPUT. These snippets need to be put together to some kind of payload suitable for the receiving system. And then this payload must be transported to it. We call the two components *formatter* and *forwarder*. The formatter takes the raw input data and creates a payload and the forwarder transmits the payload to the destination.
|
|
5
5
|
What the framework does for you behind the scenes: When forwarding to a recipient fails, the event is saved in a local sqlite database for a certain time and re-sent when the script is called next time and the recipient is available again. Logging of successful and of course failed deliveries is also done automatically.
|
|
6
|
+
Logging uses the framework's native setup with the standard logfile naming and format used by the built-in tools.
|
|
6
7
|
There is also a component *reporter* which will rarely be used. It's purpose is to run additional code after a successful or failed delivery.
|
|
7
8
|
|
|
8
9
|
Let me list some of the formatter/forwarder combinations which are usually found in enterprise environments:
|
|
@@ -6,7 +6,7 @@ import logging.handlers
|
|
|
6
6
|
import os
|
|
7
7
|
import sys
|
|
8
8
|
#import logging
|
|
9
|
-
from
|
|
9
|
+
from notificationforwarder.util import setup_logging
|
|
10
10
|
from notificationforwarder import baseclass
|
|
11
11
|
import traceback
|
|
12
12
|
|
|
@@ -78,7 +78,7 @@ Example for an HTTP-based reporter:
|
|
|
78
78
|
help='Logger type: text (default) or json, or custom logger module',
|
|
79
79
|
default='text')
|
|
80
80
|
parser.add_argument('--version', action='version',
|
|
81
|
-
version=f'%(prog)s 4.
|
|
81
|
+
version=f'%(prog)s 4.3')
|
|
82
82
|
|
|
83
83
|
args = parser.parse_args()
|
|
84
84
|
if not hasattr(args, 'formatter'):
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["hatchling"
|
|
2
|
+
requires = ["hatchling"]
|
|
3
3
|
build-backend = "hatchling.build"
|
|
4
4
|
|
|
5
5
|
[tool.hatch.build]
|
|
@@ -21,7 +21,7 @@ packages = ["src/notificationforwarder"]
|
|
|
21
21
|
|
|
22
22
|
[project]
|
|
23
23
|
name = "omdnotificationforwarder"
|
|
24
|
-
version = "4.
|
|
24
|
+
version = "4.3"
|
|
25
25
|
authors = [
|
|
26
26
|
{ name="Gerhard Lausser", email="lausser@yahoo.com" },
|
|
27
27
|
]
|
|
@@ -34,13 +34,12 @@ classifiers = [
|
|
|
34
34
|
"Operating System :: OS Independent",
|
|
35
35
|
]
|
|
36
36
|
dependencies = [
|
|
37
|
-
"coshsh",
|
|
38
37
|
"jinja2",
|
|
39
38
|
]
|
|
40
39
|
|
|
41
40
|
[project.optional-dependencies]
|
|
42
41
|
nostr = [
|
|
43
|
-
"
|
|
42
|
+
"nostr-sdk",
|
|
44
43
|
]
|
|
45
44
|
test = [
|
|
46
45
|
"requests",
|
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
"""Generate a Nostr keypair and derive bech32 values.
|
|
2
|
-
|
|
3
|
-
```python
|
|
4
|
-
from pynostr.key import PrivateKey
|
|
5
|
-
|
|
6
|
-
private_key = PrivateKey()
|
|
7
|
-
print(private_key.bech32()) # nsec1...
|
|
8
|
-
print(private_key.public_key.bech32()) # npub1...
|
|
9
|
-
```
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
1
|
import json
|
|
13
2
|
|
|
14
3
|
from notificationforwarder.baseclass import NotificationFormatter
|
|
@@ -25,11 +14,11 @@ class NostrFormatter(NotificationFormatter):
|
|
|
25
14
|
def _build_tags(self, host, service, state, extra_tags=None):
|
|
26
15
|
tags = [["t", "monitoring"]]
|
|
27
16
|
if host:
|
|
28
|
-
tags.append(["
|
|
17
|
+
tags.append(["t", "host=" + host])
|
|
29
18
|
if service:
|
|
30
|
-
tags.append(["
|
|
19
|
+
tags.append(["t", "service=" + service])
|
|
31
20
|
if state:
|
|
32
|
-
tags.append(["
|
|
21
|
+
tags.append(["t", "state=" + state])
|
|
33
22
|
if isinstance(extra_tags, str):
|
|
34
23
|
try:
|
|
35
24
|
extra_tags = json.loads(extra_tags)
|
|
@@ -54,7 +43,6 @@ class NostrFormatter(NotificationFormatter):
|
|
|
54
43
|
]
|
|
55
44
|
content = "\n".join(lines)
|
|
56
45
|
event.payload = {
|
|
57
|
-
"kind": 4,
|
|
58
46
|
"content": content,
|
|
59
47
|
"tags": self._build_tags(
|
|
60
48
|
host,
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
from nostr_sdk import Client, Keys, NostrSigner, PublicKey, RelayUrl, Tag, uniffi_set_event_loop
|
|
5
|
+
except ImportError as exc:
|
|
6
|
+
raise ImportError("missing nostr-sdk") from exc
|
|
7
|
+
|
|
8
|
+
from notificationforwarder.baseclass import NotificationForwarder, timeout
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class NostrForwarder(NotificationForwarder):
|
|
12
|
+
def __init__(self, opts):
|
|
13
|
+
super(self.__class__, self).__init__(opts)
|
|
14
|
+
setattr(self, "relays", getattr(self, "relays", "wss://relay.damus.io"))
|
|
15
|
+
setattr(self, "relay_urls", getattr(self, "relay_urls", self.relays))
|
|
16
|
+
setattr(self, "nsec", getattr(self, "nsec", None))
|
|
17
|
+
setattr(self, "timeout_seconds", int(getattr(self, "timeout_seconds", 6)))
|
|
18
|
+
|
|
19
|
+
def _relay_list(self):
|
|
20
|
+
relays = self.relay_urls if self.relay_urls is not None else self.relays
|
|
21
|
+
if isinstance(relays, str):
|
|
22
|
+
return [relay.strip() for relay in relays.split(",") if relay.strip()]
|
|
23
|
+
if isinstance(relays, (list, tuple)):
|
|
24
|
+
return [str(relay).strip() for relay in relays if str(relay).strip()]
|
|
25
|
+
return []
|
|
26
|
+
|
|
27
|
+
def _keys(self):
|
|
28
|
+
if not self.nsec:
|
|
29
|
+
raise ValueError("nsec is required for Nostr publishing")
|
|
30
|
+
return Keys.parse(self.nsec)
|
|
31
|
+
|
|
32
|
+
def _public_key(self, value):
|
|
33
|
+
if isinstance(value, PublicKey):
|
|
34
|
+
return value
|
|
35
|
+
if not isinstance(value, str):
|
|
36
|
+
raise ValueError("receiver public key must be a string or PublicKey")
|
|
37
|
+
return PublicKey.parse(value)
|
|
38
|
+
|
|
39
|
+
def _tags(self, formatted_event):
|
|
40
|
+
tags = []
|
|
41
|
+
payload = formatted_event.payload or {}
|
|
42
|
+
tag_values = payload.get("tags", [])
|
|
43
|
+
if isinstance(tag_values, str):
|
|
44
|
+
import json
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
tag_values = json.loads(tag_values)
|
|
48
|
+
except Exception:
|
|
49
|
+
tag_values = []
|
|
50
|
+
if isinstance(tag_values, (list, tuple)):
|
|
51
|
+
for tag in tag_values:
|
|
52
|
+
if isinstance(tag, (list, tuple)) and tag:
|
|
53
|
+
tags.append(Tag.parse(list(tag)))
|
|
54
|
+
return tags
|
|
55
|
+
|
|
56
|
+
def _configured_tags(self):
|
|
57
|
+
tag_values = getattr(self, "tags", [])
|
|
58
|
+
if isinstance(tag_values, str):
|
|
59
|
+
import json
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
tag_values = json.loads(tag_values)
|
|
63
|
+
except Exception:
|
|
64
|
+
tag_values = []
|
|
65
|
+
return tag_values if isinstance(tag_values, (list, tuple)) else []
|
|
66
|
+
|
|
67
|
+
def _nip_mode(self):
|
|
68
|
+
return getattr(self, "nip_mode", "nip04")
|
|
69
|
+
|
|
70
|
+
async def _send_private_msg(self, relay_urls, receiver_pubkey, message, tags):
|
|
71
|
+
uniffi_set_event_loop(asyncio.get_running_loop())
|
|
72
|
+
keys = self._keys()
|
|
73
|
+
signer = NostrSigner.keys(keys)
|
|
74
|
+
client = Client(signer)
|
|
75
|
+
relay_urls = [RelayUrl.parse(url) for url in relay_urls]
|
|
76
|
+
|
|
77
|
+
for relay_url in relay_urls:
|
|
78
|
+
await client.add_relay(relay_url)
|
|
79
|
+
|
|
80
|
+
await client.connect()
|
|
81
|
+
return await client.send_private_msg_to(relay_urls, receiver_pubkey, message, tags)
|
|
82
|
+
|
|
83
|
+
async def _send_nip04_dm(self, relay_urls, receiver_pubkey, message):
|
|
84
|
+
uniffi_set_event_loop(asyncio.get_running_loop())
|
|
85
|
+
keys = self._keys()
|
|
86
|
+
signer = NostrSigner.keys(keys)
|
|
87
|
+
client = Client(signer)
|
|
88
|
+
relay_urls = [RelayUrl.parse(url) for url in relay_urls]
|
|
89
|
+
|
|
90
|
+
for relay_url in relay_urls:
|
|
91
|
+
await client.add_relay(relay_url)
|
|
92
|
+
|
|
93
|
+
await client.connect()
|
|
94
|
+
return await client.send_private_msg_to(relay_urls, receiver_pubkey, message, [])
|
|
95
|
+
|
|
96
|
+
@timeout(30)
|
|
97
|
+
def submit(self, event):
|
|
98
|
+
relay_urls = self._relay_list()
|
|
99
|
+
if not relay_urls:
|
|
100
|
+
logger.critical("Nostr publish failed: no relays configured")
|
|
101
|
+
return False
|
|
102
|
+
|
|
103
|
+
payload = event.payload or {}
|
|
104
|
+
nip_mode = self._nip_mode()
|
|
105
|
+
tags = self._configured_tags() or payload.get("tags", [])
|
|
106
|
+
recipient_pubkey = None
|
|
107
|
+
for tag in tags or []:
|
|
108
|
+
if isinstance(tag, (list, tuple)) and len(tag) > 1 and tag[0] == "p":
|
|
109
|
+
recipient_pubkey = self._public_key(tag[1])
|
|
110
|
+
break
|
|
111
|
+
if recipient_pubkey is None:
|
|
112
|
+
raise ValueError("Nostr DM requires a recipient p tag")
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
message = payload.get("content", event.summary or str(payload))
|
|
116
|
+
nip_mode = self._nip_mode()
|
|
117
|
+
logger.debug("Nostr NIP mode: {}".format(nip_mode))
|
|
118
|
+
if nip_mode == "nip17":
|
|
119
|
+
# For NIP-17, use tags from payload (like [["t", "monitoring"]])
|
|
120
|
+
tags = self._tags(event)
|
|
121
|
+
asyncio.run(self._send_private_msg(relay_urls, recipient_pubkey, message, tags))
|
|
122
|
+
else:
|
|
123
|
+
# NIP-04: send without tags (nostr-sdk doesn't support NIP-04 tags easily)
|
|
124
|
+
asyncio.run(self._send_nip04_dm(relay_urls, recipient_pubkey, message))
|
|
125
|
+
logger.info("published Nostr DM: {}".format(event.summary))
|
|
126
|
+
self.no_more_logging()
|
|
127
|
+
return True
|
|
128
|
+
except Exception as exc:
|
|
129
|
+
logger.critical("Nostr publish failed: {}".format(str(exc)))
|
|
130
|
+
return False
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from logging.handlers import RotatingFileHandler
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def setup_logging(logdir=".", logfile="notificationforwarder.log", scrnloglevel=logging.INFO, txtloglevel=logging.INFO, format="%(asctime)s %(process)d - %(levelname)s - %(message)s", backup_count=3):
|
|
8
|
+
logdir_path = Path(logdir)
|
|
9
|
+
logdir_path.mkdir(parents=True, exist_ok=True)
|
|
10
|
+
|
|
11
|
+
logfile_path = Path(logfile)
|
|
12
|
+
abs_logfile = logfile_path if logfile_path.is_absolute() else logdir_path / logfile_path
|
|
13
|
+
abs_logfile.touch(exist_ok=True)
|
|
14
|
+
logger_name = abs_logfile.name[:-4] if abs_logfile.name.endswith(".log") else abs_logfile.name
|
|
15
|
+
logger = logging.getLogger(logger_name)
|
|
16
|
+
logger.setLevel(logging.DEBUG)
|
|
17
|
+
logger.propagate = False
|
|
18
|
+
|
|
19
|
+
for handler in list(logger.handlers):
|
|
20
|
+
handler.close()
|
|
21
|
+
logger.removeHandler(handler)
|
|
22
|
+
|
|
23
|
+
formatter = logging.Formatter(format)
|
|
24
|
+
|
|
25
|
+
file_handler = RotatingFileHandler(str(abs_logfile), maxBytes=20 * 1024 * 1024, backupCount=backup_count, delay=True)
|
|
26
|
+
file_handler.setFormatter(formatter)
|
|
27
|
+
file_handler.setLevel(txtloglevel)
|
|
28
|
+
logger.addHandler(file_handler)
|
|
29
|
+
|
|
30
|
+
console_handler = logging.StreamHandler(sys.stderr)
|
|
31
|
+
console_handler.setFormatter(formatter)
|
|
32
|
+
console_handler.setLevel(scrnloglevel)
|
|
33
|
+
logger.addHandler(console_handler)
|
|
34
|
+
|
|
35
|
+
logger.debug("Logger initialized.")
|
|
36
|
+
|
|
37
|
+
return logger
|
|
@@ -149,7 +149,7 @@ def test_alertmanager_forwarder(setup):
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
|
|
152
|
-
amgw = notificationforwarder.baseclass.new("webhook", None, "alertmanager_servicenow",
|
|
152
|
+
amgw = notificationforwarder.baseclass.new("webhook", None, "alertmanager_servicenow", True, True, forwarderopts)
|
|
153
153
|
famgw = amgw.new_formatter()
|
|
154
154
|
assert famgw.__class__.__name__ == "AlertmanagerServicenowFormatter"
|
|
155
155
|
assert famgw.__module_file__.endswith("pythonpath/local/lib/python/notificationforwarder/alertmanager_servicenow/formatter.py")
|
|
@@ -158,9 +158,10 @@ def test_alertmanager_forwarder(setup):
|
|
|
158
158
|
|
|
159
159
|
amgw.forward(eventopts)
|
|
160
160
|
log = open(get_logfile(amgw)).read()
|
|
161
|
+
assert "event has no node" in log
|
|
162
|
+
assert "replace node with 4490.example.net" in log
|
|
161
163
|
assert re.search(r'success: alertmanager sends 2 alarms.*result is .*"records": 2.*4490.*4491.*', log, flags=re.MULTILINE)
|
|
162
164
|
|
|
163
165
|
http_server.shutdown()
|
|
164
166
|
|
|
165
167
|
|
|
166
|
-
|
|
@@ -91,6 +91,64 @@ def test_split3_forwarder_split4_formatter(setup):
|
|
|
91
91
|
assert re.search(r'forwarder '+split3.__module_file__, log)
|
|
92
92
|
assert re.search(r'formatter '+fsplit3.__module_file__, log)
|
|
93
93
|
|
|
94
|
+
|
|
95
|
+
def test_formatter_module_logging_uses_runtime_logfile(setup):
|
|
96
|
+
forwarderopts = {
|
|
97
|
+
"username": "i_bims",
|
|
98
|
+
"password": "dem_is_geheim"
|
|
99
|
+
}
|
|
100
|
+
eventopts = {
|
|
101
|
+
"alertmanager_payload": {
|
|
102
|
+
"receiver": "omd-servicenow-webhook",
|
|
103
|
+
"status": "firing",
|
|
104
|
+
"alerts": [
|
|
105
|
+
{
|
|
106
|
+
"status": "firing",
|
|
107
|
+
"labels": {
|
|
108
|
+
"alertname": "4490",
|
|
109
|
+
"instance": "4490.example.net",
|
|
110
|
+
"service": "my-service",
|
|
111
|
+
"severity": "critical",
|
|
112
|
+
"snow_service_name": "routemetosvcnow"
|
|
113
|
+
},
|
|
114
|
+
"annotations": {
|
|
115
|
+
"summary": "Testing summary!"
|
|
116
|
+
},
|
|
117
|
+
"startsAt": "2024-03-15T19:51:51.78480206Z",
|
|
118
|
+
"endsAt": "0001-01-01T00:00:00Z",
|
|
119
|
+
"generatorURL": "https://prometheus.local/<generating_expression>",
|
|
120
|
+
"fingerprint": "5de8a3a5c73e68d4"
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
"groupLabels": {
|
|
124
|
+
"alertname": "4490",
|
|
125
|
+
"service": "my-service"
|
|
126
|
+
},
|
|
127
|
+
"commonLabels": {
|
|
128
|
+
"alertname": "4490",
|
|
129
|
+
"instance": "4490.example.net",
|
|
130
|
+
"service": "my-service",
|
|
131
|
+
"severity": "critical",
|
|
132
|
+
"snow_service_name": "routemetosvcnow"
|
|
133
|
+
},
|
|
134
|
+
"commonAnnotations": {
|
|
135
|
+
"summary": "Testing summary!"
|
|
136
|
+
},
|
|
137
|
+
"externalURL": "http://omd-lx01.example.com/alertmanager/alertmanager",
|
|
138
|
+
"version": "4",
|
|
139
|
+
"groupKey": "{}/{alertname=~\"^(?:.*)$\",snow_service_name=~\"^(?:..*)$\"}:{alertname=\"4490\", service=\"my-service\"}",
|
|
140
|
+
"truncatedAlerts": 0
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
amgw = notificationforwarder.baseclass.new("webhook", None, "alertmanager_servicenow", True, True, forwarderopts)
|
|
145
|
+
amgw.forward(eventopts)
|
|
146
|
+
|
|
147
|
+
log = open(get_logfile(amgw)).read()
|
|
148
|
+
assert "event has no node" in log
|
|
149
|
+
assert "replace node with 4490.example.net" in log
|
|
150
|
+
assert "job: " in log
|
|
151
|
+
|
|
94
152
|
def test_split3_forwarder_split4_formatter_bin_old(setup):
|
|
95
153
|
# this is used to find out the logfile
|
|
96
154
|
forwarderopts = {
|
|
@@ -123,4 +181,3 @@ def test_split3_forwarder_split4_formatter_bin(setup):
|
|
|
123
181
|
log = open(get_logfile(split3)).read()
|
|
124
182
|
assert "split4_"+signature+"_split4" in log
|
|
125
183
|
|
|
126
|
-
|