Exposing metrics (optional)
Timefold Solver provides a mechanism to collect metrics about both the input submitted to the solver and the output it produces. These metrics are automatically exposed through the REST API alongside the optimization result, making it straightforward to build dashboards, monitoring screens, and insights views on top of them, without any additional endpoints or custom logic.
| This page describes features which are only relevant when running Timefold Solver as a Service (Preview). The information on these pages may describe functionality which may be changed or even removed in a future release. |
1. Input metrics
Input metrics provide more information about the data provided to the solver.
The metrics should be contained in a class or record which implements the ModelInputMetrics interface.
|
The input metrics will be exposed through the REST API, for which an OpenAPI spec will be generated. It is therefore necessary to add OpenAPI Specification annotations to the fields. |
public record TimetableInputMetrics(
@JsonFormat(shape = JsonFormat.Shape.NUMBER_INT) @Schema(name = "lessons", title = "Lessons",
format = DataFormat.Values.NUMBER, description = "The number of lessons submitted in the input dataset.",
type = SchemaType.NUMBER, example = "10", readOnly = true) int lessons,
@JsonFormat(shape = JsonFormat.Shape.NUMBER_INT) @Schema(name = "timeslots", title = "Timeslots",
format = DataFormat.Values.NUMBER, description = "The number of timeslots submitted in the input dataset.",
type = SchemaType.NUMBER, example = "30", readOnly = true) int timeslots
) implements ModelInputMetrics {}
Next, the SolverModel should implement the InputMetricsAware interface and construct the defined ModelInputMetrics object.
@PlanningSolution
public class Timetable implements SolverModel<HardSoftScore>, InputMetricsAware<TimetableInputMetrics> {
@ProblemFactCollectionProperty
@ValueRangeProvider
private List<Timeslot> timeslots;
@PlanningEntityCollectionProperty
private List<Lesson> lessons;
@PlanningScore
private HardSoftScore score;
@Override
public HardSoftScore getScore() {
return score;
}
@Override
public TimetableInputMetrics getInputMetrics() {
return new TimetableInputMetrics(lessons.size(), timeslots.size());
}
// other Getters/Setters/Constructors excluded
}
2. Output metrics
Output metrics provide more information about the result produced by the solver, such as solution quality indicators or key performance indicators (KPIs).
Output metrics are calculated after solving completes.
They should be derived from the solved SolverModel, not from the input.
|
Like input metrics, they are exposed through the REST API under the |
public record TimetableOutputMetrics(
@JsonFormat(shape = JsonFormat.Shape.NUMBER_INT) @Schema(name = "unassignedLessons", title = "Unassigned lessons",
format = DataFormat.Values.NUMBER, description = "The number of lessons that could not be assigned a timeslot or room.",
type = SchemaType.NUMBER, example = "0", readOnly = true) int unassignedLessons,
@JsonFormat(shape = JsonFormat.Shape.NUMBER_INT) @Schema(name = "maxConsecutiveLessons", title = "Max consecutive lessons",
format = DataFormat.Values.NUMBER, description = "The maximum number of consecutive lessons assigned to any single teacher.",
type = SchemaType.NUMBER, example = "3", readOnly = true) int maxConsecutiveLessons
) implements ModelOutputMetrics {}
Next, the SolverModel should implement the OutputMetricsAware interface and construct the defined ModelOutputMetrics object from the solved state.
@PlanningSolution
public class Timetable implements SolverModel<HardSoftScore>, OutputMetricsAware<TimetableOutputMetrics> {
@ProblemFactCollectionProperty
@ValueRangeProvider
private List<Timeslot> timeslots;
@PlanningEntityCollectionProperty
private List<Lesson> lessons;
@PlanningScore
private HardSoftScore score;
@Override
public HardSoftScore getScore() {
return score;
}
@Override
public TimetableOutputMetrics getOutputMetrics() {
int unassigned = (int) lessons.stream()
.filter(l -> l.getTimeslot() == null || l.getRoom() == null)
.count();
int maxConsecutive = computeMaxConsecutiveLessons(lessons);
return new TimetableOutputMetrics(unassigned, maxConsecutive);
}
// other Getters/Setters/Constructors excluded
}
3. Combining input and output metrics
A SolverModel can implement both InputMetricsAware and OutputMetricsAware at the same time.
@PlanningSolution
public class Timetable implements SolverModel<HardSoftScore>,
InputMetricsAware<TimetableInputMetrics>,
OutputMetricsAware<TimetableOutputMetrics> {
// fields, getInputMetrics(), getOutputMetrics() excluded
}