cleanup: remove dead cloudwatch call (#2155)

This commit is contained in:
Daniel Salazar
2025-12-12 17:08:26 -08:00
committed by GitHub
parent 6c0daf58c4
commit 797b87b004
9 changed files with 10 additions and 305 deletions
+1
View File
@@ -9,6 +9,7 @@ import controlStructureSpacing from './eslint/control-structure-spacing.js';
import spaceUnaryOpsWithException from './eslint/space-unary-ops-with-exception.js';
export const rules = {
'no-invalid-this': 'error',
'no-unused-vars': ['error', {
vars: 'all',
args: 'after-used',
+1
View File
@@ -25,6 +25,7 @@ const mandatoryRules = {
'no-use-before-define': ['error', {
'functions': false,
}],
'no-invalid-this': 'error',
};
export default defineConfig([
-3
View File
@@ -358,9 +358,6 @@ const install = async ({ context, services, app, useapi, modapi }) => {
const { SNSService } = require('./services/SNSService');
services.registerService('sns', SNSService);
const { PerformanceMonitor } = require('./monitor/PerformanceMonitor');
services.registerService('performance-monitor', PerformanceMonitor);
const { WispService } = require('./services/WispService');
services.registerService('wisp', WispService);
// const { AWSSecretsPopulator } = require('./services/AWSSecretsPopulator.js');
+2 -1
View File
@@ -42,7 +42,8 @@ class CodeUtil {
return async function (...a) {
const op = new cls();
op.self = this;
// eslint-disable-next-line no-invalid-this
op.self = this; // TODO: fix this odd structure, what is this even bound to ?
return await op.run(...a);
};
}
+2 -1
View File
@@ -360,7 +360,8 @@ class Sequence {
if ( opt_values && opt_values instanceof Sequence.SequenceState ) {
opt_values = opt_values.scope_;
}
const state = new Sequence.SequenceState(sequence, this);
// eslint-disable-next-line no-invalid-this
const state = new Sequence.SequenceState(sequence, this); // TODO: fix this odd structure, what is this even bound to ?
await state.run(opt_values ?? undefined);
return state.last_return_;
};
@@ -243,8 +243,6 @@ class FilesystemService extends BaseService {
}
async update_child_paths (old_path, new_path, user_id) {
const svc_performanceMonitor = this.services.get('performance-monitor');
const monitor = svc_performanceMonitor.createContext('update_child_paths');
if ( ! old_path.endsWith('/') ) old_path += '/';
if ( ! new_path.endsWith('/') ) new_path += '/';
@@ -255,7 +253,6 @@ class FilesystemService extends BaseService {
const log = this.services.get('log-service').create('update_child_paths');
log.debug(`updated ${old_path} -> ${new_path}`);
monitor.end();
}
/**
+1 -6
View File
@@ -24,10 +24,10 @@ const { ManagedError } = require('./util/errorutil.js');
const { spanify } = require('./util/otelutil.js');
const APIError = require('./api/APIError.js');
const { DB_READ, DB_WRITE } = require('./services/database/consts.js');
const { BaseDatabaseAccessService } = require('./services/database/BaseDatabaseAccessService.js');
const { Context } = require('./util/context');
const { NodeUIDSelector } = require('./filesystem/node/selectors');
const { object_returned_by_get_app } = require('./annotatedobjects.js');
const { kv } = require('./util/kvSingleton');
let services = null;
const tmp_provide_services = async ss => {
@@ -1314,8 +1314,6 @@ function seconds_to_string (seconds) {
* @param {*} options
*/
async function suggest_app_for_fsentry (fsentry, options) {
const svc_performanceMonitor = services.get('performance-monitor');
const monitor = svc_performanceMonitor.createContext('suggest_app_for_fsentry');
const suggested_apps_promises = [];
let content_type = mime.contentType(fsentry.name);
@@ -1470,7 +1468,6 @@ async function suggest_app_for_fsentry (fsentry, options) {
//---------------------------------------------
const apps = kv.get(`assocs:${file_extension.slice(1)}:apps`) ?? [];
monitor.label('third party associations');
for ( const app_id of apps ) {
suggested_apps_promises.push((async () => {
// retrieve app from DB
@@ -1484,8 +1481,6 @@ async function suggest_app_for_fsentry (fsentry, options) {
}
})());
}
monitor.stamp();
monitor.end();
// return list
const suggested_apps = await Promise.all(suggested_apps_promises);
+3 -12
View File
@@ -480,31 +480,22 @@ class LogService extends BaseService {
new winston.transports.DailyRotateFile({
filename: `${this.log_directory}/%DATE%.log`,
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
maxSize: '20m',
// TODO: uncomment when we have a log backup strategy
// maxFiles: '14d',
maxFiles: '14d',
}),
new winston.transports.DailyRotateFile({
level: 'error',
filename: `${this.log_directory}/error-%DATE%.log`,
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
maxSize: '20m',
// TODO: uncomment when we have a log backup strategy
// maxFiles: '14d',
maxFiles: '14d',
}),
new winston.transports.DailyRotateFile({
level: 'system',
filename: `${this.log_directory}/system-%DATE%.log`,
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
maxSize: '20m',
// TODO: uncomment when we have a log backup strategy
// maxFiles: '14d',
maxFiles: '14d',
}),
],
}));
@@ -1,279 +0,0 @@
/*
* Copyright (C) 2024-present Puter Technologies Inc.
*
* This file is part of Puter.
*
* Puter is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
const config = require('../config');
const BaseService = require('../services/BaseService');
const { CloudWatchClient } = require('@aws-sdk/client-cloudwatch');
class Metric {
constructor (windowSize) {
this.count = 0;
this.cumulative = 0;
this.window = [];
this.WINDOW_SIZE = windowSize;
}
pushValue (v) {
this.window.push(v);
this.cumulative += v;
this.count++;
this.update_();
}
update_ () {
while ( this.window.length >= this.WINDOW_SIZE ) {
this.window.shift();
}
this.windowAverage = this.window.reduce((sum, v) => sum + v)
/ this.window.length;
this.cumulativeAverage = this.cumulative / this.count;
}
getCloudwatchMetrics (prefix) {
const metrics = [];
if ( this.count === 0 ) return [];
const Timestamp = Math.floor(Date.now() / 1000);
const Dimensions = [
{
Name: 'server-id',
Value: config.server_id || 'unknown',
},
{
Name: 'environment',
Value: config.env || 'unknown',
},
];
if ( this.cumulativeAverage ) {
metrics.push({
MetricName: `${prefix }.` + 'cumulative-avg',
Value: this.cumulativeAverage,
Timestamp,
Unit: 'Milliseconds',
Dimensions,
});
}
if ( this.windowAverage && this.count >= this.WINDOW_SIZE ) {
metrics.push({
MetricName: `${prefix }.` + 'window-avg',
Value: this.windowAverage,
Timestamp,
Unit: 'Milliseconds',
Dimensions,
});
}
return metrics;
}
}
class PerformanceMonitorContext {
constructor ({ performanceMonitor, name }) {
this.performanceMonitor = performanceMonitor;
this.name = name;
this.stamps = [];
this.children = [];
this.stamp('monitor-created');
}
branch () {
}
stamp (name) {
if ( ! name ) {
this.stamps[this.stamps.length - 1].end = Date.now();
return;
}
this.stamps.push({
name,
ts: Date.now(),
});
}
label (name) {
this.stamps.push({
name,
start: Date.now(),
});
}
end () {
this.stamp('end');
this.performanceMonitor.logMonitorContext(this);
}
}
class PerformanceMonitor extends BaseService {
static LOG_DEBUG = true;
_construct () {
this.performanceMetrics = {};
this.operationCounts = {};
this.lastCountPollTS = Date.now();
}
_init () {
if ( config.cloudwatch ) {
this.cw = new CloudWatchClient(config.cloudwatch);
}
if ( config.monitor ) {
this.config = config.monitor;
}
if ( this.config.metricsInterval > 0 ) {
setInterval(async () => {
await this.recordMetrics_();
}, this.config.metricsInterval);
}
}
createContext (name) {
return new PerformanceMonitorContext({
performanceMonitor: this,
name,
});
}
logMonitorContext (ctx) {
if ( ! this.performanceMetrics[ctx.name] ) {
this.performanceMetrics[ctx.name] =
new Metric(config.windowSize ?? 30);
}
const metricsToUpdate = {};
// Update averaging metrics
{
const begin = ctx.stamps[0];
for ( const stamp of ctx.stamps ) {
let start = stamp.start ?? begin.ts;
let end = stamp.end ?? stamp.ts;
metricsToUpdate[stamp.name] =
(metricsToUpdate[stamp.name] ?? 0) +
(end - start);
}
for ( const name in metricsToUpdate ) {
const value = metricsToUpdate[name];
this.updateMetric_(`${ctx.name}.${name}`, value);
}
}
// Update operation counts
{
if ( ! this.operationCounts[ctx.name] ) {
this.operationCounts[ctx.name] = 0;
}
this.operationCounts[ctx.name]++;
}
if ( ! config.performance_monitors_stdout ) return;
// Write to stout
{
console.log('[Monitor Snapshot]', ctx.name);
const begin = ctx.stamps[0];
for ( const stamp of ctx.stamps ) {
let start = stamp.start ?? begin.ts;
let end = stamp.end ?? stamp.ts;
console.log('|', stamp.name, `${end - start }ms`);
}
}
}
updateMetric_ (key, value) {
const metric = this.performanceMetrics[key] ??
(this.performanceMetrics[key] = new Metric(30));
metric.pushValue(value);
}
async recordMetrics_ () {
this.log.info('recording metrics');
// Only record metrics of CloudWatch is enabled
if ( ! this.cw ) return;
const MetricData = [];
for ( let key in this.performanceMetrics ) {
const prefix = key.replace(/\s+/g, '-');
const metric = this.performanceMetrics[key];
MetricData.push(...metric.getCloudwatchMetrics(prefix));
}
const Dimensions = [
{
Name: 'server-id',
Value: config.server_id || 'unknown',
},
{
Name: 'environment',
Value: config.env || 'unknown',
},
];
const ts = Date.now();
const periodInSeconds = (ts - this.lastCountPollTS) / 1000;
for ( let key in this.operationCounts ) {
const value = this.operationCounts[key] / periodInSeconds;
if ( Number.isNaN(value) ) continue;
const prefix = key.replace(/\s+/g, '-');
MetricData.push({
MetricName: `${prefix }.operations`,
Unit: 'Count/Second',
Value: value,
Dimensions,
});
this.operationCounts[key] = 0;
}
this.lastCountPollTS = ts;
if ( MetricData.length === 0 ) {
this.log.info('no metrics to record');
return;
}
const params = {
Namespace: 'heyputer',
MetricData,
};
// console.log(
// JSON.stringify(params, null, ' ')
// );
try {
await this.cw.putMetricData(params).promise();
} catch (e) {
// TODO: alarm condition
console.error('Failed to send metrics to CloudWatch',
e);
}
}
}
module.exports = {
PerformanceMonitor,
};