Merge pull request #11699 from saurabh6790/log-settings
feat: Log settings
This commit is contained in:
commit
11e54cbfbe
19 changed files with 266 additions and 18 deletions
|
|
@ -23,6 +23,11 @@ def get_data():
|
|||
"description": _("Company, Fiscal Year and Currency defaults"),
|
||||
"hide_count": True
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Log Settings",
|
||||
"description": _("Log cleanup and notification configuration")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Error Log",
|
||||
|
|
|
|||
|
|
@ -40,7 +40,11 @@ def add_authentication_log(subject, user, operation="Login", status="Success"):
|
|||
"operation": operation,
|
||||
}).insert(ignore_permissions=True, ignore_links=True)
|
||||
|
||||
def clear_authentication_logs():
|
||||
"""clear 100 day old authentication logs"""
|
||||
def clear_activity_logs(days=None):
|
||||
"""clear 90 day old authentication logs or configured in log settings"""
|
||||
|
||||
if not days:
|
||||
days = 90
|
||||
|
||||
frappe.db.sql("""delete from `tabActivity Log` where \
|
||||
creation< (NOW() - INTERVAL '100' DAY)""")
|
||||
creation< (NOW() - INTERVAL '{0}' DAY)""".format(days))
|
||||
|
|
@ -17,9 +17,6 @@ def set_old_logs_as_seen():
|
|||
frappe.db.sql("""UPDATE `tabError Log` SET `seen`=1
|
||||
WHERE `seen`=0 AND `creation` < (NOW() - INTERVAL '7' DAY)""")
|
||||
|
||||
# clear old logs
|
||||
frappe.db.sql("""DELETE FROM `tabError Log` WHERE `creation` < (NOW() - INTERVAL '30' DAY)""")
|
||||
|
||||
@frappe.whitelist()
|
||||
def clear_error_logs():
|
||||
'''Flush all Error Logs'''
|
||||
|
|
|
|||
0
frappe/core/doctype/log_setting_user/__init__.py
Normal file
0
frappe/core/doctype/log_setting_user/__init__.py
Normal file
8
frappe/core/doctype/log_setting_user/log_setting_user.js
Normal file
8
frappe/core/doctype/log_setting_user/log_setting_user.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) 2020, Frappe Technologies and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Log Setting User', {
|
||||
// refresh: function(frm) {
|
||||
|
||||
// }
|
||||
});
|
||||
34
frappe/core/doctype/log_setting_user/log_setting_user.json
Normal file
34
frappe/core/doctype/log_setting_user/log_setting_user.json
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"actions": [],
|
||||
"autoname": "field:user",
|
||||
"creation": "2020-10-08 13:09:36.034430",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"user"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "user",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "User",
|
||||
"options": "User",
|
||||
"reqd": 1,
|
||||
"unique": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-10-08 17:22:04.690348",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Log Setting User",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
||||
10
frappe/core/doctype/log_setting_user/log_setting_user.py
Normal file
10
frappe/core/doctype/log_setting_user/log_setting_user.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class LogSettingUser(Document):
|
||||
pass
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
class TestLogSettingUser(unittest.TestCase):
|
||||
pass
|
||||
0
frappe/core/doctype/log_settings/__init__.py
Normal file
0
frappe/core/doctype/log_settings/__init__.py
Normal file
8
frappe/core/doctype/log_settings/log_settings.js
Normal file
8
frappe/core/doctype/log_settings/log_settings.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) 2020, Frappe Technologies and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Log Settings', {
|
||||
// refresh: function(frm) {
|
||||
|
||||
// }
|
||||
});
|
||||
83
frappe/core/doctype/log_settings/log_settings.json
Normal file
83
frappe/core/doctype/log_settings/log_settings.json
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
{
|
||||
"actions": [],
|
||||
"creation": "2020-10-08 12:12:21.694424",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"error_log_notification_section",
|
||||
"users_to_notify",
|
||||
"log_cleanup_section",
|
||||
"clear_error_log_after",
|
||||
"clear_activity_log_after",
|
||||
"column_break_4",
|
||||
"clear_email_queue_after"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "log_cleanup_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Log Cleanup"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "error_log_notification_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Error Log Notification"
|
||||
},
|
||||
{
|
||||
"fieldname": "users_to_notify",
|
||||
"fieldtype": "Table MultiSelect",
|
||||
"label": "Users To Notify",
|
||||
"options": "Log Setting User"
|
||||
},
|
||||
{
|
||||
"default": "90",
|
||||
"description": "In Days",
|
||||
"fieldname": "clear_error_log_after",
|
||||
"fieldtype": "Int",
|
||||
"label": "Clear Error log After"
|
||||
},
|
||||
{
|
||||
"default": "90",
|
||||
"description": "In Days",
|
||||
"fieldname": "clear_activity_log_after",
|
||||
"fieldtype": "Int",
|
||||
"label": "Clear Activity Log After"
|
||||
},
|
||||
{
|
||||
"default": "90",
|
||||
"description": "In Days",
|
||||
"fieldname": "clear_email_queue_after",
|
||||
"fieldtype": "Int",
|
||||
"label": "Clear Email Queue After"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2020-10-13 12:18:48.649038",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Log Settings",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
||||
51
frappe/core/doctype/log_settings/log_settings.py
Normal file
51
frappe/core/doctype/log_settings/log_settings.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
|
||||
class LogSettings(Document):
|
||||
def clear_logs(self):
|
||||
self.clear_error_logs()
|
||||
self.clear_activity_logs()
|
||||
self.clear_email_queue()
|
||||
|
||||
def clear_error_logs(self):
|
||||
frappe.db.sql(""" DELETE FROM `tabError Log`
|
||||
WHERE `creation` < (NOW() - INTERVAL '{0}' DAY)
|
||||
""".format(self.clear_error_log_after))
|
||||
|
||||
def clear_activity_logs(self):
|
||||
from frappe.core.doctype.activity_log.activity_log import clear_activity_logs
|
||||
clear_activity_logs(days=self.clear_activity_log_after)
|
||||
|
||||
def clear_email_queue(self):
|
||||
from frappe.email.queue import clear_outbox
|
||||
clear_outbox(days=self.clear_email_queue_after)
|
||||
|
||||
def run_log_clean_up():
|
||||
doc = frappe.get_doc("Log Settings")
|
||||
doc.clear_logs()
|
||||
|
||||
@frappe.whitelist()
|
||||
def has_unseen_error_log(user):
|
||||
|
||||
def _get_response(show_alert=True):
|
||||
return {
|
||||
'show_alert': True,
|
||||
'message': _("You have unseen {0}").format('<a href="/desk#List/Error%20Log/List"> Error Logs </a>')
|
||||
}
|
||||
|
||||
if frappe.db.sql_list("select name from `tabError Log` where seen = 0 limit 1"):
|
||||
log_settings = frappe.get_cached_doc('Log Settings')
|
||||
|
||||
if log_settings.users_to_notify:
|
||||
if user in [u.user for u in log_settings.users_to_notify]:
|
||||
return _get_response()
|
||||
else:
|
||||
return _get_response(show_alert=False)
|
||||
else:
|
||||
return _get_response()
|
||||
10
frappe/core/doctype/log_settings/test_log_settings.py
Normal file
10
frappe/core/doctype/log_settings/test_log_settings.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
class TestLogSettings(unittest.TestCase):
|
||||
pass
|
||||
|
|
@ -22,7 +22,7 @@ class TestScheduledJobType(unittest.TestCase):
|
|||
self.assertEqual(all_job.frequency, 'All')
|
||||
|
||||
daily_job = frappe.get_doc('Scheduled Job Type',
|
||||
dict(method='frappe.email.queue.clear_outbox'))
|
||||
dict(method='frappe.email.queue.set_expiry_for_email_queue'))
|
||||
self.assertEqual(daily_job.frequency, 'Daily')
|
||||
|
||||
# check if cron jobs are synced
|
||||
|
|
@ -38,7 +38,7 @@ class TestScheduledJobType(unittest.TestCase):
|
|||
self.assertEqual(updated_scheduled_job.frequency, "Hourly")
|
||||
|
||||
def test_daily_job(self):
|
||||
job = frappe.get_doc('Scheduled Job Type', dict(method = 'frappe.email.queue.clear_outbox'))
|
||||
job = frappe.get_doc('Scheduled Job Type', dict(method = 'frappe.email.queue.set_expiry_for_email_queue'))
|
||||
job.db_set('last_execution', '2019-01-01 00:00:00')
|
||||
self.assertTrue(job.is_event_due(get_datetime('2019-01-02 00:00:06')))
|
||||
self.assertFalse(job.is_event_due(get_datetime('2019-01-01 00:00:06')))
|
||||
|
|
|
|||
|
|
@ -584,14 +584,15 @@ def prepare_message(email, recipient, recipients_list):
|
|||
|
||||
return safe_encode(message.as_string())
|
||||
|
||||
def clear_outbox():
|
||||
"""Remove low priority older than 31 days in Outbox and expire mails not sent for 7 days.
|
||||
Called daily via scheduler.
|
||||
def clear_outbox(days=None):
|
||||
"""Remove low priority older than 31 days in Outbox or configured in Log Settings.
|
||||
Note: Used separate query to avoid deadlock
|
||||
"""
|
||||
if not days:
|
||||
days=31
|
||||
|
||||
email_queues = frappe.db.sql_list("""SELECT `name` FROM `tabEmail Queue`
|
||||
WHERE `priority`=0 AND `modified` < (NOW() - INTERVAL '31' DAY)""")
|
||||
WHERE `priority`=0 AND `modified` < (NOW() - INTERVAL '{0}' DAY)""".format(days))
|
||||
|
||||
if email_queues:
|
||||
frappe.db.sql("""DELETE FROM `tabEmail Queue` WHERE `name` IN ({0})""".format(
|
||||
|
|
@ -602,6 +603,11 @@ def clear_outbox():
|
|||
','.join(['%s']*len(email_queues)
|
||||
)), tuple(email_queues))
|
||||
|
||||
def set_expiry_for_email_queue():
|
||||
''' Mark emails as expire that has not sent for 7 days.
|
||||
Called daily via scheduler.
|
||||
'''
|
||||
|
||||
frappe.db.sql("""
|
||||
UPDATE `tabEmail Queue`
|
||||
SET `status`='Expired'
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ scheduler_events = {
|
|||
"frappe.utils.password.delete_password_reset_cache"
|
||||
],
|
||||
"daily": [
|
||||
"frappe.email.queue.clear_outbox",
|
||||
"frappe.email.queue.set_expiry_for_email_queue",
|
||||
"frappe.desk.notifications.clear_notifications",
|
||||
"frappe.core.doctype.error_log.error_log.set_old_logs_as_seen",
|
||||
"frappe.desk.doctype.event.event.send_event_digest",
|
||||
|
|
@ -215,7 +215,6 @@ scheduler_events = {
|
|||
"frappe.realtime.remove_old_task_logs",
|
||||
"frappe.utils.scheduler.restrict_scheduler_events_if_dormant",
|
||||
"frappe.email.doctype.auto_email_report.auto_email_report.send_daily",
|
||||
"frappe.core.doctype.activity_log.activity_log.clear_authentication_logs",
|
||||
"frappe.website.doctype.personal_data_deletion_request.personal_data_deletion_request.remove_unverified_record",
|
||||
"frappe.desk.form.document_follow.send_daily_updates",
|
||||
"frappe.social.doctype.energy_point_settings.energy_point_settings.allocate_review_points",
|
||||
|
|
@ -223,7 +222,8 @@ scheduler_events = {
|
|||
"frappe.automation.doctype.auto_repeat.auto_repeat.make_auto_repeat_entry",
|
||||
"frappe.automation.doctype.auto_repeat.auto_repeat.set_auto_repeat_as_completed",
|
||||
"frappe.email.doctype.unhandled_email.unhandled_email.remove_old_unhandled_emails",
|
||||
"frappe.core.doctype.prepared_report.prepared_report.delete_expired_prepared_reports"
|
||||
"frappe.core.doctype.prepared_report.prepared_report.delete_expired_prepared_reports",
|
||||
"frappe.core.doctype.log_settings.log_settings.run_log_clean_up"
|
||||
],
|
||||
"daily_long": [
|
||||
"frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_daily",
|
||||
|
|
|
|||
|
|
@ -139,6 +139,26 @@ frappe.Application = Class.extend({
|
|||
}
|
||||
});
|
||||
}, 300000); // check every 5 minutes
|
||||
|
||||
if(frappe.user.has_role("System Manager")){
|
||||
setInterval(function() {
|
||||
frappe.call({
|
||||
method: 'frappe.core.doctype.log_settings.log_settings.has_unseen_error_log',
|
||||
args: {
|
||||
user: frappe.session.user
|
||||
},
|
||||
callback: function(r) {
|
||||
console.log(r);
|
||||
if(r.message.show_alert){
|
||||
frappe.show_alert({
|
||||
indicator: 'red',
|
||||
message: r.message.message
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 600000); // check every 10 minutes
|
||||
}
|
||||
}
|
||||
|
||||
this.fetch_tags();
|
||||
|
|
|
|||
|
|
@ -130,8 +130,10 @@ class TestEmail(unittest.TestCase):
|
|||
def test_expired(self):
|
||||
self.test_email_queue()
|
||||
frappe.db.sql("UPDATE `tabEmail Queue` SET `modified`=(NOW() - INTERVAL '8' day)")
|
||||
from frappe.email.queue import clear_outbox
|
||||
clear_outbox()
|
||||
|
||||
from frappe.email.queue import set_expiry_for_email_queue
|
||||
set_expiry_for_email_queue()
|
||||
|
||||
email_queue = frappe.db.sql("""select name from `tabEmail Queue` where status='Expired'""", as_dict=1)
|
||||
self.assertEqual(len(email_queue), 1)
|
||||
queue_recipients = [r.recipient for r in frappe.db.sql("""select recipient from `tabEmail Queue Recipient`
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class TestScheduler(TestCase):
|
|||
enqueue_events(site = frappe.local.site)
|
||||
frappe.flags.execute_job = False
|
||||
|
||||
self.assertTrue('frappe.email.queue.clear_outbox', frappe.flags.enqueued_jobs)
|
||||
self.assertTrue('frappe.email.queue.set_expiry_for_email_queue', frappe.flags.enqueued_jobs)
|
||||
self.assertTrue('frappe.utils.change_log.check_for_update', frappe.flags.enqueued_jobs)
|
||||
self.assertTrue('frappe.email.doctype.auto_email_report.auto_email_report.send_monthly', frappe.flags.enqueued_jobs)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue