mirror of
https://github.com/HeyPuter/puter.git
synced 2026-08-26 07:57:10 +00:00
move install location
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
|
||||
import { existsSync, readFileSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { isSpanContextValid, trace } from '@opentelemetry/api';
|
||||
import { puterClients } from './clients';
|
||||
import { puterControllers } from './controllers';
|
||||
import { puterDrivers } from './drivers';
|
||||
@@ -26,6 +27,7 @@ import { PuterServer } from './server';
|
||||
import { puterServices } from './services';
|
||||
import { puterStores } from './stores';
|
||||
import type { IConfig } from './types';
|
||||
import { installJsonConsole } from './util/jsonConsole.js';
|
||||
|
||||
// Config resolution order:
|
||||
// 1. `process.env.PUTER_CONFIG_PATH` — absolute path to a config file. Used
|
||||
@@ -167,6 +169,23 @@ const loadConfig = (): IConfig => {
|
||||
// if called directly, start the server
|
||||
if (require.main === module) {
|
||||
const config = loadConfig();
|
||||
|
||||
// Structured logging: when `log_format: "json"`, replace the global console
|
||||
// so each call emits one JSON line (level, timestamp, msg, and the active
|
||||
// trace id) — one event per call, so a line-oriented log collector can't
|
||||
// split stack traces across events. Installed here rather than in the OTel
|
||||
// preload so it applies even when telemetry is disabled; the trace id is
|
||||
// simply absent when no span is active.
|
||||
if (config.log_format === 'json') {
|
||||
installJsonConsole({
|
||||
getTraceContext: () => {
|
||||
const ctx = trace.getActiveSpan()?.spanContext();
|
||||
if (!ctx || !isSpanContextValid(ctx)) return undefined;
|
||||
return { traceId: ctx.traceId, spanId: ctx.spanId };
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const server = new PuterServer(
|
||||
config,
|
||||
puterClients,
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { isSpanContextValid, trace } from '@opentelemetry/api';
|
||||
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
|
||||
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';
|
||||
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
|
||||
@@ -33,59 +32,6 @@ import {
|
||||
ATTR_SERVICE_VERSION,
|
||||
} from '@opentelemetry/semantic-conventions';
|
||||
|
||||
import { existsSync, readFileSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { installJsonConsole } from './util/jsonConsole.js';
|
||||
|
||||
/**
|
||||
* Resolve `log_format` with the SAME precedence as the server's `loadConfig`
|
||||
* (index.ts): defaults from `config.default.json`, overlaid by a single
|
||||
* override file — `PUTER_CONFIG_PATH` if it exists, else `<pkg>/config.json`.
|
||||
* This preload runs before the backend loads config, so it must stay in lockstep
|
||||
* with that resolution or it'd act on a value the server never sees.
|
||||
*/
|
||||
const configLogFormat = (): unknown => {
|
||||
const pkgRoot = path.resolve(__dirname, '../../..');
|
||||
const readJson = (file: string): Record<string, unknown> => {
|
||||
try {
|
||||
return JSON.parse(readFileSync(file, 'utf8'));
|
||||
} catch {
|
||||
// A missing/invalid file is treated as no override; the server's
|
||||
// loadConfig surfaces a real parse error moments later.
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
const defaultPath = path.join(pkgRoot, 'config.default.json');
|
||||
const runtimePath = path.join(pkgRoot, 'config.json');
|
||||
const envPath = process.env.PUTER_CONFIG_PATH;
|
||||
|
||||
const defaults = existsSync(defaultPath) ? readJson(defaultPath) : {};
|
||||
const overridePath =
|
||||
envPath && existsSync(envPath)
|
||||
? envPath
|
||||
: existsSync(runtimePath)
|
||||
? runtimePath
|
||||
: null;
|
||||
const override = overridePath ? readJson(overridePath) : {};
|
||||
|
||||
// deepMerge over a scalar key == override wins when it sets the key.
|
||||
return 'log_format' in override ? override.log_format : defaults.log_format;
|
||||
};
|
||||
|
||||
// When config sets `log_format: "json"`, replace the global console so every
|
||||
// call emits one JSON line tagged with the active trace — one event per call,
|
||||
// filterable by level. Any other value (the default) leaves console untouched.
|
||||
if (configLogFormat() === 'json') {
|
||||
installJsonConsole({
|
||||
getTraceContext: () => {
|
||||
const ctx = trace.getActiveSpan()?.spanContext();
|
||||
if (!ctx || !isSpanContextValid(ctx)) return undefined;
|
||||
return { traceId: ctx.traceId, spanId: ctx.spanId };
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const endpoint =
|
||||
process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? 'http://localhost:4317';
|
||||
const sampleRatio = Number(process.env.OTEL_TRACE_SAMPLE_RATIO ?? 0.05);
|
||||
|
||||
Reference in New Issue
Block a user