26#include <unordered_map>
42 std::unordered_map<std::string, std::string>
labels;
47 std::unordered_map<std::string, std::string> l = {})
51 ,
timestamp(std::chrono::system_clock::now())
120 const std::unordered_map<std::string, std::string>& config);
126 [[nodiscard]] std::vector<service_metric>
collect();
132 [[nodiscard]] std::string
get_name()
const;
150 [[nodiscard]] std::unordered_map<std::string, double>
get_statistics()
const;
189 true,
true,
true,
true,
true,
190 true,
true,
true,
true,
true,
true
200 std::vector<service_metric>& metrics,
205 const std::string&
name,
207 const std::string& type,
208 const std::string& operation)
const;
216 : ae_title_(std::move(ae_title)) {}
219 const std::unordered_map<std::string, std::string>& config) {
221 if (
auto it = config.find(
"ae_title"); it != config.end()) {
225 init_time_ = std::chrono::steady_clock::now();
231 std::vector<service_metric> metrics;
240 static constexpr std::array<dimse_operation, 11> all_ops = {
254 for (std::size_t i = 0; i < all_ops.size(); ++i) {
259 pacs.get_counter(all_ops[i]));
273 std::vector<service_metric>& metrics,
277 const std::string op_name(
to_string(op));
281 "dicom_" + op_name +
"_requests_total",
282 static_cast<double>(
counter.total_count()),
288 "dicom_" + op_name +
"_success_total",
289 static_cast<double>(
counter.success_count.load(std::memory_order_relaxed)),
295 "dicom_" + op_name +
"_failure_total",
296 static_cast<double>(
counter.failure_count.load(std::memory_order_relaxed)),
301 if (
counter.total_count() > 0) {
304 "dicom_" + op_name +
"_duration_seconds_avg",
305 static_cast<double>(
counter.average_duration_us()) / 1'000'000.0,
310 const auto min_us =
counter.min_duration_us.load(std::memory_order_relaxed);
311 if (min_us != UINT64_MAX) {
313 "dicom_" + op_name +
"_duration_seconds_min",
314 static_cast<double>(min_us) / 1'000'000.0,
320 const auto max_us =
counter.max_duration_us.load(std::memory_order_relaxed);
323 "dicom_" + op_name +
"_duration_seconds_max",
324 static_cast<double>(max_us) / 1'000'000.0,
331 "dicom_" + op_name +
"_duration_seconds_sum",
332 static_cast<double>(
counter.total_duration_us.load(std::memory_order_relaxed)) / 1'000'000.0,
339 return "dicom_service_collector";
343 std::vector<std::string> types;
345 static constexpr std::array<dimse_operation, 11> all_ops = {
359 for (
const auto op : all_ops) {
360 const std::string op_name(
to_string(op));
361 types.push_back(
"dicom_" + op_name +
"_requests_total");
362 types.push_back(
"dicom_" + op_name +
"_success_total");
363 types.push_back(
"dicom_" + op_name +
"_failure_total");
364 types.push_back(
"dicom_" + op_name +
"_duration_seconds_avg");
365 types.push_back(
"dicom_" + op_name +
"_duration_seconds_min");
366 types.push_back(
"dicom_" + op_name +
"_duration_seconds_max");
367 types.push_back(
"dicom_" + op_name +
"_duration_seconds_sum");
377inline std::unordered_map<std::string, double>
381 std::unordered_map<std::string, double> stats;
385 const auto uptime = std::chrono::duration_cast<std::chrono::seconds>(
386 std::chrono::steady_clock::now() -
init_time_);
387 stats[
"uptime_seconds"] =
static_cast<double>(uptime.count());
412 const std::string&
name,
414 const std::string& type,
415 const std::string& operation)
const {
420 {{
"ae",
ae_title_}, {
"operation", operation}});
Collector for DICOM DIMSE service operation metrics.
dicom_service_collector(const dicom_service_collector &)=delete
service_metric create_metric(const std::string &name, double value, const std::string &type, const std::string &operation) const
void collect_operation_metrics(std::vector< service_metric > &metrics, dimse_operation op, const operation_counter &counter)
dicom_service_collector & operator=(const dicom_service_collector &)=delete
std::string get_ae_title() const
Get the current AE title.
std::chrono::steady_clock::time_point init_time_
std::array< bool, 11 > operation_enabled_
bool is_operation_enabled(dimse_operation op) const
Check if metrics are enabled for an operation.
dicom_service_collector(std::string ae_title="PACS_SCP")
Default constructor.
std::string get_name() const
Get the collector name.
bool initialize(const std::unordered_map< std::string, std::string > &config)
Initialize the collector with configuration.
~dicom_service_collector()=default
Destructor.
std::uint64_t collection_count_
dicom_service_collector(dicom_service_collector &&)=delete
std::vector< service_metric > collect()
Collect current DIMSE service metrics.
void set_ae_title(std::string ae_title)
Set the AE title for metric labels.
std::unordered_map< std::string, double > get_statistics() const
Get collector statistics.
void set_operation_enabled(dimse_operation op, bool enabled)
Enable or disable specific operation metrics.
dicom_service_collector & operator=(dicom_service_collector &&)=delete
bool is_healthy() const
Check if the collector is healthy.
std::vector< std::string > get_metric_types() const
Get supported metric types.
static pacs_metrics & global_metrics() noexcept
Get the global singleton instance.
dimse_operation
DICOM Message Service Element (DIMSE) operation types.
@ c_store
C-STORE (Storage Service)
@ c_find
C-FIND (Query Service)
@ c_get
C-GET (Retrieve Service)
@ n_create
N-CREATE (MPPS)
@ c_move
C-MOVE (Retrieve Service)
@ c_echo
C-ECHO (Verification Service)
@ counter
Monotonic increasing value.
constexpr std::string_view to_string(health_level level) noexcept
Convert health level to string representation.
Operation metrics collection for PACS DICOM services.
Atomic counter for tracking operation success/failure counts.
Standard metric structure for DIMSE service data.
service_metric(std::string n, double v, std::string t, std::unordered_map< std::string, std::string > l={})
std::chrono::system_clock::time_point timestamp
std::unordered_map< std::string, std::string > labels