// SPDX-FileCopyrightText: 2026 Icinga GmbH // SPDX-License-Identifier: GPL-3.0-or-later #pragma once #include "perfdata/otlpmetricswriter-ti.hpp" #include "base/workqueue.hpp" #include "icinga/checkable.hpp" #include "otel/otel.hpp" #include namespace icinga { class OTLPMetricsWriter final : public ObjectImpl { public: DECLARE_OBJECT(OTLPMetricsWriter); DECLARE_OBJECTNAME(OTLPMetricsWriter); static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata); void Start(bool runtimeCreated) override; void OnConfigLoaded() override; void Resume() override; void Pause() override; protected: void ValidatePort(const Lazy& lvalue, const ValidationUtils& utils) override; void ValidateFlushInterval(const Lazy& lvalue, const ValidationUtils& utils) override; void ValidateFlushThreshold(const Lazy& lvalue, const ValidationUtils& utils) override; void ValidateHostResourceAttributes(const Lazy& lvalue, const ValidationUtils& utils) override; void ValidateServiceResourceAttributes(const Lazy& lvalue, const ValidationUtils& utils) override; private: void CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr); void Flush(bool fromTimer = false); void AddBytesAndFlushIfNeeded(std::size_t newBytes = 0); void ValidateResourceAttributes(const Dictionary::Ptr& tmpl, const String& attrName); template [[nodiscard]] std::size_t Record( const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, std::string_view metric, T value, double startTime, double endTime, OTel::AttrsMap attrs ); std::atomic_uint64_t m_RecordedBytes{0}; // Total bytes recorded in the current OTel message. std::atomic_uint64_t m_DataPointsCount{0}; // Total data points recorded in the current OTel message. // Checkables and their associated OTel ResourceMetrics that are being recorded for the current OTel message. std::unordered_map> m_Metrics; WorkQueue m_WorkQueue{10'000'000, 1}; boost::signals2::connection m_CheckResultsSlot, m_ActiveChangedSlot; OTel::Ptr m_Exporter; Timer::Ptr m_FlushTimer; std::atomic_bool m_TimerFlushInProgress{false}; // Whether a timer-initiated flush is in progress. }; } // namespace icinga