Wombat Core is the Java library powering Wombat Carbon Tracker.
It is distributed separately in order to:
- make it possible to build custom extensions
- make it possible to run the core engine outside of the quarkus app
The library requires Java 21+ and adding the following in your pom.xml:
<dependency>
<groupId>tech.illuin</groupId>
<artifactId>wombat-core</artifactId>
<version>0.11.0</version>
</dependency>Additionally, some optional (but highly recommended) extension libraries can be added, at the time of this writing this includes wombat-core-modules which, as the name suggests, contains a few implementations enabled by default in the Wombat application.
WombatCore is the central orchestration engine. It aggregates registered WombatModules, tracks available asset types, and provisions two core operational services:
AssetMonitormanages the data collection phase. It is designed to be triggered periodically in an asynchronous fashion and will coordinate metric polling via registeredWombatSourceand persist resulting activity metrics using aWombatMetricPersisterAssetEvaluatorcoordinates asset activity resolution and impact estimation. It resolves service activity workload for a givenTimeRangeviaWombatActivityResolvers and can output environmental impacts as well as financial costs using registeredWombatEvaluationResolverimplementations
Wombat relies on three fundamental component interfaces representing distinct stages of the collection and evaluation pipeline:
WombatSourceare triggered periodically by theAssetMonitor, they are expected to poll telemetry endpoints (e.g. Kubernetes API, Prometheus metrics, etc.) and returnsMetricDatato be persistedWombatActivityResolverare activity data aggregators. Given anAsset, aTimeRangeand an optionalAssetFilter, it computes a standardized representation ofActivityData(e.g. CPU nanocores, LLM token counts) from historical metrics or modeled profilesWombatEvaluationResolverare evaluation engines. Given anAssetand its resolvedActivityData, it computes either multi-criteria environmental footprints (AssetImpact) or financial costs (AssetCost).
An overview:
flowchart LR
CORE_SETUP[WombatCore\nSetup]
ASSET_DECLARATION[Asset\nConfiguration]
subgraph SAMPLING[Async Activity Data Sampling]
direction LR
subgraph SOURCE[Wombat Sources]
direction LR
SOURCE_ORCHESTRATOR[Source\nOrchestration]
SOURCE_A[WombatSource A]
SOURCE_B[WombatSource B]
SOURCE_C[WombatSource C]
SOURCE_ORCHESTRATOR-->SOURCE_A
SOURCE_ORCHESTRATOR-->SOURCE_B
SOURCE_ORCHESTRATOR-->SOURCE_C
end
STORAGE_ACTIVITY[(Metrics Store)]
SOURCE==>STORAGE_ACTIVITY
end
CALL{{Evaluation call}}
subgraph ESTIMATION[Activity Evaluation]
direction LR
subgraph ACTIVITY[Wombat Activity Resolvers]
direction LR
ACTIVITY_RESOLVER_A[WombatActivity\nResolver A]
ACTIVITY_RESOLVER_B[WombatActivity\nResolver B]
end
subgraph IMPACT_FINOPS[Wombat Cost Resolvers]
direction LR
FINOPS[Cost Resolving]
FINOPS --> COST_EVAL_RESOLVER_A[WombatEvaluation\nResolver C]
FINOPS --> COST_EVAL_RESOLVER_B[WombatEvaluation\nResolver D]
end
subgraph IMPACT_GREENOPS[Wombat Impact Resolvers]
direction LR
GREENOPS[Impact Resolving]
GREENOPS --> IMPACT_EVAL_RESOLVER_A[WombatEvaluation\nResolver A]
GREENOPS --> IMPACT_EVAL_RESOLVER_B[WombatEvaluation\nResolver B]
end
ACTIVITY ==>|GreenOps| IMPACT_GREENOPS
ACTIVITY ==>|FinOps| IMPACT_FINOPS
end
GREENOPS_RESULT{{Multi-criteria Estimate\nkgCO2eq / MJ / kgSbeq}}
FINOPS_RESULT{{Cost Estimate\n€ / $ / ¥}}
%% Cross-Process Data Flows
CORE_SETUP ==> ASSET_DECLARATION
ASSET_DECLARATION ==> SAMPLING
SAMPLING -.-> CALL
CALL ==> ACTIVITY
IMPACT_GREENOPS ==> GREENOPS_RESULT
IMPACT_FINOPS ==> FINOPS_RESULT
classDef configStyle fill:#cfd8dc88,stroke:#78909c,stroke-width:2px,color:#000
classDef samplingStyle fill:#e3f2fd88,stroke:#64b5f6,stroke-width:2px,color:#000
classDef triggerStyle fill:#ef5350ee,stroke:#c62828,stroke-width:2px,color:#fff
classDef activityStyle fill:#ffe0b288,stroke:#ff9800,stroke-width:2px,color:#000
classDef greenopsStyle fill:#e8f5e988,stroke:#81c784,stroke-width:2px,color:#000
classDef finopsStyle fill:#fff9c488,stroke:#fdd835,stroke-width:2px,color:#000
class CONFIG configStyle
class SOURCE samplingStyle
class CALL triggerStyle
class ACTIVITY activityStyle
class IMPACT_GREENOPS greenopsStyle
class IMPACT_FINOPS finopsStyle
class GREENOPS_RESULT greenopsStyle
class FINOPS_RESULT finopsStyle
Core modules provide ready-to-use implementations of asset types and their associated components:
| Module | Family | Class | Components | Description |
|---|---|---|---|---|
tech.illuin.wombat-module.kubernetes-api |
KUBERNETES_CONTAINER |
KubernetesAPIModule |
source |
Connects to Kubernetes cluster APIs to poll CPU and memory resource metrics. |
tech.illuin.wombat-module.llm-static |
LLM |
LLMStaticModule |
activity-resolver |
Models static LLM workloads based on annual request profiles. |
tech.illuin.wombat-module.llm-prometheus |
LLM |
LLMPrometheusModule |
source |
Queries Prometheus via PromQL for LLM inference telemetry. |
tech.illuin.wombat-module.kubernetes-simulated |
KUBERNETES_CONTAINER |
KubernetesSimulatedModule |
Special asset type used by the Wombat app for simulation requests. | |
tech.illuin.wombat-module.lmm-simulated |
LLM |
KubernetesSimulatedModule |
Special asset type used by the Wombat app for simulation requests. |
The following components from wombat-core operate outside of specific modules and serve as default or standalone resolvers:
Activity Resolvers (WombatActivityResolver):
KubernetesActivityResolveraggregates historical container and node metrics from persisted metric storesLLMActivityResolveraggregates historical LLM request activity and token consumption from persisted telemetry
Evaluation Resolvers (WombatEvaluationResolver):
BoaviztaEvaluationResolverestimates multi-criteria environmental impacts (GHG emissions, primary energy, abiotic depletion) for server and container workloads using the Boavizta APIEcologitsEvaluationResolverestimates multi-criteria environmental footprints for AI/LLM inferences using EcoLogits
Documentation is coming soon™
Following are a few code samples demonstrating basic usage of the wombat-core library.
Custom modules enable tracking domain-specific assets or integrating custom activity modeling. To create a custom module, define an Asset with its profile, implement WombatModule, and provide the relevant resolvers (such as a WombatActivityResolver).
Here is an example of a custom module providing modeled activity data for LLM traffic:
public class MySimulationModule implements WombatModule
{
public static final AssetType TYPE = AssetType.of(
"com.example", "wombat-module", "my-simulated-llm", ActivityRegime.MODELED, ServiceFamily.LLM
);
@Override
public AssetType type() { return TYPE; }
@Override
public Class<? extends Asset> assetClass() { return MySimulationAsset.class; }
@Override
public Optional<WombatActivityResolver> createActivityResolver()
{
return Optional.of(new MySimulationActivityResolver());
}
}
public record MySimulationAsset(
AssetIdentity identity,
MySimulationProfile profile
) implements Asset {
@Override
public AssetType type() { return MySimulationModule.TYPE; }
public record MySimulationProfile(
LLMProvider provider,
String model,
String location,
long baseTokens
) implements LLMProfile {}
}
public class MySimulationActivityResolver implements WombatActivityResolver
{
@Override
public boolean accept(Asset asset)
{
return asset instanceof MySimulationAsset;
}
@Override
public Optional<ActivityData> resolve(Asset asset, TimeRange range, AssetFilter filter)
{
MySimulationProfile profile = ((MySimulationAsset) asset).profile();
// Diurnal traffic variation (sinusoidal peak during daytime hours)
int hour = range.start().atZone(ZoneOffset.UTC).getHour();
double diurnalFactor = 0.5 + 0.5 * Math.sin(Math.PI * (hour - 8) / 12.0);
// Random jitter (±10%)
double jitter = 1.0 + (ThreadLocalRandom.current().nextGaussian() * 0.1);
long simulatedTokens = (long) (profile.baseTokens() * Math.max(0.1, diurnalFactor * jitter));
double simulatedRequests = simulatedTokens / 200.0;
String serviceId = asset.identity().id();
LLMServiceActivity service = new LLMServiceActivity(
profile.provider(),
profile.model(),
profile.location(),
simulatedTokens,
simulatedRequests
);
return Optional.of(new LLMActivityData(
ActivityRegime.MODELED,
Set.of(serviceId),
range,
Map.of(serviceId, service)
));
}
}Once defined, register the custom module with WombatCore and perform evaluations:
try (WombatCore core = new WombatCore(
contextProvider,
metricsPersister,
List.of(new MySimulationModule()),
defaults -> { /** default handlers registration **/ }
); AssetEvaluator evaluator = core.createEvaluator()) {
TimeRange range = new TimeRange(Instant.now().minus(Duration.ofHours(24)), Instant.now());
List<AssetEvaluation> results = evaluator.evaluate(range, AssetFilter.none());
}Wombat, the application, obviously ships with its own WombatCore configured from core-modules and eventually user-provided extensions.
But it is also possible to create your own WombatCore for use outside the application:
Documentation is coming soon™
Building the project requires a Java 21+ JDK, in order to compile it:
mvn clean compileRun all tests:
mvn clean testPackage it (as a .jar in target/):
mvn clean packageTo package it without running tests, append -DskipTests:
mvn clean package -DskipTests