From c7029463933662585e16667bb6d3e78d1f8238b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D0=BE=D0=B2=20=D0=90=D1=80=D1=82?= =?UTF-8?q?=D0=B5=D0=BC?= Date: Fri, 3 Jul 2026 19:33:28 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=BB=D0=BE=D0=B3=D0=B8=D1=80=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 3 +++ docker-compose.yml | 1 + src/main.ts | 38 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index c304264..c9e5984 100644 --- a/.env.example +++ b/.env.example @@ -5,5 +5,8 @@ DATABASE_URL=postgres://greact:pG3526l4@194.36.208.86:5433/cloud # Optional. When set, POST /api/ingest requires x-api-key: . INGEST_API_KEY= +# Optional. Logs POST /api/ingest request metadata without x-api-key. +INGEST_DEBUG_LOG= + # Poll interval for GET /api/current/events SSE snapshots. CURRENT_EVENTS_POLL_MS=1000 diff --git a/docker-compose.yml b/docker-compose.yml index a231116..4fe08ad 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,6 +5,7 @@ services: restart: unless-stopped environment: NODE_ENV: production + BRANCH: ${branch:-} PORT: ${PORT} DATABASE_URL: ${DATABASE_URL} INGEST_API_KEY: ${INGEST_API_KEY} diff --git a/src/main.ts b/src/main.ts index d3efa04..eafb9ba 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,10 +1,30 @@ -import { ValidationPipe } from '@nestjs/common'; +import { Logger, ValidationPipe } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; import compression from 'compression'; import { AppModule } from './app.module'; +import { DbService } from './db/db.service'; + +type CurrentDatabaseRow = { + database: string; +}; + +function getMaskedDatabaseUrl(): string | undefined { + const databaseUrl = process.env.DATABASE_URL; + if (!databaseUrl) { + return undefined; + } + + try { + const url = new URL(databaseUrl); + const username = url.username ? `${url.username}:***@` : ''; + return `${url.protocol}//${username}${url.host}${url.pathname}`; + } catch { + return databaseUrl.replace(/:\/\/([^:]+):([^@]+)@/, '://$1:***@'); + } +} -/** Запускает HTTP API со сжатием и глобальной валидацией DTO. */ async function bootstrap() { + const logger = new Logger('Bootstrap'); const app = await NestFactory.create(AppModule); app.use(compression()); app.setGlobalPrefix('api'); @@ -18,6 +38,20 @@ async function bootstrap() { ); await app.listen(process.env.PORT as string); + + const db = app.get(DbService); + const currentDatabase = await db.query( + 'SELECT current_database() AS database', + ); + + logger.log({ + event: 'cloud.started', + port: process.env.PORT, + branch: process.env.BRANCH ?? process.env.branch ?? '', + database: currentDatabase.rows[0]?.database, + databaseUrl: getMaskedDatabaseUrl(), + ingestDebugLog: process.env.INGEST_DEBUG_LOG ?? '', + }); } void bootstrap();