Skip to content

Commit

Permalink
feat: initial display of recorded measures
Browse files Browse the repository at this point in the history
  • Loading branch information
metacosm committed Jan 20, 2025
1 parent db319aa commit 84e8bb8
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 37 deletions.
43 changes: 30 additions & 13 deletions deployment/src/main/resources/dev-ui/qwc-power-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export class QwcPowerInfo extends QwcHotReloadElement {
_remoteMetadata: {state: true},
_localMetadata: {state: true},
_status: {state: true},
_running: {state: true}
_running: {state: true},
_measure: {state: true},
};

constructor() {
Expand Down Expand Up @@ -46,14 +47,30 @@ export class QwcPowerInfo extends QwcHotReloadElement {
${this.renderStartOrStop()}
${this.metadata(this._localMetadata, "Local synthetic components (if any)", "No ongoing measure")}
${this.metadata(this._remoteMetadata, "System power metadata", "Couldn't retrieve metadata")}
${this.displayMeasures()}
</vaadin-vertical-layout>
</vaadin-details>
`;
</vaadin-details>`;
} else {
return html`Info unavailable`;
}
}

displayMeasures() {
if (this._measure) {
return html`
<vaadin-details theme="filled">
<vaadin-details-summary slot="summary">
Measure ${this._measure.result} (${this._measure.samplesCount} samples)
</vaadin-details-summary>
<vaadin-vertical-layout theme="spacing-s">
<ul>
${this._measure.measures.map(measure => html`<li>${measure}</li>`)}
</ul>
</vaadin-vertical-layout>
</vaadin-details>`
}
}

renderStartOrStop() {
let iconType = this._running ? "stop" : "play";
let label = this._running ? "Stop" : "Start";
Expand All @@ -75,7 +92,7 @@ export class QwcPowerInfo extends QwcHotReloadElement {
}

_metadata(metadata, emptyMsg) {
if (Object.keys(metadata).length !== 0) {
if (metadata !== undefined && Object.keys(metadata).length !== 0) {
return html`<ul>${metadata.map(component => html`<li>${this.component(component)}</li>`)}</ul>`;
} else {
return html`${emptyMsg}`;
Expand All @@ -91,16 +108,16 @@ export class QwcPowerInfo extends QwcHotReloadElement {
}

_startOrStop() {
let action = this._running ? "stop" : "start";
this.jsonRpc.startOrStop({start: !this._running}).then(jsonRpcResponse => {
let outcome = jsonRpcResponse.result;
if (!outcome) {
notifier.showErrorMessage("Couldn't " + action + " power measure");
} else {
this.hotReload();
// keep the notification open indefinitely if we're stopped to be able to see the results
notifier.showInfoMessage(outcome, "bottom-start", action === "stop" ? 15 : 5);
let stop = this._running;
this.jsonRpc.startOrStop({start: !stop}).then(jsonRpcResponse => {
let msg = "Started";
if (stop) {
this._measure = jsonRpcResponse.result;
msg = "Stopped (" + this._measure.samplesCount + " samples taken)";
}

this.hotReload();
notifier.showInfoMessage(msg);
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -36,6 +37,13 @@ public PowerMeasurer(ServerSampler sampler) {
this.withErrorHandler(null);
}

@SuppressWarnings("unused")
public static double cpuShareOfJVMProcess() {
final var processCpuLoad = osBean.getProcessCpuLoad();
final var cpuLoad = osBean.getCpuLoad();
return (processCpuLoad < 0 || cpuLoad <= 0) ? 0 : processCpuLoad / cpuLoad;
}

public ServerSampler sampler() {
return sampler;
}
Expand All @@ -48,13 +56,6 @@ public <T> Metadata<T> measureMetadata(Function<SensorMetadata.ComponentMetadata
sampler.localMetadata(), sampler.status(), converter);
}

@SuppressWarnings("unused")
public static double cpuShareOfJVMProcess() {
final var processCpuLoad = osBean.getProcessCpuLoad();
final var cpuLoad = osBean.getCpuLoad();
return (processCpuLoad < 0 || cpuLoad <= 0) ? 0 : processCpuLoad / cpuLoad;
}

public PowerMeasurer withCompletedHandler(Consumer<ServerSampler.TotalStoppedPowerMeasure> completed) {
sampler.withCompletedHandler(completed);
return this;
Expand Down Expand Up @@ -82,9 +83,7 @@ public void start(long durationInSeconds, long frequencyInMilliseconds) {
}
}

public void stop() {
if (isRunning()) {
sampler.stop();
}
public Optional<ServerSampler.TotalStoppedPowerMeasure> stop() {
return isRunning() ? Optional.of(sampler.stop()) : Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,15 @@ public static class TotalStoppedPowerMeasure extends StoppedPowerMeasure {
private final double max;
private final double avg;
private final double stdDev;
private final OngoingPowerMeasure measure; // todo: remove

public TotalStoppedPowerMeasure(TotalStoppedPowerMeasure other) {
this(other.underlyingMeasure(), other.total, other.min, other.max, other.avg, other.stdDev);
}

public TotalStoppedPowerMeasure(OngoingPowerMeasure powerMeasure, double total, double min, double max, double avg, double stdDev) {
super(powerMeasure);
this.measure = powerMeasure;
this.total = total;
this.min = min;
this.max = max;
Expand Down Expand Up @@ -84,6 +90,10 @@ public String toString() {
return String.format("total: %s (min: %s / max: %s / avg: %s / σ: %s)", withUnit(total), withUnit(min), withUnit(max), withUnit(avg), withUnit(stdDev));
}

public OngoingPowerMeasure underlyingMeasure() {
return measure;
}

public static String withUnit(double mWValue) {
var unit = "mW";
double value = mWValue;
Expand Down Expand Up @@ -201,7 +211,7 @@ public OngoingPowerMeasure start(long durationInSeconds, long frequencyInMillise

public void stopOnError(Throwable e) {
// ignore HttpClosedException todo: figure out why this exception occurs in the first place!
if (!(e instanceof HttpClosedException)) {
if (!(e instanceof HttpClosedException) && errorHandler != null) {
errorHandler.accept(e);
}
status = "error: measure failed (" + e.getMessage() + ")";
Expand Down Expand Up @@ -243,7 +253,9 @@ public synchronized TotalStoppedPowerMeasure stop() {
final var stats = totalStats.statistics();
final var measured = new TotalStoppedPowerMeasure(measure, stats.getSum(), stats.getMin(), stats.getMax(), stats.getMean(), stats.getStandardDeviation());
measure = null;
completed.accept(measured);
if (completed != null) {
completed.accept(measured);
}
status = "stopped";
return measured;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,17 @@
import java.util.List;
import java.util.function.Function;

import jakarta.annotation.PostConstruct;
import jakarta.inject.Inject;

import net.laprun.sustainability.power.SensorMetadata;
import net.laprun.sustainability.power.analysis.DescriptiveStatisticsComponentProcessor;
import net.laprun.sustainability.power.quarkus.runtime.PowerMeasurer;
import net.laprun.sustainability.power.quarkus.runtime.ServerSampler;

public class PowerService {
public static final Function<SensorMetadata.ComponentMetadata, ComponentMetadata> converter = cm -> new ComponentMetadata(cm.name(), cm.index(), cm.description(), cm.unitAsSymbol());
@Inject
PowerMeasurer measurer;
private String status;

@PostConstruct
public void init() {
measurer.withCompletedHandler((stoppedMeasure) -> status = stoppedMeasure.toString());
}

public boolean isRunning() {
return measurer.isRunning();
Expand All @@ -38,13 +33,36 @@ public List<ComponentMetadata> localMetadata() {

public record ComponentMetadata(String name, int index, String description, String unit) {}

public String startOrStop(boolean start) {
public Result startOrStop(boolean start) {
if(start) {
measurer.start(0, 500);
return "Started";
return null;
} else {
measurer.stop();
return "Stopped: " + status;
return measurer.stop().map(Result::new).orElse(null);
}
}

public static class Result extends ServerSampler.TotalStoppedPowerMeasure {

public Result(ServerSampler.TotalStoppedPowerMeasure stoppedMeasure) {
super(stoppedMeasure);
}

public String getResult() {
return toString();
}

public int getSamplesCount() {
return numberOfSamples();
}

public double[] getMeasures() {
// todo: this should be made easier
return underlyingMeasure().processors().processorsFor(4).stream()
.findFirst()
.map(DescriptiveStatisticsComponentProcessor.class::cast)
.map(dscp -> dscp.statistics().getValues())
.orElse(null);
}
}
}

0 comments on commit 84e8bb8

Please sign in to comment.