Skip to content

Commit a12df3e

Browse files
committed
DPL: make DeviceMetricsHelper more robust
- Use constraints to make sure we do not pass unexpected value types. - Cleanup usage of exceptions since the constraints now enforce the correct types. - Use string_view rather than std::string for read only variables
1 parent 3e37f60 commit a12df3e

File tree

2 files changed

+90
-57
lines changed

2 files changed

+90
-57
lines changed

Framework/Core/include/Framework/DeviceMetricsHelper.h

Lines changed: 87 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,31 @@
1313
#define O2_FRAMEWORK_DEVICEMETRICSHELPERS_H_
1414

1515
#include "Framework/DeviceMetricsInfo.h"
16-
#include "Framework/RuntimeError.h"
17-
#include <array>
16+
#include <concepts>
1817
#include <cstddef>
18+
#include <cstdint>
1919
#include <cstring>
2020
#include <functional>
21-
#include <string>
2221
#include <string_view>
2322
#include <vector>
2423

2524
namespace o2::framework
2625
{
2726
struct DriverInfo;
2827

28+
// General definition of what can of values can be put in a metric.
29+
// Notice that int8_t is used for enums.
30+
template <typename T>
31+
concept DeviceMetricValue = std::same_as<int, T> || std::same_as<float, T> || std::same_as<uint64_t, T> || std::same_as<int8_t, T>;
32+
33+
// Numeric like metrics values.
34+
template <typename T>
35+
concept DeviceMetricNumericValue = std::same_as<int, T> || std::same_as<float, T> || std::same_as<uint64_t, T>;
36+
37+
// Enum like values
38+
template <typename T>
39+
concept DeviceMetricEnumValue = std::same_as<int8_t, T>;
40+
2941
struct DeviceMetricsHelper {
3042
/// Type of the callback which can be provided to be invoked every time a new
3143
/// metric is found by the system.
@@ -43,68 +55,91 @@ struct DeviceMetricsHelper {
4355
DeviceMetricsInfo& info,
4456
NewMetricCallback newMetricCallback = nullptr);
4557
/// @return the index in metrics for the information of given metric
46-
static size_t metricIdxByName(const std::string& name,
58+
static size_t metricIdxByName(std::string_view const name,
4759
const DeviceMetricsInfo& info);
4860

49-
/// Typesafe way to get the actual store
50-
template <typename T>
61+
template <std::same_as<int> T>
5162
static auto& getMetricsStore(DeviceMetricsInfo& metrics)
5263
{
53-
if constexpr (std::is_same_v<T, int>) {
54-
return metrics.intMetrics;
55-
} else if constexpr (std::is_same_v<T, float>) {
56-
return metrics.floatMetrics;
57-
} else if constexpr (std::is_same_v<T, uint64_t>) {
58-
return metrics.uint64Metrics;
59-
} else if constexpr (std::is_same_v<T, int8_t>) {
60-
return metrics.enumMetrics;
61-
} else {
62-
throw runtime_error("Unhandled metric type");
63-
};
64+
return metrics.intMetrics;
65+
}
66+
67+
template <std::same_as<float> T>
68+
static auto& getMetricsStore(DeviceMetricsInfo& metrics)
69+
{
70+
return metrics.floatMetrics;
71+
}
72+
73+
template <std::same_as<uint64_t> T>
74+
static auto& getMetricsStore(DeviceMetricsInfo& metrics)
75+
{
76+
return metrics.uint64Metrics;
77+
}
78+
79+
template <std::same_as<int8_t> T>
80+
static auto& getMetricsStore(DeviceMetricsInfo& metrics)
81+
{
82+
return metrics.enumMetrics;
6483
}
6584

66-
/// Typesafe way to get the actual store
67-
template <typename T>
85+
template <std::same_as<int> T>
6886
static auto& getTimestampsStore(DeviceMetricsInfo& metrics)
6987
{
70-
if constexpr (std::is_same_v<T, int>) {
71-
return metrics.intTimestamps;
72-
} else if constexpr (std::is_same_v<T, float>) {
73-
return metrics.floatTimestamps;
74-
} else if constexpr (std::is_same_v<T, uint64_t>) {
75-
return metrics.uint64Timestamps;
76-
} else if constexpr (std::is_same_v<T, int8_t>) {
77-
return metrics.enumTimestamps;
78-
} else {
79-
throw runtime_error("Unhandled metric type");
80-
};
88+
return metrics.intTimestamps;
8189
}
8290

83-
template <typename T>
84-
static auto getMetricType()
91+
template <std::same_as<float> T>
92+
static auto& getTimestampsStore(DeviceMetricsInfo& metrics)
8593
{
86-
if constexpr (std::is_same_v<T, int>) {
87-
return MetricType::Int;
88-
} else if constexpr (std::is_same_v<T, float>) {
89-
return MetricType::Float;
90-
} else if constexpr (std::is_same_v<T, uint64_t>) {
91-
return MetricType::Uint64;
92-
} else if constexpr (std::is_same_v<T, int8_t>) {
93-
return MetricType::Enum;
94-
} else {
95-
throw runtime_error("Unhandled metric type");
96-
};
94+
return metrics.floatTimestamps;
95+
}
96+
97+
template <std::same_as<uint64_t> T>
98+
static auto& getTimestampsStore(DeviceMetricsInfo& metrics)
99+
{
100+
return metrics.uint64Timestamps;
101+
}
102+
103+
template <std::same_as<int8_t> T>
104+
static auto& getTimestampsStore(DeviceMetricsInfo& metrics)
105+
{
106+
return metrics.enumTimestamps;
107+
}
108+
109+
template <std::same_as<int> T>
110+
static auto getMetricType() -> MetricType
111+
{
112+
return MetricType::Int;
97113
}
98114

99-
static auto updateNumericInfo(DeviceMetricsInfo& metrics, size_t metricIndex, float value, size_t timestamp) {
100-
metrics.minDomain[metricIndex] = std::min(metrics.minDomain[metricIndex], timestamp);
101-
metrics.maxDomain[metricIndex] = std::max(metrics.maxDomain[metricIndex], timestamp);
102-
metrics.max[metricIndex] = std::max(metrics.max[metricIndex], (float)value);
103-
metrics.min[metricIndex] = std::min(metrics.min[metricIndex], (float)value);
104-
metrics.changed.at(metricIndex) = true;
115+
template <std::same_as<float> T>
116+
static auto getMetricType() -> MetricType
117+
{
118+
return MetricType::Float;
119+
}
120+
121+
template <std::same_as<uint64_t> T>
122+
static auto getMetricType() -> MetricType
123+
{
124+
return MetricType::Uint64;
125+
}
126+
127+
template <std::same_as<int8_t> T>
128+
static auto getMetricType() -> MetricType
129+
{
130+
return MetricType::Enum;
131+
}
132+
133+
static auto updateNumericInfo(DeviceMetricsInfo& metrics, size_t metricIndex, float value, size_t timestamp)
134+
{
135+
metrics.minDomain[metricIndex] = std::min(metrics.minDomain[metricIndex], timestamp);
136+
metrics.maxDomain[metricIndex] = std::max(metrics.maxDomain[metricIndex], timestamp);
137+
metrics.max[metricIndex] = std::max(metrics.max[metricIndex], (float)value);
138+
metrics.min[metricIndex] = std::min(metrics.min[metricIndex], (float)value);
139+
metrics.changed.at(metricIndex) = true;
105140
}
106141

107-
template <typename T>
142+
template <DeviceMetricNumericValue T>
108143
static auto getNumericMetricCursor(size_t metricIndex)
109144
{
110145
return [metricIndex](DeviceMetricsInfo& metrics, T value, size_t timestamp) {
@@ -123,13 +158,12 @@ struct DeviceMetricsHelper {
123158
static size_t bookMetricInfo(DeviceMetricsInfo& metrics, char const* name, MetricType type);
124159

125160
/// @return helper to insert a given value in the metrics
126-
template <typename T>
161+
template <DeviceMetricNumericValue T>
127162
static size_t
128163
bookNumericMetric(DeviceMetricsInfo& metrics,
129164
char const* name,
130165
NewMetricCallback newMetricsCallback = nullptr)
131166
{
132-
static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint64_t> || std::is_same_v<T, float>, "Unsupported metric type");
133167
size_t metricIndex = bookMetricInfo(metrics, name, getMetricType<T>());
134168
auto& metricInfo = metrics.metrics[metricIndex];
135169
if (newMetricsCallback != nullptr) {
@@ -139,13 +173,12 @@ struct DeviceMetricsHelper {
139173
}
140174

141175
/// @return helper to insert a given value in the metrics
142-
template <typename T>
176+
template <DeviceMetricNumericValue T>
143177
static std::function<void(DeviceMetricsInfo&, T value, size_t timestamp)>
144178
createNumericMetric(DeviceMetricsInfo& metrics,
145179
char const* name,
146180
NewMetricCallback newMetricsCallback = nullptr)
147181
{
148-
static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint64_t> || std::is_same_v<T, float>, "Unsupported metric type");
149182
size_t metricIndex = bookNumericMetric<T>(metrics, name, newMetricsCallback);
150183
return getNumericMetricCursor<T>(metricIndex);
151184
}

Framework/Core/src/DeviceMetricsHelper.cxx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -538,14 +538,14 @@ bool DeviceMetricsHelper::processMetric(ParsedMetricMatch& match,
538538
return true;
539539
}
540540

541-
size_t DeviceMetricsHelper::metricIdxByName(const std::string& name, const DeviceMetricsInfo& info)
541+
size_t DeviceMetricsHelper::metricIdxByName(std::string_view const name, const DeviceMetricsInfo& info)
542542
{
543543
size_t i = 0;
544544
while (i < info.metricLabels.size()) {
545-
auto& metricName = info.metricLabels[i];
545+
std::string_view metricName(info.metricLabels[i].label, info.metricLabels[i].size);
546546
// We check the size first and then the last character because that's
547547
// likely to be different for multi-index metrics
548-
if (metricName.size == name.size() && metricName.label[metricName.size - 1] == name[metricName.size - 1] && memcmp(metricName.label, name.c_str(), metricName.size) == 0) {
548+
if (metricName.size() == name.size() && metricName[metricName.size() - 1] == name[name.size() - 1] && metricName == name) {
549549
return i;
550550
}
551551
++i;

0 commit comments

Comments
 (0)