The Gaudi Framework  master (82fdf313)
Loading...
Searching...
No Matches
MonitoringHub.h
Go to the documentation of this file.
1/*****************************************************************************\
2* (c) Copyright 2020-2025 CERN for the benefit of the LHCb Collaboration *
3* *
4* This software is distributed under the terms of the GNU General Public *
5* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". *
6* *
7* In applying this licence, CERN does not waive the privileges and immunities *
8* granted to it by virtue of its status as an Intergovernmental Organization *
9* or submit itself to any jurisdiction. *
10\*****************************************************************************/
11#pragma once
12#include <deque>
13#include <functional>
14#include <iostream>
15#include <nlohmann/json.hpp>
16#include <string>
17#include <typeindex>
18#include <typeinfo>
19
20namespace Gaudi::Monitoring {
21
22 namespace details {
23
24 // type trait checking whether a given type has a friend method reset
25 template <typename Arg, typename = void> // this 3rd parameter defaults to void
26 struct has_reset_method : std::false_type {};
27 template <typename Arg>
28 struct has_reset_method<Arg, std::void_t<decltype( reset( std::declval<Arg&>() ) )>> : std::true_type {};
29 template <typename Arg>
31
32 // type trait checking whether a given type has a friend method mergeAndReset
33 template <typename Arg, typename = void> // this 3rd parameter defaults to void
34 struct has_mergeAndReset_method : std::false_type {};
35 template <typename Arg>
37 Arg, std::void_t<decltype( mergeAndReset( std::declval<Arg&>(), std::declval<Arg&>() ) )>> : std::true_type {};
38 template <typename Arg>
40
41 } // namespace details
42
47 struct Hub {
62 class Entity {
63 public:
64 template <typename T>
65 Entity( std::string component, std::string name, std::string type, T& ent )
66 : component{ std::move( component ) }
67 , name{ std::move( name ) }
68 , type{ std::move( type ) }
69 , m_ptr{ &ent }
70 , m_typeIndex{ typeid( T ) }
71 , m_getJSON{ []( void const* ptr ) -> nlohmann::json { return *reinterpret_cast<const T*>( ptr ); } }
72 , m_reset{ []( void* ptr ) {
73 if constexpr ( details::has_reset_method_v<T> ) { reset( *reinterpret_cast<T*>( ptr ) ); }
74 } }
75 , m_mergeAndReset{ []( void* e, void* o ) {
77 mergeAndReset( *reinterpret_cast<T*>( e ), *reinterpret_cast<T*>( o ) );
78 }
79 } } {}
80
81 std::string component;
83 std::string name;
85 std::string type;
87 std::type_index typeIndex() const { return m_typeIndex; }
89 friend void to_json( nlohmann::json& j, Gaudi::Monitoring::Hub::Entity const& e ) {
90 j = std::invoke( e.m_getJSON, e.m_ptr );
91 }
92
93 friend void reset( Entity const& e ) { std::invoke( e.m_reset, e.m_ptr ); }
100 friend void mergeAndReset( Entity const& ent, Entity const& other ) {
101 if ( ent.typeIndex() != other.typeIndex() ) {
102 throw std::runtime_error( std::string( "Entity: mergeAndReset called on different types: " ) +
103 ent.typeIndex().name() + " and " + other.typeIndex().name() );
104 }
105 std::invoke( ent.m_mergeAndReset, ent.m_ptr, other.m_ptr );
106 }
107
108 bool operator==( Entity const& ent ) const { return id() == ent.id(); }
110 void* id() const { return m_ptr; }
111
112 private:
114 void* m_ptr{ nullptr };
115 // The next 4 members are needed for type erasure
116 // indeed, their implementation is internal type dependant
117 // (see Constructor above and the usage of T in the reinterpret_cast)
118 std::type_index m_typeIndex;
120 nlohmann::json ( *m_getJSON )( void const* );
122 void ( *m_reset )( void* );
124 void ( *m_mergeAndReset )( void*, void* );
125 };
126
128 struct Sink {
129 virtual void registerEntity( Entity ent ) = 0;
130 virtual void removeEntity( Entity const& ent ) = 0;
131 virtual ~Sink() = default;
132 };
133
134 Hub() { m_sinks.reserve( 5 ); }
135
136 template <typename T>
137 void registerEntity( std::string c, std::string n, std::string t, T& ent ) {
138 registerEntity( { std::move( c ), std::move( n ), std::move( t ), ent } );
139 }
140 void registerEntity( Entity ent ) {
141 std::for_each( begin( m_sinks ), end( m_sinks ), [ent]( auto sink ) { sink->registerEntity( ent ); } );
142 m_entities.emplace( ent.id(), std::move( ent ) );
143 }
144 template <typename T>
145 void removeEntity( T& ent ) {
146 auto it = m_entities.find( &ent );
147 if ( it != m_entities.end() ) {
148 std::for_each( begin( m_sinks ), end( m_sinks ), [&it]( auto sink ) { sink->removeEntity( it->second ); } );
149 m_entities.erase( it );
150 }
151 }
152
153 void addSink( Sink* sink ) {
154 std::for_each( begin( m_entities ), end( m_entities ),
155 [sink]( auto ent ) { sink->registerEntity( ent.second ); } );
156 m_sinks.push_back( sink );
157 }
158 void removeSink( Sink* sink ) {
159 auto it = std::find( begin( m_sinks ), end( m_sinks ), sink );
160 if ( it != m_sinks.end() ) m_sinks.erase( it );
161 }
162
163 private:
164 std::vector<Sink*> m_sinks;
165 std::map<void*, Entity> m_entities;
166 };
167} // namespace Gaudi::Monitoring
Wrapper class for arbitrary monitoring objects.
std::string component
name of the component owning the Entity
Entity(std::string component, std::string name, std::string type, T &ent)
void * id() const
unique identifier, actually mapped to internal pointer
friend void mergeAndReset(Entity const &ent, Entity const &other)
function calling merge and reset on internal data with the internal data of another entity
std::type_index typeIndex() const
function to get internal type
nlohmann::json(* m_getJSON)(void const *)
function converting the internal data to json.
friend void to_json(nlohmann::json &j, Gaudi::Monitoring::Hub::Entity const &e)
conversion to json via nlohmann library
void(* m_mergeAndReset)(void *, void *)
function calling merge and reset on internal data with the internal data of another entity
void(* m_reset)(void *)
function reseting internal data.
bool operator==(Entity const &ent) const
operator== for comparison with an entity
std::string type
type of the entity, see comment above concerning its format and usage
void * m_ptr
pointer to the actual data inside this Entity
std::string name
name of the entity
friend void reset(Entity const &e)
function resetting internal data
constexpr bool has_mergeAndReset_method_v
constexpr bool has_reset_method_v
STL namespace.
Interface reporting services must implement.
virtual void registerEntity(Entity ent)=0
virtual void removeEntity(Entity const &ent)=0
void removeSink(Sink *sink)
void registerEntity(std::string c, std::string n, std::string t, T &ent)
std::vector< Sink * > m_sinks
std::map< void *, Entity > m_entities
void registerEntity(Entity ent)
void addSink(Sink *sink)