1+ // Copyright 2019-2025 CERN and copyright holders of ALICE O2.
2+ // See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+ // All rights not expressly granted are reserved.
4+ //
5+ // This software is distributed under the terms of the GNU General Public
6+ // License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+ //
8+ // In applying this license CERN does not waive the privileges and immunities
9+ // granted to it by virtue of its status as an Intergovernmental Organization
10+ // or submit itself to any jurisdiction.
11+
12+ #include " Framework/AggregationPolicy.h"
13+ #include " Framework/Logger.h"
14+
15+ #include < algorithm>
16+ #include < cstdlib>
17+ #include < sstream>
18+ #include < string>
19+ #include < vector>
20+ #include < regex>
21+ #include < stdexcept>
22+
23+ using namespace o2 ::framework::metricaggregator;
24+
25+ std::vector<std::string> AggregationPolicy::split (std::string_view input, char delim) const {
26+ std::vector<std::string> tokens;
27+ std::string token;
28+ std::istringstream tokenStream{std::string (input)};
29+ while (std::getline (tokenStream, token, delim)) {
30+ tokens.push_back (token);
31+ }
32+ return tokens;
33+ }
34+
35+ void AggregationPolicy::configureFromEnv ()
36+ {
37+ const char * envPolicy = std::getenv (" ALIEN_JDL_AGGREGATOR_POLICY" );
38+ if (!envPolicy) {
39+ LOGP (warn, " [AggregationPolicy] ALIEN_JDL_AGGREGATOR_POLICY is not set. Using default 'all:simple'." );
40+ mSelection = AggregationSelectionType::All;
41+ mReduction = AggregationMetricType::Simple;
42+ return ;
43+ }
44+
45+ try {
46+ std::string policyStr (envPolicy);
47+ std::vector<std::string> parts = split (policyStr, ' :' );
48+
49+ if (parts.size () < 2 ) {
50+ LOGP (error, " [AggregationPolicy] Invalid ALIEN_JDL_AGGREGATOR_POLICY format" );
51+ return ;
52+ }
53+
54+ mSelection = parseSelectionType (parts[0 ]);
55+ mReduction = parseReductionType (parts[1 ]);
56+
57+ if (mSelection == AggregationSelectionType::Specific) {
58+ const char * envDevices = std::getenv (" ALIEN_JDL_AGGREGATOR_DEVICES" );
59+ if (!envDevices) {
60+ throw std::invalid_argument (" ALIEN_JDL_AGGREGATOR_DEVICES environment variable is required when selection type is 'specific'" );
61+ }
62+ mSpecificDevices = split (std::string (envDevices), ' ,' );
63+ }
64+ if (mReduction == AggregationMetricType::Specific) {
65+ const char * envMetrics = std::getenv (" ALIEN_JDL_AGGREGATOR_METRICS" );
66+ if (!envMetrics) {
67+ LOGP (warn, " [AggregationPolicy] ALIEN_JDL_AGGREGATOR_METRICS environment variable missing for 'specific' reduction type. Using default." );
68+ mSpecificMetricRules .push_back ({std::regex (" .*" ), AggregationMetricType::Sum});
69+ return ;
70+ }
71+
72+ std::stringstream metricsStream (envMetrics);
73+ std::string metricRuleStr;
74+ while (std::getline (metricsStream, metricRuleStr, ' ;' )) {
75+ auto pos = metricRuleStr.find (' :' );
76+ if (pos == std::string::npos) {
77+ throw std::invalid_argument (" Invalid metric rule format: " + metricRuleStr);
78+ }
79+ std::string typeStr = metricRuleStr.substr (0 , pos);
80+ std::string patternStr = metricRuleStr.substr (pos + 1 );
81+ AggregationMetricType type = parseReductionType (typeStr);
82+ mSpecificMetricRules .push_back ({std::regex (patternStr), type});
83+ }
84+ }
85+ } catch (std::exception const & e) {
86+ LOGP (error, " [AggregationPolicy] Failed to parse ALIEN_JDL_AGGREGATOR_POLICY: {}" , e.what ());
87+ }
88+ }
89+
90+ AggregationMetricType AggregationPolicy::getAggregationTypeForMetric (std::string_view metricName) const
91+ {
92+ if (mReduction != AggregationMetricType::Specific) {
93+ return mReduction ;
94+ }
95+ for (const auto & rule : mSpecificMetricRules ) {
96+ if (std::regex_match (std::string (metricName), rule.metricPattern )) {
97+ return rule.type ;
98+ }
99+ }
100+ if (mReduction == AggregationMetricType::Specific) {
101+ LOGP (error, " [AggregationPolicy] No specific aggregation type found for metric '{}'" , metricName);
102+ }
103+ throw std::invalid_argument (" No specific aggregation type found for metric: " + std::string (metricName));
104+ }
105+
106+ AggregationSelectionType AggregationPolicy::getSelection () const noexcept
107+ {
108+ return mSelection ;
109+ }
110+
111+ AggregationMetricType AggregationPolicy::getReduction () const noexcept
112+ {
113+ return mReduction ;
114+ }
115+
116+ AggregationSelectionType AggregationPolicy::parseSelectionType (const std::string& str)
117+ {
118+ if (str == " all" ) {
119+ return AggregationSelectionType::All;
120+ } else if (str == " specific" ) {
121+ return AggregationSelectionType::Specific;
122+ }
123+ throw std::invalid_argument (" Invalid selection type: " + str);
124+ }
125+
126+ AggregationMetricType AggregationPolicy::parseReductionType (const std::string& str)
127+ {
128+ if (str == " sum" ) {
129+ return AggregationMetricType::Sum;
130+ } else if (str == " average" ) {
131+ return AggregationMetricType::Average;
132+ } else if (str == " rate" ) {
133+ return AggregationMetricType::Rate;
134+ } else if (str == " simple" ) {
135+ return AggregationMetricType::Simple;
136+ } else if (str == " specific" ) {
137+ return AggregationMetricType::Specific;
138+ }
139+ throw std::invalid_argument (" Invalid reduction type: " + str);
140+ }
141+
142+
143+
144+ bool AggregationPolicy::selectDevice (std::string_view deviceId) const
145+ {
146+ if (mSelection == AggregationSelectionType::Specific) {
147+ return std::find (mSpecificDevices .begin (), mSpecificDevices .end (), deviceId) != mSpecificDevices .end ();
148+ }
149+ return true ;
150+ }
0 commit comments