From c872a06940af2ca7bb45902470721e568a29f950 Mon Sep 17 00:00:00 2001 From: durpdur Date: Tue, 5 Aug 2025 14:00:04 -0700 Subject: [PATCH 1/7] Added prometheus metric to track current epoch time and when the refresh token is being refreshed --- api/cloud_api/routes/Mailer.js | 1 + api/util/metrics.js | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/api/cloud_api/routes/Mailer.js b/api/cloud_api/routes/Mailer.js index 7b512c955..363c4f917 100644 --- a/api/cloud_api/routes/Mailer.js +++ b/api/cloud_api/routes/Mailer.js @@ -29,6 +29,7 @@ router.post('/sendVerificationEmail', async (req, res) => { if (apiHandler.checkIfTokenIsExpired(tokenJson)) { logger.warn('refreshing token'); apiHandler.refreshToken(); + MetricsHandler.gcpRefreshTokenEpochTime.set(Math.floor(Date.now() / 1000)) // Updates prometheus metric } } else { logger.warn('getting new token! ', { tokenJson }); diff --git a/api/util/metrics.js b/api/util/metrics.js index bb6c75c9a..0cc3b725a 100644 --- a/api/util/metrics.js +++ b/api/util/metrics.js @@ -63,6 +63,11 @@ class MetricsHandler { labelNames: ['endpointName'] }) + gcpRefreshTokenEpochTime = new client.Gauge({ + name: 'google_cloud_refresh_token_epoch', + help: 'When the GCP refresh token needs to be refreshed, time written in eopch format' + }) + constructor() { register.setDefaultLabels({ app: 'sce-core', From 3a7acae916614e62386a65fc9e447c4c97a2b170 Mon Sep 17 00:00:00 2001 From: durpdur Date: Tue, 5 Aug 2025 15:34:22 -0700 Subject: [PATCH 2/7] fixed semicolon error --- api/cloud_api/routes/Mailer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/cloud_api/routes/Mailer.js b/api/cloud_api/routes/Mailer.js index 363c4f917..f1e551286 100644 --- a/api/cloud_api/routes/Mailer.js +++ b/api/cloud_api/routes/Mailer.js @@ -29,7 +29,7 @@ router.post('/sendVerificationEmail', async (req, res) => { if (apiHandler.checkIfTokenIsExpired(tokenJson)) { logger.warn('refreshing token'); apiHandler.refreshToken(); - MetricsHandler.gcpRefreshTokenEpochTime.set(Math.floor(Date.now() / 1000)) // Updates prometheus metric + MetricsHandler.gcpRefreshTokenEpochTime.set(Math.floor(Date.now() / 1000)); // Updates prometheus metric } } else { logger.warn('getting new token! ', { tokenJson }); From d118d3d0abd380f82589680ee8100f09b01c259a Mon Sep 17 00:00:00 2001 From: evan Date: Sun, 12 Oct 2025 16:11:15 -0700 Subject: [PATCH 3/7] gcpRefreshTokenLastUpdated --- api/cloud_api/routes/Mailer.js | 6 +++++- api/util/metrics.js | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/api/cloud_api/routes/Mailer.js b/api/cloud_api/routes/Mailer.js index f1e551286..9cd58c3bf 100644 --- a/api/cloud_api/routes/Mailer.js +++ b/api/cloud_api/routes/Mailer.js @@ -29,7 +29,11 @@ router.post('/sendVerificationEmail', async (req, res) => { if (apiHandler.checkIfTokenIsExpired(tokenJson)) { logger.warn('refreshing token'); apiHandler.refreshToken(); - MetricsHandler.gcpRefreshTokenEpochTime.set(Math.floor(Date.now() / 1000)); // Updates prometheus metric + // the time() function in prometheus returns the epoch time in seconds + // i.e. 1760310047.552 + // Date.now() returns the time in milliseconds, so we divide by 1000 + // to be consistent with prometheus. + MetricsHandler.gcpRefreshTokenLastUpdated.set(Math.floor(Date.now() / 1000)); } } else { logger.warn('getting new token! ', { tokenJson }); diff --git a/api/util/metrics.js b/api/util/metrics.js index 0cc3b725a..d2b57d4b2 100644 --- a/api/util/metrics.js +++ b/api/util/metrics.js @@ -63,8 +63,8 @@ class MetricsHandler { labelNames: ['endpointName'] }) - gcpRefreshTokenEpochTime = new client.Gauge({ - name: 'google_cloud_refresh_token_epoch', + gcpRefreshTokenLastUpdated = new client.Gauge({ + name: 'google_cloud_refresh_token_last_updated', help: 'When the GCP refresh token needs to be refreshed, time written in eopch format' }) From 3d5ae867af8a73ff1b69bb754971ae717fde9aa1 Mon Sep 17 00:00:00 2001 From: evan Date: Sun, 12 Oct 2025 16:11:51 -0700 Subject: [PATCH 4/7] no more log --- api/cloud_api/routes/Mailer.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api/cloud_api/routes/Mailer.js b/api/cloud_api/routes/Mailer.js index 9cd58c3bf..b128dca06 100644 --- a/api/cloud_api/routes/Mailer.js +++ b/api/cloud_api/routes/Mailer.js @@ -27,13 +27,12 @@ router.post('/sendVerificationEmail', async (req, res) => { if (tokenJson) { if (apiHandler.checkIfTokenIsExpired(tokenJson)) { - logger.warn('refreshing token'); - apiHandler.refreshToken(); // the time() function in prometheus returns the epoch time in seconds // i.e. 1760310047.552 // Date.now() returns the time in milliseconds, so we divide by 1000 // to be consistent with prometheus. MetricsHandler.gcpRefreshTokenLastUpdated.set(Math.floor(Date.now() / 1000)); + apiHandler.refreshToken(); } } else { logger.warn('getting new token! ', { tokenJson }); From bd9897cc66883aedb7d6c5d0ae463d9c0a6cbcb1 Mon Sep 17 00:00:00 2001 From: evan Date: Sat, 25 Oct 2025 12:59:04 -0700 Subject: [PATCH 5/7] tested and it works, one drawback is changes in config restarts nodemon, so metrics return to 0 --- api/cloud_api/routes/Mailer.js | 1 + api/cloud_api/util/SceGoogleApiHandler.js | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/api/cloud_api/routes/Mailer.js b/api/cloud_api/routes/Mailer.js index b128dca06..dca18e3be 100644 --- a/api/cloud_api/routes/Mailer.js +++ b/api/cloud_api/routes/Mailer.js @@ -73,6 +73,7 @@ router.post('/sendPasswordReset', async (req, res) => { if (tokenJson) { if (apiHandler.checkIfTokenIsExpired(tokenJson)) { logger.warn('refreshing token'); + MetricsHandler.gcpRefreshTokenLastUpdated.set(Math.floor(Date.now() / 1000)); apiHandler.refreshToken(); } } else { diff --git a/api/cloud_api/util/SceGoogleApiHandler.js b/api/cloud_api/util/SceGoogleApiHandler.js index bd863250f..135d88a3f 100644 --- a/api/cloud_api/util/SceGoogleApiHandler.js +++ b/api/cloud_api/util/SceGoogleApiHandler.js @@ -80,7 +80,16 @@ class SceGoogleApiHandler { * DevOps purposes, false for API endpoints. */ getNewToken(isDevScript) { - if (!isDevScript) return; + if (!isDevScript) { + logger.warn(` + The 'getNewToken' function was called outside of a development environment. + Token generation requires manual steps and interactive console input. + If you actually want to set this up, visit: + https://sce.sjsu.edu/s/gmailtoken + Interactive setup has been skipped. + `); + return; + }; const authUrl = this.oAuth2Client.generateAuthUrl({ /* eslint-disable-next-line */ @@ -109,6 +118,7 @@ class SceGoogleApiHandler { const configPath = __dirname + '/../../config/config.json'; let config = JSON.parse(fs.readFileSync(configPath)); + console.log({token}) config.googleApiKeys.REFRESH_TOKEN = token.refresh_token; fs.writeFile(configPath, JSON.stringify(config), (error) => { From 672daa7de7e300cfb04bc0c8abfcca304181e116 Mon Sep 17 00:00:00 2001 From: evan Date: Sun, 26 Oct 2025 17:12:05 -0700 Subject: [PATCH 6/7] sce-cloud-api:8082 --- prometheus/prometheus.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/prometheus/prometheus.yml b/prometheus/prometheus.yml index a80acfe7a..900792379 100644 --- a/prometheus/prometheus.yml +++ b/prometheus/prometheus.yml @@ -17,6 +17,9 @@ scrape_configs: - job_name: 'clark' static_configs: - targets: ['main-endpoints:8080'] + - job_name: 'clark-email' + static_configs: + - targets: ['sce-cloud-api:8082'] # the below is for discord bot - job_name: 'sarah' static_configs: From 9663bc95823093bac4707b065f2c08fa59730685 Mon Sep 17 00:00:00 2001 From: evan Date: Sun, 26 Oct 2025 17:16:55 -0700 Subject: [PATCH 7/7] lint --- api/cloud_api/util/SceGoogleApiHandler.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api/cloud_api/util/SceGoogleApiHandler.js b/api/cloud_api/util/SceGoogleApiHandler.js index 135d88a3f..e95a5fc68 100644 --- a/api/cloud_api/util/SceGoogleApiHandler.js +++ b/api/cloud_api/util/SceGoogleApiHandler.js @@ -89,7 +89,7 @@ class SceGoogleApiHandler { Interactive setup has been skipped. `); return; - }; + } const authUrl = this.oAuth2Client.generateAuthUrl({ /* eslint-disable-next-line */ @@ -118,7 +118,6 @@ class SceGoogleApiHandler { const configPath = __dirname + '/../../config/config.json'; let config = JSON.parse(fs.readFileSync(configPath)); - console.log({token}) config.googleApiKeys.REFRESH_TOKEN = token.refresh_token; fs.writeFile(configPath, JSON.stringify(config), (error) => {