IMetrics.h#

Fully qualified name: omni/observability/IMetrics.h

File members: omni/observability/IMetrics.h

// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: LicenseRef-NvidiaProprietary
//
// NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
// property and proprietary rights in and to this material, related
// documentation and any modifications thereto. Any use, reproduction,
// disclosure or distribution of this material and related documentation
// without an express license agreement from NVIDIA CORPORATION or
// its affiliates is strictly prohibited.

#pragma once

#include <omni/otel/Observer.h>
#include <omni/observability/IObservability.h>
#include <carb/ObjectUtils.h>
#include <carb/Framework.h>
#include <array>

namespace omni
{
namespace observability
{

using Attribute = omni::otel::Attribute;

template <class ValueType>
using InstrumentObserver = omni::otel::InstrumentObserver<ValueType>;

template <class ValueType>
using ObservableInstrumentCallback = omni::otel::ObservableInstrumentCallback<ValueType>;

class IMeter;

template <class ValueType>
class ICounter;
template <class ValueType>
class IHistogram;
template <class ValueType>
class IUpDownCounter;
class IObservableInstrument;

class IMeter : public carb::IObject
{
public:
    virtual ~IMeter() = default;

    // The functions below are provided for ABI stability and return raw pointers. These are lower-level functions;
    // namespace-scope create functions that return \ref carb::ObjectPtr should be preferred for better object lifetime
    // safety.

    virtual ICounter<std::uint64_t>* createCounter_uint64_t(carb::cpp::string_view name,
                                                            carb::cpp::string_view description,
                                                            carb::cpp::string_view unit) noexcept = 0;

    virtual ICounter<double>* createCounter_double(carb::cpp::string_view name,
                                                   carb::cpp::string_view description,
                                                   carb::cpp::string_view unit) noexcept = 0;

    virtual IUpDownCounter<std::int64_t>* createUpDownCounter_int64_t(carb::cpp::string_view name,
                                                                      carb::cpp::string_view description,
                                                                      carb::cpp::string_view unit) noexcept = 0;

    virtual IUpDownCounter<double>* createUpDownCounter_double(carb::cpp::string_view name,
                                                               carb::cpp::string_view description,
                                                               carb::cpp::string_view unit) noexcept = 0;

    virtual IHistogram<std::uint64_t>* createHistogram_uint64_t(carb::cpp::string_view name,
                                                                carb::cpp::string_view description,
                                                                carb::cpp::string_view unit) noexcept = 0;

    virtual IHistogram<double>* createHistogram_double(carb::cpp::string_view name,
                                                       carb::cpp::string_view description,
                                                       carb::cpp::string_view unit) noexcept = 0;

    virtual IObservableInstrument* createObservableCounter_int64_t(ObservableInstrumentCallback<std::int64_t> callback,
                                                                   void* context,
                                                                   carb::cpp::string_view name,
                                                                   carb::cpp::string_view description,
                                                                   carb::cpp::string_view unit) noexcept = 0;

    virtual IObservableInstrument* createObservableCounter_double(ObservableInstrumentCallback<double> callback,
                                                                  void* context,
                                                                  carb::cpp::string_view name,
                                                                  carb::cpp::string_view description,
                                                                  carb::cpp::string_view unit) noexcept = 0;

    virtual IObservableInstrument* createObservableUpDownCounter_int64_t(ObservableInstrumentCallback<std::int64_t> callback,
                                                                         void* context,
                                                                         carb::cpp::string_view name,
                                                                         carb::cpp::string_view description,
                                                                         carb::cpp::string_view unit) noexcept = 0;

    virtual IObservableInstrument* createObservableUpDownCounter_double(ObservableInstrumentCallback<double> callback,
                                                                        void* context,
                                                                        carb::cpp::string_view name,
                                                                        carb::cpp::string_view description,
                                                                        carb::cpp::string_view unit) noexcept = 0;

