1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
* Copyright (c) 2025-2026, Adel Noureddine.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the
* GNU Lesser General Public License v3.0 only (LGPL-3.0-only)
* which accompanies this distribution, and is available at
* https://www.gnu.org/licenses/lgpl-3.0.en.html
*
* Author : Adel Noureddine
*/
//! Joular Core is a Rust library for measuring power and energy across systems and devices.
//!
//! It measures CPU and GPU power consumption in real time, and can break that down to individual processes or applications. Joular Core runs on Linux, Windows, macOS, Raspberry Pi, and inside virtual machines.
//!
//! It allows applications, telemetry services, benchmarks, and custom developer tools to monitor CPU, GPU, and total system power, as well as attribute energy usage to specific process IDs (PIDs) or multi-process applications. It can export data to CSV files and to a shared-memory ring buffer.
//!
//! # Getting started example
//!
//! ```no_run
//! use joularcore::JoularCoreMonitor;
//!
//! let mut monitor = JoularCoreMonitor::for_app("firefox");
//!
//! std::thread::sleep(std::time::Duration::from_secs(1));
//!
//! let sample = monitor.poll();
//! println!("total {:.2} W, firefox {:.2} W", sample.total_power(), sample.target_power_or_zero());
//! ```
//!
//! ## Putting a session together
//!
//! There are three independent choices, and nothing hides them from you:
//!
//! * **What to measure** — [`MonitorConfig`], passed to
//! [`JoularCoreMonitor::from_config`].
//! * **Where to read it from** — the platform's own sensors by default. Replace
//! any of them through [`JoularCoreMonitor::builder`], which is how
//! `vm::VmSensor` (the `vm` feature) is used inside a virtual machine.
//! * **Where samples go** — push destinations onto an [`OutputBundle`].
//!
//! ## Unavailable sensors
//!
//! Power interfaces are privileged on most systems. When one cannot be read,
//! [`MonitorSample::cpu_power`] and [`MonitorSample::gpu_power`] are `None`
//! rather than `0.0`, so an unreadable sensor is never mistaken for an idle
//! machine. See the README for what each platform requires.
//!
//! ## Output
//!
//! Every destination is an [`output::OutputSink`], and [`OutputBundle`] fans
//! one sample out to all of them: CSV or bare-wattage files, and a
//! shared-memory [`ringbuffer`] for other processes to read. To send samples
//! anywhere else — over HTTP, into a database — implement `OutputSink`.
//!
//! ## Adding a sensor of your own
//!
//! The [`sensor`] module holds the traits every backend implements. Implement
//! [`sensor::PowerSensor`] for a single source of power — that is all
//! `vm::VmSensor` is — or [`sensor::Platform`] for a whole machine, and hand it
//! to [`monitor::MonitorBuilder`].
//!
//! ## Logging
//!
//! The library never writes to stdout or stderr on its own. It emits [`log`]
//! records — warnings such as "RAPL is not readable" arrive there. Install
//! whichever logger your program already uses (`env_logger`, `simplelog`, …);
//! with no logger installed the records are discarded and nothing is printed.
//!
//! # Feature flags
//!
//! * `vm` *(default)*: allow reading power from files written by a hypervisor or an
//! external meter, for use inside virtual machines.
//! * `sbc`: allow monitoring single-board computers using regression models, replacing the RAPL-based Linux one.
// Items behind a feature gate (`vm`) are named in prose
// as code spans, not intra-doc links: a link from ungated documentation to an
// item that a reduced-feature build does not compile is a rustdoc warning, and
// `cargo doc` is expected to be clean under every feature combination.
// The everyday surface, re-exported so ordinary use needs one import rather than
// one per module. Anything not here is still reachable through its module.
pub use ;
pub use ;
pub use ;
pub use ;
pub use PowerSensor;
// The README's Rust examples are the first thing a new user runs, so they are
// compiled as doctests rather than left to drift away from the API. They are
// written against the default feature set, which is what a reader following the
// README will have, so they are only compiled when those features are present.
;