From d0ad28446b58a9a27c92d77e6969820fc7f1e9da Mon Sep 17 00:00:00 2001 From: Geir Horn Date: Sat, 27 Jan 2024 18:30:53 +0100 Subject: [PATCH] Support for metric list versions including subscriptions to new metric values and cancellation of subscriptions if metrics are removed Change-Id: I967a9c1847618aa5398f247c7e2fd71de2ecc46b --- .vscode/c_cpp_properties.json | 5 ++-- MetricUpdater.cpp | 46 +++++++++++++++++++++++++++++++---- MetricUpdater.hpp | 15 ++++++++++-- 3 files changed, 57 insertions(+), 9 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 52452a6..d6b4621 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -7,11 +7,12 @@ "/home/GHo/Documents/Code/CxxOpts/include", "/opt/AMPL/amplapi/include/", "${workspaceFolder}/**", - "/usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13" + "/usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13", + "/home/GHo/Documents/Code/Theron++" ], "defines": [], "cStandard": "c23", - "intelliSenseMode": "${default}", + "intelliSenseMode": "linux-gcc-x64", "compilerPath": "/usr/bin/g++", "compilerArgs": [ "-std=c++23", diff --git a/MetricUpdater.cpp b/MetricUpdater.cpp index a817d17..6de0a2b 100644 --- a/MetricUpdater.cpp +++ b/MetricUpdater.cpp @@ -38,24 +38,59 @@ namespace NebulOuS // metric values must be updated before the complete set of metrics will be // used for finding a better configuration for the application's execution // context given by the metric values. +// +// The message is just considered if the version number of the message is larger +// than the version of the current set of metrics. The complicating factor is +// to deal with metrics that have changed in the case the metric version is +// increased. Then new metrics must be subscribed, deleted metrics must be +// unsubscribed, and values for kept metrics must be kept. void MetricUpdater::AddMetricSubscription( const MetricTopic & TheMetrics, const Address OptimiserController ) { if( TheMetrics.is_object() && - TheMetrics.at( NebulOuS::MetricList ).is_array() ) + TheMetrics.at( NebulOuS::MetricList ).is_array() && + (MetricsVersion < TheMetrics.at( MetricVersionCounter ).get()) ) { + // The first step is to try inserting the metrics into the metric value map + // and if this is successful, a subscription is created for the publisher + // of this metric value. The metric names are recorded since some of them + // may correspond to known metrics, some of them may correspond to metrics + // that are new. + + std::set< std::string > MetricNames; + for (auto & MetricRecord : TheMetrics.at( NebulOuS::MetricList ) ) { - auto [ MetricRecordPointer, NewMetric ] = MetricValues.try_emplace( + auto [ MetricRecordPointer, MetricAdded ] = MetricValues.try_emplace( MetricRecord.at( NebulOuS::MetricName ), JSON() ); - if( NewMetric ) + MetricNames.insert( MetricRecordPointer->first ); + + if( MetricAdded ) Send( Theron::AMQ::NetworkLayer::TopicSubscription( Theron::AMQ::NetworkLayer::TopicSubscription::Action::Subscription, std::string( MetricValueRootString ) + MetricRecordPointer->first ), - Theron::AMQ::Network::GetAddress( Theron::Network::Layer::Session) ); + //Theron::AMQ::Network::GetAddress( Theron::Network::Layer::Session) ); + GetSessionLayerAddress() ); } + + // There could be some metric value records that were defined by the previous + // metrics defined, but missing from the new metric set. If this is the case, + // the metric value records for the missing metrics should be unsubcribed + // and their metric records removed. + + for( const auto & TheMetric : std::views::keys( MetricValues ) ) + if( !MetricName.contains( TheMetric ) ) + { + Send( Theron::AMQ::NetworkLayer::TopicSubscription( + Theron::AMQ::NetworkLayer::TopicSubscription::Action::CloseSubscription, + std::string( MetricValueRootString ) + TheMetric ), + //Theron::AMQ::Network::GetAddress( Theron::Network::Layer::Session) ); + GetSessionLayerAddress() ); + + MetricValues.erase( TheMetric ); + } } else { @@ -184,7 +219,8 @@ MetricUpdater::MetricUpdater( const std::string UpdaterName, : Actor( UpdaterName ), StandardFallbackHandler( Actor::GetAddress().AsString() ), NetworkingActor( Actor::GetAddress().AsString() ), - MetricValues(), ValidityTime(0), TheSolverManager( ManagerOfSolvers ) + MetricValues(), ValidityTime(0), TheSolverManager( ManagerOfSolvers ), + MetricsVersion(-1) { RegisterHandler( this, &MetricUpdater::AddMetricSubscription ); RegisterHandler( this, &MetricUpdater::UpdateMetricValue ); diff --git a/MetricUpdater.hpp b/MetricUpdater.hpp index ecfde8f..423daad 100644 --- a/MetricUpdater.hpp +++ b/MetricUpdater.hpp @@ -95,8 +95,9 @@ constexpr std::string_view MetricSubscriptions // https://158.39.75.54/projects/nebulous-collaboration-hub/wiki/slo-severity-based-violation-detector // where the name of the metric is defined under as sub-key. -constexpr std::string_view MetricList = "metric_list"; -constexpr std::string_view MetricName = "name"; +constexpr std::string_view MetricList = "metric_list", + MetricName = "name", + MetricVersionCounter = "version"; // The metric value messages will be published on different topics and to // check if an inbound message is from a metric value topic, it is necessary @@ -210,6 +211,16 @@ private: virtual ~MetricTopic() = default; }; + // The metric definition message "Event type III" of the EMS is sent every + // 60 seconds in order to inform new components or crashed components about + // the metrics. The version number of the message is a counter that indicates + // if the set of metrics has changed. Thus the message should be ignored + // as long as the version number stays the same. The version number of the + // current set of metrics is therefore cached to avoid redefining the + // metrics. + + long int MetricsVersion; + // The handler for this message will check each attribute value of the // received JSON struct, and those not already existing in the metric // value map be added and a subscription made for the published