Skip to content

Commit

Permalink
Merge pull request #79 from melexis/logging
Browse files Browse the repository at this point in the history
Fix logging
  • Loading branch information
JasperCraeghs authored Sep 9, 2024
2 parents e15dd57 + 2e0355b commit 43664de
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 96 deletions.
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,11 @@ Example of custom credentials for the plugin:
'username': 'myusername',
'password': 'mypassword',
'stream': 'some_coverity_stream',
'snapshot': '1',
}
Snapshot is optional. When an empty string is given, the last snapshot is used.

Link to traceability items
==========================

Expand Down
2 changes: 0 additions & 2 deletions example/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ BUILDDIR ?= _build

# logging variables
DEBUG ?= 0
LOGLEVEL ?= WARNING

# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
Expand Down Expand Up @@ -50,7 +49,6 @@ clean:
-rm -rf $(BUILDDIR)/*

html:
export LOGLEVEL=$(LOGLEVEL)
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
Expand Down
11 changes: 1 addition & 10 deletions example/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@
import sys

import mlx.coverity
from mlx.coverity import __version__, coverity_logging
from mlx.coverity import __version__
import mlx.traceability
from decouple import config
import logging

pkg_version = __version__

Expand Down Expand Up @@ -320,11 +319,3 @@
TRACEABILITY_ITEM_ID_REGEX = r"([A-Z_]+-[A-Z0-9_]+)"
TRACEABILITY_ITEM_RELINK = {}

log_level = os.environ.get('LOGLEVEL', None)
if log_level:
try:
numeric_level = getattr(logging, log_level.upper(), None)
coverity_logging.LOGGER.setLevel(level=numeric_level)
except:
raise ValueError(f"Invalid log level: {log_level}")

3 changes: 0 additions & 3 deletions mlx/coverity/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@
"CoverityDefectListDirective",
"CoverityDefectService",
"ItemElement",
"report_info",
"report_warning",
"SphinxCoverityConnector",
]

from .__coverity_version__ import __version__
from .coverity_logging import report_info, report_warning
from .coverity import SphinxCoverityConnector
from .coverity_services import CoverityDefectService
from .coverity_item_element import ItemElement
Expand Down
75 changes: 45 additions & 30 deletions mlx/coverity/coverity.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,29 @@

from getpass import getpass
from urllib.error import URLError, HTTPError
from sphinx.util.logging import getLogger, VERBOSITY_MAP

from docutils import nodes

from .__coverity_version__ import __version__
from .coverity_logging import report_info, report_warning
from .coverity_services import CoverityDefectService
from .coverity_directives.coverity_defect_list import (
CoverityDefect,
CoverityDefectListDirective,
)

LOGGER = getLogger("mlx.coverity")


def validate_coverity_credentials(config):
"""Validate the configuration of coverity_credentials.
Args:
config (dict): The configuration `coverity_credentials`.
"""
if missing := {"hostname", "username", "password", "stream"}.difference(config):
LOGGER.error(f"Missing mandatory keys from configuration variable 'coverity_credentials' in conf.py: {missing}")


class SphinxCoverityConnector:
"""
Expand All @@ -45,42 +57,43 @@ def initialize_environment(self, app):
\\let\@noitemerr\\relax
\\makeatother"""

validate_coverity_credentials(app.config.coverity_credentials)
self.stream = app.config.coverity_credentials["stream"]
self.snapshot = app.config.coverity_credentials.get("snapshot", "")
# Login to Coverity and obtain stream information
try:
self.input_credentials(app.config.coverity_credentials)
report_info("Initialize a session on Coverity server... ", True)
LOGGER.info("Initialize a session on Coverity server... ")
self.coverity_service = CoverityDefectService(
app.config.coverity_credentials["hostname"],
)
self.coverity_service.login(
app.config.coverity_credentials["username"], app.config.coverity_credentials["password"]
)
report_info("done")
report_info("Verify the given stream name... ")
LOGGER.info("done")
LOGGER.info("Verify the given stream name... ")
self.coverity_service.validate_stream(self.stream)
report_info("done")
LOGGER.info("done")
if self.snapshot:
report_info("Verify the given snapshot ID and obtain all enabled checkers... ")
LOGGER.info("Verify the given snapshot ID and obtain all enabled checkers... ")
self.snapshot = self.coverity_service.validate_snapshot(self.snapshot)
report_info("done")
LOGGER.info("done")
else:
self.snapshot = "last()"
# Get all column keys
report_info("obtaining all column keys... ")
LOGGER.info("obtaining all column keys... ")
self.coverity_service.retrieve_column_keys()
report_info("done")
LOGGER.info("done")
# Get all checkers
report_info("obtaining all checkers... ")
LOGGER.info("obtaining all checkers... ")
self.coverity_service.retrieve_checkers()
report_info("done")
LOGGER.info("done")
except (URLError, HTTPError, Exception, ValueError) as error_info: # pylint: disable=broad-except
if isinstance(error_info, EOFError):
self.coverity_login_error_msg = "Coverity credentials are not configured."
else:
self.coverity_login_error_msg = str(error_info)
report_info("failed with: %s" % error_info)
LOGGER.info(f"failed with: {error_info}")
self.coverity_login_error = True

# -----------------------------------------------------------------------------
Expand All @@ -96,7 +109,7 @@ def process_coverity_nodes(self, app, doctree, fromdocname):
for node in doctree.traverse(CoverityDefect):
top_node = node.create_top_node("Failed to connect to Coverity Server")
node.replace_self(top_node)
report_warning("Connection failed: %s" % self.coverity_login_error_msg, fromdocname)
LOGGER.warning(f"Connection failed: {self.coverity_login_error_msg}", location=fromdocname)
return

# Item matrix:
Expand All @@ -106,20 +119,21 @@ def process_coverity_nodes(self, app, doctree, fromdocname):
# Get items from server
try:
defects = self.get_filtered_defects(node)
if defects["totalRows"] == -1:
error_message = "There are no defects with the specified filters"
report_warning(error_message, fromdocname, lineno=node["line"])
else:
report_info("building defects table and/or chart... ", True)
node.perform_replacement(defects, self, app, fromdocname)
report_info("done")
except (URLError, AttributeError, Exception) as err: # pylint: disable=broad-except
except URLError as err:
error_message = f"failed to process coverity-list with {err!r}"
report_warning(error_message, fromdocname, lineno=node["line"])
LOGGER.warning(error_message, location=(fromdocname, node["line"]))
top_node = node.create_top_node(node["title"])
top_node += nodes.paragraph(text=error_message)
node.replace_self(top_node)
continue
else:
if defects["totalRows"] == -1:
error_message = "There are no defects with the specified filters"
LOGGER.warning(error_message, location=(fromdocname, node["line"]))
else:
LOGGER.info("building defects table and/or chart... ")
node.perform_replacement(defects, self, app, fromdocname)
LOGGER.info("done")

# -----------------------------------------------------------------------------
# Helper functions of event handlers
Expand Down Expand Up @@ -150,28 +164,29 @@ def get_filtered_defects(self, node):
"rows": [list of dictionaries {"key": <key>, "value": <value>}]
}
"""
report_info("obtaining defects... ")
LOGGER.info("obtaining defects... ")
column_names = set(node["col"])
if "chart_attribute" in node and node["chart_attribute"].upper() in node.column_map:
column_names.add(node["chart_attribute"])
defects = self.coverity_service.get_defects(self.stream, node["filters"], column_names, self.snapshot)
report_info("%d received" % (defects["totalRows"]))
LOGGER.info("%d received" % (defects["totalRows"]))
return defects


# Extension setup
def setup(app):
"""Extension setup"""

# Set logging level with --verbose (-v) option of Sphinx,
# This option can be given up to three times to get more debug logging output.
LOGGER.setLevel(VERBOSITY_MAP[app.verbosity])

# Create default configuration. Can be customized in conf.py
app.add_config_value(
"coverity_credentials",
{
"hostname": "scan.coverity.com",
"username": "reporter",
"password": "coverity",
"stream": "some_stream",
},
{},
"env",
dict,
)

app.add_config_value("TRACEABILITY_ITEM_ID_REGEX", r"([A-Z_]+-[A-Z0-9_]+)", "env")
Expand Down
12 changes: 7 additions & 5 deletions mlx/coverity/coverity_directives/coverity_defect_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from hashlib import sha256
from os import environ, path
from pathlib import Path
from sphinx.util.logging import getLogger

from docutils import nodes
from docutils.parsers.rst import Directive, directives
Expand All @@ -12,9 +13,10 @@
mpl.use("Agg")
import matplotlib.pyplot as plt

from ..coverity_logging import report_info, report_warning
from ..coverity_item_element import ItemElement

LOGGER = getLogger("mlx.coverity")


def pct_wrapper(sizes):
"""Helper function for matplotlib which returns the percentage and the absolute size of the slice.
Expand Down Expand Up @@ -88,7 +90,7 @@ def perform_replacement(self, defects, connector, app, fromdocname):
try:
self.fill_table_and_count_attributes(defects["rows"], self.coverity_service.columns, app, fromdocname)
except AttributeError as err:
report_info("No issues matching your query or empty stream. %s" % err)
LOGGER.info(f"No issues matching your query or empty stream. {err}")
top_node += nodes.paragraph(text="No issues matching your query or empty stream")
# don't generate empty pie chart image
self.replace_self(top_node)
Expand Down Expand Up @@ -150,9 +152,9 @@ def initialize_labels(self, labels, docname):
attr_values = label.split("+")
for attr_val in attr_values:
if attr_val in self.chart_labels:
report_warning(
"Attribute value '%s' should be unique in chart option." % attr_val,
docname,
LOGGER.warning(
f"Attribute value {attr_val!r} should be unique in chart option.",
location=docname,
)
self.chart_labels[attr_val] = 0
if len(attr_values) > 1:
Expand Down
9 changes: 7 additions & 2 deletions mlx/coverity/coverity_item_element.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
from docutils import nodes
from sphinx.errors import NoUri
from urlextract import URLExtract
from sphinx.util.logging import getLogger

from .coverity_logging import report_warning

LOGGER = getLogger("mlx.coverity")


class ItemElement(nodes.General, nodes.Element):
Expand Down Expand Up @@ -197,7 +199,10 @@ def make_internal_item_ref(app, fromdocname, item_id, cid):
return None
item_info = env.traceability_collection.get_item(item_id)
if not item_info:
report_warning("CID %s: Could not find item ID '%s' in traceability collection." % (cid, item_id), fromdocname)
LOGGER.warning(
f"CID {cid}: Could not find item ID {item_id!r} in traceability collection.",
location=fromdocname
)
return None
ref_node = nodes.reference("", "")
ref_node["refdocname"] = item_info.docname
Expand Down
31 changes: 0 additions & 31 deletions mlx/coverity/coverity_logging.py

This file was deleted.

Loading

0 comments on commit 43664de

Please sign in to comment.