From 1d1f9e84b0b92a8785964da3590356dc112f0a6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Berm=C3=BChler?= <31950929+dbermuehler@users.noreply.github.com> Date: Fri, 19 Aug 2022 19:54:52 +0200 Subject: [PATCH] Logging silenced if parsedmarc is used as Library (#344) By default, libraries should not configure their logger to give the developer, who is using the library, the freedom to decide how log messages are logged. For this reason no handler other than the NullHandler or log level should be set by the library. For more information about this topic see here: https://realpython.com/python-logging-source-code/#library-vs-application-logging-what-is-nullhandler --- parsedmarc/__init__.py | 9 +-------- parsedmarc/cli.py | 8 +++++++- parsedmarc/elastic.py | 5 +---- parsedmarc/kafkaclient.py | 5 +---- parsedmarc/log.py | 4 ++++ parsedmarc/mail/gmail.py | 4 +--- parsedmarc/mail/graph.py | 5 +---- parsedmarc/mail/imap.py | 5 +---- parsedmarc/s3.py | 4 +--- parsedmarc/splunk.py | 4 +--- parsedmarc/syslog.py | 2 -- parsedmarc/utils.py | 2 +- 12 files changed, 20 insertions(+), 37 deletions(-) create mode 100644 parsedmarc/log.py diff --git a/parsedmarc/__init__.py b/parsedmarc/__init__.py index ea40367..8a6800c 100644 --- a/parsedmarc/__init__.py +++ b/parsedmarc/__init__.py @@ -28,6 +28,7 @@ from expiringdict import ExpiringDict from lxml import etree from mailsuite.smtp import send_email +from parsedmarc.log import logger from parsedmarc.mail import MailboxConnection from parsedmarc.utils import get_base_domain, get_ip_address_info from parsedmarc.utils import is_outlook_msg, convert_outlook_msg @@ -36,14 +37,6 @@ from parsedmarc.utils import timestamp_to_human, human_timestamp_to_datetime __version__ = "8.3.0" -formatter = logging.Formatter( - fmt='%(levelname)8s:%(filename)s:%(lineno)d:%(message)s', - datefmt='%Y-%m-%d:%H:%M:%S') -handler = logging.StreamHandler() -handler.setFormatter(formatter) - -logger = logging.getLogger("parsedmarc") -logger.addHandler(handler) logger.debug("parsedmarc v{0}".format(__version__)) feedback_report_regex = re.compile(r"^([\w\-]+): (.+)$", re.MULTILINE) diff --git a/parsedmarc/cli.py b/parsedmarc/cli.py index 2b6f17a..820b1e6 100644 --- a/parsedmarc/cli.py +++ b/parsedmarc/cli.py @@ -25,9 +25,15 @@ from parsedmarc import get_dmarc_reports_from_mailbox, watch_inbox, \ from parsedmarc.mail import IMAPConnection, MSGraphConnection, GmailConnection from parsedmarc.mail.graph import AuthMethod +from parsedmarc.log import logger from parsedmarc.utils import is_mbox -logger = logging.getLogger("parsedmarc") +formatter = logging.Formatter( + fmt='%(levelname)8s:%(filename)s:%(lineno)d:%(message)s', + datefmt='%Y-%m-%d:%H:%M:%S') +handler = logging.StreamHandler() +handler.setFormatter(formatter) +logger.addHandler(handler) def _str_to_list(s): diff --git a/parsedmarc/elastic.py b/parsedmarc/elastic.py index ee18e71..80f9f09 100644 --- a/parsedmarc/elastic.py +++ b/parsedmarc/elastic.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -import logging from collections import OrderedDict from elasticsearch_dsl.search import Q @@ -8,12 +7,10 @@ from elasticsearch_dsl import connections, Object, Document, Index, Nested, \ InnerDoc, Integer, Text, Boolean, Ip, Date, Search from elasticsearch.helpers import reindex - +from parsedmarc.log import logger from parsedmarc.utils import human_timestamp_to_datetime from parsedmarc import InvalidForensicReport -logger = logging.getLogger("parsedmarc") - class ElasticsearchError(Exception): """Raised when an Elasticsearch error occurs""" diff --git a/parsedmarc/kafkaclient.py b/parsedmarc/kafkaclient.py index 6204631..779746a 100644 --- a/parsedmarc/kafkaclient.py +++ b/parsedmarc/kafkaclient.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -import logging import json from ssl import create_default_context @@ -10,9 +9,7 @@ from collections import OrderedDict from parsedmarc.utils import human_timestamp_to_datetime from parsedmarc import __version__ - -logger = logging.getLogger("parsedmarc") - +from parsedmarc.log import logger class KafkaError(RuntimeError): """Raised when a Kafka error occurs""" diff --git a/parsedmarc/log.py b/parsedmarc/log.py new file mode 100644 index 0000000..c10988d --- /dev/null +++ b/parsedmarc/log.py @@ -0,0 +1,4 @@ +import logging + +logger = logging.getLogger(__name__) +logger.addHandler(logging.NullHandler()) diff --git a/parsedmarc/mail/gmail.py b/parsedmarc/mail/gmail.py index 504d28a..58aed20 100644 --- a/parsedmarc/mail/gmail.py +++ b/parsedmarc/mail/gmail.py @@ -1,4 +1,3 @@ -import logging from base64 import urlsafe_b64decode from functools import lru_cache from pathlib import Path @@ -11,10 +10,9 @@ from google_auth_oauthlib.flow import InstalledAppFlow from googleapiclient.discovery import build from googleapiclient.errors import HttpError +from parsedmarc.log import logger from parsedmarc.mail.mailbox_connection import MailboxConnection -logger = logging.getLogger("parsedmarc") - def _get_creds(token_file, credentials_file, scopes, oauth2_port): creds = None diff --git a/parsedmarc/mail/graph.py b/parsedmarc/mail/graph.py index 09bbbfa..80b0895 100644 --- a/parsedmarc/mail/graph.py +++ b/parsedmarc/mail/graph.py @@ -1,4 +1,3 @@ -import logging from enum import Enum from functools import lru_cache from pathlib import Path @@ -10,6 +9,7 @@ from azure.identity import UsernamePasswordCredential, \ TokenCachePersistenceOptions, AuthenticationRecord from msgraph.core import GraphClient +from parsedmarc.log import logger from parsedmarc.mail.mailbox_connection import MailboxConnection @@ -19,9 +19,6 @@ class AuthMethod(Enum): ClientSecret = 3 -logger = logging.getLogger('parsedmarc') - - def _get_cache_args(token_path: Path): cache_args = { 'cache_persistence_options': diff --git a/parsedmarc/mail/imap.py b/parsedmarc/mail/imap.py index 66ea2e6..8e7aba7 100644 --- a/parsedmarc/mail/imap.py +++ b/parsedmarc/mail/imap.py @@ -1,16 +1,13 @@ -import logging from time import sleep from imapclient.exceptions import IMAPClientError from mailsuite.imap import IMAPClient from socket import timeout +from parsedmarc.log import logger from parsedmarc.mail.mailbox_connection import MailboxConnection -logger = logging.getLogger("parsedmarc") - - class IMAPConnection(MailboxConnection): def __init__(self, host=None, diff --git a/parsedmarc/s3.py b/parsedmarc/s3.py index 499952f..e8269ab 100644 --- a/parsedmarc/s3.py +++ b/parsedmarc/s3.py @@ -1,13 +1,11 @@ # -*- coding: utf-8 -*- -import logging import json import boto3 +from parsedmarc.log import logger from parsedmarc.utils import human_timestamp_to_datetime -logger = logging.getLogger("parsedmarc") - class S3Client(object): """A client for a Amazon S3""" diff --git a/parsedmarc/splunk.py b/parsedmarc/splunk.py index 1d40282..e479794 100644 --- a/parsedmarc/splunk.py +++ b/parsedmarc/splunk.py @@ -1,4 +1,3 @@ -import logging from urllib.parse import urlparse import socket import json @@ -7,12 +6,11 @@ import urllib3 import requests from parsedmarc import __version__ +from parsedmarc.log import logger from parsedmarc.utils import human_timestamp_to_timestamp urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) -logger = logging.getLogger("parsedmarc") - class SplunkError(RuntimeError): """Raised when a Splunk API error occurs""" diff --git a/parsedmarc/syslog.py b/parsedmarc/syslog.py index fbdd136..44fca68 100644 --- a/parsedmarc/syslog.py +++ b/parsedmarc/syslog.py @@ -7,8 +7,6 @@ import json from parsedmarc import parsed_aggregate_reports_to_csv_rows,\ parsed_forensic_reports_to_csv_rows -logger = logging.getLogger("parsedmarc") - class SyslogClient(object): """A client for Syslog""" diff --git a/parsedmarc/utils.py b/parsedmarc/utils.py index e111981..cfa6283 100644 --- a/parsedmarc/utils.py +++ b/parsedmarc/utils.py @@ -32,6 +32,7 @@ import geoip2.errors import requests import publicsuffix2 +from parsedmarc.log import logger import parsedmarc.resources USER_AGENT = "Mozilla/5.0 (({0} {1})) parsedmarc".format( @@ -42,7 +43,6 @@ USER_AGENT = "Mozilla/5.0 (({0} {1})) parsedmarc".format( parenthesis_regex = re.compile(r'\s*\(.*\)\s*') null_file = open(os.devnull, "w") -logger = logging.getLogger("parsedmarc") mailparser_logger = logging.getLogger("mailparser") mailparser_logger.setLevel(logging.CRITICAL)