    template <class ValueType>
    ICounter<ValueType>* createCounter(carb::cpp::string_view name,
                                       carb::cpp::string_view description,
                                       carb::cpp::string_view unit = "") noexcept;

    template <class ValueType>
    IUpDownCounter<ValueType>* createUpDownCounter(carb::cpp::string_view name,
                                                   carb::cpp::string_view description,
                                                   carb::cpp::string_view unit = "") noexcept;

    template <class ValueType>
    IHistogram<ValueType>* createHistogram(carb::cpp::string_view name,
                                           carb::cpp::string_view description,
                                           carb::cpp::string_view unit = "") noexcept;

    template <class ValueType>
    IObservableInstrument* createObservableCounter(ObservableInstrumentCallback<ValueType> callback,
                                                   void* context,
                                                   carb::cpp::string_view name,
                                                   carb::cpp::string_view description,
                                                   carb::cpp::string_view unit = "") noexcept;

    template <class ValueType>
    IObservableInstrument* createObservableUpDownCounter(ObservableInstrumentCallback<ValueType> callback,
                                                         void* context,
                                                         carb::cpp::string_view name,
                                                         carb::cpp::string_view description,
                                                         carb::cpp::string_view unit = "") noexcept;
};

#ifndef DOXYGEN_BUILD
template <>
inline ICounter<std::uint64_t>* IMeter::createCounter<std::uint64_t>(carb::cpp::string_view name,
                                                                     carb::cpp::string_view description,
                                                                     carb::cpp::string_view unit) noexcept
{
    return createCounter_uint64_t(name, description, unit);
}

template <>
inline ICounter<double>* IMeter::createCounter<double>(carb::cpp::string_view name,
                                                       carb::cpp::string_view description,
                                                       carb::cpp::string_view unit) noexcept
{
    return createCounter_double(name, description, unit);
}

template <>
inline IUpDownCounter<std::int64_t>* IMeter::createUpDownCounter<std::int64_t>(carb::cpp::string_view name,
                                                                               carb::cpp::string_view description,
                                                                               carb::cpp::string_view unit) noexcept
{
    return createUpDownCounter_int64_t(name, description, unit);
}

template <>
inline IUpDownCounter<double>* IMeter::createUpDownCounter<double>(carb::cpp::string_view name,
                                                                   carb::cpp::string_view description,
                                                                   carb::cpp::string_view unit) noexcept
{
    return createUpDownCounter_double(name, description, unit);
}

template <>
inline IHistogram<std::uint64_t>* IMeter::createHistogram<std::uint64_t>(carb::cpp::string_view name,
                                                                         carb::cpp::string_view description,
                                                                         carb::cpp::string_view unit) noexcept
{
    return createHistogram_uint64_t(name, description, unit);
}

template <>
inline IHistogram<double>* IMeter::createHistogram<double>(carb::cpp::string_view name,
                                                           carb::cpp::string_view description,
                                                           carb::cpp::string_view unit) noexcept
{
    return createHistogram_double(name, description, unit);
}

template <>
inline IObservableInstrument* IMeter::createObservableCounter<std::int64_t>(ObservableInstrumentCallback<std::int64_t> callback,
                                                                            void* context,
                                                                            carb::cpp::string_view name,
                                                                            carb::cpp::string_view description,
                                                                            carb::cpp::string_view unit) noexcept
{
    return createObservableCounter_int64_t(callback, context, name, description, unit);
}

template <>
inline IObservableInstrument* IMeter::createObservableCounter<double>(ObservableInstrumentCallback<double> callback,
                                                                      void* context,
                                                                      carb::cpp::string_view name,
                                                                      carb::cpp::string_view description,
                                                                      carb::cpp::string_view unit) noexcept
{
    return createObservableCounter_double(callback, context, name, description, unit);
}

template <>
inline IObservableInstrument* IMeter::createObservableUpDownCounter<std::int64_t>(
    ObservableInstrumentCallback<std::int64_t> callback,
    void* context,
    carb::cpp::string_view name,
    carb::cpp::string_view description,
    carb::cpp::string_view unit) noexcept
{
    return createObservableUpDownCounter_int64_t(callback, context, name, description, unit);
}

template <>
inline IObservableInstrument* IMeter::createObservableUpDownCounter<double>(ObservableInstrumentCallback<double> callback,
                                                                            void* context,
                                                                            carb::cpp::string_view name,
                                                                            carb::cpp::string_view description,
                                                                            carb::cpp::string_view unit) noexcept
{
    return createObservableUpDownCounter_double(callback, context, name, description, unit);
}
#endif

template <class ValueType_>
class ICounter : public carb::IObject
{

public:
    using ValueType = ValueType_;
    virtual ~ICounter() = default;

