Automation Report

Using the ReportBuilder, you can create a HTML report that can be sent via email or saved as a standalone documentation file. It helps you to document the outcome of the automation process and provides a way to share the results with others. It allows you to organize messages into sections and categorize them by status (success, warning, error, etc.).

Migration Guide

Since the version 3.30.0, the report builder is the recommended way to create and send reports. The EmailNotifier is deprecated and will be removed in future version.

For creating the report builder, preferably use the report_builder() method, located in the BaseScenario class. See the example below for the differences between the old and new approach.

import aiviro

class NewReportScenario(aiviro.BaseScenario):
    def __init__(self, config: "YAMLConfig"):
        super().__init__(config)
        self.report = self.report_builder()

    def _run(self):
        try:
            # Your automation logic here
            self.report.successful("Task completed successfully")
        except Exception as e:
            self.report.error(f"Task failed: {str(e)}")

    def section_example(self):
        """Example of creating a new section and adding messages to it."""
        with self.report.create_section("Section Title", "Sub-title") as section:
            section.successful("Task completed successfully")

    def last_section_example(self):
        """Example of adding messages to the last created section."""
        with self.report.last_section as section:
            section.successful("Task completed successfully")

    def message_styling_example(self):
        """Example of using Markdown in the messages."""
        self.report.successful("Task completed successfully with **bold** and *italic* text")
        self.report.warning("Task completed with warning, check [link](https://example.com) for more details")

    def _after_run(self):
        """Example of sending the report via email client."""
        self.send_report_via_email_client(self.config.recipients)
import aiviro
from aiviro.modules.notifier import Style, Item

class DeprecatedNotifierScenario(aiviro.BaseScenario):
    def __init__(self, config: "YAMLConfig"):
        super().__init__(config)
        self.email_notifier = self.email_notifier()

    def _run(self):
        try:
            # Your automation logic here
            self.email_notifier.successful("Task completed successfully")
        except Exception as e:
            self.email_notifier.error(f"Task failed: {str(e)}")

    def block_example(self):
        """Example of creating a new block and adding messages to it."""
        notification_block = self.email_notifier.create_block("Block Title")
        notification_block.successful("Task completed successfully")

    def message_styling_example(self):
        """Example of using Style object to format the messages."""
        self.email_notifier.default_block.item_style = Style(bold=True)
        self.email_notifier.successful(Item("Task", "completed successfully"))

    def last_block_example(self):
        """Example of adding messages to the last created block."""
        self.email_notifier.last_block.successful("Task completed successfully")

    def _after_run(self):
        """Example of sending the report via email client."""
        if self.email_notifier.blocks:
            self.email_notifier.send_report(self.config.recipients)

Report Builder

class aiviro.core.services.report_service.ReportBuilder(title: str, run_id: str, start_time: datetime, message_titles: dict[LogStatus, str] | None = None, logging_level: str | None = None, metrics_to_display: list[str | MetricsNames] | None = None)

Builder for creating an HTML report, that can be sent via email. The report is used to describe the outcome of the automation process. It is split into multiple parts:

  • Header - contains title of the report, start time and duration

  • Summary - contains summary status of the run with short description of the status

  • Performance metrics - shows performance of the automation process in the last 14 days

  • Detailed summary - contains detailed summary, in form of sections of the run with all messages

  • Footer - contains link to report an issue, social media links and identifier of the run with product version

Note

The report builder supports Markdown highlighting in the messages & sub-messages.

Aiviro also supports localization of the report, it can be changed by setting the environment variable aiviro.core.utils.localization.LOCALE_KEY.

../_images/report-html.png

Example of the generated HTML report.

Parameters:
  • title – Title of the report

  • run_id – Unique identifier of the run

  • start_time – Start time of the run

  • message_titles – Custom titles for the messages, based on their status

  • logging_level – Logging level using which every message is logged, if not set no logging is performed

  • metrics_to_display – Set of sub-metrics to display in the performance metrics section. See MetricsNames for available names. Include here also custom ones that are defined in aiviro.step() decorator.

Example:

>>> import uuid
>>> import datetime
>>> import aiviro
>>>
>>> builder = aiviro.ReportBuilder(
...     title="Invoice processing Workflow",
...     run_id=uuid.uuid4().hex,
...     start_time=datetime.datetime.now(),
...     message_titles={
...         LogStatus.SUCCESS: "OK",
...         LogStatus.ERROR: "Could not process",
...     },
...     metrics_to_display=[MetricsNames.api_reader_pages, MetricsNames.email_extracted],
... )
>>> # adds message into default section
>>> builder.successful("File **ENSEGT20250000689** was successfully uploaded")
>>> builder.successful("File **ENSEGT20250000723** was successfully uploaded")
>>> # creates new section
>>> with builder.create_section("Goods dispatch") as g_section:
...     g_section.unable_to_process(f"**Attachment:** no attachments")
...     g_section.error(
...         f"An unexpected error occurred in infor: {aiviro.Input('username')} not found in 15 seconds.",
...     )
...     g_section.successful(
...         "Order 'P245H0062', Receipt 'WR2434683', Vessel fee '65.05'",
...     )
>>> # creates another section
>>> email_section = builder.create_section(
...     "Email processing - T-Mobile service statement for the period 1.6.2025 - 30.6.2025",
...     "(billing group 55237596)"
... )
>>> with email_section as section:
...     section.successful("**Attachment:** Invoice EU (CZ) 100250089.pdf")
...     section.successful("Attachment: 20250150.pdf, Internal number: FPM-12525422")
...     section.warning("Invoice number: 1018800725").add_sub_message(
...         "The total price of the invoice does not match the price in the copied record"
...     )
...     section.successful(
...         "The invoice was successfully registered in Helios under the number INFD25/0999. [Helios link](https://aiviro.com)",
...     )
property title: str

