telemetry: config telemetry to run by default (#2184)

This commit is contained in:
Daniel Salazar
2025-12-15 18:49:49 -08:00
committed by GitHub
parent 358b64124e
commit ed51a042b4
5 changed files with 109 additions and 83 deletions

76
package-lock.json generated
View File

@@ -926,7 +926,6 @@
"version": "7.28.5",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
@@ -1247,7 +1246,6 @@
}
],
"license": "MIT",
"peer": true,
"engines": {
"node": ">=18"
},
@@ -1287,7 +1285,6 @@
}
],
"license": "MIT",
"peer": true,
"engines": {
"node": ">=18"
}
@@ -3050,7 +3047,6 @@
"node_modules/@jimp/custom": {
"version": "0.22.12",
"license": "MIT",
"peer": true,
"dependencies": {
"@jimp/core": "^0.22.12"
}
@@ -3081,7 +3077,6 @@
"node_modules/@jimp/plugin-blit": {
"version": "0.22.12",
"license": "MIT",
"peer": true,
"dependencies": {
"@jimp/utils": "^0.22.12"
},
@@ -3092,7 +3087,6 @@
"node_modules/@jimp/plugin-blur": {
"version": "0.22.12",
"license": "MIT",
"peer": true,
"dependencies": {
"@jimp/utils": "^0.22.12"
},
@@ -3113,7 +3107,6 @@
"node_modules/@jimp/plugin-color": {
"version": "0.22.12",
"license": "MIT",
"peer": true,
"dependencies": {
"@jimp/utils": "^0.22.12",
"tinycolor2": "^1.6.0"
@@ -3151,7 +3144,6 @@
"node_modules/@jimp/plugin-crop": {
"version": "0.22.12",
"license": "MIT",
"peer": true,
"dependencies": {
"@jimp/utils": "^0.22.12"
},
@@ -3255,7 +3247,6 @@
"node_modules/@jimp/plugin-resize": {
"version": "0.22.12",
"license": "MIT",
"peer": true,
"dependencies": {
"@jimp/utils": "^0.22.12"
},
@@ -3266,7 +3257,6 @@
"node_modules/@jimp/plugin-rotate": {
"version": "0.22.12",
"license": "MIT",
"peer": true,
"dependencies": {
"@jimp/utils": "^0.22.12"
},
@@ -3280,7 +3270,6 @@
"node_modules/@jimp/plugin-scale": {
"version": "0.22.12",
"license": "MIT",
"peer": true,
"dependencies": {
"@jimp/utils": "^0.22.12"
},
@@ -3521,7 +3510,6 @@
"node_modules/@opentelemetry/api": {
"version": "1.9.0",
"license": "Apache-2.0",
"peer": true,
"engines": {
"node": ">=8.0.0"
}
@@ -5239,7 +5227,6 @@
"version": "8.48.0",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.48.0",
"@typescript-eslint/types": "8.48.0",
@@ -5821,7 +5808,6 @@
"node_modules/acorn": {
"version": "8.15.0",
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -6401,7 +6387,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.8.25",
"caniuse-lite": "^1.0.30001754",
@@ -6591,7 +6576,6 @@
"node_modules/chai": {
"version": "4.5.0",
"license": "MIT",
"peer": true,
"dependencies": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.3",
@@ -6857,10 +6841,6 @@
"resolved": "tools/comment-parser",
"link": true
},
"node_modules/comment-writer": {
"resolved": "tools/comment-writer",
"link": true
},
"node_modules/commondir": {
"version": "1.0.1",
"dev": true,
@@ -7846,7 +7826,6 @@
"node_modules/eslint": {
"version": "9.39.1",
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -13370,7 +13349,6 @@
"version": "8.17.1",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
@@ -14802,7 +14780,6 @@
"version": "5.9.3",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -14976,7 +14953,6 @@
"version": "7.2.6",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.5.0",
@@ -15068,7 +15044,6 @@
"version": "4.0.14",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@vitest/expect": "4.0.14",
"@vitest/mocker": "4.0.14",
@@ -15183,7 +15158,6 @@
"version": "5.103.0",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.8",
@@ -15231,7 +15205,6 @@
"version": "5.1.4",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@discoveryjs/json-ext": "^0.5.0",
"@webpack-cli/configtest": "^2.1.1",
@@ -15431,7 +15404,6 @@
"node_modules/winston": {
"version": "3.18.3",
"license": "MIT",
"peer": true,
"dependencies": {
"@colors/colors": "^1.6.0",
"@dabh/diagnostics": "^2.0.8",
@@ -15549,7 +15521,6 @@
"node_modules/ws": {
"version": "8.18.3",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=10.0.0"
},
@@ -15741,7 +15712,6 @@
"node_modules/zod": {
"version": "3.25.76",
"license": "MIT",
"peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
@@ -15768,6 +15738,7 @@
"@mistralai/mistralai": "^1.3.4",
"@opentelemetry/api": "^1.4.1",
"@opentelemetry/auto-instrumentations-node": "^0.43.0",
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.40.0",
"@opentelemetry/exporter-trace-otlp-grpc": "^0.40.0",
"@opentelemetry/sdk-metrics": "^1.14.0",
"@opentelemetry/sdk-node": "^0.49.1",
@@ -15859,7 +15830,6 @@
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.4.1.tgz",
"integrity": "sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA==",
"license": "Apache-2.0",
"peer": true,
"engines": {
"node": ">=8.0.0"
}
@@ -15869,7 +15839,6 @@
"resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.49.1.tgz",
"integrity": "sha512-kaNl/T7WzyMUQHQlVq7q0oV4Kev6+0xFwqzofryC66jgGMacd0QH5TwfpbUwSTby+SdAdprAe5UKMvBw4tKS5Q==",
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"@opentelemetry/api": "^1.0.0"
},
@@ -15971,6 +15940,46 @@
"node": ">=14"
}
},
"src/backend/node_modules/@opentelemetry/exporter-metrics-otlp-grpc": {
"version": "0.40.0",
"resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.40.0.tgz",
"integrity": "sha512-1kIEi2G4uVrxqZV+9M09Il2XeylAUOpNXg1vpS50R2CgP99u6ICzu+xhENXWucaVya+tRduwrhkVzSagyP7Mtw==",
"license": "Apache-2.0",
"dependencies": {
"@grpc/grpc-js": "^1.7.1",
"@opentelemetry/core": "1.14.0",
"@opentelemetry/exporter-metrics-otlp-http": "0.40.0",
"@opentelemetry/otlp-grpc-exporter-base": "0.40.0",
"@opentelemetry/otlp-transformer": "0.40.0",
"@opentelemetry/resources": "1.14.0",
"@opentelemetry/sdk-metrics": "1.14.0"
},
"engines": {
"node": ">=14"
},
"peerDependencies": {
"@opentelemetry/api": "^1.3.0"
}
},
"src/backend/node_modules/@opentelemetry/exporter-metrics-otlp-http": {
"version": "0.40.0",
"resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.40.0.tgz",
"integrity": "sha512-4ferfcHOyYAhy+7Xk/vMWGBI6yafeOxpLWKrRjzNFAGKzD78teOnPTvyaCecPF0nviTF4VuwT2ECgon6Q/bFBQ==",
"license": "Apache-2.0",
"dependencies": {
"@opentelemetry/core": "1.14.0",
"@opentelemetry/otlp-exporter-base": "0.40.0",
"@opentelemetry/otlp-transformer": "0.40.0",
"@opentelemetry/resources": "1.14.0",
"@opentelemetry/sdk-metrics": "1.14.0"
},
"engines": {
"node": ">=14"
},
"peerDependencies": {
"@opentelemetry/api": "^1.3.0"
}
},
"src/backend/node_modules/@opentelemetry/exporter-trace-otlp-grpc": {
"version": "0.40.0",
"resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.40.0.tgz",
@@ -17882,7 +17891,7 @@
},
"src/puter-js": {
"name": "@heyputer/puter.js",
"version": "2.1.15",
"version": "2.2.0",
"license": "Apache-2.0",
"dependencies": {
"@heyputer/kv.js": "^0.2.1"
@@ -17990,6 +17999,7 @@
},
"tools/comment-writer": {
"version": "1.0.0",
"extraneous": true,
"license": "AGPL-3.0-only",
"dependencies": {
"axios": "^1.7.8",

View File

@@ -19,6 +19,7 @@
"@opentelemetry/api": "^1.4.1",
"@opentelemetry/auto-instrumentations-node": "^0.43.0",
"@opentelemetry/exporter-trace-otlp-grpc": "^0.40.0",
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.40.0",
"@opentelemetry/sdk-metrics": "^1.14.0",
"@opentelemetry/sdk-node": "^0.49.1",
"@pagerduty/pdjs": "^2.2.4",
@@ -105,4 +106,4 @@
},
"author": "Puter Technologies Inc.",
"license": "AGPL-3.0-only"
}
}

View File

@@ -29,7 +29,7 @@ class PerfMonModule extends AdvancedBase {
async install (context) {
const services = context.get('services');
const TelemetryService = require('./TelemetryService');
const { TelemetryService } = require('./TelemetryService');
services.registerService('telemetry', TelemetryService);
}
}

View File

@@ -16,35 +16,42 @@
* 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 opentelemetry = require('@opentelemetry/api');
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { PeriodicExportingMetricReader, ConsoleMetricExporter } = require('@opentelemetry/sdk-metrics');
import { SpanStatusCode, trace } from '@opentelemetry/api';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
import { Resource } from '@opentelemetry/resources';
import { ConsoleMetricExporter, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
import { NodeSDK } from '@opentelemetry/sdk-node';
import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-base';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
import config from '../../config.js';
import BaseService from '../../services/BaseService.js';
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
const { ConsoleSpanExporter } = require('@opentelemetry/sdk-trace-base');
const config = require('../../config');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');
const BaseService = require('../../services/BaseService');
class TelemetryService extends BaseService {
export class TelemetryService extends BaseService {
/** @type {import('@opentelemetry/api').Tracer} */
#tracer = null;
_construct () {
const traceExporter = this.#getConfiguredExporter();
const metricExporter = this.#getMetricExporter();
if ( !traceExporter && !metricExporter ) {
console.log('TelemetryService not configured, skipping initialization.');
return;
}
const resource = Resource.default().merge(
new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'puter-backend',
[SemanticResourceAttributes.SERVICE_VERSION]: '0.1.0',
}));
const exporter = this.#getConfiguredExporter();
this.exporter = exporter;
const sdk = new NodeSDK({
resource,
traceExporter: exporter,
traceExporter: traceExporter,
metricReader: new PeriodicExportingMetricReader({
exporter: new ConsoleMetricExporter(),
exporter: metricExporter,
}),
instrumentations: [getNodeAutoInstrumentations()],
});
@@ -53,21 +60,24 @@ class TelemetryService extends BaseService {
this.sdk.start();
this.tracer_ = opentelemetry.trace.getTracer('puter-tracer');
this.#tracer = trace.getTracer('puter-tracer');
}
_init () {
if ( ! this.#tracer ) {
return;
}
const svc_context = this.services.get('context');
svc_context.register_context_hook('pre_arun', ({ hints, trace_name, callback, replace_callback }) => {
if ( ! trace_name ) return;
if ( ! hints.trace ) return;
console.log('APPLYING TRACE NAME', trace_name);
replace_callback(async () => {
return await this.tracer_.startActiveSpan(trace_name, async span => {
return await this.#tracer.startActiveSpan(trace_name, async span => {
try {
return await callback();
} catch ( error ) {
span.setStatus({ code: opentelemetry.SpanStatusCode.ERROR, message: error.message });
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
throw error;
} finally {
span.end();
@@ -81,9 +91,17 @@ class TelemetryService extends BaseService {
if ( config.jaeger ?? this.config.jaeger ) {
return new OTLPTraceExporter(config.jaeger ?? this.config.jaeger);
}
const exporter = new ConsoleSpanExporter();
return exporter;
if ( this.config.console ) {
return new ConsoleSpanExporter();
}
}
}
module.exports = TelemetryService;
#getMetricExporter () {
if ( config.jaeger ?? this.config.jaeger ) {
return new OTLPMetricExporter(config.jaeger ?? this.config.jaeger);
}
if ( this.config.console ) {
return new ConsoleMetricExporter();
}
}
}

View File

@@ -59,7 +59,7 @@ const surrounding_box = (col, lines) => {
const lowest_allowed = Math.max(...ver_info.map(r => r.under));
// ACTUAL VERSION CHECK
const [major, minor] = process.versions.node.split('.').map(Number);
const [major, _minor] = process.versions.node.split('.').map(Number);
if ( major < lowest_allowed ) {
const lines = [];
lines.push(`Please use a version of Node.js ${lowest_allowed} or newer.`);
@@ -80,7 +80,7 @@ const surrounding_box = (col, lines) => {
if ( ! import.meta.filename ) {
Object.defineProperty(import.meta, 'filename', {
get: () => import.meta.url.slice('file://'.length),
})
});
}
const main = async () => {
@@ -102,7 +102,7 @@ const main = async () => {
} = (await import('@heyputer/backend')).default;
const k = new Kernel({
entry_path: import.meta.filename
entry_path: import.meta.filename,
});
for ( const mod of EssentialModules ) {
k.add_module(new mod());
@@ -117,9 +117,7 @@ const main = async () => {
k.add_module(new PuterAIModule());
k.add_module(new InternetModule());
k.add_module(new DNSModule());
if ( process.env.PERFMON ) {
k.add_module(new PerfMonModule());
}
k.add_module(new PerfMonModule());
if ( process.env.UNSAFE_PUTER_DEV ) {
k.add_module(new DevelopmentModule());
}
@@ -128,35 +126,35 @@ const main = async () => {
const early_init_errors = [
{
text: `Cannot find package '@heyputer/backend'`,
text: 'Cannot find package \'@heyputer/backend\'',
notes: [
'this usually happens if you forget `npm install`'
'this usually happens if you forget `npm install`',
],
suggestions: [
'try running `npm install`'
'try running `npm install`',
],
technical_notes: [
'@heyputer/backend is in an npm workspace'
]
'@heyputer/backend is in an npm workspace',
],
},
{
text: `Cannot find package`,
text: 'Cannot find package',
notes: [
'this usually happens if you forget `npm install`'
'this usually happens if you forget `npm install`',
],
suggestions: [
'try running `npm install`'
'try running `npm install`',
],
},
{
text: 'Cannot write to path',
notes: [
'this usually happens when /var/puter isn\'t chown\'d to the right UID'
'this usually happens when /var/puter isn\'t chown\'d to the right UID',
],
suggestions: [
'check issue #645 on our github'
]
}
'check issue #645 on our github',
],
},
];
// null coalescing operator
@@ -167,13 +165,13 @@ const nco = (...args) => {
}
}
return undefined;
}
};
const _print_error_help = (error_help) => {
const lines = [];
lines.push(nco(error_help.title, error_help.text));
for ( const note of (nco(error_help.notes, [])) ) {
lines.push(`📝 ${note}`)
lines.push(`📝 ${note}`);
}
if ( error_help.suggestions ) {
lines.push('Suggestions:');
@@ -189,14 +187,13 @@ const _print_error_help = (error_help) => {
}
surrounding_box('31;1', lines);
console.error(lines.join('\n'));
}
};
(async () => {
try {
await main();
} catch (e) {
for ( const error_help of early_init_errors ) {
const message = e && e.message;
if ( e.message && e.message.includes(error_help.text) ) {
_print_error_help(error_help);
break;