Web performance metrics (Core-Web-Vitals-style grading) implementing foundation-web-analysis::Analyzer -- Google PageSpeed Insights API client, mobile/desktop Lighthouse score + LCP/CLS/INP/FCP/TTFB/TTI extraction, opportunity/diagnostic collection, and Core-Web-Vitals pass/fail + letter-grade derivation
| Tier | infrastructure |
| Role | unclassified (baselined) |
| Path | crates/infrastructure/web-performance-analyzer |
| Edition | 2021 |
| Targets | infrastructure_web_performance_analyzer |
| Public items | 25 across 2 modules |
| Tests | 40 |
What it is for
# infrastructure-web-performance-analyzer
Web performance metrics (Core-Web-Vitals-style grading) analyzer implementing foundation_web_analysis::Analyzer. Runs the Google PageSpeed Insights API for both mobile and desktop strategies, extracts the overall Lighthouse score, Core Web Vitals (LCP, CLS, INP, plus FCP/TTFB/Speed Index/TTI/TBT), and (mobile only) improvement opportunities and diagnostics. Provides letter-grade (PerformanceGrade) and per-vital (VitalRating) derivation plus a passes_core_web_vitals check.
Lifted from plumber/src/analyzers/performance.rs and plumber/src/models/performance_metrics.rs (sprint 3.46, wave 2 -- see CHANGELOG.md for provenance).
Capabilities
analyzer (other)
Web performance analyzer -- Google PageSpeed Insights API client.
| Item |
|---|
pub const DEFAULT_MAX_BYTES: usize |
pub const DEFAULT_BASE_URL: & str |
PerformanceAnalyzer
Web performance analyzer -- Google PageSpeed Insights API client.
| Item |
|---|
pub struct PerformanceAnalyzer |
PerformanceAnalyzer :: fn new(api_key : Option <String>,) -> std::result::Result <Self, infrastructure_fetcher::SafeHttpError> |
PerformanceAnalyzer :: fn with_max_bytes(mut self, max_bytes : usize) -> Self |
PerformanceAnalyzer :: fn with_base_url(mut self, base_url : impl Into <String>) -> Self |
PerformanceAnalyzer :: fn default() -> Self |
PerformanceAnalyzer :: fn name(& self) -> & 'static str |
PerformanceAnalyzer :: async fn analyze(& self, organization_id : Uuid, website_url : & str) -> Result <AnalysisResult> |
PerformanceAnalyzer :: fn requires_link_graph(& self) -> bool |
PerformanceAnalyzer :: fn cache_ttl_days(& self) -> u32 |
PerformanceDiagnostic
Web performance metrics data model.
| Item |
|---|
pub struct PerformanceDiagnostic |
PerformanceGrade
Web performance metrics data model.
| Item |
|---|
pub enum PerformanceGrade |
PerformanceGrade :: fn fmt(& self, f : & mut std::fmt::Formatter <'_>) -> std::fmt::Result |
PerformanceMetrics
Web performance metrics data model.
| Item |
|---|
pub struct PerformanceMetrics |
PerformanceMetrics :: fn default() -> Self |
PerformanceMetrics :: fn new(organization_id : Uuid, url : & str) -> Self |
PerformanceMetrics :: fn lcp_rating(& self, mobile : bool) -> Option <VitalRating> |
PerformanceMetrics :: fn cls_rating(& self, mobile : bool) -> Option <VitalRating> |
PerformanceMetrics :: fn inp_rating(& self, mobile : bool) -> Option <VitalRating> |
PerformanceMetrics :: fn grade(& self, mobile : bool) -> Option <PerformanceGrade> |
PerformanceMetrics :: fn passes_core_web_vitals(& self, mobile : bool) -> bool |
PerformanceOpportunity
Web performance metrics data model.
| Item |
|---|
pub struct PerformanceOpportunity |
VitalRating
Web performance metrics data model.
| Item |
|---|
pub enum VitalRating |
VitalRating :: fn fmt(& self, f : & mut std::fmt::Formatter <'_>) -> std::fmt::Result |
How to use it
No examples/ target and no doctest in this crate's rustdoc. The tests listed under Verification are the closest executable usage.
Module structure
infrastructure_web_performance_analyzer
analyzermodels
flowchart TD n_infrastructure_web_performance_analyzer["infrastructure_web_performance_analyzer"] n_infrastructure_web_performance_analyzer --> n_analyzer["analyzer"] n_infrastructure_web_performance_analyzer --> n_models["models"]
Public surface
`analyzer`
| Item | What it is |
|---|---|
pub const DEFAULT_MAX_BYTES: usize | Response body byte cap for a PageSpeed Insights API response (Gate 1.5.6 input limit) |
pub const DEFAULT_BASE_URL: & str | The real PageSpeed Insights v5 endpoint (source's own default). |
pub struct PerformanceAnalyzer | Analyzer for website performance using the Google PageSpeed Insights API |
PerformanceAnalyzer :: fn new(api_key : Option <String>,) -> std::result::Result <Self, infrastructure_fetcher::SafeHttpError> | Build an analyzer with the default byte cap (DEFAULT_MAX_BYTES), timeout (infrastructure_fetcher::safe_http::DEFAULT_TIMEOUT, 30s), and the real PageSpeed Insights endpoint |
PerformanceAnalyzer :: fn with_max_bytes(mut self, max_bytes : usize) -> Self | Override the response body byte cap. |
PerformanceAnalyzer :: fn with_base_url(mut self, base_url : impl Into <String>) -> Self | Override the PageSpeed Insights base URL -- a test-only escape hatch (mirrors BacklinkFinder::with_search_bases) so analyze()'s both-strategies-fail error path is exercised against an unreachable local address instead of depending on live Google API traffic in a unit test. |
PerformanceAnalyzer :: fn default() -> Self | # Panics Panics if the underlying SafeHttpClient cannot be built (TLS backend init failure) -- matches the source's expect-on-construction posture (Client::builder()...expect("Failed to build HTTP client")) |
PerformanceAnalyzer :: fn name(& self) -> & 'static str | — |
PerformanceAnalyzer :: async fn analyze(& self, organization_id : Uuid, website_url : & str) -> Result <AnalysisResult> | — |
PerformanceAnalyzer :: fn requires_link_graph(& self) -> bool | — |
PerformanceAnalyzer :: fn cache_ttl_days(& self) -> u32 | — |
`models`
| Item | What it is |
|---|---|
pub struct PerformanceMetrics | Performance metrics for one organization's website, gathered from Google PageSpeed Insights (mobile + desktop Lighthouse runs). |
pub struct PerformanceOpportunity | A Lighthouse "opportunity" audit -- a specific, actionable change with an estimated time (and, where known, byte) savings. |
pub struct PerformanceDiagnostic | A Lighthouse "diagnostic" audit -- informational detail that does not carry a savings estimate (DOM size, request counts, third-party impact). |
PerformanceMetrics :: fn default() -> Self | — |
PerformanceMetrics :: fn new(organization_id : Uuid, url : & str) -> Self | — |
PerformanceMetrics :: fn lcp_rating(& self, mobile : bool) -> Option <VitalRating> | Rate the Largest Contentful Paint against the standard Core Web Vitals thresholds (good <= 2500ms, needs improvement <= 4000ms). |
PerformanceMetrics :: fn cls_rating(& self, mobile : bool) -> Option <VitalRating> | Rate the Cumulative Layout Shift against the standard Core Web Vitals thresholds (good <= 0.1, needs improvement <= 0.25). |
PerformanceMetrics :: fn inp_rating(& self, mobile : bool) -> Option <VitalRating> | Rate the Interaction to Next Paint against the standard Core Web Vitals thresholds (good <= 200ms, needs improvement <= 500ms). |
PerformanceMetrics :: fn grade(& self, mobile : bool) -> Option <PerformanceGrade> | Overall letter grade from the Lighthouse performance score (0-100). |
PerformanceMetrics :: fn passes_core_web_vitals(& self, mobile : bool) -> bool | True only when LCP, CLS, and INP are all present and all rate Good |
pub enum VitalRating | — |
VitalRating :: fn fmt(& self, f : & mut std::fmt::Formatter <'_>) -> std::fmt::Result | — |
pub enum PerformanceGrade | — |
PerformanceGrade :: fn fmt(& self, f : & mut std::fmt::Formatter <'_>) -> std::fmt::Result | — |
Re-exports. Exported here, defined elsewhere.
| Export | Defined in |
|---|---|
{PerformanceAnalyzer,DEFAULT_BASE_URL,DEFAULT_MAX_BYTES} | analyzer::{PerformanceAnalyzer,DEFAULT_BASE_URL,DEFAULT_MAX_BYTES} |
{PerformanceDiagnostic,PerformanceGrade,PerformanceMetrics,PerformanceOpportunity,VitalRating,} | models::{PerformanceDiagnostic,PerformanceGrade,PerformanceMetrics,PerformanceOpportunity,VitalRating,} |
Boundary
Reaches into foundation.
Shares tier infrastructure with 82 other crates: infrastructure-acquire, infrastructure-adapters-google-calendar, infrastructure-adapters-google-gmail, infrastructure-adapters-google-places, infrastructure-adapters-google-trends, infrastructure-adapters-shodan, infrastructure-adapters-yelp, infrastructure-agent, … (82 total).
_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._
Where it sits
| Tier (ontology) | infrastructure |
| Architectural role (taxonomy) | unclassified (baselined) |
| Location | crates/infrastructure/web-performance-analyzer |
| Vocabulary in force (lexicon) | current |
Tier flow. Which tiers this crate's own edges cross.
flowchart LR n_infrastructure["infrastructure"] --> n_foundation["foundation"]
Dependencies
Runtime, in this workspace.
| Crate | Tier | Optional | Only on |
|---|---|---|---|
| `foundation-web-analysis` | foundation | no | always |
| `infrastructure-fetcher` | infrastructure | no | always |
Runtime, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
async-trait | ^0.1 | — | no | always |
chrono | ^0.4 | serde | no | always |
serde | ^1 | derive | no | always |
serde_json | ^1 | — | no | always |
thiserror | ^2 | — | no | always |
url | ^2 | — | no | always |
uuid | ^1 | v4, v7, serde, js | no | always |
Development, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
tokio | ^1 | full, full, test-util | no | always |
tokio-test | ^0.4 | — | no | always |
Build. None.
Depended on by. Nothing in this workspace.
Signal flow — what reaches this crate, and what it reaches.
flowchart LR SELF["infrastructure-web-performance-analyzer"] SELF -->|runtime| n_foundation_web_analysis["foundation-web-analysis"] SELF -->|runtime| n_infrastructure_fetcher["infrastructure-fetcher"] classDef self fill:#1f883d,stroke:#1f883d,color:#fff; class SELF self;
Feature flags
No Cargo features are defined: every capability is unconditional, so no consumer can receive a half-wired crate.
Targets
| Kind | Name | Source |
|---|---|---|
| lib | infrastructure_web_performance_analyzer | `src/lib.rs` |
Error model
No public error type was detected: no public item declares a type named *Error, and no public signature returns one.
Operational characteristics
| Property | Evidence |
|---|---|
| async public surface | yes |
| async runtime | none detected |
| database access | none detected |
| network I/O | none detected |
| unsafe code | none detected |
| environment variables | none detected |
No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.
Configuration
No environment variable is read with a literal name anywhere in this crate. A variable whose key is computed at run time cannot be listed here, and is not claimed to be absent.
Related capabilities
No workspace crate depends on this one.
Verification
| Kind | Count |
|---|---|
| Unit tests | 40 |
| Integration tests | 0 |
| Examples | 0 |
| Doctests | 0 |
Evidence by module. How often each public module is named by something executable.
| Module | Tests | Examples | Consumers |
|---|---|---|---|
analyzer | 3 | 0 | 0 |
models | 5 | 0 | 0 |
What the tests establish, by name:
analyze_fails_fast_on_invalid_url—src/analyzer.rsanalyze_records_errors_and_flags_manual_review_when_both_strategies_fail—src/analyzer.rscache_ttl_is_one_day—src/analyzer.rsdata_incomplete_review_absent_when_at_least_one_score_present—src/analyzer.rsdata_incomplete_review_present_when_no_scores_collected—src/analyzer.rsextract_diagnostics_captures_third_party_blocking_time—src/analyzer.rsextract_diagnostics_includes_known_diagnostic_ids—src/analyzer.rsextract_metrics_handles_missing_lighthouse_result—src/analyzer.rsextract_metrics_maps_score_and_core_web_vitals_for_mobile—src/analyzer.rsextract_metrics_only_populates_opportunities_and_diagnostics_for_mobile—src/analyzer.rsextract_metrics_writes_desktop_fields_when_not_mobile—src/analyzer.rsextract_opportunities_ignores_ids_outside_the_known_set—src/analyzer.rsextract_opportunities_includes_audit_with_positive_savings—src/analyzer.rsextract_opportunities_skips_audit_with_zero_savings_and_high_score—src/analyzer.rsname_is_performance_analyzer—src/analyzer.rsrequires_link_graph_is_false—src/analyzer.rscls_rating_good_at_or_below_point_one—src/models.rscls_rating_needs_improvement_between_point_one_and_point_two_five—src/models.rscls_rating_poor_above_point_two_five—src/models.rsgrade_a_for_score_90_to_100—src/models.rsgrade_b_for_score_80_to_89—src/models.rsgrade_c_for_score_70_to_79—src/models.rsgrade_d_for_score_50_to_69—src/models.rsgrade_f_for_score_below_50—src/models.rsgrade_none_when_score_missing—src/models.rsinp_rating_good_at_or_below_200ms—src/models.rsinp_rating_needs_improvement_between_200_and_500ms—src/models.rsinp_rating_poor_above_500ms—src/models.rslcp_rating_good_at_or_below_2500ms—src/models.rslcp_rating_needs_improvement_between_2500_and_4000ms—src/models.rs- _… 10 more_
Documentation coverage
| Measure | Documented | Total |
|---|---|---|
| Public items with rustdoc | 15 | 25 |
Public modules with a //! block | 2 | 2 |
pie showData
title Public items with rustdoc
"Documented" : 15
"No rustdoc detected" : 10
Metrics
| Metric | Value |
|---|---|
| Rust source files | 3 |
| Source lines | 1174 |
| Code lines | 918 |
| Public API items | 25 |
| Public modules | 2 |
| Tests | 40 |
| Examples | 0 |
| Cargo features | 0 |
| Direct runtime dependencies | 9 |
| Workspace reverse dependencies | 0 |
pie showData
title Public API by kind
"constant" : 2
"enum" : 2
"method" : 17
"struct" : 4
pie showData
title Rust source composition
"Code" : 918
"Blank or comment" : 256
Generation
Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.