mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
add debug config, refine and test coloredContext
This commit is contained in:
parent
bfa9367050
commit
6cf82ad87c
5
.github/workflows/test_config.yml
vendored
5
.github/workflows/test_config.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
||||
list-files: shell
|
||||
|
||||
build:
|
||||
name: typecheck - Config-Schema
|
||||
name: Unit Tests, typecheck - Config-Schema
|
||||
if: needs.files-changed.outputs.config == 'true' || needs.files-changed.outputs.docker-compose == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
@ -38,3 +38,6 @@ jobs:
|
||||
- name: typecheck
|
||||
run: cd config-schema && yarn typecheck
|
||||
|
||||
- name: unit tests
|
||||
run: cd config-schema && yarn test
|
||||
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,7 @@
|
||||
*.bak
|
||||
.turbo
|
||||
vite.config.mjs.timestamp-*
|
||||
log4js-config*.json
|
||||
/node_modules/*
|
||||
messages.pot
|
||||
nbproject
|
||||
|
||||
58
.vscode/launch.json
vendored
58
.vscode/launch.json
vendored
@ -4,13 +4,6 @@
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome",
|
||||
"url": "http://localhost:3000",
|
||||
"webRoot": "${workspaceFolder}/frontend"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
@ -27,6 +20,23 @@
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"cwd": "${workspaceFolder}/dht-node"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "DHT-Node Debug",
|
||||
"stopOnEntry": true,
|
||||
"runtimeExecutable": "yarn",
|
||||
"runtimeArgs": [
|
||||
"run",
|
||||
"dev"
|
||||
],
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"cwd": "${workspaceFolder}/dht-node"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
@ -42,6 +52,40 @@
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"cwd": "${workspaceFolder}/federation"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Federation Debug",
|
||||
"stopOnEntry": true,
|
||||
"runtimeExecutable": "yarn",
|
||||
"runtimeArgs": [
|
||||
"run",
|
||||
"dev"
|
||||
],
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"cwd": "${workspaceFolder}/federation"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Backend Debug",
|
||||
"stopOnEntry": true,
|
||||
"runtimeExecutable": "yarn",
|
||||
"runtimeArgs": [
|
||||
"run",
|
||||
"dev"
|
||||
],
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"cwd": "${workspaceFolder}/backend"
|
||||
}
|
||||
]
|
||||
}
|
||||
9
bun.lock
9
bun.lock
@ -105,6 +105,7 @@
|
||||
"@types/node": "^17.0.21",
|
||||
"@types/nodemailer": "^6.4.4",
|
||||
"@types/sodium-native": "^2.3.5",
|
||||
"@types/source-map-support": "^0.5.10",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"apollo-server-express": "^2.25.2",
|
||||
"apollo-server-testing": "^2.25.2",
|
||||
@ -143,6 +144,7 @@
|
||||
"random-bigint": "^0.0.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"regenerator-runtime": "^0.14.1",
|
||||
"source-map-support": "^0.5.21",
|
||||
"ts-jest": "27.0.5",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsconfig-paths": "^4.1.1",
|
||||
@ -161,6 +163,7 @@
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.2",
|
||||
"joi": "^17.13.3",
|
||||
"log4js": "^6.9.1",
|
||||
"source-map-support": "^0.5.21",
|
||||
"yoctocolors-cjs": "^2.1.2",
|
||||
"zod": "^3.25.61",
|
||||
@ -168,6 +171,7 @@
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
"@types/node": "^17.0.21",
|
||||
"jest": "27.2.4",
|
||||
"typescript": "^4.9.5",
|
||||
},
|
||||
},
|
||||
@ -279,6 +283,7 @@
|
||||
"nodemon": "^2.0.7",
|
||||
"prettier": "^3.5.3",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"source-map-support": "^0.5.21",
|
||||
"ts-jest": "27.0.5",
|
||||
"tsconfig-paths": "^4.1.1",
|
||||
"type-graphql": "^1.1.1",
|
||||
@ -1010,6 +1015,8 @@
|
||||
|
||||
"@types/sodium-native": ["@types/sodium-native@2.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-jZIg5ltGH1okmnH3FrLQsgwjcjOVozMSHwSiEm1/LpMekhOMHbQqp21P4H24mizh1BjwI6Q8qmphmD/HJuAqWg=="],
|
||||
|
||||
"@types/source-map-support": ["@types/source-map-support@0.5.10", "", { "dependencies": { "source-map": "^0.6.0" } }, "sha512-tgVP2H469x9zq34Z0m/fgPewGhg/MLClalNOiPIzQlXrSS2YrKu/xCdSCKnEDwkFha51VKEKB6A9wW26/ZNwzA=="],
|
||||
|
||||
"@types/stack-utils": ["@types/stack-utils@2.0.3", "", {}, "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="],
|
||||
|
||||
"@types/uuid": ["@types/uuid@8.3.4", "", {}, "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw=="],
|
||||
@ -3454,6 +3461,8 @@
|
||||
|
||||
"@types/sodium-native/@types/node": ["@types/node@18.19.96", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-PzBvgsZ7YdFs/Kng1BSW8IGv68/SPcOxYYhT7luxD7QyzIhFS1xPTpfK3K9eHBa7hVwlW+z8nN0mOd515yaduQ=="],
|
||||
|
||||
"@types/source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"@types/ws/@types/node": ["@types/node@18.19.96", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-PzBvgsZ7YdFs/Kng1BSW8IGv68/SPcOxYYhT7luxD7QyzIhFS1xPTpfK3K9eHBa7hVwlW+z8nN0mOd515yaduQ=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
"build": "esbuild src/index.ts --outdir=build --sourcemap --platform=node --target=node18.20.7 --bundle --packages=external",
|
||||
"build:bun": "bun build src/index.ts --outdir=build --target=bun --packages=external",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"test": "bun test",
|
||||
"lint": "biome check --error-on-warnings .",
|
||||
"lint:fix": "biome check --error-on-warnings . --write"
|
||||
},
|
||||
|
||||
@ -68,8 +68,7 @@ export function createAppenderConfig(
|
||||
}
|
||||
dateFile.layout = {
|
||||
type: 'coloredContext',
|
||||
withStack: appender.withStack,
|
||||
withFile: appender.withFile,
|
||||
...appender.layout,
|
||||
}
|
||||
customAppender[appender.name] = dateFile
|
||||
})
|
||||
|
||||
135
config-schema/src/log4js-config/coloredContext.test.ts
Normal file
135
config-schema/src/log4js-config/coloredContext.test.ts
Normal file
@ -0,0 +1,135 @@
|
||||
import { createColoredContextLayout } from './coloredContext'
|
||||
import { levels, LoggingEvent } from 'log4js'
|
||||
import colors from 'yoctocolors-cjs'
|
||||
|
||||
let defaultLogEvent: LoggingEvent
|
||||
let colorFn: (input: string) => string
|
||||
const startTime = new Date()
|
||||
const startTimeString = startTime.toISOString()
|
||||
|
||||
describe('createColoredContextLayout', () => {
|
||||
beforeEach(() => {
|
||||
defaultLogEvent = {
|
||||
level: levels.INFO,
|
||||
categoryName: 'config',
|
||||
data: ['message'],
|
||||
context: { user: 1 },
|
||||
startTime,
|
||||
fileName: 'file',
|
||||
lineNumber: 1,
|
||||
callStack: 'stack',
|
||||
pid: 1,
|
||||
serialise: () => {
|
||||
throw new Error('Function not implemented.')
|
||||
},
|
||||
}
|
||||
})
|
||||
it('returns a function', () => {
|
||||
expect(typeof createColoredContextLayout({})).toBe('function')
|
||||
})
|
||||
describe('level:info, color:green', () => {
|
||||
beforeEach(() => {
|
||||
defaultLogEvent.level = levels.INFO
|
||||
colorFn = colors.green
|
||||
})
|
||||
it('format with all undefined', () => {
|
||||
const coloredString = colorFn(`[${startTimeString}] [${levels.INFO}] config -`)
|
||||
expect(createColoredContextLayout({})(defaultLogEvent)).toBe(
|
||||
`${coloredString} user=1 message`,
|
||||
)
|
||||
})
|
||||
it('format with stack', () => {
|
||||
const coloredString = colorFn(`[${startTimeString}] [${levels.INFO}] config -`)
|
||||
expect(createColoredContextLayout({ withStack: true })(defaultLogEvent)).toBe(
|
||||
`${coloredString} user=1 message \nstack`,
|
||||
)
|
||||
})
|
||||
it('format with file', () => {
|
||||
const coloredString = colorFn(`[${startTimeString}] [${levels.INFO}] config -`)
|
||||
expect(createColoredContextLayout({ withFile: true })(defaultLogEvent)).toBe(
|
||||
`${coloredString} user=1 message \n at file:1`,
|
||||
)
|
||||
})
|
||||
it('format with file only if it where level:warn', () => {
|
||||
const coloredString = colorFn(`[${startTimeString}] [${levels.INFO}] config -`)
|
||||
expect(createColoredContextLayout({ withFile: 'warn' })(defaultLogEvent)).toBe(
|
||||
`${coloredString} user=1 message`,
|
||||
)
|
||||
})
|
||||
it('format with line', () => {
|
||||
const coloredString = colorFn(`[${startTimeString}] [${levels.INFO}] config:1 -`)
|
||||
expect(createColoredContextLayout({ withLine: true })(defaultLogEvent)).toBe(
|
||||
`${coloredString} user=1 message`,
|
||||
)
|
||||
})
|
||||
it('format with line only if it where level:warn', () => {
|
||||
const coloredString = colorFn(`[${startTimeString}] [${levels.INFO}] config -`)
|
||||
expect(createColoredContextLayout({ withLine: 'warn' })(defaultLogEvent)).toBe(
|
||||
`${coloredString} user=1 message`,
|
||||
)
|
||||
})
|
||||
it('format with file and line', () => {
|
||||
const coloredString = colorFn(`[${startTimeString}] [${levels.INFO}] config -`)
|
||||
expect(createColoredContextLayout({ withFile: true, withLine: true })(defaultLogEvent)).toBe(
|
||||
`${coloredString} user=1 message \n at file:1`,
|
||||
)
|
||||
})
|
||||
it('format withStack: error, withLine: true, withFile: warn', () => {
|
||||
const coloredString = colorFn(`[${startTimeString}] [${levels.INFO}] config:1 -`)
|
||||
expect(createColoredContextLayout({
|
||||
withStack: 'error',
|
||||
withFile: 'warn',
|
||||
withLine: true
|
||||
})(defaultLogEvent)).toBe(
|
||||
`${coloredString} user=1 message`,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('level:error, color:red', () => {
|
||||
beforeEach(() => {
|
||||
defaultLogEvent.level = levels.ERROR
|
||||
colorFn = colors.redBright
|
||||
})
|
||||
it('format with all undefined', () => {
|
||||
const coloredString = colorFn(`[${startTimeString}] [${levels.ERROR}] config -`)
|
||||
expect(createColoredContextLayout({})(defaultLogEvent)).toBe(
|
||||
`${coloredString} user=1 message`,
|
||||
)
|
||||
})
|
||||
it('format with stack', () => {
|
||||
const coloredString = colorFn(`[${startTimeString}] [${levels.ERROR}] config -`)
|
||||
expect(createColoredContextLayout({ withStack: true })(defaultLogEvent)).toBe(
|
||||
`${coloredString} user=1 message \nstack`,
|
||||
)
|
||||
})
|
||||
it('format with file', () => {
|
||||
const coloredString = colorFn(`[${startTimeString}] [${levels.ERROR}] config -`)
|
||||
expect(createColoredContextLayout({ withFile: true })(defaultLogEvent)).toBe(
|
||||
`${coloredString} user=1 message \n at file:1`,
|
||||
)
|
||||
})
|
||||
it('format with line', () => {
|
||||
const coloredString = colorFn(`[${startTimeString}] [${levels.ERROR}] config:1 -`)
|
||||
expect(createColoredContextLayout({ withLine: true })(defaultLogEvent)).toBe(
|
||||
`${coloredString} user=1 message`,
|
||||
)
|
||||
})
|
||||
it('format with file and line', () => {
|
||||
const coloredString = colorFn(`[${startTimeString}] [${levels.ERROR}] config -`)
|
||||
expect(createColoredContextLayout({ withFile: true, withLine: true })(defaultLogEvent)).toBe(
|
||||
`${coloredString} user=1 message \n at file:1`,
|
||||
)
|
||||
})
|
||||
it('format withStack: error, withLine: true, withFile: warn', () => {
|
||||
const coloredString = colorFn(`[${startTimeString}] [${levels.ERROR}] config -`)
|
||||
expect(createColoredContextLayout({
|
||||
withStack: 'error',
|
||||
withFile: 'warn',
|
||||
withLine: true
|
||||
})(defaultLogEvent)).toBe(
|
||||
`${coloredString} user=1 message \nstack`,
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -1,12 +1,6 @@
|
||||
import { Level, LoggingEvent } from 'log4js'
|
||||
import colors from 'yoctocolors-cjs'
|
||||
import { LogLevel } from './types'
|
||||
|
||||
export type coloredContextLayoutConfig = {
|
||||
withStack?: LogLevel | boolean
|
||||
withFile?: LogLevel | boolean
|
||||
withLine?: LogLevel | boolean
|
||||
}
|
||||
import { LogLevel, ColoredContextLayoutConfig } from './types'
|
||||
|
||||
function colorize(str: string, level: Level): string {
|
||||
switch (level.colour) {
|
||||
@ -36,12 +30,14 @@ function colorize(str: string, level: Level): string {
|
||||
// distinguish between objects with valid toString function (for examples classes derived from AbstractLoggingView) and other objects
|
||||
function composeDataString(data: (string | Object)[]): string {
|
||||
return data
|
||||
.map((data) => {
|
||||
.map((d) => {
|
||||
// if it is a object and his toString function return only garbage
|
||||
if (typeof data === 'object' && data.toString() === '[object Object]') {
|
||||
return JSON.stringify(data)
|
||||
if (typeof d === 'object' && d.toString() === '[object Object]') {
|
||||
return JSON.stringify(d)
|
||||
}
|
||||
if (d) {
|
||||
return d.toString()
|
||||
}
|
||||
return data.toString()
|
||||
})
|
||||
.join(' ')
|
||||
}
|
||||
@ -72,7 +68,7 @@ enum DetailKind {
|
||||
File = 'file',
|
||||
Line = 'line',
|
||||
}
|
||||
function resolveDetailKind(logEvent: LoggingEvent, config: coloredContextLayoutConfig): DetailKind | undefined {
|
||||
function resolveDetailKind(logEvent: LoggingEvent, config: ColoredContextLayoutConfig): DetailKind | undefined {
|
||||
if (logEvent.callStack && isEnabledByLogLevel(logEvent.level, config.withStack)) {
|
||||
return DetailKind.Callstack
|
||||
}
|
||||
@ -85,7 +81,7 @@ function resolveDetailKind(logEvent: LoggingEvent, config: coloredContextLayoutC
|
||||
return undefined
|
||||
}
|
||||
|
||||
export function createColoredContextLayout(config: coloredContextLayoutConfig) {
|
||||
export function createColoredContextLayout(config: ColoredContextLayoutConfig) {
|
||||
return (logEvent: LoggingEvent) => {
|
||||
const result: string[] = []
|
||||
const detailKind = resolveDetailKind(logEvent, config)
|
||||
|
||||
28
config-schema/src/log4js-config/index.test.ts
Normal file
28
config-schema/src/log4js-config/index.test.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { createLog4jsConfig, defaultCategory } from '.'
|
||||
|
||||
describe('createLog4jsConfig', () => {
|
||||
it('should create a log4js config', () => {
|
||||
const config = createLog4jsConfig([
|
||||
defaultCategory('test', 'debug')
|
||||
])
|
||||
expect(config).toBeDefined()
|
||||
expect(config.appenders).toBeDefined()
|
||||
expect(config.categories).toBeDefined()
|
||||
expect(config.appenders).toHaveProperty('test')
|
||||
expect(config.categories).toHaveProperty('test')
|
||||
expect(config.appenders.test).toMatchObject({
|
||||
type: 'dateFile',
|
||||
pattern: 'yyyy-MM-dd',
|
||||
compress: true,
|
||||
keepFileExt: true,
|
||||
fileNameSep: '_',
|
||||
numBackups: 30,
|
||||
filename: 'test.log',
|
||||
layout: {
|
||||
type: 'coloredContext',
|
||||
withStack: 'error',
|
||||
withLine: true
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -2,9 +2,11 @@ import { readFileSync, writeFileSync } from 'node:fs'
|
||||
import { Configuration, LoggingEvent, addLayout, configure } from 'log4js'
|
||||
import { createAppenderConfig } from './appenders'
|
||||
import { createColoredContextLayout } from './coloredContext'
|
||||
import { Category, CustomFileAppender, LogLevel, defaultCategory } from './types'
|
||||
import type { Category, CustomFileAppender, LogLevel } from './types'
|
||||
import { defaultCategory } from './types'
|
||||
|
||||
export { Category, LogLevel, defaultCategory }
|
||||
export type { Category, LogLevel }
|
||||
export { defaultCategory }
|
||||
|
||||
/**
|
||||
* Creates the log4js configuration.
|
||||
@ -33,8 +35,7 @@ export function createLog4jsConfig(categories: Category[], basePath?: string): C
|
||||
customFileAppenders.push({
|
||||
name: category.name,
|
||||
filename: category.filename,
|
||||
withLine: true,
|
||||
withStack: 'error',
|
||||
layout: category.layout,
|
||||
})
|
||||
// needed by log4js, show all error message accidentally without (proper) Category
|
||||
result.categories.default = {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { LogLevel } from './LogLevel'
|
||||
import { ColoredContextLayoutConfig } from './ColoredContextLayoutConfig'
|
||||
|
||||
/**
|
||||
* Configuration for a log4js category.
|
||||
@ -8,6 +9,7 @@ import { LogLevel } from './LogLevel'
|
||||
* @property {boolean} [stdout] - Whether to log to stdout.
|
||||
* @property {boolean} [additionalErrorsFile] - Whether to log errors additional to the default error file.
|
||||
* @property {LogLevel} level - The logging level.
|
||||
* @property {ColoredContextLayoutConfig} [layout] - The layout for the category.
|
||||
*/
|
||||
export type Category = {
|
||||
name: string
|
||||
@ -15,6 +17,7 @@ export type Category = {
|
||||
stdout?: boolean
|
||||
additionalErrorsFile?: boolean
|
||||
level: LogLevel
|
||||
layout?: ColoredContextLayoutConfig
|
||||
}
|
||||
|
||||
export function defaultCategory(name: string, level: LogLevel): Category {
|
||||
@ -23,5 +26,10 @@ export function defaultCategory(name: string, level: LogLevel): Category {
|
||||
level,
|
||||
stdout: true,
|
||||
additionalErrorsFile: true,
|
||||
layout: {
|
||||
withStack: 'error',
|
||||
withFile: 'warn',
|
||||
withLine: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
import { LogLevel } from './LogLevel'
|
||||
|
||||
export type ColoredContextLayoutConfig = {
|
||||
withStack?: LogLevel | boolean
|
||||
withFile?: LogLevel | boolean
|
||||
withLine?: LogLevel | boolean
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
import { LogLevel } from './LogLevel'
|
||||
import { ColoredContextLayoutConfig } from './ColoredContextLayoutConfig'
|
||||
/**
|
||||
* use default dateFile Template for custom file appenders
|
||||
*
|
||||
@ -29,7 +30,5 @@ import { LogLevel } from './LogLevel'
|
||||
export type CustomFileAppender = {
|
||||
name: string
|
||||
filename?: string
|
||||
withStack?: LogLevel | boolean // with stack if boolean or from log level on or above
|
||||
withFile?: LogLevel | boolean // with filename and line if boolean or from log level on or above
|
||||
withLine?: LogLevel | boolean // with line if boolean or from log level on or above
|
||||
layout?: ColoredContextLayoutConfig
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
export * from './Category'
|
||||
export * from './CustomFileAppender'
|
||||
export * from './LogLevel'
|
||||
export * from './ColoredContextLayoutConfig'
|
||||
|
||||
@ -1,59 +1,99 @@
|
||||
jest.setTimeout(1000000)
|
||||
|
||||
const loggers: { [key: string]: any } = {}
|
||||
const logs: { level: string; message: string; logger: string; additional: string }[] = []
|
||||
type LogEntry = {
|
||||
level: string;
|
||||
message: string;
|
||||
logger: string;
|
||||
context: string;
|
||||
additional: any[];
|
||||
}
|
||||
|
||||
function addLog(level: string, message: string, logger: string, additional: any[]) {
|
||||
logs.push({ level, message, logger, additional: JSON.stringify(additional, null, 2) })
|
||||
const loggers: { [key: string]: any } = {}
|
||||
const logs: LogEntry[] = []
|
||||
|
||||
function addLog(level: string, message: string, logger: string, context: Map<string, string>, additional: any[]) {
|
||||
logs.push({
|
||||
level,
|
||||
context: [...context.entries()].map(([key, value]) => `${key}=${value}`).join(' ').trimEnd(),
|
||||
message,
|
||||
logger,
|
||||
additional
|
||||
})
|
||||
}
|
||||
|
||||
export function printLogs() {
|
||||
for (const log of logs) {
|
||||
process.stdout.write(`${log.logger} [${log.level}] ${log.message} ${log.additional}\n`)
|
||||
const messages = []
|
||||
messages.push(log.message)
|
||||
messages.push(log.additional.map((d) => {
|
||||
if (typeof d === 'object' && d.toString() === '[object Object]') {
|
||||
return JSON.stringify(d)
|
||||
}
|
||||
if (d) {
|
||||
return d.toString()
|
||||
}
|
||||
}).filter((d) => d))
|
||||
process.stdout.write(`${log.logger} [${log.level}] ${log.context} ${messages.join(' ')}\n`)
|
||||
}
|
||||
}
|
||||
|
||||
export function cleanLogs(): void {
|
||||
export function clearLogs(): void {
|
||||
logs.length = 0
|
||||
}
|
||||
|
||||
const getLoggerMocked = jest.fn().mockImplementation((param: any) => {
|
||||
if (loggers[param]) {
|
||||
// TODO: check if it is working when tests run in parallel
|
||||
loggers[param].clearContext()
|
||||
return loggers[param]
|
||||
}
|
||||
// console.log('getLogger called with: ', param)
|
||||
const fakeLogger = {
|
||||
context: new Map<string, string>(),
|
||||
addContext: jest.fn((key: string, value: string) => {
|
||||
fakeLogger.context.set(key, value)
|
||||
}),
|
||||
trace: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('trace', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
debug: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('debug', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
warn: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('warn', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
info: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('info', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
error: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('error', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
fatal: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('fatal', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
removeContext: jest.fn((key: string) => {
|
||||
fakeLogger.context.delete(key)
|
||||
}),
|
||||
clearContext: jest.fn(() => {
|
||||
fakeLogger.context.clear()
|
||||
})
|
||||
}
|
||||
loggers[param] = fakeLogger
|
||||
return fakeLogger
|
||||
})
|
||||
|
||||
jest.mock('log4js', () => {
|
||||
const originalModule = jest.requireActual('log4js')
|
||||
return {
|
||||
__esModule: true,
|
||||
...originalModule,
|
||||
getLogger: jest.fn().mockImplementation((param: any) => {
|
||||
// console.log('getLogger called with: ', param)
|
||||
const fakeLogger = {
|
||||
addContext: jest.fn(),
|
||||
trace: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('trace', message, param, args)
|
||||
}),
|
||||
debug: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('debug', message, param, args)
|
||||
}),
|
||||
warn: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('warn', message, param, args)
|
||||
}),
|
||||
info: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('info', message, param, args)
|
||||
}),
|
||||
error: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('error', message, param, args)
|
||||
}),
|
||||
fatal: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('fatal', message, param, args)
|
||||
}),
|
||||
}
|
||||
loggers[param] = fakeLogger
|
||||
return fakeLogger
|
||||
}),
|
||||
getLogger: getLoggerMocked
|
||||
}
|
||||
})
|
||||
|
||||
export function getLogger(name: string) {
|
||||
if (!loggers[name]) {
|
||||
throw new Error(`No logger with name ${name} was requested from code`)
|
||||
return getLoggerMocked(name)
|
||||
}
|
||||
return loggers[name]
|
||||
}
|
||||
|
||||
@ -23,7 +23,11 @@ export abstract class AbstractLoggingView {
|
||||
|
||||
public dateToString(date: Date | undefined | null): string | undefined {
|
||||
if (date) {
|
||||
return date.toISOString()
|
||||
if (date instanceof Date) {
|
||||
return date.toISOString()
|
||||
} else {
|
||||
return new Date(date).toISOString()
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
@ -59,7 +59,6 @@ export const startDHT = async (topic: string): Promise<void> => {
|
||||
const server = node.createServer()
|
||||
|
||||
server.on('connection', function (socket: any) {
|
||||
logger.addContext('pubkey', socket.remotePublicKey.toString('hex'))
|
||||
logger.info(`server on... with Remote public key: ${socket.remotePublicKey.toString('hex')}`)
|
||||
|
||||
socket.on('data', async (data: Buffer) => {
|
||||
@ -111,10 +110,10 @@ export const startDHT = async (topic: string): Promise<void> => {
|
||||
const variables = {
|
||||
apiVersion: recApiVersion.api,
|
||||
endPoint: recApiVersion.url,
|
||||
publicKey: socket.remotePublicKey,
|
||||
publicKey: socket.remotePublicKey.toString('hex'),
|
||||
lastAnnouncedAt: new Date(),
|
||||
}
|
||||
logger.debug(`upsert with variables=${JSON.stringify(variables)}`)
|
||||
logger.debug(`upsert with variables=${JSON.stringify(variables, null, 2)}`)
|
||||
// this will NOT update the updatedAt column, to distingue between a normal update and the last announcement
|
||||
await DbFederatedCommunity.createQueryBuilder()
|
||||
.insert()
|
||||
|
||||
@ -26,7 +26,6 @@ const createServer = async (
|
||||
logger: Logger = dltLogger,
|
||||
// localization: i18n.I18n = i18n,
|
||||
): Promise<ServerDef> => {
|
||||
logger.addContext('user', 'unknown')
|
||||
logger.debug('createServer...')
|
||||
|
||||
// connect to db and test db version
|
||||
|
||||
@ -115,8 +115,5 @@ COPY --chown=app:app --from=build ${DOCKER_WORKDIR}/federation/build/index.js ./
|
||||
# add node_modules from production_node_modules
|
||||
COPY --chown=app:app --from=production-node-modules ${DOCKER_WORKDIR}/node_modules ./node_modules
|
||||
|
||||
# Copy log4js-config.json to provide log configuration
|
||||
COPY --chown=app:app --from=build ${DOCKER_WORKDIR}/federation/log4js-config.json ./log4js-config.json
|
||||
|
||||
# Run command
|
||||
CMD ["node", "index.js"]
|
||||
@ -59,6 +59,7 @@
|
||||
"nodemon": "^2.0.7",
|
||||
"prettier": "^3.5.3",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"source-map-support": "^0.5.21",
|
||||
"ts-jest": "27.0.5",
|
||||
"tsconfig-paths": "^4.1.1",
|
||||
"type-graphql": "^1.1.1",
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import 'source-map-support/register'
|
||||
import { createServer } from './server/createServer'
|
||||
|
||||
import { defaultCategory, initLogger } from 'config-schema'
|
||||
@ -7,7 +8,7 @@ import { CONFIG } from './config'
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from './config/const'
|
||||
|
||||
async function main() {
|
||||
// init logger
|
||||
// init logger
|
||||
const log4jsConfigFileName = CONFIG.LOG4JS_CONFIG_PLACEHOLDER.replace('%v', CONFIG.FEDERATION_API)
|
||||
initLogger(
|
||||
[defaultCategory('federation', CONFIG.LOG_LEVEL), defaultCategory('apollo', CONFIG.LOG_LEVEL)],
|
||||
|
||||
@ -4,7 +4,6 @@ import { createTestClient } from 'apollo-server-testing'
|
||||
import { createServer } from '@/server/createServer'
|
||||
|
||||
import { getLogger } from 'config-schema/test/testSetup'
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
|
||||
export const headerPushMock = jest.fn((t) => {
|
||||
context.token = t.value
|
||||
@ -26,7 +25,7 @@ export const cleanDB = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
export const testEnvironment = async (testLogger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.apollo`) /*, testI18n = i18n */) => {
|
||||
export const testEnvironment = async (testLogger = getLogger('apollo') /*, testI18n = i18n */) => {
|
||||
const server = await createServer(/* context, */ testLogger /* , testI18n */)
|
||||
const con = server.con
|
||||
const testClient = createTestClient(server.apollo)
|
||||
|
||||
@ -2569,6 +2569,13 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/source-map-support@^0.5.10":
|
||||
version "0.5.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/source-map-support/-/source-map-support-0.5.10.tgz#824dcef989496bae98e9d04c8dc1ac1d70e1bd39"
|
||||
integrity sha512-tgVP2H469x9zq34Z0m/fgPewGhg/MLClalNOiPIzQlXrSS2YrKu/xCdSCKnEDwkFha51VKEKB6A9wW26/ZNwzA==
|
||||
dependencies:
|
||||
source-map "^0.6.0"
|
||||
|
||||
"@types/stack-utils@^2.0.0":
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user