Skip to main content

SensorReportBuilder

Struct SensorReportBuilder 

Source
pub struct SensorReportBuilder { /* private fields */ }
Expand description

Builder for constructing a SensorReport from a PerfgateReport.

This builder provides a fluent API for constructing sensor reports suitable for cockpit integration. It handles:

  • Mapping verdict status (Pass/Warn/Fail) to sensor vocabulary (Pass/Warn/Error)
  • Generating fingerprints for findings
  • Truncating findings when limits are exceeded
  • Aggregating multiple bench outcomes
  • Sorting artifacts deterministically

§Example

use perfgate_sensor::SensorReportBuilder;
use perfgate_types::{ToolInfo, PerfgateReport, VerdictStatus, Verdict, VerdictCounts, ReportSummary, REPORT_SCHEMA_V1};

let tool = ToolInfo {
    name: "perfgate".to_string(),
    version: "0.1.0".to_string(),
};

let report = PerfgateReport {
    report_type: REPORT_SCHEMA_V1.to_string(),
    verdict: Verdict {
        status: VerdictStatus::Pass,
        counts: VerdictCounts { pass: 2, warn: 0, fail: 0 },
        reasons: vec![],
    },
    compare: None,
    findings: vec![],
    summary: ReportSummary { pass_count: 2, warn_count: 0, fail_count: 0, total_count: 2 },
};

let sensor_report = SensorReportBuilder::new(tool, "2024-01-01T00:00:00Z".to_string())
    .ended_at("2024-01-01T00:01:00Z".to_string(), 60000)
    .baseline(true, None)
    .artifact("report.json".to_string(), "sensor_report".to_string())
    .build(&report);

assert_eq!(sensor_report.verdict.status, perfgate_types::SensorVerdictStatus::Pass);
assert_eq!(sensor_report.verdict.counts.info, 2);

Implementations§

Source§

impl SensorReportBuilder

Source

pub fn new(tool: ToolInfo, started_at: String) -> SensorReportBuilder

Create a new SensorReportBuilder.

§Examples
use perfgate_sensor::SensorReportBuilder;
use perfgate_types::ToolInfo;

let tool = ToolInfo { name: "perfgate".to_string(), version: "0.1.0".to_string() };
let builder = SensorReportBuilder::new(tool, "2024-01-01T00:00:00Z".to_string());
Source

pub fn ended_at(self, ended_at: String, duration_ms: u64) -> SensorReportBuilder

Set the end time and duration.

§Examples
use perfgate_sensor::SensorReportBuilder;
use perfgate_types::ToolInfo;

let tool = ToolInfo { name: "perfgate".to_string(), version: "0.1.0".to_string() };
let builder = SensorReportBuilder::new(tool, "2024-01-01T00:00:00Z".to_string())
    .ended_at("2024-01-01T00:01:00Z".to_string(), 60000);
Source

pub fn baseline( self, available: bool, reason: Option<String>, ) -> SensorReportBuilder

Set baseline availability.

§Examples
use perfgate_sensor::SensorReportBuilder;
use perfgate_types::ToolInfo;

let tool = ToolInfo { name: "perfgate".to_string(), version: "0.1.0".to_string() };
// Baseline available
let builder = SensorReportBuilder::new(tool, "2024-01-01T00:00:00Z".to_string())
    .baseline(true, None);
Source

pub fn engine(self, capability: Capability) -> SensorReportBuilder

Set engine capability explicitly.

§Examples
use perfgate_sensor::SensorReportBuilder;
use perfgate_types::{ToolInfo, Capability, CapabilityStatus};

let tool = ToolInfo { name: "perfgate".to_string(), version: "0.1.0".to_string() };
let builder = SensorReportBuilder::new(tool, "2024-01-01T00:00:00Z".to_string())
    .engine(Capability {
        status: CapabilityStatus::Available,
        reason: None,
    });
Source

pub fn artifact( self, path: String, artifact_type: String, ) -> SensorReportBuilder

Add an artifact.

§Examples
use perfgate_sensor::SensorReportBuilder;
use perfgate_types::ToolInfo;

let tool = ToolInfo { name: "perfgate".to_string(), version: "0.1.0".to_string() };
let builder = SensorReportBuilder::new(tool, "2024-01-01T00:00:00Z".to_string())
    .artifact("report.json".to_string(), "sensor_report".to_string());
Source

pub fn max_findings(self, limit: usize) -> SensorReportBuilder

Set the maximum number of findings to include. When exceeded, findings are truncated and a meta-finding is appended. findings_emitted in the output counts real findings only (excluding the truncation meta-finding).

§Examples
use perfgate_sensor::SensorReportBuilder;
use perfgate_types::ToolInfo;

let tool = ToolInfo { name: "perfgate".to_string(), version: "0.1.0".to_string() };
let builder = SensorReportBuilder::new(tool, "2024-01-01T00:00:00Z".to_string())
    .max_findings(50);
Source

pub fn take_artifacts(&mut self) -> Vec<SensorArtifact>