    virtual void addArr(ValueType value, const Attribute attributes[], std::size_t attributeCount) noexcept = 0;

    template <class T, class... A>
    void add(T value, A&&... a) noexcept
    {
        const std::array<Attribute, sizeof...(A)> attrs = { Attribute(std::forward<A>(a))... };
        this->addArr(value, attrs.data(), sizeof...(A));
    }

    template <class T>
    void add(T value, std::initializer_list<Attribute> attributes) noexcept
    {
        this->addArr(value, attributes.begin(), attributes.size());
    }
};

template <class ValueType_>
class IUpDownCounter : public carb::IObject
{

public:
    using ValueType = ValueType_;
    virtual ~IUpDownCounter() = default;

    virtual void addArr(ValueType value, const Attribute attributes[], std::size_t attributeCount) noexcept = 0;

    template <class T, class... A>
    void add(T value, A&&... a) noexcept
    {
        const std::array<Attribute, sizeof...(A)> attrs = { Attribute(std::forward<A>(a))... };
        this->addArr(value, attrs.data(), sizeof...(A));
    }

    template <class T>
    void add(T value, std::initializer_list<Attribute> attributes) noexcept
    {
        this->addArr(value, attributes.begin(), attributes.size());
    }
};

template <class ValueType_>
class IHistogram : public carb::IObject
{

public:
    using ValueType = ValueType_;
    virtual ~IHistogram() = default;

    virtual void recordArr(ValueType value, const Attribute attributes[], std::size_t attributeCount) noexcept = 0;

    template <class T, class... A>
    void record(T value, A&&... a) noexcept
    {
        const std::array<Attribute, sizeof...(A)> attrs = { Attribute(std::forward<A>(a))... };
        this->recordArr(value, attrs.data(), sizeof...(A));
    }

