Module bug_trail.view_detail

Detail page. Displays one error log entry.

Expand source code
"""
Detail page. Displays one error log entry.
"""
import json
import logging
import os

from bug_trail.data_code import fetch_log_data_grouped
from bug_trail.view_shared import (
    add_url_to_source_context,
    detail_file_name_grouped,
    humanize_time,
    humanize_time_span,
    initialize_jinja,
    path_to_file_url,
    replace_msg_args,
)

logger = logging.getLogger(__name__)


def render_detail(db_path: str, log_folder: str, source_folder: str) -> str:
    """
    Render the detail page of a log entry

    Args:
        db_path (str): Path to the SQLite database
        log_folder (str): Path to the folder containing the log files
        source_folder (str): Path to the folder containing the source code

    Returns:
        str: The location of the detail page
    """
    env = initialize_jinja()
    log_data = fetch_log_data_grouped(db_path)  # Your log records here

    # Render the template with the selected log data
    template = env.get_template("view_detail.jinja")

    location = ""
    for log_entry in log_data:
        # Selected log record for display
        selected_log = log_entry
        # Using a unique key for each log entry, like a timestamp or a combination of fields
        key = detail_file_name_grouped(selected_log)

        location = f"{log_folder}/{key}"
        if os.path.exists(location):
            print(f"Already exists, {location}, skipping")

        if log_entry["ExceptionDetails"]["exception_hierarchy"]:
            exception_hierarchy = json.loads(log_entry["ExceptionDetails"]["exception_hierarchy"])
            print(exception_hierarchy)
            interesting_hierarchy = []
            for the_type, description in exception_hierarchy:
                if the_type not in ("type", "object"):
                    interesting_hierarchy.append({"type": the_type, "description": description})
            if not interesting_hierarchy:
                del log_entry["ExceptionDetails"]["exception_hierarchy"]
            else:
                log_entry["ExceptionDetails"]["exception_hierarchy"] = interesting_hierarchy

        # Clean up time
        temporal_details = selected_log["TemporalDetails"]
        temporal_details["created"] = humanize_time(temporal_details["created"], temporal_details["msecs"])
        del temporal_details["msecs"]
        formatted_time, apx_time = humanize_time_span(temporal_details["relativeCreated"])
        temporal_details["relativeCreated"] = f"{formatted_time} ({apx_time})"

        # Consolidate level
        message_details = selected_log["MessageDetails"]
        message_details["levelname"] = str(message_details["levelname"]) + f" ({str(message_details['levelno'])})"
        del message_details["levelno"]

        # Consolidate msg and args
        replace_msg_args(message_details)

        # Convert pathname to url
        source_context = selected_log["SourceContext"]

        # TODO: make this pretty

        path_to_file_url(source_context, log_folder, source_folder)
        add_url_to_source_context(source_context)

        # Remove empty fields
        for section in selected_log:
            to_delete = []
            for section_name, value in selected_log[section].items():
                if value is None or value == "":
                    to_delete.append(section_name)
            for section_name in to_delete:
                del selected_log[section][section_name]
        to_delete = []
        for section_name in selected_log:
            if len(selected_log[section_name]) == 0:
                to_delete.append(section_name)
        for section_name in to_delete:
            del selected_log[section_name]

        html_output = template.render(log=selected_log)

        # Write `html_output` to a file
        os.makedirs(location.rsplit("/", 1)[0], exist_ok=True)
        logger.info(f"Writing detail page to {location}")
        with open(location, "w", encoding="utf-8") as f:
            f.write(html_output)
    return location

Functions

def render_detail(db_path: str, log_folder: str, source_folder: str) ‑> str

Render the detail page of a log entry

Args

db_path : str
Path to the SQLite database
log_folder : str
Path to the folder containing the log files
source_folder : str
Path to the folder containing the source code

Returns

str
The location of the detail page
Expand source code
def render_detail(db_path: str, log_folder: str, source_folder: str) -> str:
    """
    Render the detail page of a log entry

    Args:
        db_path (str): Path to the SQLite database
        log_folder (str): Path to the folder containing the log files
        source_folder (str): Path to the folder containing the source code

    Returns:
        str: The location of the detail page
    """
    env = initialize_jinja()
    log_data = fetch_log_data_grouped(db_path)  # Your log records here

    # Render the template with the selected log data
    template = env.get_template("view_detail.jinja")

    location = ""
    for log_entry in log_data:
        # Selected log record for display
        selected_log = log_entry
        # Using a unique key for each log entry, like a timestamp or a combination of fields
        key = detail_file_name_grouped(selected_log)

        location = f"{log_folder}/{key}"
        if os.path.exists(location):
            print(f"Already exists, {location}, skipping")

        if log_entry["ExceptionDetails"]["exception_hierarchy"]:
            exception_hierarchy = json.loads(log_entry["ExceptionDetails"]["exception_hierarchy"])
            print(exception_hierarchy)
            interesting_hierarchy = []
            for the_type, description in exception_hierarchy:
                if the_type not in ("type", "object"):
                    interesting_hierarchy.append({"type": the_type, "description": description})
            if not interesting_hierarchy:
                del log_entry["ExceptionDetails"]["exception_hierarchy"]
            else:
                log_entry["ExceptionDetails"]["exception_hierarchy"] = interesting_hierarchy

        # Clean up time
        temporal_details = selected_log["TemporalDetails"]
        temporal_details["created"] = humanize_time(temporal_details["created"], temporal_details["msecs"])
        del temporal_details["msecs"]
        formatted_time, apx_time = humanize_time_span(temporal_details["relativeCreated"])
        temporal_details["relativeCreated"] = f"{formatted_time} ({apx_time})"

        # Consolidate level
        message_details = selected_log["MessageDetails"]
        message_details["levelname"] = str(message_details["levelname"]) + f" ({str(message_details['levelno'])})"
        del message_details["levelno"]

        # Consolidate msg and args
        replace_msg_args(message_details)

        # Convert pathname to url
        source_context = selected_log["SourceContext"]

        # TODO: make this pretty

        path_to_file_url(source_context, log_folder, source_folder)
        add_url_to_source_context(source_context)

        # Remove empty fields
        for section in selected_log:
            to_delete = []
            for section_name, value in selected_log[section].items():
                if value is None or value == "":
                    to_delete.append(section_name)
            for section_name in to_delete:
                del selected_log[section][section_name]
        to_delete = []
        for section_name in selected_log:
            if len(selected_log[section_name]) == 0:
                to_delete.append(section_name)
        for section_name in to_delete:
            del selected_log[section_name]

        html_output = template.render(log=selected_log)

        # Write `html_output` to a file
        os.makedirs(location.rsplit("/", 1)[0], exist_ok=True)
        logger.info(f"Writing detail page to {location}")
        with open(location, "w", encoding="utf-8") as f:
            f.write(html_output)
    return location