diff --git a/.pnp.cjs b/.pnp.cjs index 58f912b1c..abafa20d5 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -4751,6 +4751,7 @@ const RAW_RUNTIME_STATE = ["@types/jest", "npm:29.5.1"],\ ["@types/jsonwebtoken", "npm:9.0.2"],\ ["@types/newrelic", "npm:9.13.0"],\ + ["@types/node", "npm:20.2.5"],\ ["@types/prettyjson", "npm:0.0.30"],\ ["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.59.2"],\ ["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.59.2"],\ @@ -4811,6 +4812,7 @@ const RAW_RUNTIME_STATE = ["@types/ioredis", "npm:5.0.0"],\ ["@types/jest", "npm:29.5.1"],\ ["@types/newrelic", "npm:9.13.0"],\ + ["@types/node", "npm:20.2.5"],\ ["@types/otplib", "npm:10.0.0"],\ ["@types/prettyjson", "npm:0.0.30"],\ ["@types/ua-parser-js", "npm:0.7.36"],\ @@ -4874,6 +4876,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@standardnotes/domain-core", "workspace:packages/domain-core"],\ ["@types/jest", "npm:29.5.1"],\ + ["@types/node", "npm:20.2.5"],\ ["@types/uuid", "npm:8.3.4"],\ ["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.59.2"],\ ["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.59.2"],\ @@ -5019,6 +5022,7 @@ const RAW_RUNTIME_STATE = ["@types/jest", "npm:29.5.1"],\ ["@types/jsonwebtoken", "npm:9.0.2"],\ ["@types/newrelic", "npm:9.13.0"],\ + ["@types/node", "npm:20.2.5"],\ ["@types/prettyjson", "npm:0.0.30"],\ ["@types/uuid", "npm:8.3.4"],\ ["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.59.2"],\ @@ -5153,6 +5157,7 @@ const RAW_RUNTIME_STATE = ["@types/express", "npm:4.17.17"],\ ["@types/jest", "npm:29.5.1"],\ ["@types/newrelic", "npm:9.13.0"],\ + ["@types/node", "npm:20.2.5"],\ ["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.59.2"],\ ["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.59.2"],\ ["cors", "npm:2.8.5"],\ @@ -5338,6 +5343,7 @@ const RAW_RUNTIME_STATE = ["@types/jest", "npm:29.5.1"],\ ["@types/jsonwebtoken", "npm:9.0.2"],\ ["@types/newrelic", "npm:9.13.0"],\ + ["@types/node", "npm:20.2.5"],\ ["@types/prettyjson", "npm:0.0.30"],\ ["@types/ua-parser-js", "npm:0.7.36"],\ ["@types/uuid", "npm:8.3.4"],\ diff --git a/packages/api-gateway/package.json b/packages/api-gateway/package.json index da1f1198f..cd827ffe3 100644 --- a/packages/api-gateway/package.json +++ b/packages/api-gateway/package.json @@ -54,6 +54,7 @@ "@types/jest": "^29.5.1", "@types/jsonwebtoken": "^9.0.1", "@types/newrelic": "^9.13.0", + "@types/node": "^20.2.5", "@types/prettyjson": "^0.0.30", "@typescript-eslint/eslint-plugin": "^5.59.2", "@typescript-eslint/parser": "^5.59.2", diff --git a/packages/api-gateway/src/Bootstrap/Container.ts b/packages/api-gateway/src/Bootstrap/Container.ts index 6094fa574..089509a15 100644 --- a/packages/api-gateway/src/Bootstrap/Container.ts +++ b/packages/api-gateway/src/Bootstrap/Container.ts @@ -21,12 +21,13 @@ import { EndpointResolverInterface } from '../Service/Resolver/EndpointResolverI import { EndpointResolver } from '../Service/Resolver/EndpointResolver' import { RequiredCrossServiceTokenMiddleware } from '../Controller/RequiredCrossServiceTokenMiddleware' import { OptionalCrossServiceTokenMiddleware } from '../Controller/OptionalCrossServiceTokenMiddleware' +import { Transform } from 'stream' // eslint-disable-next-line @typescript-eslint/no-var-requires const newrelicFormatter = require('@newrelic/winston-enricher') export class ContainerConfigLoader { - async load(serviceContainer?: ServiceContainerInterface): Promise { + async load(configuration?: { serviceContainer?: ServiceContainerInterface; logger?: Transform }): Promise { const env: Env = new Env() env.load() @@ -40,13 +41,17 @@ export class ContainerConfigLoader { winstonFormatters.push(newrelicWinstonFormatter()) } - const logger = winston.createLogger({ - level: env.get('LOG_LEVEL') || 'info', - format: winston.format.combine(...winstonFormatters), - transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })], - defaultMeta: { service: 'api-gateway' }, - }) - container.bind(TYPES.Logger).toConstantValue(logger) + if (configuration?.logger) { + container.bind(TYPES.Logger).toConstantValue(configuration.logger as winston.Logger) + } else { + const logger = winston.createLogger({ + level: env.get('LOG_LEVEL') || 'info', + format: winston.format.combine(...winstonFormatters), + transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })], + defaultMeta: { service: 'api-gateway' }, + }) + container.bind(TYPES.Logger).toConstantValue(logger) + } if (!isConfiguredForHomeServer) { const redisUrl = env.get('REDIS_URL') @@ -91,12 +96,14 @@ export class ContainerConfigLoader { // Services if (isConfiguredForHomeServer) { - if (!serviceContainer) { + if (!configuration?.serviceContainer) { throw new Error('Service container is required when configured for home server') } container .bind(TYPES.ServiceProxy) - .toConstantValue(new DirectCallServiceProxy(serviceContainer, container.get(TYPES.FILES_SERVER_URL))) + .toConstantValue( + new DirectCallServiceProxy(configuration.serviceContainer, container.get(TYPES.FILES_SERVER_URL)), + ) } else { container.bind(TYPES.ServiceProxy).to(HttpServiceProxy) } diff --git a/packages/api-gateway/src/Bootstrap/Service.ts b/packages/api-gateway/src/Bootstrap/Service.ts index f4d9e7199..1efe460da 100644 --- a/packages/api-gateway/src/Bootstrap/Service.ts +++ b/packages/api-gateway/src/Bootstrap/Service.ts @@ -1,12 +1,19 @@ import { ServiceContainerInterface, ServiceIdentifier, ServiceInterface } from '@standardnotes/domain-core' import { ContainerConfigLoader } from './Container' +import { Transform } from 'stream' export class Service implements ServiceInterface { + private logger: Transform | undefined + constructor(private serviceContainer: ServiceContainerInterface) { this.serviceContainer.register(this.getId(), this) } + setLogger(logger: Transform): void { + this.logger = logger + } + async handleRequest(_request: never, _response: never, _endpointOrMethodIdentifier: string): Promise { throw new Error('Requests are handled via inversify-express at ApiGateway level') } @@ -14,7 +21,10 @@ export class Service implements ServiceInterface { async getContainer(): Promise { const config = new ContainerConfigLoader() - return config.load(this.serviceContainer) + return config.load({ + serviceContainer: this.serviceContainer, + logger: this.logger, + }) } getId(): ServiceIdentifier { diff --git a/packages/api-gateway/src/Bootstrap/index.ts b/packages/api-gateway/src/Bootstrap/index.ts index df1a81eab..22cddecef 100644 --- a/packages/api-gateway/src/Bootstrap/index.ts +++ b/packages/api-gateway/src/Bootstrap/index.ts @@ -1,2 +1 @@ export * from './Service' -export * from './Types' diff --git a/packages/auth/package.json b/packages/auth/package.json index 675ee4916..ce6bb0db4 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -82,6 +82,7 @@ "@types/ioredis": "^5.0.0", "@types/jest": "^29.5.1", "@types/newrelic": "^9.13.0", + "@types/node": "^20.2.5", "@types/otplib": "^10.0.0", "@types/prettyjson": "^0.0.30", "@types/ua-parser-js": "^0.7.36", diff --git a/packages/auth/src/Bootstrap/Container.ts b/packages/auth/src/Bootstrap/Container.ts index a7b88de1f..435d22eeb 100644 --- a/packages/auth/src/Bootstrap/Container.ts +++ b/packages/auth/src/Bootstrap/Container.ts @@ -250,6 +250,7 @@ import { HomeServerUsersController } from '../Infra/InversifyExpressUtils/HomeSe import { HomeServerValetTokenController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerValetTokenController' import { HomeServerWebSocketsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerWebSocketsController' import { HomeServerSessionsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerSessionsController' +import { Transform } from 'stream' // eslint-disable-next-line @typescript-eslint/no-var-requires const newrelicFormatter = require('@newrelic/winston-enricher') @@ -258,6 +259,7 @@ export class ContainerConfigLoader { async load(configuration?: { controllerConatiner?: ControllerContainerInterface directCallDomainEventPublisher?: DirectCallDomainEventPublisher + logger?: Transform }): Promise { const directCallDomainEventPublisher = configuration?.directCallDomainEventPublisher ?? new DirectCallDomainEventPublisher() @@ -290,13 +292,17 @@ export class ContainerConfigLoader { winstonFormatters.push(newrelicWinstonFormatter()) } - const logger = winston.createLogger({ - level: env.get('LOG_LEVEL') || 'info', - format: winston.format.combine(...winstonFormatters), - transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })], - defaultMeta: { service: 'auth' }, - }) - container.bind(TYPES.Auth_Logger).toConstantValue(logger) + if (configuration?.logger) { + container.bind(TYPES.Auth_Logger).toConstantValue(configuration.logger as winston.Logger) + } else { + const logger = winston.createLogger({ + level: env.get('LOG_LEVEL') || 'info', + format: winston.format.combine(...winstonFormatters), + transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })], + defaultMeta: { service: 'auth' }, + }) + container.bind(TYPES.Auth_Logger).toConstantValue(logger) + } container.bind(TYPES.Auth_Timer).toConstantValue(new Timer()) diff --git a/packages/auth/src/Bootstrap/Service.ts b/packages/auth/src/Bootstrap/Service.ts index b68caefca..2be4540dc 100644 --- a/packages/auth/src/Bootstrap/Service.ts +++ b/packages/auth/src/Bootstrap/Service.ts @@ -7,8 +7,11 @@ import { import { ContainerConfigLoader } from './Container' import { DirectCallDomainEventPublisher } from '@standardnotes/domain-events-infra' +import { Transform } from 'stream' export class Service implements ServiceInterface { + private logger: Transform | undefined + constructor( private serviceContainer: ServiceContainerInterface, private controllerContainer: ControllerContainerInterface, @@ -17,6 +20,10 @@ export class Service implements ServiceInterface { this.serviceContainer.register(this.getId(), this) } + setLogger(logger: Transform): void { + this.logger = logger + } + async handleRequest(request: never, response: never, endpointOrMethodIdentifier: string): Promise { const method = this.controllerContainer.get(endpointOrMethodIdentifier) @@ -33,6 +40,7 @@ export class Service implements ServiceInterface { return config.load({ controllerConatiner: this.controllerContainer, directCallDomainEventPublisher: this.directCallDomainEventPublisher, + logger: this.logger, }) } diff --git a/packages/domain-core/package.json b/packages/domain-core/package.json index 5d7fdb9c9..74d9caf38 100644 --- a/packages/domain-core/package.json +++ b/packages/domain-core/package.json @@ -27,6 +27,7 @@ }, "devDependencies": { "@types/jest": "^29.5.1", + "@types/node": "^20.2.5", "@types/uuid": "^8.3.0", "@typescript-eslint/eslint-plugin": "^5.59.2", "@typescript-eslint/parser": "^5.59.2", diff --git a/packages/domain-core/src/Domain/Service/ServiceInterface.ts b/packages/domain-core/src/Domain/Service/ServiceInterface.ts index c047a7966..3fee53d43 100644 --- a/packages/domain-core/src/Domain/Service/ServiceInterface.ts +++ b/packages/domain-core/src/Domain/Service/ServiceInterface.ts @@ -1,7 +1,9 @@ import { ServiceIdentifier } from './ServiceIdentifier' +import { Transform } from 'stream' export interface ServiceInterface { getContainer(): Promise + setLogger(logger: Transform): void getId(): ServiceIdentifier handleRequest(request: never, response: never, endpointOrMethodIdentifier: string): Promise } diff --git a/packages/files/package.json b/packages/files/package.json index d9a698c1e..8c0a3f673 100644 --- a/packages/files/package.json +++ b/packages/files/package.json @@ -64,6 +64,7 @@ "@types/jest": "^29.5.1", "@types/jsonwebtoken": "^9.0.1", "@types/newrelic": "^9.13.0", + "@types/node": "^20.2.5", "@types/prettyjson": "^0.0.30", "@types/uuid": "^8.3.0", "@typescript-eslint/eslint-plugin": "^5.59.2", diff --git a/packages/files/src/Bootstrap/Container.ts b/packages/files/src/Bootstrap/Container.ts index bc430d049..a850f53a2 100644 --- a/packages/files/src/Bootstrap/Container.ts +++ b/packages/files/src/Bootstrap/Container.ts @@ -47,9 +47,13 @@ import { MarkFilesToBeRemoved } from '../Domain/UseCase/MarkFilesToBeRemoved/Mar import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler' import { SharedSubscriptionInvitationCanceledEventHandler } from '../Domain/Handler/SharedSubscriptionInvitationCanceledEventHandler' import { InMemoryUploadRepository } from '../Infra/InMemory/InMemoryUploadRepository' +import { Transform } from 'stream' export class ContainerConfigLoader { - async load(configuration?: { directCallDomainEventPublisher?: DirectCallDomainEventPublisher }): Promise { + async load(configuration?: { + directCallDomainEventPublisher?: DirectCallDomainEventPublisher + logger?: Transform + }): Promise { const directCallDomainEventPublisher = configuration?.directCallDomainEventPublisher ?? new DirectCallDomainEventPublisher() @@ -60,8 +64,11 @@ export class ContainerConfigLoader { const isConfiguredForHomeServer = env.get('CACHE_TYPE') === 'memory' - const logger = this.createLogger({ env }) - container.bind(TYPES.Files_Logger).toConstantValue(logger) + if (configuration?.logger) { + container.bind(TYPES.Files_Logger).toConstantValue(configuration.logger as winston.Logger) + } else { + container.bind(TYPES.Files_Logger).toConstantValue(this.createLogger({ env })) + } container.bind(TYPES.Files_Timer).toConstantValue(new Timer()) diff --git a/packages/files/src/Bootstrap/Service.ts b/packages/files/src/Bootstrap/Service.ts index 0bcfc790c..b2d01bd3a 100644 --- a/packages/files/src/Bootstrap/Service.ts +++ b/packages/files/src/Bootstrap/Service.ts @@ -2,8 +2,11 @@ import { ServiceContainerInterface, ServiceIdentifier, ServiceInterface } from ' import { DirectCallDomainEventPublisher } from '@standardnotes/domain-events-infra' import { ContainerConfigLoader } from './Container' +import { Transform } from 'stream' export class Service implements ServiceInterface { + private logger: Transform | undefined + constructor( private serviceContainer: ServiceContainerInterface, private directCallDomainEventPublisher: DirectCallDomainEventPublisher, @@ -11,6 +14,10 @@ export class Service implements ServiceInterface { this.serviceContainer.register(this.getId(), this) } + setLogger(logger: Transform): void { + this.logger = logger + } + async handleRequest(_request: never, _response: never, _endpointOrMethodIdentifier: string): Promise { throw new Error('Requests are handled via inversify-express at ApiGateway level') } @@ -20,6 +27,7 @@ export class Service implements ServiceInterface { return config.load({ directCallDomainEventPublisher: this.directCallDomainEventPublisher, + logger: this.logger, }) } diff --git a/packages/home-server/bin/server.ts b/packages/home-server/bin/server.ts index e11f2fd03..0ce8b123c 100644 --- a/packages/home-server/bin/server.ts +++ b/packages/home-server/bin/server.ts @@ -1,4 +1,4 @@ -import { HomeServer } from '../src/Bootstrap/HomeServer' +import { HomeServer } from '../src/Server/HomeServer' const homeServer = new HomeServer() diff --git a/packages/home-server/src/Bootstrap/index.ts b/packages/home-server/src/Bootstrap/index.ts deleted file mode 100644 index b5c42383c..000000000 --- a/packages/home-server/src/Bootstrap/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './HomeServer' diff --git a/packages/home-server/src/Bootstrap/HomeServer.ts b/packages/home-server/src/Server/HomeServer.ts similarity index 63% rename from packages/home-server/src/Bootstrap/HomeServer.ts rename to packages/home-server/src/Server/HomeServer.ts index 494359991..555e471a1 100644 --- a/packages/home-server/src/Bootstrap/HomeServer.ts +++ b/packages/home-server/src/Server/HomeServer.ts @@ -1,7 +1,7 @@ import 'reflect-metadata' import { ControllerContainer, ServiceContainer } from '@standardnotes/domain-core' -import { Service as ApiGatewayService, TYPES as ApiGatewayTYPES } from '@standardnotes/api-gateway' +import { Service as ApiGatewayService } from '@standardnotes/api-gateway' import { Service as FilesService } from '@standardnotes/files-server' import { DirectCallDomainEventPublisher } from '@standardnotes/domain-events-infra' import { Service as AuthService } from '@standardnotes/auth-server' @@ -11,24 +11,39 @@ import { Container } from 'inversify' import { InversifyExpressServer } from 'inversify-express-utils' import helmet from 'helmet' import * as cors from 'cors' +import * as http from 'http' import { text, json, Request, Response, NextFunction } from 'express' import * as winston from 'winston' +import { PassThrough } from 'stream' // eslint-disable-next-line @typescript-eslint/no-var-requires const robots = require('express-robots-txt') -import { Env } from './Env' +import { Env } from '../Bootstrap/Env' +import { HomeServerInterface } from './HomeServerInterface' + +export class HomeServer implements HomeServerInterface { + private serverInstance: http.Server | undefined -export class HomeServer { async start(): Promise { const controllerContainer = new ControllerContainer() const serviceContainer = new ServiceContainer() const directCallDomainEventPublisher = new DirectCallDomainEventPublisher() + const env: Env = new Env() + env.load() + + this.configureLoggers(env) + const apiGatewayService = new ApiGatewayService(serviceContainer) + apiGatewayService.setLogger(winston.loggers.get('api-gateway')) const authService = new AuthService(serviceContainer, controllerContainer, directCallDomainEventPublisher) + authService.setLogger(winston.loggers.get('auth-server')) const syncingService = new SyncingService(serviceContainer, controllerContainer, directCallDomainEventPublisher) + syncingService.setLogger(winston.loggers.get('syncing-server')) const revisionsService = new RevisionsService(serviceContainer, controllerContainer, directCallDomainEventPublisher) + revisionsService.setLogger(winston.loggers.get('revisions-server')) const filesService = new FilesService(serviceContainer, directCallDomainEventPublisher) + filesService.setLogger(winston.loggers.get('files-server')) const container = Container.merge( (await apiGatewayService.getContainer()) as Container, @@ -38,9 +53,6 @@ export class HomeServer { (await filesService.getContainer()) as Container, ) - const env: Env = new Env() - env.load() - const server = new InversifyExpressServer(container) server.setConfig((app) => { @@ -81,7 +93,7 @@ export class HomeServer { ) }) - const logger: winston.Logger = container.get(ApiGatewayTYPES.Logger) + const logger: winston.Logger = winston.loggers.get('home-server') server.setErrorConfig((app) => { app.use((error: Record, _request: Request, response: Response, _next: NextFunction) => { @@ -96,10 +108,57 @@ export class HomeServer { }) }) - const serverInstance = server.build() - - serverInstance.listen(env.get('PORT', true) ? +env.get('PORT', true) : 3000) + this.serverInstance = server.build().listen(env.get('PORT', true) ? +env.get('PORT', true) : 3000) logger.info(`Server started on port ${process.env.PORT}`) } + + async stop(): Promise { + if (this.serverInstance) { + this.serverInstance.close() + } + } + + async restart(): Promise { + await this.stop() + await this.start() + } + + async isRunning(): Promise { + if (!this.serverInstance) { + return false + } + + return this.serverInstance.address() !== null + } + + logs(): NodeJS.ReadableStream { + const passThroughStream = new PassThrough() + + for (const logger of winston.loggers.loggers.values()) { + logger.stream({ start: -1 }).pipe(passThroughStream, { end: false }) + } + + return passThroughStream + } + + private configureLoggers(env: Env): void { + const winstonFormatters = [winston.format.splat(), winston.format.json()] + + for (const loggerName of [ + 'auth-server', + 'syncing-server', + 'revisions-server', + 'files-server', + 'api-gateway', + 'home-server', + ]) { + winston.loggers.add(loggerName, { + level: env.get('LOG_LEVEL') || 'info', + format: winston.format.combine(...winstonFormatters), + transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })], + defaultMeta: { service: loggerName }, + }) + } + } } diff --git a/packages/home-server/src/Server/HomeServerInterface.ts b/packages/home-server/src/Server/HomeServerInterface.ts new file mode 100644 index 000000000..f0a3c8af8 --- /dev/null +++ b/packages/home-server/src/Server/HomeServerInterface.ts @@ -0,0 +1,7 @@ +export interface HomeServerInterface { + start(): Promise + stop(): Promise + restart(): Promise + isRunning(): Promise + logs(): NodeJS.ReadableStream +} diff --git a/packages/home-server/src/Server/index.ts b/packages/home-server/src/Server/index.ts new file mode 100644 index 000000000..df0decc7c --- /dev/null +++ b/packages/home-server/src/Server/index.ts @@ -0,0 +1,2 @@ +export * from './HomeServer' +export * from './HomeServerInterface' diff --git a/packages/home-server/src/index.ts b/packages/home-server/src/index.ts index c82bbe40e..6ce6de005 100644 --- a/packages/home-server/src/index.ts +++ b/packages/home-server/src/index.ts @@ -1 +1 @@ -export * from './Bootstrap' +export * from './Server' diff --git a/packages/revisions/package.json b/packages/revisions/package.json index 9131d0c4e..1f676453d 100644 --- a/packages/revisions/package.json +++ b/packages/revisions/package.json @@ -54,6 +54,7 @@ "@types/express": "^4.17.14", "@types/jest": "^29.5.1", "@types/newrelic": "^9.13.0", + "@types/node": "^20.2.5", "@typescript-eslint/eslint-plugin": "^5.59.2", "@typescript-eslint/parser": "^5.59.2", "eslint": "^8.39.0", diff --git a/packages/revisions/src/Bootstrap/Container.ts b/packages/revisions/src/Bootstrap/Container.ts index d70a1ffa4..8f93358f4 100644 --- a/packages/revisions/src/Bootstrap/Container.ts +++ b/packages/revisions/src/Bootstrap/Container.ts @@ -46,6 +46,7 @@ import { FSDumpRepository } from '../Infra/FS/FSDumpRepository' import { S3DumpRepository } from '../Infra/S3/S3ItemDumpRepository' import { RevisionItemStringMapper } from '../Mapping/RevisionItemStringMapper' import { HomeServerRevisionsController } from '../Infra/InversifyExpress/HomeServer/HomeServerRevisionsController' +import { Transform } from 'stream' // eslint-disable-next-line @typescript-eslint/no-var-requires const newrelicFormatter = require('@newrelic/winston-enricher') @@ -54,6 +55,7 @@ export class ContainerConfigLoader { async load(configuration?: { controllerConatiner?: ControllerContainerInterface directCallDomainEventPublisher?: DirectCallDomainEventPublisher + logger?: Transform }): Promise { const directCallDomainEventPublisher = configuration?.directCallDomainEventPublisher ?? new DirectCallDomainEventPublisher() @@ -71,24 +73,28 @@ export class ContainerConfigLoader { container.bind(TYPES.Revisions_Env).toConstantValue(env) - container.bind(TYPES.Revisions_Logger).toDynamicValue((context: interfaces.Context) => { - const env: Env = context.container.get(TYPES.Revisions_Env) + if (configuration?.logger) { + container.bind(TYPES.Revisions_Logger).toConstantValue(configuration.logger as winston.Logger) + } else { + container.bind(TYPES.Revisions_Logger).toDynamicValue((context: interfaces.Context) => { + const env: Env = context.container.get(TYPES.Revisions_Env) - const newrelicWinstonFormatter = newrelicFormatter(winston) - const winstonFormatters = [winston.format.splat(), winston.format.json()] - if (env.get('NEW_RELIC_ENABLED', true) === 'true') { - winstonFormatters.push(newrelicWinstonFormatter()) - } + const newrelicWinstonFormatter = newrelicFormatter(winston) + const winstonFormatters = [winston.format.splat(), winston.format.json()] + if (env.get('NEW_RELIC_ENABLED', true) === 'true') { + winstonFormatters.push(newrelicWinstonFormatter()) + } - const logger = winston.createLogger({ - level: env.get('LOG_LEVEL') || 'info', - format: winston.format.combine(...winstonFormatters), - transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })], - defaultMeta: { service: 'revisions' }, + const logger = winston.createLogger({ + level: env.get('LOG_LEVEL') || 'info', + format: winston.format.combine(...winstonFormatters), + transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })], + defaultMeta: { service: 'revisions' }, + }) + + return logger }) - - return logger - }) + } container.bind(TYPES.Revisions_NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true)) container.bind(TYPES.Revisions_VERSION).toConstantValue(env.get('VERSION')) diff --git a/packages/revisions/src/Bootstrap/Service.ts b/packages/revisions/src/Bootstrap/Service.ts index 5b1a728dd..260571e52 100644 --- a/packages/revisions/src/Bootstrap/Service.ts +++ b/packages/revisions/src/Bootstrap/Service.ts @@ -7,8 +7,11 @@ import { import { ContainerConfigLoader } from './Container' import { DirectCallDomainEventPublisher } from '@standardnotes/domain-events-infra' +import { Transform } from 'stream' export class Service implements ServiceInterface { + private logger: Transform | undefined + constructor( private serviceContainer: ServiceContainerInterface, private controllerContainer: ControllerContainerInterface, @@ -17,6 +20,10 @@ export class Service implements ServiceInterface { this.serviceContainer.register(this.getId(), this) } + setLogger(logger: Transform): void { + this.logger = logger + } + async handleRequest(request: never, response: never, endpointOrMethodIdentifier: string): Promise { const method = this.controllerContainer.get(endpointOrMethodIdentifier) @@ -33,6 +40,7 @@ export class Service implements ServiceInterface { return config.load({ controllerConatiner: this.controllerContainer, directCallDomainEventPublisher: this.directCallDomainEventPublisher, + logger: this.logger, }) } diff --git a/packages/syncing-server/package.json b/packages/syncing-server/package.json index 42e176de7..39606d192 100644 --- a/packages/syncing-server/package.json +++ b/packages/syncing-server/package.json @@ -66,6 +66,7 @@ "@types/jest": "^29.5.1", "@types/jsonwebtoken": "^9.0.1", "@types/newrelic": "^9.13.0", + "@types/node": "^20.2.5", "@types/prettyjson": "^0.0.30", "@types/ua-parser-js": "^0.7.36", "@types/uuid": "^8.3.0", diff --git a/packages/syncing-server/src/Bootstrap/Container.ts b/packages/syncing-server/src/Bootstrap/Container.ts index 03a79e7b9..4fb37b056 100644 --- a/packages/syncing-server/src/Bootstrap/Container.ts +++ b/packages/syncing-server/src/Bootstrap/Container.ts @@ -72,6 +72,7 @@ import { AuthHttpService } from '../Infra/HTTP/AuthHttpService' import { S3ItemBackupService } from '../Infra/S3/S3ItemBackupService' import { ControllerContainer, ControllerContainerInterface } from '@standardnotes/domain-core' import { HomeServerItemsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerItemsController' +import { Transform } from 'stream' // eslint-disable-next-line @typescript-eslint/no-var-requires const newrelicFormatter = require('@newrelic/winston-enricher') @@ -83,6 +84,7 @@ export class ContainerConfigLoader { async load(configuration?: { controllerConatiner?: ControllerContainerInterface directCallDomainEventPublisher?: DirectCallDomainEventPublisher + logger?: Transform }): Promise { const directCallDomainEventPublisher = configuration?.directCallDomainEventPublisher ?? new DirectCallDomainEventPublisher() @@ -100,24 +102,28 @@ export class ContainerConfigLoader { container.bind(TYPES.Sync_Env).toConstantValue(env) - container.bind(TYPES.Sync_Logger).toDynamicValue((context: interfaces.Context) => { - const env: Env = context.container.get(TYPES.Sync_Env) + if (configuration?.logger) { + container.bind(TYPES.Sync_Logger).toConstantValue(configuration.logger as winston.Logger) + } else { + container.bind(TYPES.Sync_Logger).toDynamicValue((context: interfaces.Context) => { + const env: Env = context.container.get(TYPES.Sync_Env) - const newrelicWinstonFormatter = newrelicFormatter(winston) - const winstonFormatters = [winston.format.splat(), winston.format.json()] - if (env.get('NEW_RELIC_ENABLED', true) === 'true') { - winstonFormatters.push(newrelicWinstonFormatter()) - } + const newrelicWinstonFormatter = newrelicFormatter(winston) + const winstonFormatters = [winston.format.splat(), winston.format.json()] + if (env.get('NEW_RELIC_ENABLED', true) === 'true') { + winstonFormatters.push(newrelicWinstonFormatter()) + } - const logger = winston.createLogger({ - level: env.get('LOG_LEVEL') || 'info', - format: winston.format.combine(...winstonFormatters), - transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })], - defaultMeta: { service: 'syncing-server' }, + const logger = winston.createLogger({ + level: env.get('LOG_LEVEL') || 'info', + format: winston.format.combine(...winstonFormatters), + transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })], + defaultMeta: { service: 'syncing-server' }, + }) + + return logger }) - - return logger - }) + } if (isConfiguredForHomeServer) { container diff --git a/packages/syncing-server/src/Bootstrap/Service.ts b/packages/syncing-server/src/Bootstrap/Service.ts index 422a688e8..1a7b99e44 100644 --- a/packages/syncing-server/src/Bootstrap/Service.ts +++ b/packages/syncing-server/src/Bootstrap/Service.ts @@ -7,8 +7,11 @@ import { import { ContainerConfigLoader } from './Container' import { DirectCallDomainEventPublisher } from '@standardnotes/domain-events-infra' +import { Transform } from 'stream' export class Service implements ServiceInterface { + private logger: Transform | undefined + constructor( private serviceContainer: ServiceContainerInterface, private controllerContainer: ControllerContainerInterface, @@ -17,6 +20,10 @@ export class Service implements ServiceInterface { this.serviceContainer.register(this.getId(), this) } + setLogger(logger: Transform): void { + this.logger = logger + } + async handleRequest(request: never, response: never, endpointOrMethodIdentifier: string): Promise { const method = this.controllerContainer.get(endpointOrMethodIdentifier) @@ -33,6 +40,7 @@ export class Service implements ServiceInterface { return config.load({ controllerConatiner: this.controllerContainer, directCallDomainEventPublisher: this.directCallDomainEventPublisher, + logger: this.logger, }) } diff --git a/yarn.lock b/yarn.lock index a639bd497..6a1145b98 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4281,6 +4281,7 @@ __metadata: "@types/jest": "npm:^29.5.1" "@types/jsonwebtoken": "npm:^9.0.1" "@types/newrelic": "npm:^9.13.0" + "@types/node": "npm:^20.2.5" "@types/prettyjson": "npm:^0.0.30" "@typescript-eslint/eslint-plugin": "npm:^5.59.2" "@typescript-eslint/parser": "npm:^5.59.2" @@ -4355,6 +4356,7 @@ __metadata: "@types/ioredis": "npm:^5.0.0" "@types/jest": "npm:^29.5.1" "@types/newrelic": "npm:^9.13.0" + "@types/node": "npm:^20.2.5" "@types/otplib": "npm:^10.0.0" "@types/prettyjson": "npm:^0.0.30" "@types/ua-parser-js": "npm:^0.7.36" @@ -4414,6 +4416,7 @@ __metadata: resolution: "@standardnotes/domain-core@workspace:packages/domain-core" dependencies: "@types/jest": "npm:^29.5.1" + "@types/node": "npm:^20.2.5" "@types/uuid": "npm:^8.3.0" "@typescript-eslint/eslint-plugin": "npm:^5.59.2" "@typescript-eslint/parser": "npm:^5.59.2" @@ -4549,6 +4552,7 @@ __metadata: "@types/jest": "npm:^29.5.1" "@types/jsonwebtoken": "npm:^9.0.1" "@types/newrelic": "npm:^9.13.0" + "@types/node": "npm:^20.2.5" "@types/prettyjson": "npm:^0.0.30" "@types/uuid": "npm:^8.3.0" "@typescript-eslint/eslint-plugin": "npm:^5.59.2" @@ -4675,6 +4679,7 @@ __metadata: "@types/express": "npm:^4.17.14" "@types/jest": "npm:^29.5.1" "@types/newrelic": "npm:^9.13.0" + "@types/node": "npm:^20.2.5" "@typescript-eslint/eslint-plugin": "npm:^5.59.2" "@typescript-eslint/parser": "npm:^5.59.2" cors: "npm:2.8.5" @@ -4850,6 +4855,7 @@ __metadata: "@types/jest": "npm:^29.5.1" "@types/jsonwebtoken": "npm:^9.0.1" "@types/newrelic": "npm:^9.13.0" + "@types/node": "npm:^20.2.5" "@types/prettyjson": "npm:^0.0.30" "@types/ua-parser-js": "npm:^0.7.36" "@types/uuid": "npm:^8.3.0" @@ -5343,7 +5349,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^20.2.0": +"@types/node@npm:^20.2.0, @types/node@npm:^20.2.5": version: 20.2.5 resolution: "@types/node@npm:20.2.5" checksum: 55e4f8d08e3c225e48e012e04458d6c1db5af6e4991e3abb003b82d3f10018a14742c0512b27991cb02e54768be560ea1fe4c17208e04273247132c9eb07499a