@@ -20,6 +20,35 @@ std::shared_ptr<std::string> configurer::Configuration::m_cache_home =
2020std::shared_ptr<std::string> configurer::Configuration::m_tls_ca_file =
2121 std::make_shared<std::string>(" " );
2222
23+ // Monitoring file config (empty string means disabled)
24+ // Protected by mutex; atomic flag for fast-path check
25+ std::string configurer::Configuration::m_monitoring_file;
26+ std::mutex configurer::Configuration::m_monitoring_file_mutex;
27+ std::atomic<bool > configurer::Configuration::m_monitoring_file_configured{
28+ false };
29+ std::atomic_int configurer::Configuration::m_monitoring_file_interval{60 };
30+
31+ void configurer::Configuration::set_monitoring_file (const std::string &path) {
32+ std::lock_guard<std::mutex> lock (m_monitoring_file_mutex);
33+ m_monitoring_file = path;
34+ // Update the atomic flag after setting the string
35+ m_monitoring_file_configured.store (!path.empty (),
36+ std::memory_order_release);
37+ }
38+
39+ std::string configurer::Configuration::get_monitoring_file () {
40+ std::lock_guard<std::mutex> lock (m_monitoring_file_mutex);
41+ return m_monitoring_file;
42+ }
43+
44+ void configurer::Configuration::set_monitoring_file_interval (int seconds) {
45+ m_monitoring_file_interval = seconds;
46+ }
47+
48+ int configurer::Configuration::get_monitoring_file_interval () {
49+ return m_monitoring_file_interval;
50+ }
51+
2352SciTokenKey scitoken_key_create (const char *key_id, const char *alg,
2453 const char *public_contents,
2554 const char *private_contents, char **err_msg) {
@@ -246,10 +275,12 @@ int scitoken_get_expiration(const SciToken token, long long *expiry,
246275 // Float value - convert to integer (truncate)
247276 // Float value - convert to integer using std::floor().
248277 // This ensures expiration is not extended by fractional seconds.
249- result = static_cast <long long >(std::floor (claim_value.get <double >()));
278+ result =
279+ static_cast <long long >(std::floor (claim_value.get <double >()));
250280 } else {
251281 if (err_msg) {
252- *err_msg = strdup (" 'exp' claim must be a number (integer or float)" );
282+ *err_msg =
283+ strdup (" 'exp' claim must be a number (integer or float)" );
253284 }
254285 return -1 ;
255286 }
@@ -1024,6 +1055,17 @@ int scitoken_config_set_int(const char *key, int value, char **err_msg) {
10241055 return 0 ;
10251056 }
10261057
1058+ else if (_key == " monitoring.file_interval_s" ) {
1059+ if (value < 0 ) {
1060+ if (err_msg) {
1061+ *err_msg = strdup (" Interval cannot be negative." );
1062+ }
1063+ return -1 ;
1064+ }
1065+ configurer::Configuration::set_monitoring_file_interval (value);
1066+ return 0 ;
1067+ }
1068+
10271069 else {
10281070 if (err_msg) {
10291071 *err_msg = strdup (" Key not recognized." );
@@ -1053,6 +1095,10 @@ int scitoken_config_get_int(const char *key, char **err_msg) {
10531095 return configurer::Configuration::get_expiry_delta ();
10541096 }
10551097
1098+ else if (_key == " monitoring.file_interval_s" ) {
1099+ return configurer::Configuration::get_monitoring_file_interval ();
1100+ }
1101+
10561102 else {
10571103 if (err_msg) {
10581104 *err_msg = strdup (" Key not recognized." );
@@ -1080,9 +1126,12 @@ int scitoken_config_set_str(const char *key, const char *value,
10801126 return -1 ;
10811127 }
10821128 } else if (_key == " tls.ca_file" ) {
1083- configurer::Configuration::set_tls_ca_file (value ? std::string (value) : " " );
1084- }
1085- else {
1129+ configurer::Configuration::set_tls_ca_file (value ? std::string (value)
1130+ : " " );
1131+ } else if (_key == " monitoring.file" ) {
1132+ configurer::Configuration::set_monitoring_file (
1133+ value ? std::string (value) : " " );
1134+ } else {
10861135 if (err_msg) {
10871136 *err_msg = strdup (" Key not recognized." );
10881137 }
@@ -1104,6 +1153,9 @@ int scitoken_config_get_str(const char *key, char **output, char **err_msg) {
11041153 *output = strdup (configurer::Configuration::get_cache_home ().c_str ());
11051154 } else if (_key == " tls.ca_file" ) {
11061155 *output = strdup (configurer::Configuration::get_tls_ca_file ().c_str ());
1156+ } else if (_key == " monitoring.file" ) {
1157+ *output =
1158+ strdup (configurer::Configuration::get_monitoring_file ().c_str ());
11071159 }
11081160
11091161 else {
@@ -1114,3 +1166,35 @@ int scitoken_config_get_str(const char *key, char **output, char **err_msg) {
11141166 }
11151167 return 0 ;
11161168}
1169+
1170+ int scitoken_get_monitoring_json (char **json_out, char **err_msg) {
1171+ if (!json_out) {
1172+ if (err_msg) {
1173+ *err_msg = strdup (" JSON output pointer may not be null." );
1174+ }
1175+ return -1 ;
1176+ }
1177+ try {
1178+ std::string json =
1179+ scitokens::internal::MonitoringStats::instance ().get_json ();
1180+ *json_out = strdup (json.c_str ());
1181+ } catch (std::exception &exc) {
1182+ if (err_msg) {
1183+ *err_msg = strdup (exc.what ());
1184+ }
1185+ return -1 ;
1186+ }
1187+ return 0 ;
1188+ }
1189+
1190+ int scitoken_reset_monitoring_stats (char **err_msg) {
1191+ try {
1192+ scitokens::internal::MonitoringStats::instance ().reset ();
1193+ } catch (std::exception &exc) {
1194+ if (err_msg) {
1195+ *err_msg = strdup (exc.what ());
1196+ }
1197+ return -1 ;
1198+ }
1199+ return 0 ;
1200+ }
0 commit comments