From d830e0f6f4e9c1da802755fc2df86fb3bf61d5c5 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 6 Jun 2026 09:25:28 +0200 Subject: [PATCH] Task/migrate backend logger to instance pattern (#6966) * Refactor backend logging to use instance-based Logger * Update changelog --- CHANGELOG.md | 4 ++ apps/api/src/app/admin/admin.controller.ts | 4 +- apps/api/src/app/auth/auth.module.ts | 4 +- apps/api/src/app/auth/google.strategy.ts | 4 +- apps/api/src/app/auth/oidc.strategy.ts | 9 +-- apps/api/src/app/auth/web-auth.service.ts | 6 +- .../benchmarks/benchmarks.service.ts | 7 ++- .../ghostfolio/ghostfolio.service.ts | 12 ++-- apps/api/src/app/health/health.controller.ts | 4 +- apps/api/src/app/import/import.controller.ts | 4 +- .../calculator/portfolio-calculator.ts | 7 ++- .../calculator/roai/portfolio-calculator.ts | 6 +- .../src/app/portfolio/portfolio.service.ts | 7 ++- .../app/redis-cache/redis-cache.service.ts | 6 +- .../subscription/subscription.controller.ts | 14 ++--- .../app/subscription/subscription.service.ts | 9 +-- apps/api/src/app/symbol/symbol.service.ts | 4 +- .../events/asset-profile-changed.listener.ts | 12 ++-- .../src/events/portfolio-changed.listener.ts | 7 +-- .../performance-logging.service.ts | 4 +- apps/api/src/main.ts | 18 +++--- .../middlewares/html-template.middleware.ts | 8 +-- .../services/benchmark/benchmark.service.ts | 6 +- .../coingecko/coingecko.service.ts | 8 ++- .../trackinsight/trackinsight.service.ts | 7 ++- .../yahoo-finance/yahoo-finance.service.ts | 6 +- .../data-provider/data-provider.service.ts | 31 ++++++----- .../eod-historical-data.service.ts | 21 ++++--- .../financial-modeling-prep.service.ts | 13 +++-- .../ghostfolio/ghostfolio.service.ts | 12 ++-- .../google-sheets/google-sheets.service.ts | 4 +- .../data-provider/manual/manual.service.ts | 9 +-- .../rapid-api/rapid-api.service.ts | 6 +- .../yahoo-finance/yahoo-finance.service.ts | 23 +++----- .../exchange-rate-data.service.ts | 19 +++---- apps/api/src/services/fetch/fetch.service.ts | 24 +++----- apps/api/src/services/i18n/i18n.service.ts | 8 ++- .../api/src/services/prisma/prisma.service.ts | 4 +- .../data-gathering.processor.ts | 42 ++++++-------- .../data-gathering/data-gathering.service.ts | 15 ++--- .../portfolio-snapshot.processor.ts | 17 +++--- .../statistics-gathering.processor.ts | 55 +++++++------------ .../twitter-bot/twitter-bot.service.ts | 9 +-- 43 files changed, 249 insertions(+), 250 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e315dfc9..35ca028a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added an automatic refresh every 30 seconds to the users table in the admin control panel +### Changed + +- Refactored the backend logging to use the instance-based `Logger` + ### Fixed - Fixed a layout issue in the asset profile dialog of the admin control by truncating long titles diff --git a/apps/api/src/app/admin/admin.controller.ts b/apps/api/src/app/admin/admin.controller.ts index 69b619625..97642feb5 100644 --- a/apps/api/src/app/admin/admin.controller.ts +++ b/apps/api/src/app/admin/admin.controller.ts @@ -58,6 +58,8 @@ import { AdminService } from './admin.service'; @Controller('admin') export class AdminController { + private readonly logger = new Logger(AdminController.name); + public constructor( private readonly adminService: AdminService, private readonly apiService: ApiService, @@ -260,7 +262,7 @@ export class AdminController { `Could not parse the market price for ${symbol} (${dataSource})` ); } catch (error) { - Logger.error(error, 'AdminController'); + this.logger.error(error); throw new HttpException(error.message, StatusCodes.BAD_REQUEST); } diff --git a/apps/api/src/app/auth/auth.module.ts b/apps/api/src/app/auth/auth.module.ts index f55093bbf..1d6990307 100644 --- a/apps/api/src/app/auth/auth.module.ts +++ b/apps/api/src/app/auth/auth.module.ts @@ -50,6 +50,8 @@ import { OidcStrategy } from './oidc.strategy'; configurationService: ConfigurationService, fetchService: FetchService ) => { + const logger = new Logger('OidcStrategy'); + const isOidcEnabled = configurationService.get( 'ENABLE_FEATURE_AUTH_OIDC' ); @@ -101,7 +103,7 @@ import { OidcStrategy } from './oidc.strategy'; tokenURL = manualTokenUrl || config.token_endpoint; userInfoURL = manualUserInfoUrl || config.userinfo_endpoint; } catch (error) { - Logger.error(error, 'OidcStrategy'); + logger.error(error); throw new Error('Failed to fetch OIDC configuration from issuer'); } } diff --git a/apps/api/src/app/auth/google.strategy.ts b/apps/api/src/app/auth/google.strategy.ts index 3e4b4ca0d..53720c383 100644 --- a/apps/api/src/app/auth/google.strategy.ts +++ b/apps/api/src/app/auth/google.strategy.ts @@ -10,6 +10,8 @@ import { AuthService } from './auth.service'; @Injectable() export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { + private readonly logger = new Logger(GoogleStrategy.name); + public constructor( private readonly authService: AuthService, configurationService: ConfigurationService @@ -40,7 +42,7 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { done(null, { jwt }); } catch (error) { - Logger.error(error, 'GoogleStrategy'); + this.logger.error(error); done(error, false); } } diff --git a/apps/api/src/app/auth/oidc.strategy.ts b/apps/api/src/app/auth/oidc.strategy.ts index 96b284121..661f2a821 100644 --- a/apps/api/src/app/auth/oidc.strategy.ts +++ b/apps/api/src/app/auth/oidc.strategy.ts @@ -15,6 +15,8 @@ import { OidcStateStore } from './oidc-state.store'; @Injectable() export class OidcStrategy extends PassportStrategy(Strategy, 'oidc') { + private readonly logger = new Logger(OidcStrategy.name); + private static readonly stateStore = new OidcStateStore(); public constructor( @@ -52,9 +54,8 @@ export class OidcStrategy extends PassportStrategy(Strategy, 'oidc') { }); if (!thirdPartyId) { - Logger.error( - `Missing subject identifier in OIDC response from ${issuer}`, - 'OidcStrategy' + this.logger.error( + `Missing subject identifier in OIDC response from ${issuer}` ); throw new Error('Missing subject identifier in OIDC response'); @@ -62,7 +63,7 @@ export class OidcStrategy extends PassportStrategy(Strategy, 'oidc') { return { jwt }; } catch (error) { - Logger.error(error, 'OidcStrategy'); + this.logger.error(error); throw error; } } diff --git a/apps/api/src/app/auth/web-auth.service.ts b/apps/api/src/app/auth/web-auth.service.ts index 6cffcd244..5764eeece 100644 --- a/apps/api/src/app/auth/web-auth.service.ts +++ b/apps/api/src/app/auth/web-auth.service.ts @@ -33,6 +33,8 @@ import ms from 'ms'; @Injectable() export class WebAuthService { + private readonly logger = new Logger(WebAuthService.name); + public constructor( private readonly configurationService: ConfigurationService, private readonly deviceService: AuthDeviceService, @@ -103,7 +105,7 @@ export class WebAuthService { verification = await verifyRegistrationResponse(opts); } catch (error) { - Logger.error(error, 'WebAuthService'); + this.logger.error(error); throw new InternalServerErrorException(error.message); } @@ -210,7 +212,7 @@ export class WebAuthService { verification = await verifyAuthenticationResponse(opts); } catch (error) { - Logger.error(error, 'WebAuthService'); + this.logger.error(error); throw new InternalServerErrorException({ error: error.message }); } diff --git a/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts b/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts index 03ff32c21..0b95880d4 100644 --- a/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts +++ b/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts @@ -17,6 +17,8 @@ import { isNumber } from 'lodash'; @Injectable() export class BenchmarksService { + private readonly logger = new Logger(BenchmarksService.name); + public constructor( private readonly benchmarkService: BenchmarkService, private readonly exchangeRateDataService: ExchangeRateDataService, @@ -96,12 +98,11 @@ export class BenchmarksService { })?.marketPrice; if (!marketPriceAtStartDate) { - Logger.error( + this.logger.error( `No historical market data has been found for ${symbol} (${dataSource}) at ${format( startDate, DATE_FORMAT - )}`, - 'BenchmarkService' + )}` ); return { marketData }; diff --git a/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts b/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts index 3f91dbecc..b84ca881f 100644 --- a/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts +++ b/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts @@ -34,6 +34,8 @@ import { Big } from 'big.js'; @Injectable() export class GhostfolioService { + private readonly logger = new Logger(GhostfolioService.name); + public constructor( private readonly configurationService: ConfigurationService, private readonly dataProviderService: DataProviderService, @@ -99,7 +101,7 @@ export class GhostfolioService { return result; } catch (error) { - Logger.error(error, 'GhostfolioService'); + this.logger.error(error); throw error; } @@ -141,7 +143,7 @@ export class GhostfolioService { return result; } catch (error) { - Logger.error(error, 'GhostfolioService'); + this.logger.error(error); throw error; } @@ -183,7 +185,7 @@ export class GhostfolioService { return result; } catch (error) { - Logger.error(error, 'GhostfolioService'); + this.logger.error(error); throw error; } @@ -271,7 +273,7 @@ export class GhostfolioService { return results; } catch (error) { - Logger.error(error, 'GhostfolioService'); + this.logger.error(error); throw error; } @@ -348,7 +350,7 @@ export class GhostfolioService { return results; } catch (error) { - Logger.error(error, 'GhostfolioService'); + this.logger.error(error); throw error; } diff --git a/apps/api/src/app/health/health.controller.ts b/apps/api/src/app/health/health.controller.ts index 35f3fa348..4f88a03f0 100644 --- a/apps/api/src/app/health/health.controller.ts +++ b/apps/api/src/app/health/health.controller.ts @@ -24,6 +24,8 @@ import { HealthService } from './health.service'; @Controller('health') export class HealthController { + private readonly logger = new Logger(HealthController.name); + public constructor( private readonly aiService: AiService, private readonly healthService: HealthService @@ -61,7 +63,7 @@ export class HealthController { .json({ status: getReasonPhrase(StatusCodes.OK) }); } } catch (error) { - Logger.error(error, 'HealthController'); + this.logger.error(error); } return response diff --git a/apps/api/src/app/import/import.controller.ts b/apps/api/src/app/import/import.controller.ts index 521be56f7..c3e79a29f 100644 --- a/apps/api/src/app/import/import.controller.ts +++ b/apps/api/src/app/import/import.controller.ts @@ -31,6 +31,8 @@ import { ImportService } from './import.service'; @Controller('import') export class ImportController { + private readonly logger = new Logger(ImportController.name); + public constructor( private readonly configurationService: ConfigurationService, private readonly importService: ImportService, @@ -81,7 +83,7 @@ export class ImportController { return { activities }; } catch (error) { - Logger.error(error, ImportController); + this.logger.error(error); throw new HttpException( { diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index d57b85d8c..ab3f76703 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -62,6 +62,8 @@ import { isNumber, sortBy, sum, uniqBy } from 'lodash'; export abstract class PortfolioCalculator { protected static readonly ENABLE_LOGGING = false; + protected readonly logger = new Logger(PortfolioCalculator.name); + protected accountBalanceItems: HistoricalDataItem[]; protected activities: PortfolioOrder[]; @@ -1119,12 +1121,11 @@ export abstract class PortfolioCalculator { if (cachedPortfolioSnapshot) { this.snapshot = cachedPortfolioSnapshot; - Logger.debug( + this.logger.debug( `Fetched portfolio snapshot from cache in ${( (performance.now() - startTimeTotal) / 1000 - ).toFixed(3)} seconds`, - 'PortfolioCalculator' + ).toFixed(3)} seconds` ); if (isCachedPortfolioSnapshotExpired) { diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts index 2841e9975..d5efc4bf2 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts @@ -11,7 +11,6 @@ import { PortfolioSnapshot, TimelinePosition } from '@ghostfolio/common/models'; import { DateRange } from '@ghostfolio/common/types'; import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; -import { Logger } from '@nestjs/common'; import { Big } from 'big.js'; import { addMilliseconds, @@ -96,9 +95,8 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { currentPosition.timeWeightedInvestmentWithCurrencyEffect ); } else if (!currentPosition.quantity.eq(0)) { - Logger.warn( - `Missing historical market data for ${currentPosition.symbol} (${currentPosition.dataSource})`, - 'PortfolioCalculator' + this.logger.warn( + `Missing historical market data for ${currentPosition.symbol} (${currentPosition.dataSource})` ); hasErrors = true; diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 37d76bcfa..4feb0f77a 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -108,6 +108,8 @@ const europeMarkets = require('../../assets/countries/europe-markets.json'); @Injectable() export class PortfolioService { + private readonly logger = new Logger(PortfolioService.name); + public constructor( private readonly accountBalanceService: AccountBalanceService, private readonly accountService: AccountService, @@ -619,9 +621,8 @@ export class PortfolioService { symbolProfileMap[getAssetProfileIdentifier({ dataSource, symbol })]; if (!assetProfile) { - Logger.warn( - `Asset profile not found for ${symbol} (${dataSource})`, - 'PortfolioService' + this.logger.warn( + `Asset profile not found for ${symbol} (${dataSource})` ); continue; diff --git a/apps/api/src/app/redis-cache/redis-cache.service.ts b/apps/api/src/app/redis-cache/redis-cache.service.ts index 619d23fc5..b87740f8c 100644 --- a/apps/api/src/app/redis-cache/redis-cache.service.ts +++ b/apps/api/src/app/redis-cache/redis-cache.service.ts @@ -10,6 +10,8 @@ import { createHash, randomUUID } from 'node:crypto'; @Injectable() export class RedisCacheService { + private readonly logger = new Logger(RedisCacheService.name); + private client: Keyv; public constructor( @@ -27,7 +29,7 @@ export class RedisCacheService { }; this.client.on('error', (error) => { - Logger.error(error, 'RedisCacheService'); + this.logger.error(error); }); } @@ -101,7 +103,7 @@ export class RedisCacheService { return true; } catch (error) { - Logger.error(error?.message, 'RedisCacheService'); + this.logger.error(error?.message); return false; } finally { diff --git a/apps/api/src/app/subscription/subscription.controller.ts b/apps/api/src/app/subscription/subscription.controller.ts index 3e6316ec6..074a9db0e 100644 --- a/apps/api/src/app/subscription/subscription.controller.ts +++ b/apps/api/src/app/subscription/subscription.controller.ts @@ -33,6 +33,8 @@ import { SubscriptionService } from './subscription.service'; @Controller('subscription') export class SubscriptionController { + private readonly logger = new Logger(SubscriptionController.name); + public constructor( private readonly configurationService: ConfigurationService, private readonly propertyService: PropertyService, @@ -80,9 +82,8 @@ export class SubscriptionController { value: JSON.stringify(coupons) }); - Logger.log( - `Subscription for user '${this.request.user.id}' has been created with a coupon for ${coupon.duration}`, - 'SubscriptionController' + this.logger.log( + `Subscription for user '${this.request.user.id}' has been created with a coupon for ${coupon.duration}` ); return { @@ -101,9 +102,8 @@ export class SubscriptionController { ); if (userId) { - Logger.log( - `Subscription for user '${userId}' has been created via Stripe`, - 'SubscriptionController' + this.logger.log( + `Subscription for user '${userId}' has been created via Stripe` ); } @@ -126,7 +126,7 @@ export class SubscriptionController { user: this.request.user }); } catch (error) { - Logger.error(error, 'SubscriptionController'); + this.logger.error(error); throw new HttpException( getReasonPhrase(StatusCodes.BAD_REQUEST), diff --git a/apps/api/src/app/subscription/subscription.service.ts b/apps/api/src/app/subscription/subscription.service.ts index 557d81976..a811d2243 100644 --- a/apps/api/src/app/subscription/subscription.service.ts +++ b/apps/api/src/app/subscription/subscription.service.ts @@ -24,6 +24,8 @@ import Stripe from 'stripe'; @Injectable() export class SubscriptionService { + private readonly logger = new Logger(SubscriptionService.name); + private stripe: Stripe; public constructor( @@ -166,9 +168,8 @@ export class SubscriptionService { error instanceof Prisma.PrismaClientKnownRequestError && error.code === 'P2002' ) { - Logger.log( - `Stripe Checkout Session '${session.id}' has already been redeemed`, - 'SubscriptionService' + this.logger.log( + `Stripe Checkout Session '${session.id}' has already been redeemed` ); } else { throw error; @@ -177,7 +178,7 @@ export class SubscriptionService { return session.client_reference_id; } catch (error) { - Logger.error(error, 'SubscriptionService'); + this.logger.error(error); } } diff --git a/apps/api/src/app/symbol/symbol.service.ts b/apps/api/src/app/symbol/symbol.service.ts index 15498e80d..fdbc7f84c 100644 --- a/apps/api/src/app/symbol/symbol.service.ts +++ b/apps/api/src/app/symbol/symbol.service.ts @@ -15,6 +15,8 @@ import { format, subDays } from 'date-fns'; @Injectable() export class SymbolService { + private readonly logger = new Logger(SymbolService.name); + public constructor( private readonly dataProviderService: DataProviderService, private readonly marketDataService: MarketDataService @@ -119,7 +121,7 @@ export class SymbolService { results.items = items; return results; } catch (error) { - Logger.error(error, 'SymbolService'); + this.logger.error(error); throw error; } diff --git a/apps/api/src/events/asset-profile-changed.listener.ts b/apps/api/src/events/asset-profile-changed.listener.ts index cc70edad6..e2aea382e 100644 --- a/apps/api/src/events/asset-profile-changed.listener.ts +++ b/apps/api/src/events/asset-profile-changed.listener.ts @@ -15,6 +15,8 @@ import { AssetProfileChangedEvent } from './asset-profile-changed.event'; @Injectable() export class AssetProfileChangedListener { + private readonly logger = new Logger(AssetProfileChangedListener.name); + private static readonly DEBOUNCE_DELAY = ms('5 seconds'); private debounceTimers = new Map(); @@ -67,10 +69,7 @@ export class AssetProfileChangedListener { dataSource: DataSource; symbol: string; }) { - Logger.log( - `Asset profile of ${symbol} (${dataSource}) has changed`, - 'AssetProfileChangedListener' - ); + this.logger.log(`Asset profile of ${symbol} (${dataSource}) has changed`); if ( this.configurationService.get( @@ -84,10 +83,7 @@ export class AssetProfileChangedListener { const existingCurrencies = this.exchangeRateDataService.getCurrencies(); if (!existingCurrencies.includes(currency)) { - Logger.log( - `New currency ${currency} has been detected`, - 'AssetProfileChangedListener' - ); + this.logger.log(`New currency ${currency} has been detected`); await this.exchangeRateDataService.initialize(); } diff --git a/apps/api/src/events/portfolio-changed.listener.ts b/apps/api/src/events/portfolio-changed.listener.ts index f8e2a9229..12441517b 100644 --- a/apps/api/src/events/portfolio-changed.listener.ts +++ b/apps/api/src/events/portfolio-changed.listener.ts @@ -8,6 +8,8 @@ import { PortfolioChangedEvent } from './portfolio-changed.event'; @Injectable() export class PortfolioChangedListener { + private readonly logger = new Logger(PortfolioChangedListener.name); + private static readonly DEBOUNCE_DELAY = ms('5 seconds'); private debounceTimers = new Map(); @@ -35,10 +37,7 @@ export class PortfolioChangedListener { } private async processPortfolioChanged({ userId }: { userId: string }) { - Logger.log( - `Portfolio of user '${userId}' has changed`, - 'PortfolioChangedListener' - ); + this.logger.log(`Portfolio of user '${userId}' has changed`); await this.redisCacheService.removePortfolioSnapshotsByUserId({ userId }); } diff --git a/apps/api/src/interceptors/performance-logging/performance-logging.service.ts b/apps/api/src/interceptors/performance-logging/performance-logging.service.ts index 1b1faf8e0..a07783cd9 100644 --- a/apps/api/src/interceptors/performance-logging/performance-logging.service.ts +++ b/apps/api/src/interceptors/performance-logging/performance-logging.service.ts @@ -2,6 +2,8 @@ import { Injectable, Logger } from '@nestjs/common'; @Injectable() export class PerformanceLoggingService { + private readonly logger = new Logger(PerformanceLoggingService.name); + public logPerformance({ className, methodName, @@ -13,7 +15,7 @@ export class PerformanceLoggingService { }) { const endTime = performance.now(); - Logger.debug( + this.logger.debug( `Completed execution of ${methodName}() in ${((endTime - startTime) / 1000).toFixed(3)} seconds`, className ); diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts index 94e389f6a..63185a48b 100644 --- a/apps/api/src/main.ts +++ b/apps/api/src/main.ts @@ -23,6 +23,8 @@ import { EnvHttpProxyAgent, setGlobalDispatcher } from 'undici'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; +const logger = new Logger('Bootstrap'); + async function bootstrap() { // Respect HTTP_PROXY / HTTPS_PROXY / NO_PROXY for outbound HTTP requests setGlobalDispatcher(new EnvHttpProxyAgent()); @@ -114,20 +116,20 @@ async function bootstrap() { address = `${host}:${addressObject.port}`; } - Logger.log(`Listening at http://${address}`); - Logger.log(''); + logger.log(`Listening at http://${address}`); + logger.log(''); }); } function logLogo() { - Logger.log(' ________ __ ____ ___'); - Logger.log(' / ____/ /_ ____ _____/ /_/ __/___ / (_)___'); - Logger.log(' / / __/ __ \\/ __ \\/ ___/ __/ /_/ __ \\/ / / __ \\'); - Logger.log('/ /_/ / / / / /_/ (__ ) /_/ __/ /_/ / / / /_/ /'); - Logger.log( + logger.log(' ________ __ ____ ___'); + logger.log(' / ____/ /_ ____ _____/ /_/ __/___ / (_)___'); + logger.log(' / / __/ __ \\/ __ \\/ ___/ __/ /_/ __ \\/ / / __ \\'); + logger.log('/ /_/ / / / / /_/ (__ ) /_/ __/ /_/ / / / /_/ /'); + logger.log( `\\____/_/ /_/\\____/____/\\__/_/ \\____/_/_/\\____/ ${environment.version}` ); - Logger.log(''); + logger.log(''); } bootstrap(); diff --git a/apps/api/src/middlewares/html-template.middleware.ts b/apps/api/src/middlewares/html-template.middleware.ts index 2b8820e81..c256ada56 100644 --- a/apps/api/src/middlewares/html-template.middleware.ts +++ b/apps/api/src/middlewares/html-template.middleware.ts @@ -92,6 +92,8 @@ const locales = { @Injectable() export class HtmlTemplateMiddleware implements NestMiddleware { + private readonly logger = new Logger(HtmlTemplateMiddleware.name); + private indexHtmlMap: { [languageCode: string]: string } = {}; public constructor(private readonly i18nService: I18nService) { @@ -107,11 +109,7 @@ export class HtmlTemplateMiddleware implements NestMiddleware { {} ); } catch (error) { - Logger.error( - 'Failed to initialize index HTML map', - error, - 'HTMLTemplateMiddleware' - ); + this.logger.error('Failed to initialize index HTML map', error); } } diff --git a/apps/api/src/services/benchmark/benchmark.service.ts b/apps/api/src/services/benchmark/benchmark.service.ts index 4b1d9a65f..022a0e928 100644 --- a/apps/api/src/services/benchmark/benchmark.service.ts +++ b/apps/api/src/services/benchmark/benchmark.service.ts @@ -28,6 +28,8 @@ import { BenchmarkValue } from './interfaces/benchmark-value.interface'; @Injectable() export class BenchmarkService { + private readonly logger = new Logger(BenchmarkService.name); + private readonly CACHE_KEY_BENCHMARKS = 'BENCHMARKS'; public constructor( @@ -87,7 +89,7 @@ export class BenchmarkService { const { benchmarks, expiration }: BenchmarkValue = JSON.parse(cachedBenchmarkValue); - Logger.debug('Fetched benchmarks from cache', 'BenchmarkService'); + this.logger.debug('Fetched benchmarks from cache'); if (isAfter(new Date(), new Date(expiration))) { this.calculateAndCacheBenchmarks({ @@ -227,7 +229,7 @@ export class BenchmarkService { private async calculateAndCacheBenchmarks({ enableSharing = false }): Promise { - Logger.debug('Calculate benchmarks', 'BenchmarkService'); + this.logger.debug('Calculate benchmarks'); const benchmarkAssetProfiles = await this.getBenchmarkAssetProfiles({ enableSharing diff --git a/apps/api/src/services/data-provider/coingecko/coingecko.service.ts b/apps/api/src/services/data-provider/coingecko/coingecko.service.ts index b01ba177b..5d6ed79aa 100644 --- a/apps/api/src/services/data-provider/coingecko/coingecko.service.ts +++ b/apps/api/src/services/data-provider/coingecko/coingecko.service.ts @@ -29,6 +29,8 @@ import { format, fromUnixTime, getUnixTime } from 'date-fns'; @Injectable() export class CoinGeckoService implements DataProviderInterface, OnModuleInit { + private readonly logger = new Logger(CoinGeckoService.name); + private apiUrl: string; private headers: HeadersInit = {}; @@ -88,7 +90,7 @@ export class CoinGeckoService implements DataProviderInterface, OnModuleInit { ).toFixed(3)} seconds`; } - Logger.error(message, 'CoinGeckoService'); + this.logger.error(message); } return response; @@ -214,7 +216,7 @@ export class CoinGeckoService implements DataProviderInterface, OnModuleInit { ).toFixed(3)} seconds`; } - Logger.error(message, 'CoinGeckoService'); + this.logger.error(message); } return response; @@ -262,7 +264,7 @@ export class CoinGeckoService implements DataProviderInterface, OnModuleInit { ).toFixed(3)} seconds`; } - Logger.error(message, 'CoinGeckoService'); + this.logger.error(message); } return { items }; diff --git a/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts b/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts index eeccf725e..a74aaeb46 100644 --- a/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts +++ b/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts @@ -11,6 +11,8 @@ import { countries } from 'countries-list'; @Injectable() export class TrackinsightDataEnhancerService implements DataEnhancerInterface { + private readonly logger = new Logger(TrackinsightDataEnhancerService.name); + private static baseUrl = 'https://www.trackinsight.com/data-api'; private static countriesMapping = { 'Russian Federation': 'Russia', @@ -209,9 +211,8 @@ export class TrackinsightDataEnhancerService implements DataEnhancerInterface { return undefined; }) .catch(({ message }) => { - Logger.error( - `Failed to search Trackinsight symbol for ${symbol} (${message})`, - 'TrackinsightDataEnhancerService' + this.logger.error( + `Failed to search Trackinsight symbol for ${symbol} (${message})` ); return undefined; diff --git a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts index 30ad81c09..034916a5f 100644 --- a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts +++ b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts @@ -23,6 +23,8 @@ import type { Price } from 'yahoo-finance2/esm/src/modules/quoteSummary-iface'; @Injectable() export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { + private readonly logger = new Logger(YahooFinanceDataEnhancerService.name); + private readonly yahooFinance = new YahooFinance({ suppressNotices: ['yahooSurvey'] }); @@ -123,7 +125,7 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { response.url = url; } } catch (error) { - Logger.error(error, 'YahooFinanceDataEnhancerService'); + this.logger.error(error); } return response; @@ -266,7 +268,7 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { `No data found, ${aSymbol} (${this.getName()}) may be delisted` ); } else { - Logger.error(error, 'YahooFinanceService'); + this.logger.error(error); } } diff --git a/apps/api/src/services/data-provider/data-provider.service.ts b/apps/api/src/services/data-provider/data-provider.service.ts index 5f0a6928a..1ea2d6436 100644 --- a/apps/api/src/services/data-provider/data-provider.service.ts +++ b/apps/api/src/services/data-provider/data-provider.service.ts @@ -41,6 +41,8 @@ import { AssetProfileInvalidError } from './errors/asset-profile-invalid.error'; @Injectable() export class DataProviderService implements OnModuleInit { + private readonly logger = new Logger(DataProviderService.name); + private dataProviderMapping: { [dataProviderName: string]: string }; public constructor( @@ -129,7 +131,7 @@ export class DataProviderService implements OnModuleInit { ); } } catch (error) { - Logger.error(error, 'DataProviderService'); + this.logger.error(error); throw error; } @@ -391,7 +393,7 @@ export class DataProviderService implements OnModuleInit { return r; }, {}); } catch (error) { - Logger.error(error, 'DataProviderService'); + this.logger.error(error); } finally { return response; } @@ -503,7 +505,7 @@ export class DataProviderService implements OnModuleInit { result[symbol] = data; } } catch (error) { - Logger.error(error, 'DataProviderService'); + this.logger.error(error); throw error; } @@ -567,13 +569,12 @@ export class DataProviderService implements OnModuleInit { const numberOfItemsInCache = Object.keys(response)?.length; if (numberOfItemsInCache) { - Logger.debug( + this.logger.debug( `Fetched ${numberOfItemsInCache} quote${ numberOfItemsInCache > 1 ? 's' : '' } from cache in ${((performance.now() - startTimeTotal) / 1000).toFixed( 3 - )} seconds`, - 'DataProviderService' + )} seconds` ); } @@ -684,14 +685,13 @@ export class DataProviderService implements OnModuleInit { } } - Logger.debug( + this.logger.debug( `Fetched ${symbolsChunk.length} quote${ symbolsChunk.length > 1 ? 's' : '' } from ${dataSource} in ${( (performance.now() - startTimeDataSource) / 1000 - ).toFixed(3)} seconds`, - 'DataProviderService' + ).toFixed(3)} seconds` ); try { @@ -722,15 +722,18 @@ export class DataProviderService implements OnModuleInit { await Promise.all(promises); - Logger.debug('--------------------------------------------------------'); - Logger.debug( + this.logger.debug( + '--------------------------------------------------------' + ); + this.logger.debug( `Fetched ${items.length} quote${items.length > 1 ? 's' : ''} in ${( (performance.now() - startTimeTotal) / 1000 - ).toFixed(3)} seconds`, - 'DataProviderService' + ).toFixed(3)} seconds` + ); + this.logger.debug( + '========================================================' ); - Logger.debug('========================================================'); return response; } diff --git a/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts b/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts index 3fa38842b..06173c25b 100644 --- a/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts +++ b/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts @@ -37,6 +37,8 @@ import { isNumber } from 'lodash'; export class EodHistoricalDataService implements DataProviderInterface, OnModuleInit { + private readonly logger = new Logger(EodHistoricalDataService.name); + private apiKey: string; private readonly URL = 'https://eodhistoricaldata.com/api'; @@ -127,12 +129,11 @@ export class EodHistoricalDataService return response; } catch (error) { - Logger.error( + this.logger.error( `Could not get dividends for ${symbol} (${this.getName()}) from ${format( from, DATE_FORMAT - )} to ${format(to, DATE_FORMAT)}: [${error.name}] ${error.message}`, - 'EodHistoricalDataService' + )} to ${format(to, DATE_FORMAT)}: [${error.name}] ${error.message}` ); return {}; @@ -172,9 +173,8 @@ export class EodHistoricalDataService marketPrice: adjusted_close }; } else { - Logger.error( - `Could not get historical market data for ${symbol} (${this.getName()}) at ${date}`, - 'EodHistoricalDataService' + this.logger.error( + `Could not get historical market data for ${symbol} (${this.getName()}) at ${date}` ); } @@ -292,9 +292,8 @@ export class EodHistoricalDataService dataSource: this.getName() }; } else { - Logger.error( - `Could not get quote for ${this.convertFromEodSymbol(code)} (${this.getName()})`, - 'EodHistoricalDataService' + this.logger.error( + `Could not get quote for ${this.convertFromEodSymbol(code)} (${this.getName()})` ); } } @@ -311,7 +310,7 @@ export class EodHistoricalDataService ).toFixed(3)} seconds`; } - Logger.error(message, 'EodHistoricalDataService'); + this.logger.error(message); } return {}; @@ -465,7 +464,7 @@ export class EodHistoricalDataService ).toFixed(3)} seconds`; } - Logger.error(message, 'EodHistoricalDataService'); + this.logger.error(message); } return searchResult; diff --git a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts index fa36a0d17..80eeadeb0 100644 --- a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts +++ b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts @@ -49,6 +49,8 @@ import { uniqBy } from 'lodash'; export class FinancialModelingPrepService implements DataProviderInterface, OnModuleInit { + private readonly logger = new Logger(FinancialModelingPrepService.name); + private static countriesMapping = { 'Korea (the Republic of)': 'South Korea', 'Russian Federation': 'Russia', @@ -265,7 +267,7 @@ export class FinancialModelingPrepService ).toFixed(3)} seconds`; } - Logger.error(message, 'FinancialModelingPrepService'); + this.logger.error(message); } return response; @@ -325,12 +327,11 @@ export class FinancialModelingPrepService return response; } catch (error) { - Logger.error( + this.logger.error( `Could not get dividends for ${symbol} (${this.getName()}) from ${format( from, DATE_FORMAT - )} to ${format(to, DATE_FORMAT)}: [${error.name}] ${error.message}`, - 'FinancialModelingPrepService' + )} to ${format(to, DATE_FORMAT)}: [${error.name}] ${error.message}` ); return {}; @@ -518,7 +519,7 @@ export class FinancialModelingPrepService ).toFixed(3)} seconds`; } - Logger.error(message, 'FinancialModelingPrepService'); + this.logger.error(message); } return response; @@ -638,7 +639,7 @@ export class FinancialModelingPrepService ).toFixed(3)} seconds`; } - Logger.error(message, 'FinancialModelingPrepService'); + this.logger.error(message); } return { items }; diff --git a/apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts b/apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts index 2f2601d5d..2b91855a6 100644 --- a/apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts +++ b/apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts @@ -33,6 +33,8 @@ import { StatusCodes } from 'http-status-codes'; @Injectable() export class GhostfolioService implements DataProviderInterface { + private readonly logger = new Logger(GhostfolioService.name); + private readonly URL = environment.production ? 'https://ghostfol.io/api' : `${this.configurationService.get('ROOT_URL')}/api`; @@ -89,7 +91,7 @@ export class GhostfolioService implements DataProviderInterface { 'RequestError: The API key is invalid. Please update it in the Settings section of the Admin Control panel.'; } - Logger.error(message, 'GhostfolioService'); + this.logger.error(message); } return assetProfile; @@ -154,7 +156,7 @@ export class GhostfolioService implements DataProviderInterface { 'RequestError: The API key is invalid. Please update it in the Settings section of the Admin Control panel.'; } - Logger.error(message, 'GhostfolioService'); + this.logger.error(message); } return dividends; @@ -211,7 +213,7 @@ export class GhostfolioService implements DataProviderInterface { 'RequestError: The API key is invalid. Please update it in the Settings section of the Admin Control panel.'; } - Logger.error(error.message, 'GhostfolioService'); + this.logger.error(error.message); throw new Error( `Could not get historical market data for ${symbol} (${this.getName()}) from ${format( @@ -283,7 +285,7 @@ export class GhostfolioService implements DataProviderInterface { 'RequestError: The API key is invalid. Please update it in the Settings section of the Admin Control panel.'; } - Logger.error(message, 'GhostfolioService'); + this.logger.error(message); } return quotes; @@ -338,7 +340,7 @@ export class GhostfolioService implements DataProviderInterface { 'RequestError: The API key is invalid. Please update it in the Settings section of the Admin Control panel.'; } - Logger.error(message, 'GhostfolioService'); + this.logger.error(message); } return searchResult; diff --git a/apps/api/src/services/data-provider/google-sheets/google-sheets.service.ts b/apps/api/src/services/data-provider/google-sheets/google-sheets.service.ts index ba1e5bbe5..13f671bd4 100644 --- a/apps/api/src/services/data-provider/google-sheets/google-sheets.service.ts +++ b/apps/api/src/services/data-provider/google-sheets/google-sheets.service.ts @@ -24,6 +24,8 @@ import { GoogleSpreadsheet } from 'google-spreadsheet'; @Injectable() export class GoogleSheetsService implements DataProviderInterface { + private readonly logger = new Logger(GoogleSheetsService.name); + public constructor( private readonly configurationService: ConfigurationService, private readonly prismaService: PrismaService, @@ -144,7 +146,7 @@ export class GoogleSheetsService implements DataProviderInterface { return response; } catch (error) { - Logger.error(error, 'GoogleSheetsService'); + this.logger.error(error); } return {}; diff --git a/apps/api/src/services/data-provider/manual/manual.service.ts b/apps/api/src/services/data-provider/manual/manual.service.ts index 11e0aae6a..87e116dda 100644 --- a/apps/api/src/services/data-provider/manual/manual.service.ts +++ b/apps/api/src/services/data-provider/manual/manual.service.ts @@ -31,6 +31,8 @@ import { addDays, format, isBefore } from 'date-fns'; @Injectable() export class ManualService implements DataProviderInterface { + private readonly logger = new Logger(ManualService.name); + public constructor( private readonly configurationService: ConfigurationService, private readonly fetchService: FetchService, @@ -181,9 +183,8 @@ export class ManualService implements DataProviderInterface { }); return { marketPrice, symbol }; } catch (error) { - Logger.error( - `Could not get quote for ${symbol} (${this.getName()}): [${error.name}] ${error.message}`, - 'ManualService' + this.logger.error( + `Could not get quote for ${symbol} (${this.getName()}): [${error.name}] ${error.message}` ); return { symbol, marketPrice: undefined }; } @@ -216,7 +217,7 @@ export class ManualService implements DataProviderInterface { return response; } catch (error) { - Logger.error(error, 'ManualService'); + this.logger.error(error); } return {}; diff --git a/apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts b/apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts index 22896cccc..9941ae9eb 100644 --- a/apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts +++ b/apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts @@ -26,6 +26,8 @@ import { format } from 'date-fns'; @Injectable() export class RapidApiService implements DataProviderInterface { + private readonly logger = new Logger(RapidApiService.name); + public constructor( private readonly configurationService: ConfigurationService, private readonly fetchService: FetchService @@ -122,7 +124,7 @@ export class RapidApiService implements DataProviderInterface { }; } } catch (error) { - Logger.error(error, 'RapidApiService'); + this.logger.error(error); } return {}; @@ -167,7 +169,7 @@ export class RapidApiService implements DataProviderInterface { ).toFixed(3)} seconds`; } - Logger.error(message, 'RapidApiService'); + this.logger.error(message); return undefined; } diff --git a/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts b/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts index de8807098..93949ebc0 100644 --- a/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts +++ b/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts @@ -41,6 +41,8 @@ import { SearchQuoteNonYahoo } from 'yahoo-finance2/esm/src/modules/search'; @Injectable() export class YahooFinanceService implements DataProviderInterface { + private readonly logger = new Logger(YahooFinanceService.name); + private readonly yahooFinance = new YahooFinance({ suppressNotices: ['yahooSurvey'] }); @@ -105,12 +107,11 @@ export class YahooFinanceService implements DataProviderInterface { return response; } catch (error) { - Logger.error( + this.logger.error( `Could not get dividends for ${symbol} (${this.getName()}) from ${format( from, DATE_FORMAT - )} to ${format(to, DATE_FORMAT)}: [${error.name}] ${error.message}`, - 'YahooFinanceService' + )} to ${format(to, DATE_FORMAT)}: [${error.name}] ${error.message}` ); return {}; @@ -198,12 +199,9 @@ export class YahooFinanceService implements DataProviderInterface { try { quotes = await this.yahooFinance.quote(yahooFinanceSymbols); } catch (error) { - Logger.error(error, 'YahooFinanceService'); + this.logger.error(error); - Logger.warn( - 'Fallback to yahooFinance.quoteSummary()', - 'YahooFinanceService' - ); + this.logger.warn('Fallback to yahooFinance.quoteSummary()'); quotes = await this.getQuotesWithQuoteSummary(yahooFinanceSymbols); } @@ -229,7 +227,7 @@ export class YahooFinanceService implements DataProviderInterface { return response; } catch (error) { - Logger.error(error, 'YahooFinanceService'); + this.logger.error(error); return {}; } @@ -334,7 +332,7 @@ export class YahooFinanceService implements DataProviderInterface { }); } } catch (error) { - Logger.error(error, 'YahooFinanceService'); + this.logger.error(error); } return { items }; @@ -365,10 +363,7 @@ export class YahooFinanceService implements DataProviderInterface { .filter( (result): result is PromiseFulfilledResult => { if (result.status === 'rejected') { - Logger.error( - `Could not get quote summary: ${result.reason}`, - 'YahooFinanceService' - ); + this.logger.error(`Could not get quote summary: ${result.reason}`); return false; } diff --git a/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts b/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts index 024bdf4e1..708bfa591 100644 --- a/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts +++ b/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts @@ -30,6 +30,8 @@ import { ExchangeRatesByCurrency } from './interfaces/exchange-rate-data.interfa @Injectable() export class ExchangeRateDataService { + private readonly logger = new Logger(ExchangeRateDataService.name); + private currencies: string[] = []; private currencyPairs: DataGatheringItem[] = []; private derivedCurrencyFactors: { [currencyPair: string]: number } = {}; @@ -110,9 +112,8 @@ export class ExchangeRateDataService { previousExchangeRate; if (currency === DEFAULT_CURRENCY && isBefore(date, new Date())) { - Logger.error( - `No exchange rate has been found for ${currency}${targetCurrency} at ${dateString}`, - 'ExchangeRateDataService' + this.logger.error( + `No exchange rate has been found for ${currency}${targetCurrency} at ${dateString}` ); } } else { @@ -253,9 +254,8 @@ export class ExchangeRateDataService { } // Fallback with error, if currencies are not available - Logger.error( - `No exchange rate has been found for ${aFromCurrency}${aToCurrency}`, - 'ExchangeRateDataService' + this.logger.error( + `No exchange rate has been found for ${aFromCurrency}${aToCurrency}` ); return aValue; @@ -341,12 +341,11 @@ export class ExchangeRateDataService { return factor * aValue; } - Logger.error( + this.logger.error( `No exchange rate has been found for ${aFromCurrency}${aToCurrency} at ${format( aDate, DATE_FORMAT - )}`, - 'ExchangeRateDataService' + )}` ); return undefined; @@ -483,7 +482,7 @@ export class ExchangeRateDataService { errorMessage = `${errorMessage} and ${DEFAULT_CURRENCY}${currencyTo}`; } - Logger.error(`${errorMessage}.`, 'ExchangeRateDataService'); + this.logger.error(`${errorMessage}.`); } } } diff --git a/apps/api/src/services/fetch/fetch.service.ts b/apps/api/src/services/fetch/fetch.service.ts index f32e56a1c..31034f81c 100644 --- a/apps/api/src/services/fetch/fetch.service.ts +++ b/apps/api/src/services/fetch/fetch.service.ts @@ -15,6 +15,8 @@ import { WebFetchRoute } from './interfaces/web-fetch-route.interface'; @Injectable() export class FetchService implements OnModuleInit { + private readonly logger = new Logger(FetchService.name); + private static readonly REDACTED_QUERY_PARAM_NAMES = ['apikey', 'api_token']; private static readonly WEB_FETCH_TIMEOUT = ms('30 seconds'); @@ -39,7 +41,7 @@ export class FetchService implements OnModuleInit { const url = input instanceof Request ? input.url : input.toString(); const urlRedacted = this.redactUrl(url); - Logger.debug(`${method} ${urlRedacted}`, 'FetchService'); + this.logger.debug(`${method} ${urlRedacted}`); if (method === 'GET') { const webFetchRoute = this.getMatchingWebFetchRoute(url); @@ -60,15 +62,11 @@ export class FetchService implements OnModuleInit { return await globalThis.fetch(input, init); } catch (error) { if (error instanceof Error) { - Logger.error( - `${method} ${urlRedacted} failed: [${error.name}] ${error.message}`, - 'FetchService' + this.logger.error( + `${method} ${urlRedacted} failed: [${error.name}] ${error.message}` ); } else { - Logger.error( - `${method} ${urlRedacted} failed: ${String(error)}`, - 'FetchService' - ); + this.logger.error(`${method} ${urlRedacted} failed: ${String(error)}`); } throw error; @@ -145,10 +143,7 @@ export class FetchService implements OnModuleInit { } } - Logger.debug( - `Routed ${this.redactUrl(url)} via web fetch tool`, - 'FetchService' - ); + this.logger.debug(`Routed ${this.redactUrl(url)} via web fetch tool`); return new Response(body, { headers: webFetchRoute.responseContentType @@ -159,11 +154,10 @@ export class FetchService implements OnModuleInit { return undefined; } catch (error) { - Logger.error( + this.logger.error( `Web fetch tool failed for ${this.redactUrl(url)}: ${ error instanceof Error ? error.message : String(error) - }`, - 'FetchService' + }` ); return undefined; diff --git a/apps/api/src/services/i18n/i18n.service.ts b/apps/api/src/services/i18n/i18n.service.ts index 1cdb811a9..65c51b2f0 100644 --- a/apps/api/src/services/i18n/i18n.service.ts +++ b/apps/api/src/services/i18n/i18n.service.ts @@ -7,6 +7,8 @@ import { join } from 'node:path'; @Injectable() export class I18nService implements OnModuleInit { + private readonly logger = new Logger(I18nService.name); + private localesPath = join(__dirname, 'assets', 'locales'); private translations: { [locale: string]: cheerio.CheerioAPI } = {}; @@ -26,7 +28,7 @@ export class I18nService implements OnModuleInit { const $ = this.translations[languageCode]; if (!$) { - Logger.warn(`Translation not found for locale '${languageCode}'`); + this.logger.warn(`Translation not found for locale '${languageCode}'`); } let translatedText = $( @@ -36,7 +38,7 @@ export class I18nService implements OnModuleInit { ).text(); if (!translatedText) { - Logger.warn( + this.logger.warn( `Translation not found for id '${id}' in locale '${languageCode}'` ); } @@ -60,7 +62,7 @@ export class I18nService implements OnModuleInit { this.parseXml(xmlData); } } catch (error) { - Logger.error(error, 'I18nService'); + this.logger.error(error); } } diff --git a/apps/api/src/services/prisma/prisma.service.ts b/apps/api/src/services/prisma/prisma.service.ts index cdbc1cdfd..ebbd3afd4 100644 --- a/apps/api/src/services/prisma/prisma.service.ts +++ b/apps/api/src/services/prisma/prisma.service.ts @@ -14,6 +14,8 @@ export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy { + private readonly logger = new Logger(PrismaService.name); + public constructor(configService: ConfigService) { const adapter = new PrismaPg({ connectionString: configService.get('DATABASE_URL') @@ -43,7 +45,7 @@ export class PrismaService try { await this.$connect(); } catch (error) { - Logger.error(error, 'PrismaService'); + this.logger.error(error); } } diff --git a/apps/api/src/services/queues/data-gathering/data-gathering.processor.ts b/apps/api/src/services/queues/data-gathering/data-gathering.processor.ts index 1a4038652..ee5cb838a 100644 --- a/apps/api/src/services/queues/data-gathering/data-gathering.processor.ts +++ b/apps/api/src/services/queues/data-gathering/data-gathering.processor.ts @@ -32,6 +32,8 @@ import { DataGatheringService } from './data-gathering.service'; @Injectable() @Processor(DATA_GATHERING_QUEUE) export class DataGatheringProcessor { + private readonly logger = new Logger(DataGatheringProcessor.name); + public constructor( private readonly dataGatheringService: DataGatheringService, private readonly dataProviderService: DataProviderService, @@ -51,16 +53,14 @@ export class DataGatheringProcessor { const { dataSource, symbol } = job.data; try { - Logger.log( - `Asset profile data gathering has been started for ${symbol} (${dataSource})`, - `DataGatheringProcessor (${GATHER_ASSET_PROFILE_PROCESS_JOB_NAME})` + this.logger.log( + `Asset profile data gathering has been started for ${symbol} (${dataSource})` ); await this.dataGatheringService.gatherAssetProfiles([job.data]); - Logger.log( - `Asset profile data gathering has been completed for ${symbol} (${dataSource})`, - `DataGatheringProcessor (${GATHER_ASSET_PROFILE_PROCESS_JOB_NAME})` + this.logger.log( + `Asset profile data gathering has been completed for ${symbol} (${dataSource})` ); } catch (error) { if (error instanceof AssetProfileDelistedError) { @@ -74,18 +74,14 @@ export class DataGatheringProcessor { } ); - Logger.log( - `Asset profile data gathering has been discarded for ${symbol} (${dataSource})`, - `DataGatheringProcessor (${GATHER_ASSET_PROFILE_PROCESS_JOB_NAME})` + this.logger.log( + `Asset profile data gathering has been discarded for ${symbol} (${dataSource})` ); return job.discard(); } - Logger.error( - error, - `DataGatheringProcessor (${GATHER_ASSET_PROFILE_PROCESS_JOB_NAME})` - ); + this.logger.error(error); throw error; } @@ -105,12 +101,11 @@ export class DataGatheringProcessor { try { let currentDate = parseISO(date as unknown as string); - Logger.log( + this.logger.log( `Historical market data gathering has been started for ${symbol} (${dataSource}) at ${format( currentDate, DATE_FORMAT - )}${force ? ' (forced update)' : ''}`, - `DataGatheringProcessor (${GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_NAME})` + )}${force ? ' (forced update)' : ''}` ); const historicalData = await this.dataProviderService.getHistoricalRaw({ @@ -167,12 +162,11 @@ export class DataGatheringProcessor { await this.marketDataService.updateMany({ data }); } - Logger.log( + this.logger.log( `Historical market data gathering has been completed for ${symbol} (${dataSource}) at ${format( currentDate, DATE_FORMAT - )}`, - `DataGatheringProcessor (${GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_NAME})` + )}` ); } catch (error) { if (error instanceof AssetProfileDelistedError) { @@ -186,18 +180,14 @@ export class DataGatheringProcessor { } ); - Logger.log( - `Historical market data gathering has been discarded for ${symbol} (${dataSource})`, - `DataGatheringProcessor (${GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_NAME})` + this.logger.log( + `Historical market data gathering has been discarded for ${symbol} (${dataSource})` ); return job.discard(); } - Logger.error( - error, - `DataGatheringProcessor (${GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_NAME})` - ); + this.logger.error(error); throw error; } diff --git a/apps/api/src/services/queues/data-gathering/data-gathering.service.ts b/apps/api/src/services/queues/data-gathering/data-gathering.service.ts index cec63c3eb..51f609d22 100644 --- a/apps/api/src/services/queues/data-gathering/data-gathering.service.ts +++ b/apps/api/src/services/queues/data-gathering/data-gathering.service.ts @@ -34,6 +34,8 @@ import ms, { StringValue } from 'ms'; @Injectable() export class DataGatheringService { + private readonly logger = new Logger(DataGatheringService.name); + public constructor( @Inject('DataEnhancers') private readonly dataEnhancers: DataEnhancerInterface[], @@ -145,7 +147,7 @@ export class DataGatheringService { }); } } catch (error) { - Logger.error(error, 'DataGatheringService'); + this.logger.error(error); } finally { return undefined; } @@ -187,12 +189,11 @@ export class DataGatheringService { symbol: symbolMapping?.[dataEnhancer.getName()] ?? symbol }); } catch (error) { - Logger.error( + this.logger.error( `Failed to enhance data for ${symbol} (${ assetProfile.dataSource }) by ${dataEnhancer.getName()}`, - error, - 'DataGatheringService' + error ); } } @@ -256,11 +257,7 @@ export class DataGatheringService { } }); } catch (error) { - Logger.error( - `${symbol}: ${error?.meta?.cause}`, - error, - 'DataGatheringService' - ); + this.logger.error(`${symbol}: ${error?.meta?.cause}`, error); if (assetProfileIdentifiers.length === 1) { throw error; diff --git a/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts b/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts index f3aa6e77e..cf94a9d2b 100644 --- a/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts +++ b/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts @@ -21,6 +21,8 @@ import { PortfolioSnapshotQueueJob } from './interfaces/portfolio-snapshot-queue @Injectable() @Processor(PORTFOLIO_SNAPSHOT_COMPUTATION_QUEUE) export class PortfolioSnapshotProcessor { + private readonly logger = new Logger(PortfolioSnapshotProcessor.name); + public constructor( private readonly accountBalanceService: AccountBalanceService, private readonly activitiesService: ActivitiesService, @@ -41,9 +43,8 @@ export class PortfolioSnapshotProcessor { try { const startTime = performance.now(); - Logger.log( - `Portfolio snapshot calculation of user '${job.data.userId}' has been started`, - `PortfolioSnapshotProcessor (${PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME})` + this.logger.log( + `Portfolio snapshot calculation of user '${job.data.userId}' has been started` ); const { activities } = @@ -72,12 +73,11 @@ export class PortfolioSnapshotProcessor { const snapshot = await portfolioCalculator.computeSnapshot(); - Logger.log( + this.logger.log( `Portfolio snapshot calculation of user '${job.data.userId}' has been completed in ${( (performance.now() - startTime) / 1000 - ).toFixed(3)} seconds`, - `PortfolioSnapshotProcessor (${PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME})` + ).toFixed(3)} seconds` ); const expiration = addMilliseconds( @@ -101,10 +101,7 @@ export class PortfolioSnapshotProcessor { return snapshot; } catch (error) { - Logger.error( - error, - `PortfolioSnapshotProcessor (${PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME})` - ); + this.logger.error(error); throw new Error(error); } diff --git a/apps/api/src/services/queues/statistics-gathering/statistics-gathering.processor.ts b/apps/api/src/services/queues/statistics-gathering/statistics-gathering.processor.ts index a523ef4f2..7eefc101f 100644 --- a/apps/api/src/services/queues/statistics-gathering/statistics-gathering.processor.ts +++ b/apps/api/src/services/queues/statistics-gathering/statistics-gathering.processor.ts @@ -27,6 +27,8 @@ import { format, subDays } from 'date-fns'; @Injectable() @Processor(STATISTICS_GATHERING_QUEUE) export class StatisticsGatheringProcessor { + private readonly logger = new Logger(StatisticsGatheringProcessor.name); + public constructor( private readonly configurationService: ConfigurationService, private readonly fetchService: FetchService, @@ -35,10 +37,7 @@ export class StatisticsGatheringProcessor { @Process(GATHER_STATISTICS_DOCKER_HUB_PULLS_PROCESS_JOB_NAME) public async gatherDockerHubPullsStatistics() { - Logger.log( - 'Docker Hub pulls statistics gathering has been started', - 'StatisticsGatheringProcessor' - ); + this.logger.log('Docker Hub pulls statistics gathering has been started'); const dockerHubPulls = await this.countDockerHubPulls(); @@ -47,17 +46,13 @@ export class StatisticsGatheringProcessor { value: String(dockerHubPulls) }); - Logger.log( - 'Docker Hub pulls statistics gathering has been completed', - 'StatisticsGatheringProcessor' - ); + this.logger.log('Docker Hub pulls statistics gathering has been completed'); } @Process(GATHER_STATISTICS_GITHUB_CONTRIBUTORS_PROCESS_JOB_NAME) public async gatherGitHubContributorsStatistics() { - Logger.log( - 'GitHub contributors statistics gathering has been started', - 'StatisticsGatheringProcessor' + this.logger.log( + 'GitHub contributors statistics gathering has been started' ); const gitHubContributors = await this.countGitHubContributors(); @@ -67,18 +62,14 @@ export class StatisticsGatheringProcessor { value: String(gitHubContributors) }); - Logger.log( - 'GitHub contributors statistics gathering has been completed', - 'StatisticsGatheringProcessor' + this.logger.log( + 'GitHub contributors statistics gathering has been completed' ); } @Process(GATHER_STATISTICS_GITHUB_STARGAZERS_PROCESS_JOB_NAME) public async gatherGitHubStargazersStatistics() { - Logger.log( - 'GitHub stargazers statistics gathering has been started', - 'StatisticsGatheringProcessor' - ); + this.logger.log('GitHub stargazers statistics gathering has been started'); const gitHubStargazers = await this.countGitHubStargazers(); @@ -87,9 +78,8 @@ export class StatisticsGatheringProcessor { value: String(gitHubStargazers) }); - Logger.log( - 'GitHub stargazers statistics gathering has been completed', - 'StatisticsGatheringProcessor' + this.logger.log( + 'GitHub stargazers statistics gathering has been completed' ); } @@ -100,18 +90,14 @@ export class StatisticsGatheringProcessor { ); if (!monitorId) { - Logger.log( - `Uptime statistics gathering has been skipped as no ${PROPERTY_BETTER_UPTIME_MONITOR_ID} is configured`, - 'StatisticsGatheringProcessor' + this.logger.log( + `Uptime statistics gathering has been skipped as no ${PROPERTY_BETTER_UPTIME_MONITOR_ID} is configured` ); return; } - Logger.log( - 'Uptime statistics gathering has been started', - 'StatisticsGatheringProcessor' - ); + this.logger.log('Uptime statistics gathering has been started'); const uptime = await this.getUptime(monitorId); @@ -120,10 +106,7 @@ export class StatisticsGatheringProcessor { value: String(uptime) }); - Logger.log( - 'Uptime statistics gathering has been completed', - 'StatisticsGatheringProcessor' - ); + this.logger.log('Uptime statistics gathering has been completed'); } private async countDockerHubPulls(): Promise { @@ -139,7 +122,7 @@ export class StatisticsGatheringProcessor { return pull_count; } catch (error) { - Logger.error(error, 'StatisticsGatheringProcessor - DockerHub'); + this.logger.error(error); throw error; } @@ -169,7 +152,7 @@ export class StatisticsGatheringProcessor { value }); } catch (error) { - Logger.error(error, 'StatisticsGatheringProcessor - GitHub'); + this.logger.error(error); throw error; } @@ -188,7 +171,7 @@ export class StatisticsGatheringProcessor { return stargazers_count; } catch (error) { - Logger.error(error, 'StatisticsGatheringProcessor - GitHub'); + this.logger.error(error); throw error; } @@ -217,7 +200,7 @@ export class StatisticsGatheringProcessor { return data.attributes.availability / 100; } catch (error) { - Logger.error(error, 'StatisticsGatheringProcessor - Better Stack'); + this.logger.error(error); throw error; } diff --git a/apps/api/src/services/twitter-bot/twitter-bot.service.ts b/apps/api/src/services/twitter-bot/twitter-bot.service.ts index b424f7198..ffd0c5452 100644 --- a/apps/api/src/services/twitter-bot/twitter-bot.service.ts +++ b/apps/api/src/services/twitter-bot/twitter-bot.service.ts @@ -16,6 +16,8 @@ import { TwitterApi, TwitterApiReadWrite } from 'twitter-api-v2'; @Injectable() export class TwitterBotService implements OnModuleInit { + private readonly logger = new Logger(TwitterBotService.name); + private twitterClient: TwitterApiReadWrite; public constructor( @@ -71,13 +73,12 @@ export class TwitterBotService implements OnModuleInit { const { data: createdTweet } = await this.twitterClient.v2.tweet(status); - Logger.log( - `Fear & Greed Index has been posted: https://x.com/ghostfolio_/status/${createdTweet.id}`, - 'TwitterBotService' + this.logger.log( + `Fear & Greed Index has been posted: https://x.com/ghostfolio_/status/${createdTweet.id}` ); } } catch (error) { - Logger.error(error, 'TwitterBotService'); + this.logger.error(error); } }