kopia lustrzana https://github.com/dgtlmoon/changedetection.io
Notification error log handler (#403)
* Add a notifications debug/error log interface (Link available under the notification URLs list)pull/405/head
rodzic
5a645fb74d
commit
abaec224f6
|
@ -70,6 +70,7 @@ app.config['LOGIN_DISABLED'] = False
|
|||
# Disables caching of the templates
|
||||
app.config['TEMPLATES_AUTO_RELOAD'] = True
|
||||
|
||||
notification_debug_log=[]
|
||||
|
||||
def init_app_secret(datastore_path):
|
||||
secret = ""
|
||||
|
@ -529,6 +530,7 @@ def changedetection_app(config=None, datastore_o=None):
|
|||
'notification_title': form.notification_title.data,
|
||||
'notification_body': form.notification_body.data,
|
||||
'notification_format': form.notification_format.data,
|
||||
'uuid': uuid
|
||||
}
|
||||
notification_q.put(n_object)
|
||||
flash('Test notification queued.')
|
||||
|
@ -765,6 +767,14 @@ def changedetection_app(config=None, datastore_o=None):
|
|||
uuid=uuid)
|
||||
return output
|
||||
|
||||
@app.route("/settings/notification-logs", methods=['GET'])
|
||||
@login_required
|
||||
def notification_logs():
|
||||
global notification_debug_log
|
||||
output = render_template("notification-log.html",
|
||||
logs=notification_debug_log if len(notification_debug_log) else ["No errors or warnings detected"])
|
||||
|
||||
return output
|
||||
@app.route("/api/<string:uuid>/snapshot/current", methods=['GET'])
|
||||
@login_required
|
||||
def api_snapshot(uuid):
|
||||
|
@ -997,6 +1007,7 @@ def check_for_new_version():
|
|||
app.config.exit.wait(86400)
|
||||
|
||||
def notification_runner():
|
||||
global notification_debug_log
|
||||
while not app.config.exit.is_set():
|
||||
try:
|
||||
# At the moment only one thread runs (single runner)
|
||||
|
@ -1011,8 +1022,18 @@ def notification_runner():
|
|||
notification.process_notification(n_object, datastore)
|
||||
|
||||
except Exception as e:
|
||||
print("Watch URL: {} Error {}".format(n_object['watch_url'], e))
|
||||
datastore.update_watch(uuid=n_object['uuid'], update_obj={'last_error': "Notification error: " + str(e)})
|
||||
print("Watch URL: {} Error {}".format(n_object['watch_url'], str(e)))
|
||||
|
||||
# UUID wont be present when we submit a 'test' from the global settings
|
||||
if 'uuid' in n_object:
|
||||
datastore.update_watch(uuid=n_object['uuid'], update_obj={'last_error': "Notification error detected, please see logs."})
|
||||
|
||||
log_lines = str(e).splitlines()
|
||||
notification_debug_log += log_lines
|
||||
|
||||
# Trim the log length
|
||||
notification_debug_log = notification_debug_log[-100:]
|
||||
|
||||
|
||||
|
||||
# Thread runner to check every minute, look for new watches to feed into the Queue.
|
||||
|
|
|
@ -25,9 +25,7 @@ default_notification_body = '{watch_url} had a change.\n---\n{diff}\n---\n'
|
|||
default_notification_title = 'ChangeDetection.io Notification - {watch_url}'
|
||||
|
||||
def process_notification(n_object, datastore):
|
||||
import logging
|
||||
log = logging.getLogger('apprise')
|
||||
log.setLevel('TRACE')
|
||||
|
||||
apobj = apprise.Apprise(debug=True)
|
||||
|
||||
for url in n_object['notification_urls']:
|
||||
|
@ -53,11 +51,22 @@ def process_notification(n_object, datastore):
|
|||
n_title = n_title.replace(token, val)
|
||||
n_body = n_body.replace(token, val)
|
||||
|
||||
apobj.notify(
|
||||
# https://github.com/caronc/apprise/wiki/Development_LogCapture
|
||||
# Anything higher than or equal to WARNING (which covers things like Connection errors)
|
||||
# raise it as an exception
|
||||
|
||||
with apprise.LogCapture(level=apprise.logging.DEBUG) as logs:
|
||||
apobj.notify(
|
||||
body=n_body,
|
||||
title=n_title,
|
||||
body_format=n_format,
|
||||
)
|
||||
body_format=n_format)
|
||||
|
||||
# Returns empty string if nothing found, multi-line string otherwise
|
||||
log_value = logs.getvalue()
|
||||
if log_value and 'WARNING' in log_value or 'ERROR' in log_value:
|
||||
raise Exception(log_value)
|
||||
|
||||
|
||||
|
||||
# Notification title + body content parameters get created here.
|
||||
def create_notification_parameters(n_object, datastore):
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<li>Use <a target=_new href="https://github.com/caronc/apprise">AppRise URLs</a> for notification to just about any service! <i><a target=_new href="https://github.com/dgtlmoon/changedetection.io/wiki/Notification-configuration-notes">Please read the notification services wiki here for important configuration notes</a></i>.</li>
|
||||
<li><code>discord://</code> will silently fail if the total message length is more than 2000 chars.</li>
|
||||
<li><code>tgram://</code> bots cant send messages to other bots, so you should specify chat ID of non-bot user.</li>
|
||||
<li>Go here for <a href="{{url_for('notification_logs')}}">Notification debug logs</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="edit-form">
|
||||
<div class="inner">
|
||||
|
||||
<h4 style="margin-top: 0px;">The following issues were detected when sending notifications</h4>
|
||||
<div id="notification-customisation">
|
||||
<ul style="font-size: 80%; margin:0px; padding: 0 0 0 7px">
|
||||
{% for log in logs|reverse %}
|
||||
<li>{{log}}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -59,6 +59,8 @@
|
|||
{{ render_common_settings_form(form, current_base_url) }}
|
||||
</div>
|
||||
</fieldset>
|
||||
<a href="{{url_for('notification_logs')}}">Notification debug logs</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="tab-pane-inner" id="fetching">
|
||||
|
|
|
@ -226,3 +226,32 @@ def test_check_notification(client, live_server):
|
|||
)
|
||||
assert b"Notification Body and Title is required when a Notification URL is used" in res.data
|
||||
|
||||
|
||||
# Check we capture the failure, we can just use trigger_check = y here
|
||||
res = client.post(
|
||||
url_for("edit_page", uuid="first"),
|
||||
data={"notification_urls": "jsons://broken-url.changedetection.io/test",
|
||||
"notification_title": "xxx",
|
||||
"notification_body": "xxxxx",
|
||||
"notification_format": "Text",
|
||||
"url": test_url,
|
||||
"tag": "my tag",
|
||||
"title": "my title",
|
||||
"headers": "",
|
||||
"fetch_backend": "html_requests",
|
||||
"trigger_check": "y"},
|
||||
follow_redirects=True
|
||||
)
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
# The error should show in the notification logs
|
||||
res = client.get(
|
||||
url_for("notification_logs"))
|
||||
assert bytes("Name or service not known".encode('utf-8')) in res.data
|
||||
|
||||
# And it should be listed on the watch overview
|
||||
res = client.get(
|
||||
url_for("index"))
|
||||
assert bytes("Notification error detected".encode('utf-8')) in res.data
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue