Generating Reports from Logs
Problem Definition
From Log Data to Human-Readable Reports
When executing workflows with actor-IaC, various data is recorded in logs:
- Workflow execution history (Transitions)
- System information collected from each node (JsonState)
- Data accumulated with % notation
We want to convert this log data into human-readable reports suited for specific purposes.
Requirements:
- Pluggable - Compose reports by combining sections
- Purpose-specific reports - Alert reports, system overview reports, etc.
- Assembled in workflow YAML - Change report composition without code changes
Limitations of "Built-in" Design
Traditional ReportBuilder had a fixed design:
reportBuilder.addWorkflowInfo() // Fixed format
reportBuilder.addJsonStateSection() // Fixed format
reportBuilder.report() // Fixed output
To change the output format, you had to modify ReportBuilder itself or create a separate class.
How to do it
Section Plugin Approach
Place section builders as child actors of ReportBuilder, and determine the combination in workflow YAML.
ROOT
└── reportBuilder
├── wfName ← Workflow name
├── wfDesc ← Workflow description
└── nodeData ← Node data
Basic Usage
Workflow example:
name: basic-report
steps:
# 1. Create ReportBuilder and section builders
- states: ["0", "1"]
note: Create ReportBuilder and sections
actions:
- actor: loader
method: createChild
arguments: ["ROOT", "reportBuilder", "com.scivicslab.actoriac.report.ReportBuilderIIAR"]
- actor: loader
method: createChild
arguments: ["reportBuilder", "wfName", "com.scivicslab.actoriac.report.sections.basic.WorkflowNameSectionIIAR"]
- actor: loader
method: createChild
arguments: ["reportBuilder", "wfDesc", "com.scivicslab.actoriac.report.sections.basic.WorkflowDescriptionSectionIIAR"]
# 2. Data collection (execute sub-workflow on each node)
- states: ["1", "2"]
note: Collect system info
actions:
- actor: nodeGroup
method: apply
arguments:
actor: "node-*"
method: runWorkflow
arguments: ["collect-sysinfo.yaml"]
# 3. Generate report
- states: ["2", "end"]
note: Generate report
actions:
- actor: reportBuilder
method: report
Available Section Builders
Standard sections included in actor-IaC (core):
Sections are output in the order they were createChild'd.
| IIAR Class | What it outputs |
|---|---|
WorkflowNameSectionIIAR | Workflow name (YAML name field) |
WorkflowFileSectionIIAR | Workflow file path |
WorkflowDescriptionSectionIIAR | Workflow description (YAML description field) |
CheckResultsSectionIIAR | Collects lines output with % notation |
JsonStateSectionIIAR | Outputs specified actor's JsonState in YAML format |
TransitionHistorySectionIIAR | Workflow state transition history |
GpuSummarySectionIIAR | GPU information summary (NVIDIA/AMD) |
All classes are in the com.scivicslab.actoriac.report.sections.basic package.
actor-IaC-plugins (optional):
Currently, no SectionBuilder plugins are provided. For creating custom sections, refer to Plugin Development.
Purpose-Specific Report Examples
Deployment result report:
name: deployment-report
steps:
- states: ["0", "1"]
note: Create ReportBuilder and sections
actions:
- actor: loader
method: createChild
arguments: ["ROOT", "reportBuilder", "...ReportBuilderIIAR"]
- actor: loader
method: createChild
arguments: ["reportBuilder", "wfName", "...WorkflowNameSectionIIAR"]
- actor: loader
method: createChild
arguments: ["reportBuilder", "wfDesc", "...WorkflowDescriptionSectionIIAR"]
- actor: loader
method: createChild
arguments: ["reportBuilder", "checkResults", "...CheckResultsSectionIIAR"]
- actor: loader
method: createChild
arguments: ["reportBuilder", "trans:nodeGroup:children", "...TransitionHistorySectionIIAR"]
- states: ["1", "2"]
note: Deploy
actions:
- actor: nodeGroup
method: apply
arguments:
actor: "node-*"
method: runWorkflow
arguments: ["deploy.yaml"]
- states: ["2", "end"]
actions:
- actor: reportBuilder
method: report
System status report:
name: system-status-report
steps:
- states: ["0", "1"]
note: Create ReportBuilder with state sections
actions:
- actor: loader
method: createChild
arguments: ["ROOT", "reportBuilder", "...ReportBuilderIIAR"]
- actor: loader
method: createChild
arguments: ["reportBuilder", "wfName", "...WorkflowNameSectionIIAR"]
- actor: loader
method: createChild
arguments: ["reportBuilder", "wfFile", "...WorkflowFileSectionIIAR"]
- actor: loader
method: createChild
arguments: ["reportBuilder", "state:nodeGroup:cluster", "...JsonStateSectionIIAR"]
- actor: loader
method: createChild
arguments: ["reportBuilder", "gpuSummary", "...GpuSummarySectionIIAR"]
- states: ["1", "2"]
note: Collect system info
actions:
- actor: nodeGroup
method: apply
arguments:
actor: "node-*"
method: runWorkflow
arguments: ["collect-sysinfo.yaml"]
- states: ["2", "end"]
actions:
- actor: reportBuilder
method: report
Output Destinations
Reports are output via outputMultiplexer. That means:
- Console - Real-time viewing
- File - When
--file-logoption is specified - Database - Structured storage in H2 DB
Reports themselves are also saved as logs, so they can be referenced later.
Under the hood
POJO and IIActorRef Separation Design
Section builders are implemented with separation of POJO (business logic) and IIAR (actor layer).
Design principles:
- POJO is pure POJO - Does not implement
CallableByActionName - IIAR handles action exposure - Exposes methods with
@Actionannotation - String argument constraint - Ensures messaging in distributed actor systems
Class structure example:
WorkflowNameSection (POJO)
- String generate() // Business logic
- String getTitle()
WorkflowNameSectionIIAR extends IIActorRef<WorkflowNameSection>
- @Action("generate") // Calls POJO method
- @Action("getTitle")
SectionBuilder Interface (POJO)
/**
* POJO interface for section builders.
* Does not inherit CallableByActionName.
*/
public interface SectionBuilder {
/** Generate section content */
String generate();
/** Section title (null to omit) */
default String getTitle() { return null; }
}
ReportBuilder Operation
The report action of ReportBuilder calls the generate action of child actors in order of addition.
// Overview of ReportBuilder.build()
public String build() {
StringBuilder sb = new StringBuilder();
sb.append("=== Workflow Execution Report ===\n");
// Collect sections from child actors (in order of addition)
for (String childName : selfRef.getNamesOfChildren()) {
IIActorRef<?> child = system.getIIActor(childName);
// Call generate action
ActionResult result = child.callByActionName("generate", "");
if (result.isSuccess()) {
String content = result.getResult();
String title = getTitle(child);
appendSection(sb, title, content);
}
}
return sb.toString();
}
Related Documents
This section contains detailed documentation for each SectionBuilder:
| Document | Description |
|---|---|
| WorkflowNameSection | Outputs workflow name |
| WorkflowDescriptionSection | Outputs workflow description |
| WorkflowFileSection | Outputs workflow file path |
| CheckResultsSection | Collects % notation output |
| JsonStateSection | Outputs JsonState in YAML format |
| TransitionHistorySection | Outputs state transition history |
| GpuSummarySection | Summarizes GPU information |
| Actor Tree in Report | Including actor tree in reports |