Returns title of the report.

property active_section_id: str

Returns identifier of the active section.

property last_section: ReportSectionManager

Returns section manager for the last created section.

property is_empty: bool

Returns True if there are no messages in the report.

set_active_section(section_id: str) None

Sets active section.

Parameters:

section_id – Identifier of the section

generate_html_report(end_time: datetime, performance_metrics: PerformanceMetrics | ScenarioRunStats | None = None) str

Generates HTML report.

Parameters:
  • end_time – End time of the run

  • performance_metrics – Performance metrics to include in the report

create_section(title: str, sub_title: str | None = None, section_id: str | None = None) ReportSectionManager

Creates new section in the report.

Parameters:
  • title – Title of the section

  • sub_title – Sub-title of the section

  • section_id – Identifier of the section, if not set title is used as identifier

Returns:

SectionManager object, which can be used to add messages to the section

custom(message: str, status: LogStatus, sub_messages: list[str] | None = None) LogEntry

Creates a message in the report with custom status.

Parameters:
  • message – Main message of the report

  • status – Status of the message

  • sub_messages – List of sub-messages

Returns:

LogEntry object, which represents the message in the report.

inactive(message: str, sub_messages: list[str] | None = None) LogEntry

Creates an ‘inactive’ (gray) message in the report.

Parameters:
  • message – Main message of the report

  • sub_messages – List of sub-messages

successful(message: str, sub_messages: list[str] | None = None) LogEntry

Creates a ‘successful’ (green) message in the report.

Parameters:
  • message – Main message of the report

  • sub_messages – List of sub-messages

unable_to_process(message: str, sub_messages: list[str] | None = None) LogEntry

Creates an ‘unable to process’ (blue) message in the report.

Parameters:
  • message – Main message of the report

  • sub_messages – List of sub-messages

warning(message: str, sub_messages: list[str] | None = None) LogEntry

Creates a ‘warning’ (yellow) message in the report.

Parameters:
  • message – Main message of the report

  • sub_messages – List of sub-messages

error(message: str, sub_messages: list[str] | None = None) LogEntry

Creates an ‘error’ (red) message in the report.

Parameters:
  • message – Main message of the report

  • sub_messages – List of sub-messages

class aiviro.core.services.report_service.ReportSectionManager(builder: ReportBuilder, section_id: str)

Context manager for managing active section, enables writing into section using with statement.

property id: str

Returns identifier of the section.

pydantic model aiviro.core.services.report_service.ReportSection

Represents a section in the report.

field log_entries: list[LogEntry] [Optional]
field sub_title: str | None = None
field title: str [Required]
property is_empty: bool

Checks if there are any log entries in the section.

class aiviro.core.services.report_service.LogStatus(value)

Represents the status for an individual LogEntry.

INACTIVE = 0

Gray colored message for skipped or inactive items.

SUCCESS = 10

Green colored message for successful operations.

INFO = 20

Blue colored message for general information.

WARNING = 30

Yellow colored message for non-critical issues.

ERROR = 40

Red colored message for errors or failures.

pydantic model aiviro.core.services.report_service.LogEntry
field message: str [Required]
field status: LogStatus [Required]
field status_text: str | None = None
field sub_messages: list[str] [Optional]
field timestamp: datetime [Optional]
add_sub_message(message: str | list[str]) LogEntry

Adds sub-message to the log entry.

property html_message: str

Converts markdown message to safe html.

property html_sub_messages: list[str]

Converts markdown sub-messages to safe html.

pydantic model aiviro.core.services.report_service.PerformanceMetrics
field sub_metrics: list[PerformanceSubMetric] [Optional]
field success_rate: float = 0.0
Constraints:
  • ge = 0.0

  • le = 1.0

field total_duration: timedelta = datetime.timedelta(0)
field total_runs: int = 0
Constraints:
  • ge = 0

pydantic model aiviro.core.services.report_service.PerformanceSubMetric
field name: str [Required]
field value: int | float [Required]
class aiviro.core.utils.metrics.constants.MetricsNames(value)

List of available default metrics.

cache_usage = 'cache_usage'

Percentage of cache hits

api_reader_documents = 'api_reader_documents'

Number of documents processed using Aiviro Reader

api_reader_pages = 'api_reader_pages'

Number of pages processed using Aiviro Reader

api_llm_usage = 'api_llm_usage'

Number of tokens used by LLM features

email_extracted = 'email_extracted'

Number of emails extracted from mailbox

email_sent = 'email_sent'

Number of emails sent

pdf_processed = 'pdf_processed'

Number of PDFs processed

actions_used = 'actions_used'

Number of actions used in the scenario