mirror of
https://github.com/HeyPuter/puter.git
synced 2026-05-04 08:30:39 +00:00
fix: alerting for metering (#2399)
This commit is contained in:
@@ -16,11 +16,8 @@
|
||||
* 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 JSON5 = require('json5');
|
||||
const seedrandom = require('seedrandom');
|
||||
|
||||
const util = require('util');
|
||||
const _path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const BaseService = require('../../services/BaseService.js');
|
||||
@@ -250,13 +247,14 @@ class AlarmService extends BaseService {
|
||||
}
|
||||
|
||||
this.pager.alert({
|
||||
id: `${alarm.id ?? 'something-bad' }-r_\${alarm.count}`,
|
||||
id: alarm.id ?? 'something-bad',
|
||||
message: alarm.message ?? alarm.id ?? 'something bad happened',
|
||||
source: 'alarm-service',
|
||||
severity,
|
||||
custom: {
|
||||
fields: fields_clean,
|
||||
trace: alarm.error?.stack,
|
||||
repeat_count: alarm.count,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -431,7 +429,7 @@ class AlarmService extends BaseService {
|
||||
{
|
||||
id: 'clear-all',
|
||||
description: 'clear all alarms',
|
||||
handler: async (args, log) => {
|
||||
handler: async (_args, _log) => {
|
||||
const alarms = Object.values(this.alarms);
|
||||
this.alarms = {};
|
||||
for ( const alarm of alarms ) {
|
||||
@@ -442,7 +440,7 @@ class AlarmService extends BaseService {
|
||||
{
|
||||
id: 'sound',
|
||||
description: 'sound an alarm',
|
||||
handler: async (args, log) => {
|
||||
handler: async (args, _log) => {
|
||||
const [id, message] = args;
|
||||
this.create(id ?? 'test', message, {});
|
||||
},
|
||||
|
||||
@@ -81,9 +81,9 @@ export class MeteringService {
|
||||
const mappedCost = COST_MAPS[usageType as keyof typeof COST_MAPS];
|
||||
const totalCost = (((costOverride && costOverride < 0) ? 1 : costOverride) ?? ((mappedCost || 0) * usageAmount));
|
||||
|
||||
if ( totalCost === 0 && mappedCost !== 0 && costOverride !== 0 ) {
|
||||
// could be something is off, there are some models that cost nothing from openrouter, but then our overrides should not be undefined, so will flag
|
||||
this.#alarmService.create('metering-service-0-cost-warning', 'potential abuse vector', {
|
||||
if ( totalCost === 0 && (mappedCost !== 0 && costOverride !== 0) ) {
|
||||
// cost is zero but no explicit override to 0, so flag as potential abuse
|
||||
this.#alarmService.create(`metering unexpected 0 cost access to: ${usageType}`, '0 cost abuse vector', {
|
||||
userId: actor.type?.user?.uuid,
|
||||
username: actor.type?.user?.username,
|
||||
appId: actor.type?.app?.uid,
|
||||
@@ -179,7 +179,7 @@ export class MeteringService {
|
||||
const isChangeOverPastOverage = previousAllowedUsageMultiple < allowedUsageMultiple;
|
||||
const hasNoAddonCredit = (actorAddons.purchasedCredits || 0) <= (actorAddons.consumedPurchaseCredits || 0);
|
||||
if ( isOver2x && isChangeOverPastOverage && hasNoAddonCredit ) {
|
||||
this.#alarmService.create('metering-service-usage-limit-exceeded', `Actor ${userId} has exceeded their usage allowance significantly`, {
|
||||
this.#alarmService.create(`metering usage exceeded by user: ${actor.type?.user?.username}`, `Actor ${userId} has exceeded their usage allowance significantly`, {
|
||||
userId: actor.type?.user?.uuid,
|
||||
username: actor.type?.user?.username,
|
||||
appId: actor.type?.app?.uid,
|
||||
@@ -194,7 +194,7 @@ export class MeteringService {
|
||||
});
|
||||
} catch ( e ) {
|
||||
console.error('Metering: Failed to increment usage for actor', actor, 'usageType', usageType, 'usageAmount', usageAmount, e);
|
||||
this.#alarmService.create('metering-service-error', (e as Error).message, {
|
||||
this.#alarmService.create(`metering service error for user: ${ actor.type?.user?.username} app: ${ actor.type.app.uid}`, (e as Error).message, {
|
||||
userId: actor.type?.user?.uuid,
|
||||
username: actor.type?.user?.username,
|
||||
appId: actor.type?.app?.uid,
|
||||
@@ -242,9 +242,9 @@ export class MeteringService {
|
||||
totalBatchCost += totalCost;
|
||||
|
||||
// Check for zero cost warning (only flag once per batch)
|
||||
if ( !hasZeroCostWarning && totalCost === 0 && mappedCost !== 0 && costOverride !== 0 ) {
|
||||
if ( !hasZeroCostWarning && totalCost === 0 && (mappedCost !== 0 && costOverride !== 0 ) ) {
|
||||
hasZeroCostWarning = true;
|
||||
this.#alarmService.create('metering-service-0-cost-warning', 'potential abuse vector', {
|
||||
this.#alarmService.create(`metering unexpected 0 cost access to: ${usageType}`, '0 cost abuse vector', {
|
||||
userId: actor.type?.user?.uuid,
|
||||
username: actor.type?.user?.username,
|
||||
appId: actor.type?.app?.uid,
|
||||
@@ -343,7 +343,7 @@ export class MeteringService {
|
||||
const hasNoAddonCredit = (actorAddons.purchasedCredits || 0) <= (actorAddons.consumedPurchaseCredits || 0);
|
||||
|
||||
if ( isOver2x && isChangeOverPastOverage && hasNoAddonCredit ) {
|
||||
this.#alarmService.create('metering-service-usage-limit-exceeded', `Actor ${userId} has exceeded their usage allowance significantly`, {
|
||||
this.#alarmService.create(`metering usage exceeded by user: ${actor.type?.user?.username}`, `Actor ${userId} has exceeded their usage allowance significantly`, {
|
||||
userId: actor.type?.user?.uuid,
|
||||
username: actor.type?.user?.username,
|
||||
appId: actor.type?.app?.uid,
|
||||
@@ -358,7 +358,7 @@ export class MeteringService {
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('Metering: Failed to batch increment usage for actor', actor, 'usages', usages, e);
|
||||
this.#alarmService.create('metering-service-error', (e as Error).message, {
|
||||
this.#alarmService.create(`metering service error for user: ${ actor.type?.user?.username} app: ${ actor.type.app.uid}`, (e as Error).message, {
|
||||
userId: actor.type?.user?.uuid,
|
||||
username: actor.type?.user?.username,
|
||||
appId: actor.type?.app?.uid,
|
||||
|
||||
Reference in New Issue
Block a user