pub mod carbon;
pub(crate) mod carbon_profiles;
pub mod cloud_energy;
pub mod electricity_maps;
#[cfg(feature = "daemon")]
pub(crate) mod energy_state;
pub mod scaphandre;
use std::cmp::Ordering;
use std::collections::{BTreeMap, HashMap};
use crate::correlate::Trace;
use crate::detect::{Finding, GreenImpact};
use crate::report::{GreenSummary, TopOffender};
use carbon::{
CO2_MODEL, CO2_MODEL_CLOUD_SPECPOWER, CO2_MODEL_EMAPS, CO2_MODEL_SCAPHANDRE, CO2_MODEL_V2,
CO2_MODEL_V3, CarbonContext, CarbonEstimate, CarbonReport, ENERGY_PER_IO_OP_KWH, GENERIC_PUE,
IntensitySource, REGION_STATUS_KNOWN, REGION_STATUS_OUT_OF_TABLE, REGION_STATUS_UNRESOLVED,
RegionBreakdown, UNKNOWN_REGION, energy_coefficient, extract_hostname,
hourly_profile_for_region_lower, is_valid_region_id, lookup_region_lower, per_op_gco2,
resolve_region,
};
const MAX_REGIONS: usize = 256;
struct EndpointStats<'a> {
total_io_ops: usize,
invocation_count: usize,
service: &'a str,
last_seen_trace: usize,
}
fn count_endpoint_stats(traces: &[Trace]) -> (HashMap<&str, EndpointStats<'_>>, usize) {
let mut endpoint_stats: HashMap<&str, EndpointStats<'_>> =
HashMap::with_capacity(traces.len().min(64));
let mut total_io_ops: usize = 0;
for (trace_idx, trace) in traces.iter().enumerate() {
for span in &trace.spans {
total_io_ops += 1;
let key = span.event.source.endpoint.as_str();
let stats = endpoint_stats.entry(key).or_insert_with(|| EndpointStats {
total_io_ops: 0,
invocation_count: 0,
service: span.event.service.as_str(),
last_seen_trace: usize::MAX,
});
stats.total_io_ops += 1;
if stats.last_seen_trace != trace_idx {
stats.invocation_count += 1;
stats.last_seen_trace = trace_idx;
}
}
}
(endpoint_stats, total_io_ops)
}
#[must_use]
#[allow(clippy::too_many_lines)] pub fn score_green(
traces: &[Trace],
findings: Vec<Finding>,
carbon: Option<&CarbonContext>,
) -> (Vec<Finding>, GreenSummary) {
let (endpoint_stats, total_io_ops) = count_endpoint_stats(traces);
let mut dedup: HashMap<(&str, &str, &str), usize> = HashMap::with_capacity(findings.len());
for f in &findings {
if !f.finding_type.is_avoidable_io() {
continue;
}
let avoidable = f.pattern.occurrences.saturating_sub(1);
let entry = dedup
.entry((&f.trace_id, &f.pattern.template, &f.source_endpoint))
.or_insert(0);
*entry = (*entry).max(avoidable);
}
let avoidable_io_ops: usize = dedup.values().sum();
let iis_map: HashMap<&str, f64> = endpoint_stats
.iter()
.map(|(&ep, stats)| {
let invocations = stats.invocation_count.max(1) as f64;
(ep, stats.total_io_ops as f64 / invocations)
})
.collect();
let mut enriched = findings;
for f in &mut enriched {
let iis = iis_map
.get(f.source_endpoint.as_str())
.copied()
.unwrap_or(0.0);
let extra = if f.finding_type.is_avoidable_io() {
f.pattern.occurrences.saturating_sub(1)
} else {
0
};
f.green_impact = Some(GreenImpact {
estimated_extra_io_ops: extra,
io_intensity_score: iis,
io_intensity_band: crate::report::interpret::InterpretationLevel::for_iis(iis),
});
}
let (co2, regions, multi_region_active) = match carbon {
Some(ctx) => compute_carbon_report(traces, ctx, total_io_ops, avoidable_io_ops),
None => (None, Vec::new(), false),
};
let per_op_active = carbon.is_some_and(|ctx| ctx.per_operation_coefficients);
let has_energy_modifier = carbon.is_some_and(|ctx| {
ctx.energy_snapshot.as_ref().is_some_and(|s| !s.is_empty())
|| ctx.calibration.is_some()
|| ctx
.real_time_intensity
.as_ref()
.is_some_and(|rt| !rt.is_empty())
});
let default_region_lower = if multi_region_active || per_op_active || has_energy_modifier {
None
} else {
carbon
.and_then(|ctx| ctx.default_region.as_deref())
.map(str::to_ascii_lowercase)
};
let mut top_offenders: Vec<TopOffender> = endpoint_stats
.iter()
.map(|(endpoint, stats)| {
let iis = iis_map.get(endpoint).copied().unwrap_or(0.0);
let co2_grams = default_region_lower
.as_deref()
.and_then(|r| carbon::io_ops_to_co2_grams(stats.total_io_ops, r));
TopOffender {
endpoint: (*endpoint).to_string(),
service: stats.service.to_string(),
io_intensity_score: iis,
io_intensity_band: crate::report::interpret::InterpretationLevel::for_iis(iis),
co2_grams,
}
})
.collect();
top_offenders.sort_by(|a, b| {
b.io_intensity_score
.partial_cmp(&a.io_intensity_score)
.unwrap_or(Ordering::Equal)
.then_with(|| a.endpoint.cmp(&b.endpoint))
});
let io_waste_ratio = if total_io_ops > 0 {
avoidable_io_ops as f64 / total_io_ops as f64
} else {
0.0
};
let green_summary = GreenSummary {
total_io_ops,
avoidable_io_ops,
io_waste_ratio,
io_waste_ratio_band: crate::report::interpret::InterpretationLevel::for_waste_ratio(
io_waste_ratio,
),
top_offenders,
transport_gco2: co2.as_ref().and_then(|r| r.transport_gco2),
co2,
regions,
};
(enriched, green_summary)
}
#[derive(Default)]
struct RegionAccumulator {
co2_gco2: f64,
total_ops: usize,
intensity_sum_per_op: f64,
max_intensity_source: IntensitySource,
any_scaphandre: bool,
any_cloud_specpower: bool,
any_calibrated: bool,
}
#[derive(Default, Clone, Copy)]
#[allow(clippy::struct_excessive_bools)]
struct ReportFlags {
any_hourly: bool,
any_monthly_hourly: bool,
any_scaphandre: bool,
any_cloud_specpower: bool,
any_calibrated: bool,
any_realtime: bool,
}
#[derive(Default)]
struct CarbonRunState {
per_region: BTreeMap<String, RegionAccumulator>,
unknown_ops: usize,
overflow_warned: bool,
total_transport_gco2: f64,
multi_region_active: bool,
}
struct SpanRegionContext<'a> {
region_key: Option<String>,
region_ref: &'a str,
custom_profile: Option<&'a carbon_profiles::HourlyProfile>,
embedded_profile: Option<carbon_profiles::HourlyProfileRef<'static>>,
annual_intensity: f64,
pue: f64,
}
fn compute_carbon_report(
traces: &[Trace],
ctx: &CarbonContext,
total_io_ops: usize,
avoidable_io_ops: usize,
) -> (Option<CarbonReport>, Vec<RegionBreakdown>, bool) {
let mut state = CarbonRunState {
multi_region_active: !ctx.service_regions.is_empty(),
..Default::default()
};
if traces.is_empty() {
return (None, Vec::new(), state.multi_region_active);
}
for trace in traces {
for span in &trace.spans {
process_span_for_carbon(&mut state, span, ctx);
}
}
let (mut regions, flags, operational_gco2) =
build_region_breakdowns(state.per_region, state.unknown_ops);
let model = select_co2_model_tag(flags);
let report = finalize_carbon_report(
traces.len(),
operational_gco2,
state.total_transport_gco2,
total_io_ops,
avoidable_io_ops,
state.unknown_ops,
ctx.embodied_per_request_gco2,
model,
);
sort_regions_by_co2_desc(&mut regions);
(Some(report), regions, state.multi_region_active)
}
fn process_span_for_carbon(
state: &mut CarbonRunState,
span: &crate::normalize::NormalizedEvent,
ctx: &CarbonContext,
) {
if span.event.cloud_region.is_some() {
state.multi_region_active = true;
}
let Some(region_ctx) = resolve_span_region(span, ctx, state) else {
return;
};
let (intensity_used, span_source) = resolve_span_intensity(span, ®ion_ctx, ctx);
let (energy_kwh, measured_model, calibrated) = resolve_span_energy(span, ctx);
let op_co2 = per_op_gco2(energy_kwh, intensity_used, region_ctx.pue);
let region_ref = region_ctx.region_ref;
let pue = region_ctx.pue;
accumulate_span_into_region(
&mut state.per_region,
region_ctx,
op_co2,
intensity_used,
span_source,
measured_model,
calibrated,
);
state.total_transport_gco2 +=
network_transport_contribution(span, region_ref, intensity_used, pue, ctx);
}
fn resolve_span_region<'a>(
span: &'a crate::normalize::NormalizedEvent,
ctx: &'a CarbonContext,
state: &mut CarbonRunState,
) -> Option<SpanRegionContext<'a>> {
let Some(region_ref) = resolve_region(&span.event, ctx) else {
state.unknown_ops += 1;
return None;
};
debug_assert!(
is_valid_region_id(region_ref),
"unvalidated region '{region_ref}' reached compute_carbon_report; \
ingestion boundary should have sanitized it"
);
let needs_lowercase = region_ref.bytes().any(|b| b.is_ascii_uppercase());
let region_key: Option<String> = if needs_lowercase {
Some(region_ref.to_ascii_lowercase())
} else {
None
};
let region_key_borrow: &str = region_key.as_deref().unwrap_or(region_ref);
if state.per_region.len() >= MAX_REGIONS && !state.per_region.contains_key(region_key_borrow) {
state.unknown_ops += 1;
if !state.overflow_warned {
tracing::debug!(
"Region cardinality cap ({MAX_REGIONS}) exceeded; \
additional distinct regions folded into 'unknown'."
);
state.overflow_warned = true;
}
return None;
}
let custom_profile = ctx
.custom_hourly_profiles
.as_ref()
.and_then(|m| m.get(region_key_borrow));
let has_realtime = ctx
.real_time_intensity
.as_ref()
.is_some_and(|rt| rt.contains_key(region_key_borrow));
let (annual_intensity, pue) = lookup_region_lower(region_key_borrow).unwrap_or_else(|| {
let fallback_pue = if custom_profile.is_some() || has_realtime {
GENERIC_PUE
} else {
0.0
};
(0.0, fallback_pue)
});
let embedded_profile = if custom_profile.is_none() {
hourly_profile_for_region_lower(region_key_borrow)
} else {
None
};
Some(SpanRegionContext {
region_key,
region_ref,
custom_profile,
embedded_profile,
annual_intensity,
pue,
})
}
fn resolve_span_intensity(
span: &crate::normalize::NormalizedEvent,
region_ctx: &SpanRegionContext<'_>,
ctx: &CarbonContext,
) -> (f64, IntensitySource) {
let region_key_borrow: &str = region_ctx
.region_key
.as_deref()
.unwrap_or(region_ctx.region_ref);
let real_time_val = ctx
.real_time_intensity
.as_ref()
.and_then(|rt| rt.get(region_key_borrow));
if let Some(&rt_intensity) = real_time_val {
return (rt_intensity, IntensitySource::RealTime);
}
let region_has_hourly = ctx.use_hourly_profiles
&& (region_ctx.custom_profile.is_some() || region_ctx.embedded_profile.is_some());
if !region_has_hourly {
return (region_ctx.annual_intensity, IntensitySource::Annual);
}
let Some(hour) = crate::time::parse_utc_hour(&span.event.timestamp) else {
return (region_ctx.annual_intensity, IntensitySource::Annual);
};
let month_opt = crate::time::parse_utc_month(&span.event.timestamp);
if let Some(cp) = region_ctx.custom_profile {
let val = cp.intensity_at(hour, month_opt);
let src = if cp.is_monthly() {
IntensitySource::MonthlyHourly
} else {
IntensitySource::Hourly
};
return (val, src);
}
if let Some(ep) = region_ctx.embedded_profile {
let val = ep.intensity_at(hour, month_opt);
let src = if ep.is_monthly() {
IntensitySource::MonthlyHourly
} else {
IntensitySource::Hourly
};
return (val, src);
}
debug_assert!(false, "region_has_hourly was true but no profile found");
(region_ctx.annual_intensity, IntensitySource::Annual)
}
fn resolve_span_energy(
span: &crate::normalize::NormalizedEvent,
ctx: &CarbonContext,
) -> (f64, Option<&'static str>, bool) {
let mut proxy_energy_kwh = if ctx.per_operation_coefficients {
ENERGY_PER_IO_OP_KWH * energy_coefficient(&span.event)
} else {
ENERGY_PER_IO_OP_KWH
};
let calibrated = if let Some(ref cal) = ctx.calibration {
if let Some(factor) = cal.factor_for(&span.event.service) {
proxy_energy_kwh *= factor;
true
} else {
false
}
} else {
false
};
let (energy_kwh, measured_model) = match &ctx.energy_snapshot {
Some(snapshot) => match snapshot.get(&span.event.service) {
Some(entry) => (entry.energy_per_op_kwh, Some(entry.model_tag)),
None => (proxy_energy_kwh, None),
},
None => (proxy_energy_kwh, None),
};
(energy_kwh, measured_model, calibrated)
}
fn accumulate_span_into_region(
per_region: &mut BTreeMap<String, RegionAccumulator>,
region_ctx: SpanRegionContext<'_>,
op_co2: f64,
intensity_used: f64,
span_source: IntensitySource,
measured_model: Option<&'static str>,
calibrated: bool,
) {
let SpanRegionContext {
region_key,
region_ref,
..
} = region_ctx;
let acc = if let Some(lowered) = region_key {
per_region.entry(lowered).or_default()
} else if let Some(existing) = per_region.get_mut(region_ref) {
existing
} else {
per_region.entry(region_ref.to_string()).or_default()
};
acc.co2_gco2 += op_co2;
acc.total_ops += 1;
acc.intensity_sum_per_op += intensity_used;
if span_source > acc.max_intensity_source {
acc.max_intensity_source = span_source;
}
match measured_model {
Some(CO2_MODEL_SCAPHANDRE) => acc.any_scaphandre = true,
Some(CO2_MODEL_CLOUD_SPECPOWER) => acc.any_cloud_specpower = true,
_ => {
if calibrated {
acc.any_calibrated = true;
}
}
}
}
fn network_transport_contribution(
span: &crate::normalize::NormalizedEvent,
caller_region: &str,
intensity_used: f64,
pue: f64,
ctx: &CarbonContext,
) -> f64 {
if !ctx.include_network_transport || span.event.event_type != crate::event::EventType::HttpOut {
return 0.0;
}
let Some(bytes) = span.event.response_size_bytes else {
return 0.0;
};
let callee_region = extract_hostname(&span.event.target)
.and_then(|host| {
if host.bytes().any(|b| b.is_ascii_uppercase()) {
ctx.service_regions.get(&host.to_ascii_lowercase())
} else {
ctx.service_regions.get(host)
}
})
.map(String::as_str);
let Some(callee) = callee_region else {
return 0.0;
};
if caller_region.eq_ignore_ascii_case(callee) {
return 0.0;
}
let transport_energy = bytes as f64 * ctx.network_energy_per_byte_kwh;
transport_energy * intensity_used * pue
}
fn build_region_breakdowns(
per_region: BTreeMap<String, RegionAccumulator>,
unknown_ops: usize,
) -> (Vec<RegionBreakdown>, ReportFlags, f64) {
let mut regions: Vec<RegionBreakdown> = Vec::with_capacity(per_region.len() + 1);
let mut flags = ReportFlags::default();
let mut operational_gco2: f64 = 0.0;
for (region, acc) in per_region {
operational_gco2 += acc.co2_gco2;
update_flags_from_accumulator(&mut flags, &acc);
regions.push(build_single_region_row(region, &acc));
}
if unknown_ops > 0 {
tracing::debug!(
"{unknown_ops} I/O ops had no resolvable region and were excluded \
from operational COâ‚‚ estimates. Set [green] default_region or \
[green.service_regions] to attribute them."
);
regions.push(RegionBreakdown {
status: REGION_STATUS_UNRESOLVED,
region: UNKNOWN_REGION.to_string(),
grid_intensity_gco2_kwh: 0.0,
pue: 0.0,
io_ops: unknown_ops,
co2_gco2: 0.0,
intensity_source: IntensitySource::Annual,
});
}
(regions, flags, operational_gco2)
}
fn update_flags_from_accumulator(flags: &mut ReportFlags, acc: &RegionAccumulator) {
match acc.max_intensity_source {
IntensitySource::RealTime => {
flags.any_realtime = true;
}
IntensitySource::MonthlyHourly => {
flags.any_monthly_hourly = true;
flags.any_hourly = true;
}
IntensitySource::Hourly => {
flags.any_hourly = true;
}
IntensitySource::Annual => {}
}
flags.any_scaphandre |= acc.any_scaphandre;
flags.any_cloud_specpower |= acc.any_cloud_specpower;
flags.any_calibrated |= acc.any_calibrated;
}
fn build_single_region_row(region: String, acc: &RegionAccumulator) -> RegionBreakdown {
if let Some((_, pue)) = lookup_region_lower(®ion) {
let mean_intensity = acc.intensity_sum_per_op / acc.total_ops as f64;
let intensity_source = acc.max_intensity_source;
maybe_warn_eu_central_1_profile(®ion, intensity_source);
return RegionBreakdown {
status: REGION_STATUS_KNOWN,
region,
grid_intensity_gco2_kwh: mean_intensity,
pue,
io_ops: acc.total_ops,
co2_gco2: acc.co2_gco2,
intensity_source,
};
}
let has_co2 = acc.co2_gco2 > 0.0;
if !has_co2 {
tracing::debug!(
"Region '{region}' is not in the embedded carbon table; \
{ops} I/O ops contribute 0 to operational COâ‚‚. \
See docs/CONFIGURATION.md for the list of supported regions.",
ops = acc.total_ops
);
}
let mean_intensity = if acc.total_ops > 0 && has_co2 {
acc.intensity_sum_per_op / acc.total_ops as f64
} else {
0.0
};
let pue_display = if has_co2 { GENERIC_PUE } else { 0.0 };
RegionBreakdown {
status: REGION_STATUS_OUT_OF_TABLE,
region,
grid_intensity_gco2_kwh: mean_intensity,
pue: pue_display,
io_ops: acc.total_ops,
co2_gco2: acc.co2_gco2,
intensity_source: if has_co2 {
acc.max_intensity_source
} else {
IntensitySource::Annual
},
}
}
fn maybe_warn_eu_central_1_profile(region: &str, intensity_source: IntensitySource) {
if intensity_source > IntensitySource::Annual && region == "eu-central-1" {
use std::sync::Once;
static WARN: Once = Once::new();
WARN.call_once(|| {
tracing::debug!(
region = "eu-central-1",
annual_gco2_kwh = 338.0,
hourly_mean_gco2_kwh = 442.0,
"Hourly carbon profile for eu-central-1 (DE) averages \
~31% above the flat annual value. This reflects recent \
grid data. Disable with [green] use_hourly_profiles = false \
to use the annual baseline instead."
);
});
}
}
fn select_co2_model_tag(flags: ReportFlags) -> &'static str {
let cal = flags.any_calibrated && !flags.any_scaphandre && !flags.any_cloud_specpower;
if flags.any_realtime {
CO2_MODEL_EMAPS
} else if flags.any_scaphandre {
CO2_MODEL_SCAPHANDRE
} else if flags.any_cloud_specpower {
CO2_MODEL_CLOUD_SPECPOWER
} else if flags.any_monthly_hourly {
if cal {
carbon::CO2_MODEL_V3_CAL
} else {
CO2_MODEL_V3
}
} else if flags.any_hourly {
if cal {
carbon::CO2_MODEL_V2_CAL
} else {
CO2_MODEL_V2
}
} else if cal {
carbon::CO2_MODEL_V1_CAL
} else {
CO2_MODEL
}
}
#[allow(clippy::too_many_arguments)]
fn finalize_carbon_report(
traces_len: usize,
operational_gco2: f64,
total_transport_gco2: f64,
total_io_ops: usize,
avoidable_io_ops: usize,
unknown_ops: usize,
embodied_per_request_gco2: f64,
model: &'static str,
) -> CarbonReport {
let embodied_gco2 = traces_len as f64 * embodied_per_request_gco2;
let total_mid = operational_gco2 + embodied_gco2 + total_transport_gco2;
let accounted_io_ops = total_io_ops.saturating_sub(unknown_ops);
let avoidable_mid = if accounted_io_ops > 0 {
let ratio = (avoidable_io_ops as f64 / accounted_io_ops as f64).min(1.0);
operational_gco2 * ratio
} else {
0.0
};
let transport_gco2 = if total_transport_gco2 > 0.0 {
Some(total_transport_gco2)
} else {
None
};
let total_methodology = if transport_gco2.is_some() {
carbon::METHODOLOGY_SCI_NUMERATOR_TRANSPORT
} else {
carbon::METHODOLOGY_SCI_NUMERATOR
};
CarbonReport {
total: CarbonEstimate::new_with_model(total_mid, model, total_methodology),
avoidable: CarbonEstimate::operational_ratio_with_model(avoidable_mid, model),
operational_gco2,
embodied_gco2,
transport_gco2,
}
}
fn sort_regions_by_co2_desc(regions: &mut [RegionBreakdown]) {
regions.sort_by(|a, b| {
b.co2_gco2
.partial_cmp(&a.co2_gco2)
.unwrap_or(Ordering::Equal)
.then_with(|| a.region.cmp(&b.region))
});
}
#[cfg(test)]
mod tests {
use super::*;
use crate::detect::{Confidence, FindingType, Pattern, Severity};
use crate::event::SpanEvent;
use crate::test_helpers::{make_http_event, make_sql_event, make_trace};
#[test]
fn empty_input_returns_empty_summary() {
let (findings, summary) = score_green(&[], vec![], None);
assert!(findings.is_empty());
assert_eq!(summary.total_io_ops, 0);
assert_eq!(summary.avoidable_io_ops, 0);
assert!((summary.io_waste_ratio - 0.0).abs() < f64::EPSILON);
assert!(summary.top_offenders.is_empty());
}
#[test]
fn single_trace_computes_iis() {
let events: Vec<SpanEvent> = (1..=6)
.map(|i| {
make_sql_event(
"trace-1",
&format!("span-{i}"),
&format!("SELECT * FROM order_item WHERE order_id = {i}"),
&format!("2025-07-10T14:32:01.{:03}Z", i * 50),
)
})
.collect();
let trace = make_trace(events);
let finding = Finding {
finding_type: FindingType::NPlusOneSql,
severity: Severity::Warning,
trace_id: "trace-1".to_string(),
service: "order-svc".to_string(),
source_endpoint: "POST /api/orders/42/submit".to_string(),
pattern: Pattern {
template: "SELECT * FROM order_item WHERE order_id = ?".to_string(),
occurrences: 6,
window_ms: 250,
distinct_params: 6,
},
suggestion: "batch".to_string(),
first_timestamp: "2025-07-10T14:32:01.050Z".to_string(),
last_timestamp: "2025-07-10T14:32:01.300Z".to_string(),
green_impact: None,
confidence: Confidence::default(),
code_location: None,
};
let (findings, summary) = score_green(&[trace], vec![finding], None);
assert_eq!(summary.total_io_ops, 6);
assert_eq!(summary.avoidable_io_ops, 5);
assert!((summary.io_waste_ratio - 5.0 / 6.0).abs() < f64::EPSILON);
assert_eq!(summary.top_offenders.len(), 1);
assert!((summary.top_offenders[0].io_intensity_score - 6.0).abs() < f64::EPSILON);
assert_eq!(findings.len(), 1);
let impact = findings[0].green_impact.as_ref().unwrap();
assert_eq!(impact.estimated_extra_io_ops, 5);
assert!((impact.io_intensity_score - 6.0).abs() < f64::EPSILON);
}
#[test]
fn multiple_traces_same_endpoint() {
let events_t1: Vec<SpanEvent> = (1..=3)
.map(|i| {
make_sql_event(
"trace-A",
&format!("span-a{i}"),
&format!("SELECT * FROM order_item WHERE order_id = {i}"),
&format!("2025-07-10T14:32:01.{:03}Z", i * 50),
)
})
.collect();
let events_t2: Vec<SpanEvent> = (1..=3)
.map(|i| {
make_sql_event(
"trace-B",
&format!("span-b{i}"),
&format!("SELECT * FROM order_item WHERE order_id = {}", i + 10),
&format!("2025-07-10T14:32:02.{:03}Z", i * 50),
)
})
.collect();
let trace_a = make_trace(events_t1);
let trace_b = make_trace(events_t2);
let (_, summary) = score_green(&[trace_a, trace_b], vec![], None);
assert_eq!(summary.total_io_ops, 6);
assert_eq!(summary.top_offenders.len(), 1);
assert!((summary.top_offenders[0].io_intensity_score - 3.0).abs() < f64::EPSILON);
}
#[test]
fn top_offenders_sorted_by_iis_desc() {
let mut events_a: Vec<SpanEvent> = (1..=6)
.map(|i| {
make_sql_event(
"trace-1",
&format!("span-a{i}"),
&format!("SELECT * FROM order_item WHERE order_id = {i}"),
&format!("2025-07-10T14:32:01.{:03}Z", i * 50),
)
})
.collect();
let mut events_b: Vec<SpanEvent> = (1..=2)
.map(|i| {
let mut e = make_sql_event(
"trace-1",
&format!("span-b{i}"),
&format!("SELECT * FROM orders WHERE user_id = {i}"),
&format!("2025-07-10T14:32:02.{:03}Z", i * 50),
);
e.source.endpoint = "GET /api/orders".to_string();
e
})
.collect();
let mut all_events = Vec::new();
all_events.append(&mut events_a);
all_events.append(&mut events_b);
let trace = make_trace(all_events);
let (_, summary) = score_green(&[trace], vec![], None);
assert_eq!(summary.top_offenders.len(), 2);
assert_eq!(
summary.top_offenders[0].endpoint,
"POST /api/orders/42/submit"
);
assert_eq!(summary.top_offenders[1].endpoint, "GET /api/orders");
assert!(
summary.top_offenders[0].io_intensity_score
>= summary.top_offenders[1].io_intensity_score
);
}
#[test]
fn green_impact_populated_on_findings() {
let events: Vec<SpanEvent> = (1..=6)
.map(|i| {
make_sql_event(
"trace-1",
&format!("span-{i}"),
&format!("SELECT * FROM order_item WHERE order_id = {i}"),
&format!("2025-07-10T14:32:01.{:03}Z", i * 50),
)
})
.collect();
let trace = make_trace(events);
let finding = Finding {
finding_type: FindingType::NPlusOneSql,
severity: Severity::Warning,
trace_id: "trace-1".to_string(),
service: "order-svc".to_string(),
source_endpoint: "POST /api/orders/42/submit".to_string(),
pattern: Pattern {
template: "SELECT * FROM order_item WHERE order_id = ?".to_string(),
occurrences: 6,
window_ms: 250,
distinct_params: 6,
},
suggestion: "batch".to_string(),
first_timestamp: "2025-07-10T14:32:01.050Z".to_string(),
last_timestamp: "2025-07-10T14:32:01.300Z".to_string(),
green_impact: None,
confidence: Confidence::default(),
code_location: None,
};
let (findings, _) = score_green(&[trace], vec![finding], None);
let impact = findings[0].green_impact.as_ref().unwrap();
assert_eq!(impact.estimated_extra_io_ops, 5);
assert!((impact.io_intensity_score - 6.0).abs() < f64::EPSILON);
}
#[test]
fn dedup_avoidable_across_finding_types() {
let events: Vec<SpanEvent> = (1..=6)
.map(|i| {
make_sql_event(
"trace-1",
&format!("span-{i}"),
&format!("SELECT * FROM order_item WHERE order_id = {i}"),
&format!("2025-07-10T14:32:01.{:03}Z", i * 50),
)
})
.collect();
let trace = make_trace(events);
let template = "SELECT * FROM order_item WHERE order_id = ?".to_string();
let findings = vec![
Finding {
finding_type: FindingType::NPlusOneSql,
severity: Severity::Warning,
trace_id: "trace-1".to_string(),
service: "order-svc".to_string(),
source_endpoint: "POST /api/orders/42/submit".to_string(),
pattern: Pattern {
template: template.clone(),
occurrences: 6,
window_ms: 250,
distinct_params: 6,
},
suggestion: "batch".to_string(),
first_timestamp: "2025-07-10T14:32:01.050Z".to_string(),
last_timestamp: "2025-07-10T14:32:01.300Z".to_string(),
green_impact: None,
confidence: Confidence::default(),
code_location: None,
},
Finding {
finding_type: FindingType::RedundantSql,
severity: Severity::Info,
trace_id: "trace-1".to_string(),
service: "order-svc".to_string(),
source_endpoint: "POST /api/orders/42/submit".to_string(),
pattern: Pattern {
template,
occurrences: 3,
window_ms: 100,
distinct_params: 1,
},
suggestion: "cache".to_string(),
first_timestamp: "2025-07-10T14:32:01.050Z".to_string(),
last_timestamp: "2025-07-10T14:32:01.300Z".to_string(),
green_impact: None,
confidence: Confidence::default(),
code_location: None,
},
];
let (_, summary) = score_green(&[trace], findings, None);
assert_eq!(summary.avoidable_io_ops, 5);
}
#[test]
fn clean_traces_zero_waste() {
let events = vec![
make_sql_event(
"trace-1",
"span-1",
"SELECT * FROM users WHERE id = 1",
"2025-07-10T14:32:01.000Z",
),
make_sql_event(
"trace-1",
"span-2",
"SELECT * FROM orders WHERE id = 2",
"2025-07-10T14:32:01.050Z",
),
make_http_event(
"trace-1",
"span-3",
"http://svc:5000/api/health",
"2025-07-10T14:32:01.100Z",
),
make_sql_event(
"trace-1",
"span-4",
"INSERT INTO logs (msg) VALUES ('ok')",
"2025-07-10T14:32:01.150Z",
),
];
let trace = make_trace(events);
let (findings, summary) = score_green(&[trace], vec![], None);
assert!(findings.is_empty());
assert_eq!(summary.total_io_ops, 4);
assert_eq!(summary.avoidable_io_ops, 0);
assert!((summary.io_waste_ratio - 0.0).abs() < f64::EPSILON);
assert_eq!(summary.top_offenders.len(), 1); }
fn ctx_with_region(region: &str) -> CarbonContext {
CarbonContext {
default_region: Some(region.to_string()),
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: false,
energy_snapshot: None,
per_operation_coefficients: false,
..CarbonContext::default()
}
}
#[test]
fn co2_computed_when_region_set() {
let events: Vec<SpanEvent> = (1..=6)
.map(|i| {
make_sql_event(
"trace-1",
&format!("span-{i}"),
&format!("SELECT * FROM order_item WHERE order_id = {i}"),
&format!("2025-07-10T14:32:01.{:03}Z", i * 50),
)
})
.collect();
let trace = make_trace(events);
let finding = Finding {
finding_type: FindingType::NPlusOneSql,
severity: Severity::Warning,
trace_id: "trace-1".to_string(),
service: "order-svc".to_string(),
source_endpoint: "POST /api/orders/42/submit".to_string(),
pattern: Pattern {
template: "SELECT * FROM order_item WHERE order_id = ?".to_string(),
occurrences: 6,
window_ms: 250,
distinct_params: 6,
},
suggestion: "batch".to_string(),
first_timestamp: "2025-07-10T14:32:01.050Z".to_string(),
last_timestamp: "2025-07-10T14:32:01.300Z".to_string(),
green_impact: None,
confidence: Confidence::default(),
code_location: None,
};
let ctx = ctx_with_region("eu-west-3");
let (_, summary) = score_green(&[trace], vec![finding], Some(&ctx));
let co2 = summary.co2.as_ref().expect("co2 should be present");
assert!(co2.total.mid > 0.0);
assert!(co2.avoidable.mid > 0.0);
assert_eq!(co2.total.model, "io_proxy_v1");
assert_eq!(co2.total.methodology, "sci_v1_numerator");
assert_eq!(co2.avoidable.methodology, "sci_v1_operational_ratio");
assert!((co2.total.low - co2.total.mid * 0.5).abs() < f64::EPSILON);
assert!((co2.total.high - co2.total.mid * 2.0).abs() < f64::EPSILON);
assert_eq!(summary.regions.len(), 1);
assert_eq!(summary.regions[0].region, "eu-west-3");
assert_eq!(summary.regions[0].io_ops, 6);
assert!(summary.regions[0].co2_gco2 > 0.0);
assert_eq!(summary.top_offenders.len(), 1);
assert!(summary.top_offenders[0].co2_grams.is_some());
assert!(summary.top_offenders[0].co2_grams.unwrap() > 0.0);
}
#[test]
fn co2_none_when_no_carbon_context() {
let events: Vec<SpanEvent> = (1..=3)
.map(|i| {
make_sql_event(
"trace-1",
&format!("span-{i}"),
&format!("SELECT * FROM order_item WHERE order_id = {i}"),
&format!("2025-07-10T14:32:01.{:03}Z", i * 50),
)
})
.collect();
let trace = make_trace(events);
let (_, summary) = score_green(&[trace], vec![], None);
assert!(summary.co2.is_none());
assert!(summary.regions.is_empty());
for offender in &summary.top_offenders {
assert!(offender.co2_grams.is_none());
}
}
#[test]
fn unknown_region_yields_zero_operational_but_keeps_embodied() {
let events = vec![make_sql_event(
"trace-1",
"span-1",
"SELECT 1",
"2025-07-10T14:32:01.000Z",
)];
let trace = make_trace(events);
let ctx = CarbonContext {
default_region: Some("mars-1".to_string()),
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.001,
use_hourly_profiles: true,
energy_snapshot: None,
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().expect("co2 should be present");
assert!(
(co2.operational_gco2 - 0.0).abs() < f64::EPSILON,
"unknown region contributes 0 to operational"
);
assert!(
(co2.embodied_gco2 - 0.001).abs() < f64::EPSILON,
"1 trace × 0.001 g/req embodied"
);
assert!(
(co2.total.mid - 0.001).abs() < f64::EPSILON,
"total = operational (0) + embodied (0.001)"
);
assert!(summary.regions.iter().any(|r| r.region == "mars-1"));
let mars = summary
.regions
.iter()
.find(|r| r.region == "mars-1")
.unwrap();
assert_eq!(mars.io_ops, 1);
assert!((mars.co2_gco2 - 0.0).abs() < f64::EPSILON);
for offender in &summary.top_offenders {
assert!(offender.co2_grams.is_none());
}
}
#[test]
fn slow_findings_do_not_inflate_waste_ratio() {
use crate::test_helpers::make_sql_event_with_duration;
let events: Vec<SpanEvent> = (1..=3)
.map(|i| {
make_sql_event_with_duration(
"trace-1",
&format!("span-{i}"),
&format!("SELECT * FROM t WHERE id = {i}"),
&format!("2025-07-10T14:32:01.{:03}Z", i * 50),
600_000,
)
})
.collect();
let trace = make_trace(events);
let slow_finding = Finding {
finding_type: FindingType::SlowSql,
severity: Severity::Warning,
trace_id: "trace-1".to_string(),
service: "order-svc".to_string(),
source_endpoint: "POST /api/orders/42/submit".to_string(),
pattern: Pattern {
template: "SELECT * FROM t WHERE id = ?".to_string(),
occurrences: 3,
window_ms: 100,
distinct_params: 3,
},
suggestion: "Consider adding an index".to_string(),
first_timestamp: "2025-07-10T14:32:01.050Z".to_string(),
last_timestamp: "2025-07-10T14:32:01.150Z".to_string(),
green_impact: None,
confidence: Confidence::default(),
code_location: None,
};
let (findings, summary) = score_green(&[trace], vec![slow_finding], None);
assert_eq!(summary.avoidable_io_ops, 0, "slow ops are not avoidable");
assert!((summary.io_waste_ratio - 0.0).abs() < f64::EPSILON);
let impact = findings[0].green_impact.as_ref().unwrap();
assert_eq!(impact.estimated_extra_io_ops, 0);
}
#[test]
fn slow_and_n_plus_one_waste_separate() {
use crate::test_helpers::make_sql_event_with_duration;
let mut events: Vec<SpanEvent> = (1..=6)
.map(|i| {
make_sql_event(
"trace-1",
&format!("span-{i}"),
&format!("SELECT * FROM order_item WHERE order_id = {i}"),
&format!("2025-07-10T14:32:01.{:03}Z", i * 50),
)
})
.collect();
for i in 7..=9 {
events.push(make_sql_event_with_duration(
"trace-1",
&format!("span-{i}"),
&format!("SELECT * FROM slow_table WHERE id = {}", i - 6),
&format!("2025-07-10T14:32:02.{:03}Z", (i - 6) * 50),
600_000,
));
}
let trace = make_trace(events);
let n1_finding = Finding {
finding_type: FindingType::NPlusOneSql,
severity: Severity::Warning,
trace_id: "trace-1".to_string(),
service: "order-svc".to_string(),
source_endpoint: "POST /api/orders/42/submit".to_string(),
pattern: Pattern {
template: "SELECT * FROM order_item WHERE order_id = ?".to_string(),
occurrences: 6,
window_ms: 250,
distinct_params: 6,
},
suggestion: "batch".to_string(),
first_timestamp: "2025-07-10T14:32:01.050Z".to_string(),
last_timestamp: "2025-07-10T14:32:01.300Z".to_string(),
green_impact: None,
confidence: Confidence::default(),
code_location: None,
};
let slow_finding = Finding {
finding_type: FindingType::SlowSql,
severity: Severity::Warning,
trace_id: "trace-1".to_string(),
service: "order-svc".to_string(),
source_endpoint: "POST /api/orders/42/submit".to_string(),
pattern: Pattern {
template: "SELECT * FROM slow_table WHERE id = ?".to_string(),
occurrences: 3,
window_ms: 100,
distinct_params: 3,
},
suggestion: "Consider adding an index".to_string(),
first_timestamp: "2025-07-10T14:32:02.050Z".to_string(),
last_timestamp: "2025-07-10T14:32:02.150Z".to_string(),
green_impact: None,
confidence: Confidence::default(),
code_location: None,
};
let (findings, summary) = score_green(&[trace], vec![n1_finding, slow_finding], None);
assert_eq!(summary.avoidable_io_ops, 5);
let n1 = findings
.iter()
.find(|f| f.finding_type == FindingType::NPlusOneSql)
.unwrap();
assert_eq!(n1.green_impact.as_ref().unwrap().estimated_extra_io_ops, 5);
let slow = findings
.iter()
.find(|f| f.finding_type == FindingType::SlowSql)
.unwrap();
assert_eq!(
slow.green_impact.as_ref().unwrap().estimated_extra_io_ops,
0
);
}
fn make_trace_with_region(trace_id: &str, region: &str, count: usize) -> Trace {
let mut events = Vec::with_capacity(count);
for i in 1..=count {
let mut event = make_sql_event(
trace_id,
&format!("span-{i}"),
&format!("SELECT * FROM t WHERE id = {i}"),
&format!("2025-07-10T14:32:01.{:03}Z", i * 50),
);
event.cloud_region = Some(region.to_string());
events.push(event);
}
make_trace(events)
}
#[test]
fn co2_includes_embodied_term() {
let trace = make_trace_with_region("t1", "eu-west-3", 6);
let ctx = CarbonContext {
default_region: None,
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.001, use_hourly_profiles: false,
energy_snapshot: None,
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
let expected_op = 6.0 * 0.000_000_1 * 56.0 * 1.135;
assert!((co2.operational_gco2 - expected_op).abs() < 1e-12);
assert!((co2.embodied_gco2 - 0.001).abs() < f64::EPSILON);
assert!((co2.total.mid - (expected_op + 0.001)).abs() < 1e-12);
}
#[test]
fn avoidable_excludes_embodied() {
let trace = make_trace_with_region("t1", "eu-west-3", 6);
let finding = Finding {
finding_type: FindingType::NPlusOneSql,
severity: Severity::Warning,
trace_id: "t1".to_string(),
service: "order-svc".to_string(),
source_endpoint: "POST /api/orders/42/submit".to_string(),
pattern: Pattern {
template: "SELECT * FROM t WHERE id = ?".to_string(),
occurrences: 6,
window_ms: 250,
distinct_params: 6,
},
suggestion: "batch".to_string(),
first_timestamp: "2025-07-10T14:32:01.050Z".to_string(),
last_timestamp: "2025-07-10T14:32:01.300Z".to_string(),
green_impact: None,
confidence: Confidence::default(),
code_location: None,
};
let ctx = CarbonContext {
default_region: None,
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.5, use_hourly_profiles: false,
energy_snapshot: None,
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![finding], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
let expected_avoidable = co2.operational_gco2 * (5.0 / 6.0);
assert!((co2.avoidable.mid - expected_avoidable).abs() < 1e-12);
assert!(co2.avoidable.mid < co2.total.mid);
assert!(co2.avoidable.mid < co2.operational_gco2 + 0.5);
}
#[test]
fn multi_region_bucketing_distinct_per_region() {
let trace_eu = make_trace_with_region("t1", "eu-west-3", 3);
let trace_us = make_trace_with_region("t2", "us-east-1", 2);
let ctx = ctx_with_region("eu-west-3");
let (_, summary) = score_green(&[trace_eu, trace_us], vec![], Some(&ctx));
assert_eq!(summary.regions.len(), 2);
assert_eq!(summary.regions[0].region, "us-east-1");
assert_eq!(summary.regions[0].io_ops, 2);
assert_eq!(summary.regions[1].region, "eu-west-3");
assert_eq!(summary.regions[1].io_ops, 3);
assert!(summary.regions[0].co2_gco2 > summary.regions[1].co2_gco2);
let co2 = summary.co2.as_ref().unwrap();
let sum: f64 = summary.regions.iter().map(|r| r.co2_gco2).sum();
assert!((sum - co2.operational_gco2).abs() < 1e-12);
}
#[test]
fn region_resolution_chain_priority() {
let mut span1 = make_sql_event("t1", "s1", "SELECT 1", "2025-07-10T14:32:01.001Z");
span1.cloud_region = Some("ap-south-1".to_string());
let mut span2 = make_sql_event("t1", "s2", "SELECT 2", "2025-07-10T14:32:01.002Z");
span2.service = "order-svc".to_string();
let mut span3 = make_sql_event("t1", "s3", "SELECT 3", "2025-07-10T14:32:01.003Z");
span3.service = "other-svc".to_string();
let trace = make_trace(vec![span1, span2, span3]);
let mut service_regions = HashMap::new();
service_regions.insert("order-svc".to_string(), "us-east-1".to_string());
let ctx = CarbonContext {
default_region: Some("eu-west-3".to_string()),
service_regions,
embodied_per_request_gco2: 0.0,
use_hourly_profiles: true,
energy_snapshot: None,
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let region_names: Vec<&str> = summary.regions.iter().map(|r| r.region.as_str()).collect();
assert!(region_names.contains(&"ap-south-1"));
assert!(region_names.contains(&"us-east-1"));
assert!(region_names.contains(&"eu-west-3"));
for region in &summary.regions {
assert_eq!(region.io_ops, 1, "{}", region.region);
}
}
#[test]
fn unknown_bucket_for_unresolvable_events() {
let trace = make_trace(vec![make_sql_event(
"t1",
"s1",
"SELECT 1",
"2025-07-10T14:32:01.001Z",
)]);
let ctx = CarbonContext::default(); let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let unknown = summary
.regions
.iter()
.find(|r| r.region == UNKNOWN_REGION)
.expect("unknown bucket should exist");
assert_eq!(unknown.io_ops, 1);
assert!((unknown.co2_gco2 - 0.0).abs() < f64::EPSILON);
let co2 = summary.co2.as_ref().unwrap();
assert!((co2.operational_gco2 - 0.0).abs() < f64::EPSILON);
}
#[test]
fn regions_sorted_by_co2_desc() {
let trace_us = make_trace_with_region("t1", "us-east-1", 1);
let trace_eu = make_trace_with_region("t2", "eu-west-3", 1);
let trace_ap = make_trace_with_region("t3", "ap-south-1", 1);
let ctx = ctx_with_region("eu-west-3");
let (_, summary) = score_green(&[trace_us, trace_eu, trace_ap], vec![], Some(&ctx));
let names: Vec<&str> = summary.regions.iter().map(|r| r.region.as_str()).collect();
assert_eq!(names, vec!["ap-south-1", "us-east-1", "eu-west-3"]);
assert!(summary.regions[0].co2_gco2 > summary.regions[1].co2_gco2);
assert!(summary.regions[1].co2_gco2 > summary.regions[2].co2_gco2);
}
#[test]
fn regions_output_deterministic_under_permutation() {
let ctx = ctx_with_region("eu-west-3");
let order_a = vec![
make_trace_with_region("t1", "us-east-1", 2),
make_trace_with_region("t2", "eu-west-3", 3),
make_trace_with_region("t3", "ap-south-1", 1),
];
let order_b = vec![
make_trace_with_region("t3", "ap-south-1", 1),
make_trace_with_region("t1", "us-east-1", 2),
make_trace_with_region("t2", "eu-west-3", 3),
];
let (_, sa) = score_green(&order_a, vec![], Some(&ctx));
let (_, sb) = score_green(&order_b, vec![], Some(&ctx));
assert_eq!(sa.regions, sb.regions);
assert_eq!(
sa.co2.as_ref().map(|c| c.operational_gco2),
sb.co2.as_ref().map(|c| c.operational_gco2)
);
}
#[test]
fn confidence_interval_factors_match_constants() {
let trace = make_trace_with_region("t1", "eu-west-3", 100);
let ctx = ctx_with_region("eu-west-3");
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert!((co2.total.low - co2.total.mid * 0.5).abs() < f64::EPSILON);
assert!((co2.total.high - co2.total.mid * 2.0).abs() < f64::EPSILON);
assert!((co2.avoidable.low - co2.avoidable.mid * 0.5).abs() < f64::EPSILON);
assert!((co2.avoidable.high - co2.avoidable.mid * 2.0).abs() < f64::EPSILON);
}
#[test]
fn co2_methodology_labels_set() {
let trace = make_trace_with_region("t1", "eu-west-3", 1);
let ctx = ctx_with_region("eu-west-3");
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, "io_proxy_v1");
assert_eq!(co2.total.methodology, "sci_v1_numerator");
assert_eq!(co2.avoidable.model, "io_proxy_v1");
assert_eq!(co2.avoidable.methodology, "sci_v1_operational_ratio");
}
#[test]
fn cloud_region_attribute_beats_service_mapping() {
let mut event = make_sql_event("t1", "s1", "SELECT 1", "2025-07-10T14:32:01.001Z");
event.service = "order-svc".to_string();
event.cloud_region = Some("ap-south-1".to_string());
let trace = make_trace(vec![event]);
let mut service_regions = HashMap::new();
service_regions.insert("order-svc".to_string(), "eu-west-3".to_string());
let ctx = CarbonContext {
default_region: Some("us-east-1".to_string()),
service_regions,
embodied_per_request_gco2: 0.0,
use_hourly_profiles: true,
energy_snapshot: None,
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
assert_eq!(summary.regions.len(), 1);
assert_eq!(summary.regions[0].region, "ap-south-1");
assert_eq!(summary.regions[0].io_ops, 1);
}
#[test]
fn top_offender_co2_some_in_single_region_mode() {
let trace = make_trace_with_region_no_cloud("t1", 6);
let ctx = CarbonContext {
default_region: Some("eu-west-3".to_string()),
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: true,
energy_snapshot: None,
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
assert!(!summary.top_offenders.is_empty());
assert!(
summary.top_offenders[0].co2_grams.is_some(),
"single-region mode should populate TopOffender.co2_grams"
);
}
#[test]
fn top_offender_co2_none_when_multi_region_via_service_regions() {
let trace = make_trace_with_region_no_cloud("t1", 6);
let mut service_regions = HashMap::new();
service_regions.insert("order-svc".to_string(), "us-east-1".to_string());
let ctx = CarbonContext {
default_region: Some("eu-west-3".to_string()),
service_regions,
embodied_per_request_gco2: 0.0,
use_hourly_profiles: true,
energy_snapshot: None,
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
assert!(!summary.top_offenders.is_empty());
for offender in &summary.top_offenders {
assert!(
offender.co2_grams.is_none(),
"multi-region via service_regions should null TopOffender.co2_grams, got {:?}",
offender.co2_grams
);
}
}
#[test]
fn top_offender_co2_none_when_multi_region_via_span_attribute() {
let trace = make_trace_with_region("t1", "ap-south-1", 6);
let ctx = CarbonContext {
default_region: Some("eu-west-3".to_string()),
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: true,
energy_snapshot: None,
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
assert!(!summary.top_offenders.is_empty());
for offender in &summary.top_offenders {
assert!(
offender.co2_grams.is_none(),
"multi-region via cloud.region attribute should null TopOffender.co2_grams"
);
}
}
#[test]
fn region_cardinality_cap_folds_overflow_into_unknown() {
let mut events = Vec::with_capacity(260);
for i in 0..260 {
let mut event = make_sql_event(
"t1",
&format!("span-{i}"),
"SELECT 1",
"2025-07-10T14:32:01.001Z",
);
event.cloud_region = Some(format!("test-region-{i:04}"));
events.push(event);
}
let trace = make_trace(events);
let ctx = CarbonContext::default();
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let non_unknown_rows: Vec<&RegionBreakdown> = summary
.regions
.iter()
.filter(|r| r.region != UNKNOWN_REGION)
.collect();
assert_eq!(
non_unknown_rows.len(),
256,
"cap should produce exactly 256 known rows, got {}",
non_unknown_rows.len()
);
for row in &non_unknown_rows {
assert_eq!(row.status, "out_of_table");
}
let unknown = summary
.regions
.iter()
.find(|r| r.region == UNKNOWN_REGION)
.expect("unknown bucket should exist when cap is exceeded");
assert_eq!(
unknown.io_ops, 4,
"exactly 260 - 256 = 4 ops should land in unknown"
);
assert_eq!(unknown.status, "unresolved");
let total_bucketed: usize = summary.regions.iter().map(|r| r.io_ops).sum();
assert_eq!(total_bucketed, 260);
}
#[test]
fn avoidable_ratio_excludes_unknown_bucket_from_denominator() {
use crate::test_helpers::make_sql_event as helper;
let mut events_eu = Vec::new();
for i in 1..=10 {
let mut e = helper(
"trace-eu",
&format!("s{i}"),
&format!("SELECT * FROM t WHERE id = {i}"),
&format!("2025-07-10T14:32:01.{:03}Z", i * 20),
);
e.cloud_region = Some("eu-west-3".to_string());
events_eu.push(e);
}
let trace_eu = make_trace(events_eu);
let mut events_orphan = Vec::new();
for i in 1..=5 {
events_orphan.push(helper(
"trace-orphan",
&format!("o{i}"),
"SELECT 1",
"2025-07-10T14:32:02.000Z",
));
}
let trace_orphan = make_trace(events_orphan);
let finding = Finding {
finding_type: FindingType::NPlusOneSql,
severity: Severity::Warning,
trace_id: "trace-eu".to_string(),
service: "order-svc".to_string(),
source_endpoint: "POST /api/orders/42/submit".to_string(),
pattern: Pattern {
template: "SELECT * FROM t WHERE id = ?".to_string(),
occurrences: 4, window_ms: 250,
distinct_params: 4,
},
suggestion: "batch".to_string(),
first_timestamp: "2025-07-10T14:32:01.000Z".to_string(),
last_timestamp: "2025-07-10T14:32:01.300Z".to_string(),
green_impact: None,
confidence: Confidence::default(),
code_location: None,
};
let ctx = CarbonContext {
default_region: None, service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: true,
energy_snapshot: None,
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace_eu, trace_orphan], vec![finding], Some(&ctx));
assert_eq!(summary.total_io_ops, 15);
assert_eq!(summary.avoidable_io_ops, 3);
let co2 = summary.co2.as_ref().unwrap();
let expected = co2.operational_gco2 * (3.0 / 10.0);
assert!(
(co2.avoidable.mid - expected).abs() < 1e-12,
"avoidable.mid = {} vs expected {} (denominator 10)",
co2.avoidable.mid,
expected
);
}
fn make_trace_with_region_no_cloud(trace_id: &str, count: usize) -> Trace {
let mut events = Vec::with_capacity(count);
for i in 1..=count {
events.push(make_sql_event(
trace_id,
&format!("span-{i}"),
&format!("SELECT * FROM t WHERE id = {i}"),
&format!("2025-07-10T14:32:01.{:03}Z", i * 50),
));
}
make_trace(events)
}
#[test]
fn empty_traces_with_carbon_context_returns_no_co2() {
let ctx = ctx_with_region("eu-west-3");
let (_, summary) = score_green(&[], vec![], Some(&ctx));
assert!(
summary.co2.is_none(),
"empty traces must not emit an all-zeros co2 object"
);
assert!(summary.regions.is_empty());
}
#[test]
fn region_breakdown_distinguishes_out_of_table_from_unresolved() {
let mut span_mars = make_sql_event("t1", "s1", "SELECT 1", "2025-07-10T14:32:01.001Z");
span_mars.cloud_region = Some("mars-1".to_string());
let span_orphan = make_sql_event("t1", "s2", "SELECT 2", "2025-07-10T14:32:01.002Z");
let trace = make_trace(vec![span_mars, span_orphan]);
let ctx = CarbonContext::default();
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let mars = summary
.regions
.iter()
.find(|r| r.region == "mars-1")
.expect("mars-1 row should exist");
assert_eq!(mars.status, "out_of_table");
assert!((mars.co2_gco2 - 0.0).abs() < f64::EPSILON);
let unknown = summary
.regions
.iter()
.find(|r| r.region == "unknown")
.expect("unknown row should exist");
assert_eq!(unknown.status, "unresolved");
assert!((unknown.co2_gco2 - 0.0).abs() < f64::EPSILON);
}
#[test]
fn region_breakdown_status_known_for_in_table_region() {
let trace = make_trace_with_region("t1", "eu-west-3", 3);
let ctx = ctx_with_region("eu-west-3");
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
assert_eq!(summary.regions.len(), 1);
assert_eq!(summary.regions[0].status, "known");
assert!(summary.regions[0].co2_gco2 > 0.0);
}
fn make_trace_at_hour(trace_id: &str, region: &str, hour: u8, count: usize) -> Trace {
let mut events = Vec::with_capacity(count);
for i in 1..=count {
let mut event = make_sql_event(
trace_id,
&format!("span-{i}"),
&format!("SELECT * FROM t WHERE id = {i}"),
&format!("2025-07-10T{hour:02}:00:00.{i:03}Z"),
);
event.cloud_region = Some(region.to_string());
events.push(event);
}
make_trace(events)
}
fn ctx_hourly(use_hourly: bool) -> CarbonContext {
CarbonContext {
default_region: None,
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: use_hourly,
energy_snapshot: None,
per_operation_coefficients: false,
..CarbonContext::default()
}
}
#[test]
fn hourly_profile_different_co2_night_vs_evening_fr() {
let trace_night = make_trace_at_hour("t_night", "eu-west-3", 3, 6);
let trace_evening = make_trace_at_hour("t_evening", "eu-west-3", 19, 6);
let ctx = ctx_hourly(true);
let (_, night) = score_green(&[trace_night], vec![], Some(&ctx));
let (_, evening) = score_green(&[trace_evening], vec![], Some(&ctx));
let co2_night = night.co2.as_ref().unwrap().operational_gco2;
let co2_evening = evening.co2.as_ref().unwrap().operational_gco2;
assert!(
co2_night < co2_evening,
"night ({co2_night}) should be less than evening ({co2_evening}) in eu-west-3"
);
}
#[test]
fn hourly_profile_flips_model_to_v3_for_monthly_region() {
let trace = make_trace_at_hour("t1", "eu-west-3", 14, 6);
let ctx = ctx_hourly(true);
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, "io_proxy_v3");
assert_eq!(co2.avoidable.model, "io_proxy_v3");
assert_eq!(summary.regions.len(), 1);
assert_eq!(
summary.regions[0].intensity_source,
IntensitySource::MonthlyHourly
);
}
#[test]
fn hourly_profile_disabled_stays_on_v1() {
let trace = make_trace_at_hour("t1", "eu-west-3", 14, 6);
let ctx = ctx_hourly(false);
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, "io_proxy_v1");
assert_eq!(summary.regions[0].intensity_source, IntensitySource::Annual);
}
#[test]
fn hourly_profile_fallback_to_annual_for_region_without_profile() {
let trace = make_trace_at_hour("t1", "us-central1", 10, 6);
let ctx = ctx_hourly(true);
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, "io_proxy_v1");
assert_eq!(summary.regions[0].intensity_source, IntensitySource::Annual);
}
#[test]
fn de_flat_annual_numerical_regression() {
let trace = make_trace_at_hour("t_de", "eu-central-1", 12, 6);
let ctx = CarbonContext {
default_region: None,
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: false, energy_snapshot: None,
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, "io_proxy_v1");
let expected = 6.0 * 1e-7 * 338.0 * 1.135;
assert!(
(co2.operational_gco2 - expected).abs() < 1e-12,
"DE flat-annual math drifted: expected {expected}, got {}",
co2.operational_gco2
);
assert_eq!(summary.regions.len(), 1);
assert_eq!(summary.regions[0].region, "eu-central-1");
assert_eq!(summary.regions[0].intensity_source, IntensitySource::Annual);
assert!((summary.regions[0].grid_intensity_gco2_kwh - 338.0).abs() < f64::EPSILON);
}
#[test]
fn mixed_report_monthly_hourly_and_annual_tags_v3_per_row() {
let trace_eu = make_trace_at_hour("t_eu", "eu-west-3", 12, 3);
let trace_us = make_trace_at_hour("t_us", "us-central1", 12, 3);
let ctx = ctx_hourly(true);
let (_, summary) = score_green(&[trace_eu, trace_us], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(
co2.total.model, "io_proxy_v3",
"mixed report with any monthly hourly region tags model = v3"
);
let eu_row = summary
.regions
.iter()
.find(|r| r.region == "eu-west-3")
.expect("eu-west-3 row");
assert_eq!(eu_row.intensity_source, IntensitySource::MonthlyHourly);
let us_row = summary
.regions
.iter()
.find(|r| r.region == "us-central1")
.expect("us-central1 row");
assert_eq!(us_row.intensity_source, IntensitySource::Annual);
}
#[test]
fn mixed_report_flat_hourly_and_annual_tags_v2() {
let trace_ie = make_trace_at_hour("t_ie", "eu-west-1", 12, 3);
let trace_us = make_trace_at_hour("t_us", "us-central1", 12, 3);
let ctx = ctx_hourly(true);
let (_, summary) = score_green(&[trace_ie, trace_us], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, "io_proxy_v2");
let ie_row = summary
.regions
.iter()
.find(|r| r.region == "eu-west-1")
.expect("eu-west-1 row");
assert_eq!(ie_row.intensity_source, IntensitySource::Hourly);
}
#[test]
fn hourly_row_intensity_is_time_weighted_mean() {
let trace = make_trace_at_hour("t1", "eu-west-3", 3, 6);
let ctx = ctx_hourly(true);
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let row = &summary.regions[0];
let expected = carbon::resolve_hourly_intensity(
"eu-west-3",
3,
Some(6), None,
)
.unwrap()
.0;
assert!(
(row.grid_intensity_gco2_kwh - expected).abs() < f64::EPSILON,
"expected {expected} g/kWh at hour 3 UTC July, got {}",
row.grid_intensity_gco2_kwh
);
}
#[test]
fn custom_profile_overrides_embedded_in_scoring_loop() {
let trace = make_trace_at_hour("t1", "eu-west-3", 12, 6);
let mut custom = HashMap::new();
custom.insert(
"eu-west-3".to_string(),
carbon::HourlyProfile::FlatYear([999.0; 24]),
);
let ctx = CarbonContext {
default_region: None,
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: true,
energy_snapshot: None,
per_operation_coefficients: false,
custom_hourly_profiles: Some(std::sync::Arc::new(custom)),
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let row = &summary.regions[0];
assert!(
(row.grid_intensity_gco2_kwh - 999.0).abs() < f64::EPSILON,
"expected custom intensity 999.0, got {}",
row.grid_intensity_gco2_kwh
);
assert_eq!(row.intensity_source, IntensitySource::Hourly);
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, "io_proxy_v2");
}
#[test]
fn custom_profile_on_out_of_table_region_uses_generic_pue() {
let trace = make_trace_at_hour("t1", "my-datacenter", 12, 6);
let mut custom = HashMap::new();
custom.insert(
"my-datacenter".to_string(),
carbon::HourlyProfile::FlatYear([500.0; 24]),
);
let ctx = CarbonContext {
default_region: None,
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: true,
energy_snapshot: None,
per_operation_coefficients: false,
custom_hourly_profiles: Some(std::sync::Arc::new(custom)),
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
let expected = 6.0 * 1e-7 * 500.0 * 1.2;
assert!(
(co2.operational_gco2 - expected).abs() < 1e-12,
"expected {expected}, got {}",
co2.operational_gco2
);
assert!(
co2.operational_gco2 > 0.0,
"custom profile on out-of-table region must produce non-zero CO2"
);
assert_eq!(summary.regions.len(), 1);
let row = &summary.regions[0];
assert_eq!(row.region, "my-datacenter");
assert!(
(row.co2_gco2 - expected).abs() < 1e-12,
"breakdown row co2 must match accumulated value"
);
assert!(
(row.pue - 1.2).abs() < f64::EPSILON,
"out-of-table region with custom profile should use generic PUE 1.2"
);
assert!(
(row.grid_intensity_gco2_kwh - 500.0).abs() < f64::EPSILON,
"breakdown row should report the custom profile intensity"
);
assert_eq!(row.intensity_source, IntensitySource::Hourly);
let sum: f64 = summary.regions.iter().map(|r| r.co2_gco2).sum();
assert!(
(sum - co2.operational_gco2).abs() < 1e-12,
"breakdown sum ({sum}) must equal operational_gco2 ({})",
co2.operational_gco2
);
}
#[test]
fn scaphandre_snapshot_flips_model_and_replaces_coefficient() {
let trace = make_trace_at_hour("t1", "eu-west-3", 12, 6);
let mut snapshot = HashMap::new();
snapshot.insert(
"order-svc".to_string(),
carbon::EnergyEntry::scaphandre(5e-7),
);
let ctx = CarbonContext {
default_region: None,
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: false, energy_snapshot: Some(snapshot),
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, "scaphandre_rapl");
let expected = 6.0 * 5e-7 * 56.0 * 1.135;
assert!(
(co2.operational_gco2 - expected).abs() < 1e-12,
"expected {expected}, got {}",
co2.operational_gco2
);
}
#[test]
fn scaphandre_empty_snapshot_stays_on_proxy() {
let trace = make_trace_at_hour("t1", "eu-west-3", 12, 6);
let ctx = CarbonContext {
default_region: None,
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: false,
energy_snapshot: Some(HashMap::new()),
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, "io_proxy_v1");
}
#[test]
fn scaphandre_takes_precedence_over_hourly_in_model_tag() {
let trace = make_trace_at_hour("t1", "eu-west-3", 3, 6);
let mut snapshot = HashMap::new();
snapshot.insert(
"order-svc".to_string(),
carbon::EnergyEntry::scaphandre(3e-7),
);
let ctx = CarbonContext {
default_region: None,
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: true,
energy_snapshot: Some(snapshot),
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, "scaphandre_rapl");
assert_eq!(
summary.regions[0].intensity_source,
IntensitySource::MonthlyHourly
);
}
#[test]
fn cloud_snapshot_flips_model_to_cloud_specpower() {
let trace = make_trace_at_hour("t1", "eu-west-3", 12, 6);
let mut snapshot = HashMap::new();
snapshot.insert("order-svc".to_string(), carbon::EnergyEntry::cloud(5e-7));
let ctx = CarbonContext {
default_region: None,
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: false,
energy_snapshot: Some(snapshot),
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, "cloud_specpower");
let expected = 6.0 * 5e-7 * 56.0 * 1.135;
assert!(
(co2.operational_gco2 - expected).abs() < 1e-12,
"expected {expected}, got {}",
co2.operational_gco2
);
}
#[test]
fn cloud_takes_precedence_over_hourly_in_model_tag() {
let trace = make_trace_at_hour("t1", "eu-west-3", 3, 6);
let mut snapshot = HashMap::new();
snapshot.insert("order-svc".to_string(), carbon::EnergyEntry::cloud(3e-7));
let ctx = CarbonContext {
default_region: None,
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: true,
energy_snapshot: Some(snapshot),
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, "cloud_specpower");
}
#[test]
fn scaphandre_takes_precedence_over_cloud_in_model_tag() {
let trace = make_trace_at_hour("t1", "eu-west-3", 12, 6);
let mut snapshot = HashMap::new();
snapshot.insert(
"order-svc".to_string(),
carbon::EnergyEntry::scaphandre(5e-7),
);
snapshot.insert("other-svc".to_string(), carbon::EnergyEntry::cloud(3e-7));
let ctx = CarbonContext {
default_region: None,
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: false,
energy_snapshot: Some(snapshot),
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, "scaphandre_rapl");
}
#[test]
fn cloud_empty_snapshot_stays_on_proxy() {
let trace = make_trace_at_hour("t1", "eu-west-3", 12, 6);
let ctx = CarbonContext {
default_region: None,
service_regions: HashMap::new(),
embodied_per_request_gco2: 0.0,
use_hourly_profiles: false,
energy_snapshot: Some(HashMap::new()),
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, "io_proxy_v1");
}
#[test]
fn per_op_coefficients_select_lower_than_insert() {
let select_events: Vec<SpanEvent> = (1..=6)
.map(|i| {
make_sql_event(
"t1",
&format!("s{i}"),
&format!("SELECT * FROM users WHERE id = {i}"),
&format!("2025-07-10T14:32:01.{i:03}Z"),
)
})
.collect();
let insert_events: Vec<SpanEvent> = (1..=6)
.map(|i| {
make_sql_event(
"t2",
&format!("s{i}"),
&format!("INSERT INTO users (name) VALUES ('user{i}')"),
&format!("2025-07-10T14:32:01.{i:03}Z"),
)
})
.collect();
let trace_select = make_trace(select_events);
let trace_insert = make_trace(insert_events);
let ctx = CarbonContext {
default_region: Some("eu-west-3".to_string()),
use_hourly_profiles: false,
per_operation_coefficients: true,
..CarbonContext::default()
};
let (_, summary_select) = score_green(&[trace_select], vec![], Some(&ctx));
let (_, summary_insert) = score_green(&[trace_insert], vec![], Some(&ctx));
let co2_select = summary_select.co2.as_ref().unwrap().operational_gco2;
let co2_insert = summary_insert.co2.as_ref().unwrap().operational_gco2;
assert!(
co2_insert > co2_select,
"INSERT CO2 ({co2_insert}) should be > SELECT CO2 ({co2_select})"
);
let ratio = co2_insert / co2_select;
assert!(
(ratio - 3.0).abs() < 1e-6,
"INSERT/SELECT ratio should be 3.0, got {ratio}"
);
}
#[test]
fn per_op_coefficients_disabled_uses_flat() {
let select_events: Vec<SpanEvent> = (1..=6)
.map(|i| {
make_sql_event(
"t1",
&format!("s{i}"),
&format!("SELECT * FROM users WHERE id = {i}"),
&format!("2025-07-10T14:32:01.{i:03}Z"),
)
})
.collect();
let insert_events: Vec<SpanEvent> = (1..=6)
.map(|i| {
make_sql_event(
"t2",
&format!("s{i}"),
&format!("INSERT INTO users (name) VALUES ('user{i}')"),
&format!("2025-07-10T14:32:01.{i:03}Z"),
)
})
.collect();
let trace_select = make_trace(select_events);
let trace_insert = make_trace(insert_events);
let ctx = CarbonContext {
default_region: Some("eu-west-3".to_string()),
use_hourly_profiles: false,
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary_select) = score_green(&[trace_select], vec![], Some(&ctx));
let (_, summary_insert) = score_green(&[trace_insert], vec![], Some(&ctx));
let co2_select = summary_select.co2.as_ref().unwrap().operational_gco2;
let co2_insert = summary_insert.co2.as_ref().unwrap().operational_gco2;
assert!(
(co2_insert - co2_select).abs() < 1e-15,
"with per_op disabled, SELECT ({co2_select}) and INSERT ({co2_insert}) should match"
);
}
#[test]
fn per_op_coefficients_measured_energy_ignores_coefficient() {
let events: Vec<SpanEvent> = (1..=6)
.map(|i| {
make_sql_event(
"t1",
&format!("s{i}"),
&format!("SELECT * FROM users WHERE id = {i}"),
&format!("2025-07-10T14:32:01.{i:03}Z"),
)
})
.collect();
let trace = make_trace(events);
let measured_energy = 5e-7;
let mut snapshot = HashMap::new();
snapshot.insert(
"order-svc".to_string(),
carbon::EnergyEntry::scaphandre(measured_energy),
);
let ctx = CarbonContext {
default_region: Some("eu-west-3".to_string()),
use_hourly_profiles: false,
per_operation_coefficients: true,
energy_snapshot: Some(snapshot),
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
let expected = 6.0 * measured_energy * 56.0 * 1.135;
assert!(
(co2.operational_gco2 - expected).abs() < 1e-12,
"expected {expected}, got {}",
co2.operational_gco2
);
}
#[test]
fn transport_co2_cross_region_http() {
use crate::test_helpers::make_http_event_with_size;
let mut event = make_http_event_with_size(
"t1",
"s1",
"http://order-api:8080/api/orders",
"2025-07-10T14:32:01.000Z",
Some(100_000), );
event.cloud_region = Some("eu-west-3".to_string());
let trace = make_trace(vec![event]);
let mut service_regions = HashMap::new();
service_regions.insert("order-api".to_string(), "us-east-1".to_string());
let ctx = CarbonContext {
default_region: Some("eu-west-3".to_string()),
service_regions,
use_hourly_profiles: false,
per_operation_coefficients: false,
include_network_transport: true,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
assert!(
summary.transport_gco2.is_some(),
"transport_gco2 should be present for cross-region HTTP"
);
assert!(
summary.transport_gco2.unwrap() > 0.0,
"transport_gco2 should be positive"
);
}
#[test]
fn transport_co2_same_region_zero() {
use crate::test_helpers::make_http_event_with_size;
let mut event = make_http_event_with_size(
"t1",
"s1",
"http://order-api:8080/api/orders",
"2025-07-10T14:32:01.000Z",
Some(100_000),
);
event.cloud_region = Some("eu-west-3".to_string());
let trace = make_trace(vec![event]);
let mut service_regions = HashMap::new();
service_regions.insert("order-api".to_string(), "eu-west-3".to_string());
let ctx = CarbonContext {
default_region: Some("eu-west-3".to_string()),
service_regions,
use_hourly_profiles: false,
per_operation_coefficients: false,
include_network_transport: true,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
assert!(
summary.transport_gco2.is_none(),
"transport_gco2 should be None for same-region calls"
);
}
#[test]
fn transport_co2_disabled_by_default() {
use crate::test_helpers::make_http_event_with_size;
let mut event = make_http_event_with_size(
"t1",
"s1",
"http://order-api:8080/api/orders",
"2025-07-10T14:32:01.000Z",
Some(100_000),
);
event.cloud_region = Some("eu-west-3".to_string());
let trace = make_trace(vec![event]);
let mut service_regions = HashMap::new();
service_regions.insert("order-api".to_string(), "us-east-1".to_string());
let ctx = CarbonContext {
default_region: Some("eu-west-3".to_string()),
service_regions,
use_hourly_profiles: false,
per_operation_coefficients: false,
include_network_transport: false, ..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
assert!(
summary.transport_gco2.is_none(),
"transport_gco2 should be None when disabled"
);
}
#[test]
fn transport_co2_no_response_size() {
use crate::test_helpers::make_http_event_with_size;
let mut event = make_http_event_with_size(
"t1",
"s1",
"http://order-api:8080/api/orders",
"2025-07-10T14:32:01.000Z",
None, );
event.cloud_region = Some("eu-west-3".to_string());
let trace = make_trace(vec![event]);
let mut service_regions = HashMap::new();
service_regions.insert("order-api".to_string(), "us-east-1".to_string());
let ctx = CarbonContext {
default_region: Some("eu-west-3".to_string()),
service_regions,
use_hourly_profiles: false,
per_operation_coefficients: false,
include_network_transport: true,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
assert!(
summary.transport_gco2.is_none(),
"transport_gco2 should be None when response_size_bytes is absent"
);
}
#[test]
fn transport_co2_sql_excluded() {
let mut event = make_sql_event(
"t1",
"s1",
"SELECT * FROM users WHERE id = 1",
"2025-07-10T14:32:01.000Z",
);
event.cloud_region = Some("eu-west-3".to_string());
event.response_size_bytes = Some(100_000);
let trace = make_trace(vec![event]);
let mut service_regions = HashMap::new();
service_regions.insert("order-api".to_string(), "us-east-1".to_string());
let ctx = CarbonContext {
default_region: Some("eu-west-3".to_string()),
service_regions,
use_hourly_profiles: false,
per_operation_coefficients: false,
include_network_transport: true,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
assert!(
summary.transport_gco2.is_none(),
"transport_gco2 should be None for SQL spans"
);
}
#[test]
fn transport_co2_numerical_value() {
use crate::test_helpers::make_http_event_with_size;
let response_bytes: u64 = 100_000;
let mut event = make_http_event_with_size(
"t1",
"s1",
"http://order-api:8080/api/orders",
"2025-07-10T14:32:01.000Z",
Some(response_bytes),
);
event.cloud_region = Some("eu-west-3".to_string());
let trace = make_trace(vec![event]);
let mut service_regions = HashMap::new();
service_regions.insert("order-api".to_string(), "us-east-1".to_string());
let ctx = CarbonContext {
default_region: Some("eu-west-3".to_string()),
service_regions,
use_hourly_profiles: false,
per_operation_coefficients: false,
include_network_transport: true,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let transport = summary.transport_gco2.unwrap();
let expected =
response_bytes as f64 * carbon::DEFAULT_NETWORK_ENERGY_PER_BYTE_KWH * 56.0 * 1.135;
assert!(
(transport - expected).abs() < 1e-18,
"expected {expected}, got {transport}"
);
}
#[test]
fn transport_co2_uppercase_hostname_matches() {
use crate::test_helpers::make_http_event_with_size;
let mut event = make_http_event_with_size(
"t1",
"s1",
"http://Order-API:8080/api/orders",
"2025-07-10T14:32:01.000Z",
Some(50_000),
);
event.cloud_region = Some("eu-west-3".to_string());
let trace = make_trace(vec![event]);
let mut service_regions = HashMap::new();
service_regions.insert("order-api".to_string(), "us-east-1".to_string());
let ctx = CarbonContext {
default_region: Some("eu-west-3".to_string()),
service_regions,
use_hourly_profiles: false,
per_operation_coefficients: false,
include_network_transport: true,
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
assert!(
summary.transport_gco2.is_some(),
"uppercase hostname should match lowercase service_regions key"
);
}
#[test]
fn realtime_intensity_overrides_annual() {
let trace = make_trace_with_region("trace-1", "eu-west-3", 4);
let mut rt = HashMap::new();
rt.insert("eu-west-3".to_string(), 200.0);
let ctx = CarbonContext {
default_region: None,
use_hourly_profiles: false,
per_operation_coefficients: false,
real_time_intensity: Some(rt),
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, CO2_MODEL_EMAPS);
assert_eq!(
summary.regions[0].intensity_source,
IntensitySource::RealTime
);
assert!((summary.regions[0].grid_intensity_gco2_kwh - 200.0).abs() < 1e-6);
}
#[test]
fn realtime_intensity_overrides_hourly_profile() {
let trace = make_trace_at_hour("trace-1", "eu-west-3", 14, 4);
let mut rt = HashMap::new();
rt.insert("eu-west-3".to_string(), 300.0);
let ctx = CarbonContext {
default_region: None,
use_hourly_profiles: true,
per_operation_coefficients: false,
real_time_intensity: Some(rt),
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, CO2_MODEL_EMAPS);
assert_eq!(
summary.regions[0].intensity_source,
IntensitySource::RealTime
);
}
#[test]
fn realtime_with_scaphandre_uses_emaps_model() {
let trace = make_trace_with_region("trace-1", "eu-west-3", 4);
let mut energy_snap = HashMap::new();
energy_snap.insert(
"order-svc".to_string(),
carbon::EnergyEntry::scaphandre(5e-7),
);
let mut rt = HashMap::new();
rt.insert("eu-west-3".to_string(), 100.0);
let ctx = CarbonContext {
default_region: None,
use_hourly_profiles: false,
per_operation_coefficients: false,
energy_snapshot: Some(energy_snap),
real_time_intensity: Some(rt),
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, CO2_MODEL_EMAPS);
}
#[test]
fn realtime_for_out_of_table_region_uses_generic_pue() {
let trace = make_trace_with_region("trace-1", "moon-base-1", 4);
let mut rt = HashMap::new();
rt.insert("moon-base-1".to_string(), 150.0);
let ctx = CarbonContext {
default_region: None,
use_hourly_profiles: false,
per_operation_coefficients: false,
real_time_intensity: Some(rt),
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert!(
co2.total.mid > 0.0,
"out-of-table region with real-time intensity should produce non-zero CO2"
);
}
#[test]
fn calibration_factor_scales_proxy_energy() {
let trace = make_trace_with_region("trace-1", "eu-west-3", 4);
let ctx_no_cal = CarbonContext {
default_region: None,
use_hourly_profiles: false,
per_operation_coefficients: false,
..CarbonContext::default()
};
let (_, summary_no_cal) =
score_green(std::slice::from_ref(&trace), vec![], Some(&ctx_no_cal));
let co2_no_cal = summary_no_cal.co2.as_ref().unwrap().total.mid;
let cal_data = crate::calibrate::CalibrationData {
calibration: crate::calibrate::CalibrationSection {
base_energy_per_io_op_kwh: ENERGY_PER_IO_OP_KWH,
services: {
let mut m = HashMap::new();
m.insert(
"order-svc".to_string(),
crate::calibrate::ServiceCalibration {
factor: 2.0,
measured_energy_per_op_kwh: ENERGY_PER_IO_OP_KWH * 2.0,
},
);
m
},
},
};
let ctx_cal = CarbonContext {
default_region: None,
use_hourly_profiles: false,
per_operation_coefficients: false,
calibration: Some(cal_data),
..CarbonContext::default()
};
let (_, summary_cal) = score_green(&[trace], vec![], Some(&ctx_cal));
let co2_cal = summary_cal.co2.as_ref().unwrap().total.mid;
assert!(
(co2_cal / co2_no_cal - 2.0).abs() < 0.01,
"2x calibration factor should double CO2: {co2_cal} vs {co2_no_cal}"
);
}
#[test]
fn calibration_appends_cal_suffix_to_model_tag() {
let trace = make_trace_with_region("trace-1", "eu-west-3", 4);
let cal_data = crate::calibrate::CalibrationData {
calibration: crate::calibrate::CalibrationSection {
base_energy_per_io_op_kwh: ENERGY_PER_IO_OP_KWH,
services: {
let mut m = HashMap::new();
m.insert(
"order-svc".to_string(),
crate::calibrate::ServiceCalibration {
factor: 1.5,
measured_energy_per_op_kwh: ENERGY_PER_IO_OP_KWH * 1.5,
},
);
m
},
},
};
let ctx = CarbonContext {
default_region: None,
use_hourly_profiles: false,
per_operation_coefficients: false,
calibration: Some(cal_data),
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, carbon::CO2_MODEL_V1_CAL);
}
#[test]
fn calibration_not_applied_when_scaphandre_overrides() {
let trace = make_trace_with_region("trace-1", "eu-west-3", 4);
let mut energy_snap = HashMap::new();
energy_snap.insert(
"order-svc".to_string(),
carbon::EnergyEntry::scaphandre(5e-7),
);
let cal_data = crate::calibrate::CalibrationData {
calibration: crate::calibrate::CalibrationSection {
base_energy_per_io_op_kwh: ENERGY_PER_IO_OP_KWH,
services: {
let mut m = HashMap::new();
m.insert(
"order-svc".to_string(),
crate::calibrate::ServiceCalibration {
factor: 3.0,
measured_energy_per_op_kwh: ENERGY_PER_IO_OP_KWH * 3.0,
},
);
m
},
},
};
let ctx = CarbonContext {
default_region: None,
use_hourly_profiles: false,
per_operation_coefficients: false,
energy_snapshot: Some(energy_snap),
calibration: Some(cal_data),
..CarbonContext::default()
};
let (_, summary) = score_green(&[trace], vec![], Some(&ctx));
let co2 = summary.co2.as_ref().unwrap();
assert_eq!(co2.total.model, CO2_MODEL_SCAPHANDRE);
}
}