    template <class T>
    void record(T value, std::initializer_list<Attribute> attributes) noexcept
    {
        this->recordArr(value, attributes.begin(), attributes.size());
    }
};

class IObservableInstrument : public carb::IObject
{

public:
    virtual ~IObservableInstrument() = default;
};

// Factory functions for creating instruments

template <class ValueType>
carb::ObjectPtr<ICounter<ValueType>> createCounter(const carb::ObjectPtr<IMeter>& meter,
                                                   carb::cpp::string_view name,
                                                   carb::cpp::string_view description,
                                                   carb::cpp::string_view unit = "")
{
    if (!meter)
        return {};
    return carb::stealObject(meter->createCounter<ValueType>(name, description, unit));
}

template <class ValueType>
carb::ObjectPtr<IUpDownCounter<ValueType>> createUpDownCounter(const carb::ObjectPtr<IMeter>& meter,
                                                               carb::cpp::string_view name,
                                                               carb::cpp::string_view description,
                                                               carb::cpp::string_view unit = "")
{
    if (!meter)
        return {};
    return carb::stealObject(meter->createUpDownCounter<ValueType>(name, description, unit));
}

template <class ValueType>
carb::ObjectPtr<IHistogram<ValueType>> createHistogram(const carb::ObjectPtr<IMeter>& meter,
                                                       carb::cpp::string_view name,
                                                       carb::cpp::string_view description,
                                                       carb::cpp::string_view unit = "")
{
    if (!meter)
        return {};
    return carb::stealObject(meter->createHistogram<ValueType>(name, description, unit));
}

template <class ValueType>
carb::ObjectPtr<IObservableInstrument> createObservableCounter(const carb::ObjectPtr<IMeter>& meter,
                                                               ObservableInstrumentCallback<ValueType> callback,
                                                               void* context,
                                                               carb::cpp::string_view name,
                                                               carb::cpp::string_view description,
                                                               carb::cpp::string_view unit = "")
{
    if (!meter)
        return {};
    return carb::stealObject(meter->createObservableCounter<ValueType>(callback, context, name, description, unit));
}

template <class ValueType>
carb::ObjectPtr<IObservableInstrument> createObservableUpDownCounter(const carb::ObjectPtr<IMeter>& meter,
                                                                     ObservableInstrumentCallback<ValueType> callback,
                                                                     void* context,
                                                                     carb::cpp::string_view name,
                                                                     carb::cpp::string_view description,
                                                                     carb::cpp::string_view unit = "")
{
    if (!meter)
        return {};
    return carb::stealObject(meter->createObservableUpDownCounter<ValueType>(callback, context, name, description, unit));
}

// Convenience functions for using instruments

template <class ValueType, class T, class... A>
void add(const carb::ObjectPtr<ICounter<ValueType>>& counter, T value, A&&... a) noexcept
{
    if (counter)
        counter->add(value, std::forward<A>(a)...);
}

template <class ValueType, class T>
void add(const carb::ObjectPtr<ICounter<ValueType>>& counter, T value, std::initializer_list<Attribute> attributes) noexcept
{
    if (counter)
        counter->add(value, attributes);
}

template <class ValueType, class T>
void addArr(const carb::ObjectPtr<ICounter<ValueType>>& counter,
            T value,
            const Attribute attributes[],
            std::size_t attributeCount) noexcept
{
    if (counter)
        counter->addArr(value, attributes, attributeCount);
}

template <class ValueType, class T, class... A>
void add(const carb::ObjectPtr<IUpDownCounter<ValueType>>& upDownCounter, T value, A&&... a) noexcept
{
    if (upDownCounter)
        upDownCounter->add(value, std::forward<A>(a)...);
}

template <class ValueType, class T>
void add(const carb::ObjectPtr<IUpDownCounter<ValueType>>& upDownCounter,
         T value,
         std::initializer_list<Attribute> attributes) noexcept
{
    if (upDownCounter)
        upDownCounter->add(value, attributes);
}

template <class ValueType, class T>
void addArr(const carb::ObjectPtr<IUpDownCounter<ValueType>>& upDownCounter,
            T value,
            const Attribute attributes[],
            std::size_t attributeCount) noexcept
{
    if (upDownCounter)
        upDownCounter->addArr(value, attributes, attributeCount);
}

template <class ValueType, class T, class... A>
void record(const carb::ObjectPtr<IHistogram<ValueType>>& histogram, T value, A&&... a) noexcept
{
    if (histogram)
        histogram->record(value, std::forward<A>(a)...);
}

template <class ValueType, class T>
void record(const carb::ObjectPtr<IHistogram<ValueType>>& histogram,
            T value,
            std::initializer_list<Attribute> attributes) noexcept
{
    if (histogram)
        histogram->record(value, attributes);
}

template <class ValueType, class T>
void recordArr(const carb::ObjectPtr<IHistogram<ValueType>>& histogram,
               T value,
               const Attribute attributes[],
               std::size_t attributeCount) noexcept
{
    if (histogram)
        histogram->recordArr(value, attributes, attributeCount);
}

} // namespace observability
} // namespace omni