Take ownership of accumulated artifacts (for manual report building).

§Examples
use perfgate_sensor::SensorReportBuilder;
use perfgate_types::ToolInfo;

let tool = ToolInfo { name: "perfgate".to_string(), version: "0.1.0".to_string() };
let mut builder = SensorReportBuilder::new(tool, "2024-01-01T00:00:00Z".to_string())
    .artifact("report.json".to_string(), "sensor_report".to_string());
let artifacts = builder.take_artifacts();
assert_eq!(artifacts.len(), 1);
assert_eq!(artifacts[0].path, "report.json");
Source

pub fn build(self, report: &PerfgateReport) -> SensorReport

Build the SensorReport from a PerfgateReport.

§Examples
use perfgate_sensor::SensorReportBuilder;
use perfgate_types::{
    ToolInfo, PerfgateReport, VerdictStatus, Verdict, VerdictCounts,
    ReportSummary, SensorVerdictStatus, REPORT_SCHEMA_V1,
};

let tool = ToolInfo { name: "perfgate".to_string(), version: "0.1.0".to_string() };
let report = PerfgateReport {
    report_type: REPORT_SCHEMA_V1.to_string(),
    verdict: Verdict {
        status: VerdictStatus::Pass,
        counts: VerdictCounts { pass: 1, warn: 0, fail: 0 },
        reasons: vec![],
    },
    compare: None,
    findings: vec![],
    summary: ReportSummary {
        pass_count: 1, warn_count: 0, fail_count: 0, total_count: 1,
    },
};

let sensor = SensorReportBuilder::new(tool, "2024-01-01T00:00:00Z".to_string())
    .ended_at("2024-01-01T00:01:00Z".to_string(), 60000)
    .baseline(true, None)
    .build(&report);

assert_eq!(sensor.verdict.status, SensorVerdictStatus::Pass);
assert_eq!(sensor.verdict.counts.info, 1);
Source

pub fn build_error( self, error_message: &str, stage: &str, error_kind: &str, ) -> SensorReport

Build an error SensorReport for catastrophic failures.

This creates a report when the sensor itself failed to run properly. stage indicates which phase failed (e.g. “config_parse”, “run_command”). error_kind classifies the error (e.g. “io_error”, “parse_error”, “exec_error”).

§Examples
use perfgate_sensor::SensorReportBuilder;
use perfgate_types::{ToolInfo, SensorVerdictStatus};

let tool = ToolInfo { name: "perfgate".to_string(), version: "0.1.0".to_string() };
let sensor = SensorReportBuilder::new(tool, "2024-01-01T00:00:00Z".to_string())
    .build_error("config not found", "config_parse", "parse_error");

assert_eq!(sensor.verdict.status, SensorVerdictStatus::Fail);
assert_eq!(sensor.verdict.counts.error, 1);
assert_eq!(sensor.findings.len(), 1);
Source

pub fn build_aggregated( self, outcomes: &[BenchOutcome], ) -> (SensorReport, String)

Build an aggregated SensorReport from multiple bench outcomes.

This encapsulates the multi-bench cockpit aggregation logic:

  • Maps findings from each bench’s PerfgateReport to sensor findings
  • In multi-bench mode: prefixes messages with [bench_name], injects bench_name into finding data, includes bench_name in fingerprint seed
  • Aggregates counts (sum), verdict (worst-of), reasons (union/deduped)
  • Registers per-bench artifacts
  • Combines markdown with \n---\n\n separator in multi-bench
  • Applies truncation via truncate_findings() using self.max_findings
  • Returns (SensorReport, combined_markdown)
§Examples
use perfgate_sensor::{SensorReportBuilder, BenchOutcome};
use perfgate_types::{
    ToolInfo, PerfgateReport, VerdictStatus, Verdict, VerdictCounts,
    ReportSummary, SensorVerdictStatus, REPORT_SCHEMA_V1,
};

let tool = ToolInfo { name: "perfgate".to_string(), version: "0.1.0".to_string() };
let report = PerfgateReport {
    report_type: REPORT_SCHEMA_V1.to_string(),
    verdict: Verdict {
        status: VerdictStatus::Pass,
        counts: VerdictCounts { pass: 1, warn: 0, fail: 0 },
        reasons: vec![],
    },
    compare: None,
    findings: vec![],
    summary: ReportSummary {
        pass_count: 1, warn_count: 0, fail_count: 0, total_count: 1,
    },
};

let outcome = BenchOutcome::Success {
    bench_name: "my-bench".to_string(),
    report,
    has_compare: false,
    baseline_available: false,
    markdown: "## Results\n".to_string(),
    extras_prefix: "extras".to_string(),
};

let (sensor, markdown) = SensorReportBuilder::new(tool, "2024-01-01T00:00:00Z".to_string())
    .build_aggregated(&[outcome]);

assert_eq!(sensor.verdict.status, SensorVerdictStatus::Pass);
assert!(markdown.contains("Results"));

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V