Source code for apptools.logger.plugin.logger_service
# (C) Copyright 2005-2022 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!
# Standard library imports
from io import BytesIO
import logging
import os
import zipfile
# Enthought library imports
from pyface.workbench.api import View as WorkbenchView
from traits.api import (
Any,
Callable,
HasTraits,
Instance,
List,
Property,
Undefined,
observe,
)
root_logger = logging.getLogger()
logger = logging.getLogger(__name__)
[docs]class LoggerService(HasTraits):
"""The persistent service exposing the Logger plugin's API."""
# The Envisage application.
application = Any()
# The logging Handler we use.
handler = Any()
# Our associated LoggerPreferences.
preferences = Any()
# The view we use.
plugin_view = Instance(WorkbenchView)
# Contributions from other plugins.
mail_files = Property(List(Callable))
[docs] def save_preferences(self):
"""Save the preferences."""
self.preferences.preferences.save()
[docs] def whole_log_text(self):
"""Return all of the logged data as formatted text."""
lines = [self.handler.format(rec) for rec in self.handler.get()]
# Ensure that we end with a newline.
lines.append("")
text = "\n".join(lines)
return text
[docs] def create_email_message(
self,
fromaddr,
toaddrs,
ccaddrs,
subject,
priority,
include_userdata=False,
stack_trace="",
comments="",
include_environment=True,
):
"""Format a bug report email from the log files."""
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
message = MIMEMultipart()
message["Subject"] = "%s [priority=%s]" % (subject, priority)
message["To"] = ", ".join(toaddrs)
message["Cc"] = ", ".join(ccaddrs)
message["From"] = fromaddr
message.preamble = (
"You will not see this in a MIME-aware mail " "reader.\n"
)
message.epilogue = " " # To guarantee the message ends with a newline
# First section is simple ASCII data ...
m = []
m.append("Bug Report")
m.append("==============================")
m.append("")
if len(comments) > 0:
m.append("Comments:")
m.append("========")
m.append(comments)
m.append("")
if len(stack_trace) > 0:
m.append("Stack Trace:")
m.append("===========")
m.append(stack_trace)
m.append("")
msg = MIMEText("\n".join(m))
message.attach(msg)
# Include the log file ...
logtext = self.whole_log_text()
msg = MIMEText(logtext)
msg.add_header(
"Content-Disposition", "attachment", filename="logfile.txt"
)
message.attach(msg)
# Include the environment variables ...
# FIXME: ask the user, maybe?
if include_environment:
# Transmit the user's environment settings as well. Main purpose
# is to work out the user name to help with following up on bug
# reports and in future we should probably send less data.
entries = []
for key, value in sorted(os.environ.items()):
entries.append("%30s : %s\n" % (key, value))
msg = MIMEText("".join(entries))
msg.add_header(
"Content-Disposition", "attachment", filename="environment.txt"
)
message.attach(msg)
if include_userdata and len(self.mail_files) != 0:
f = BytesIO()
zf = zipfile.ZipFile(f, "w")
for mf in self.mail_files:
mf(zf)
zf.close()
msg = MIMEApplication(f.getvalue())
msg.add_header(
"Content-Disposition", "attachment", filename="userdata.zip"
)
message.attach(msg)
return message
[docs] def send_bug_report(
self, smtp_server, fromaddr, toaddrs, ccaddrs, message
):
"""Send a bug report email."""
try:
import smtplib
logger.debug("Connecting to: %s" % smtp_server)
server = smtplib.SMTP(host=smtp_server)
logger.debug("Connected: %s" % server)
# server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs + ccaddrs, message.as_string())
server.quit()
except Exception:
logger.exception("Problem sending error report")
#### Traits stuff #########################################################
def _get_mail_files(self):
return self.application.get_extensions(
"apptools.logger.plugin.mail_files"
)
@observe("preferences.level_")
def _use_updated_preferences_level(self, event):
new = event.new
if (
new is not None
and new is not Undefined
and self.handler is not None
):
root_logger.setLevel(self.preferences.level_)
self.handler.setLevel(self.preferences.level_)