mirror of
https://github.com/pockethost/pockethost.git
synced 2025-06-08 07:06:41 +00:00
Winston log provider
This commit is contained in:
parent
a11e819d5e
commit
46aeaaa1c2
@ -34,7 +34,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: `health-compact`,
|
name: `health-compact`,
|
||||||
restart_delay: 60 * 1000, // 1 minute
|
restart_delay: 60 * 60 * 1000 * 24, // 1 day
|
||||||
script: 'pnpm prod:cli health compact',
|
script: 'pnpm prod:cli health compact',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -65,7 +65,8 @@
|
|||||||
"url-pattern": "^1.0.3",
|
"url-pattern": "^1.0.3",
|
||||||
"vhost": "^3.0.2",
|
"vhost": "^3.0.2",
|
||||||
"winston": "^3.11.0",
|
"winston": "^3.11.0",
|
||||||
"winston-syslog": "^2.7.0"
|
"winston-syslog": "^2.7.0",
|
||||||
|
"winston-transport": "^4.7.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/cors": "^2.8.17",
|
"@types/cors": "^2.8.17",
|
||||||
|
@ -140,7 +140,6 @@ export class PhFs implements FileSystem {
|
|||||||
? normalize(resolvedVirtualPath)
|
? normalize(resolvedVirtualPath)
|
||||||
: join('/', this.cwd, resolvedVirtualPath)
|
: join('/', this.cwd, resolvedVirtualPath)
|
||||||
|
|
||||||
console.log(`***finalVirtualPath`, { finalVirtualPath })
|
|
||||||
// Create local filesystem path using the platform separator
|
// Create local filesystem path using the platform separator
|
||||||
const [empty, subdomain, ...restOfVirtualPath] = finalVirtualPath.split('/')
|
const [empty, subdomain, ...restOfVirtualPath] = finalVirtualPath.split('/')
|
||||||
dbg({
|
dbg({
|
||||||
@ -154,7 +153,7 @@ export class PhFs implements FileSystem {
|
|||||||
|
|
||||||
// Check if the instance is valid
|
// Check if the instance is valid
|
||||||
const instance = await (async () => {
|
const instance = await (async () => {
|
||||||
console.log(`***checking validity`, { subdomain })
|
dbg(`checking validity`, { subdomain })
|
||||||
if (!subdomain) return
|
if (!subdomain) return
|
||||||
const instance = await this.client
|
const instance = await this.client
|
||||||
.collection(`instances`)
|
.collection(`instances`)
|
||||||
@ -225,8 +224,7 @@ export class PhFs implements FileSystem {
|
|||||||
async list(path = '.') {
|
async list(path = '.') {
|
||||||
const { dbg, error } = this.log
|
const { dbg, error } = this.log
|
||||||
.create(`list`)
|
.create(`list`)
|
||||||
.breadcrumb(`cwd:${this.cwd}`)
|
.breadcrumb({ cwd: this.cwd, path })
|
||||||
.breadcrumb(path)
|
|
||||||
|
|
||||||
const { fsPath, instance } = await this._resolvePath(path)
|
const { fsPath, instance } = await this._resolvePath(path)
|
||||||
|
|
||||||
@ -277,9 +275,7 @@ export class PhFs implements FileSystem {
|
|||||||
|
|
||||||
const { dbg, error } = this.log
|
const { dbg, error } = this.log
|
||||||
.create(`get`)
|
.create(`get`)
|
||||||
.breadcrumb(`cwd:${this.cwd}`)
|
.breadcrumb({ cwd: this.cwd, fileName, fsPath })
|
||||||
.breadcrumb(fileName)
|
|
||||||
.breadcrumb(fsPath)
|
|
||||||
dbg(`get`)
|
dbg(`get`)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -325,8 +321,7 @@ export class PhFs implements FileSystem {
|
|||||||
) {
|
) {
|
||||||
const { dbg, error } = this.log
|
const { dbg, error } = this.log
|
||||||
.create(`write`)
|
.create(`write`)
|
||||||
.breadcrumb(`cwd:${this.cwd}`)
|
.breadcrumb({ cwd: this.cwd, fileName })
|
||||||
.breadcrumb(fileName)
|
|
||||||
dbg(`write`)
|
dbg(`write`)
|
||||||
|
|
||||||
const { fsPath, clientPath, instance } = await this._resolvePath(fileName)
|
const { fsPath, clientPath, instance } = await this._resolvePath(fileName)
|
||||||
@ -362,8 +357,7 @@ export class PhFs implements FileSystem {
|
|||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
const { dbg, error } = this.log
|
const { dbg, error } = this.log
|
||||||
.create(`read`)
|
.create(`read`)
|
||||||
.breadcrumb(`cwd:${this.cwd}`)
|
.breadcrumb({ cwd: this.cwd, fileName })
|
||||||
.breadcrumb(fileName)
|
|
||||||
dbg(`read`)
|
dbg(`read`)
|
||||||
|
|
||||||
const { fsPath, clientPath } = await this._resolvePath(fileName)
|
const { fsPath, clientPath } = await this._resolvePath(fileName)
|
||||||
@ -387,8 +381,7 @@ export class PhFs implements FileSystem {
|
|||||||
async delete(path: string) {
|
async delete(path: string) {
|
||||||
const { dbg, error } = this.log
|
const { dbg, error } = this.log
|
||||||
.create(`delete`)
|
.create(`delete`)
|
||||||
.breadcrumb(`cwd:${this.cwd}`)
|
.breadcrumb({ cwd: this.cwd, path })
|
||||||
.breadcrumb(path)
|
|
||||||
dbg(`delete`)
|
dbg(`delete`)
|
||||||
|
|
||||||
const { fsPath, instance } = await this._resolvePath(path)
|
const { fsPath, instance } = await this._resolvePath(path)
|
||||||
@ -405,8 +398,7 @@ export class PhFs implements FileSystem {
|
|||||||
async mkdir(path: string) {
|
async mkdir(path: string) {
|
||||||
const { dbg, error } = this.log
|
const { dbg, error } = this.log
|
||||||
.create(`mkdir`)
|
.create(`mkdir`)
|
||||||
.breadcrumb(`cwd:${this.cwd}`)
|
.breadcrumb({ cwd: this.cwd, path })
|
||||||
.breadcrumb(path)
|
|
||||||
dbg(`mkdir`)
|
dbg(`mkdir`)
|
||||||
|
|
||||||
const { fsPath } = await this._resolvePath(path)
|
const { fsPath } = await this._resolvePath(path)
|
||||||
@ -417,9 +409,7 @@ export class PhFs implements FileSystem {
|
|||||||
async rename(from: string, to: string) {
|
async rename(from: string, to: string) {
|
||||||
const { dbg, error } = this.log
|
const { dbg, error } = this.log
|
||||||
.create(`rename`)
|
.create(`rename`)
|
||||||
.breadcrumb(`cwd:${this.cwd}`)
|
.breadcrumb({ cwd: this.cwd, from, to })
|
||||||
.breadcrumb(from)
|
|
||||||
.breadcrumb(to)
|
|
||||||
dbg(`rename`)
|
dbg(`rename`)
|
||||||
|
|
||||||
const { fsPath: fromPath, instance } = await this._resolvePath(from)
|
const { fsPath: fromPath, instance } = await this._resolvePath(from)
|
||||||
@ -434,9 +424,7 @@ export class PhFs implements FileSystem {
|
|||||||
async chmod(path: string, mode: Mode) {
|
async chmod(path: string, mode: Mode) {
|
||||||
const { dbg, error } = this.log
|
const { dbg, error } = this.log
|
||||||
.create(`chmod`)
|
.create(`chmod`)
|
||||||
.breadcrumb(`cwd:${this.cwd}`)
|
.breadcrumb({ cwd: this.cwd, path, mode })
|
||||||
.breadcrumb(path)
|
|
||||||
.breadcrumb(mode.toString())
|
|
||||||
dbg(`chmod`)
|
dbg(`chmod`)
|
||||||
|
|
||||||
const { fsPath } = await this._resolvePath(path)
|
const { fsPath } = await this._resolvePath(path)
|
||||||
|
@ -1,20 +1,22 @@
|
|||||||
import { Request } from 'express'
|
import { Request } from 'express'
|
||||||
import { createProxyMiddleware } from 'http-proxy-middleware'
|
import { createProxyMiddleware } from 'http-proxy-middleware'
|
||||||
import vhost from 'vhost'
|
import vhost from 'vhost'
|
||||||
|
import { logger } from '../../../../../core/ioc'
|
||||||
|
|
||||||
export function createVhostProxyMiddleware(
|
export function createVhostProxyMiddleware(
|
||||||
host: string,
|
host: string,
|
||||||
target: string,
|
target: string,
|
||||||
ws = false,
|
ws = false,
|
||||||
) {
|
) {
|
||||||
console.log(`Creating ${host}->${target}`)
|
const { dbg } = logger()
|
||||||
|
dbg(`Creating ${host}->${target}`)
|
||||||
const handler = createProxyMiddleware({ target, ws, changeOrigin: ws })
|
const handler = createProxyMiddleware({ target, ws, changeOrigin: ws })
|
||||||
return vhost(host, (_req, res, next) => {
|
return vhost(host, (_req, res, next) => {
|
||||||
const req = _req as unknown as Request
|
const req = _req as unknown as Request
|
||||||
const method = req.method
|
const method = req.method
|
||||||
const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl
|
const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl
|
||||||
|
|
||||||
console.log(`${method} ${fullUrl} -> ${target}`)
|
dbg(`${method} ${fullUrl} -> ${target}`)
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return handler(req, res, next)
|
return handler(req, res, next)
|
||||||
})
|
})
|
||||||
|
@ -7,7 +7,6 @@ import fs from 'fs'
|
|||||||
import http from 'http'
|
import http from 'http'
|
||||||
import { createProxyMiddleware } from 'http-proxy-middleware'
|
import { createProxyMiddleware } from 'http-proxy-middleware'
|
||||||
import https from 'https'
|
import https from 'https'
|
||||||
import { LoggerService } from '../../../../../common'
|
|
||||||
import {
|
import {
|
||||||
APEX_DOMAIN,
|
APEX_DOMAIN,
|
||||||
APP_NAME,
|
APP_NAME,
|
||||||
@ -18,13 +17,13 @@ import {
|
|||||||
MOTHERSHIP_PORT,
|
MOTHERSHIP_PORT,
|
||||||
SSL_CERT,
|
SSL_CERT,
|
||||||
SSL_KEY,
|
SSL_KEY,
|
||||||
discordAlert,
|
|
||||||
} from '../../../../../core'
|
} from '../../../../../core'
|
||||||
|
import { logger } from '../../../../../core/ioc'
|
||||||
import { createIpWhitelistMiddleware } from './cidr'
|
import { createIpWhitelistMiddleware } from './cidr'
|
||||||
import { createVhostProxyMiddleware } from './createVhostProxyMiddleware'
|
import { createVhostProxyMiddleware } from './createVhostProxyMiddleware'
|
||||||
|
|
||||||
export const firewall = async () => {
|
export const firewall = async () => {
|
||||||
const { debug } = LoggerService().create(`proxy`)
|
const { dbg, error } = logger()
|
||||||
|
|
||||||
const PROD_ROUTES = {
|
const PROD_ROUTES = {
|
||||||
[`${MOTHERSHIP_NAME()}.${APEX_DOMAIN()}`]: `http://localhost:${MOTHERSHIP_PORT()}`,
|
[`${MOTHERSHIP_NAME()}.${APEX_DOMAIN()}`]: `http://localhost:${MOTHERSHIP_PORT()}`,
|
||||||
@ -49,10 +48,12 @@ export const firewall = async () => {
|
|||||||
app.use(createIpWhitelistMiddleware(IPCIDR_LIST()))
|
app.use(createIpWhitelistMiddleware(IPCIDR_LIST()))
|
||||||
|
|
||||||
forEach(hostnameRoutes, (target, host) => {
|
forEach(hostnameRoutes, (target, host) => {
|
||||||
|
dbg(`Creating ${host}->${target}`)
|
||||||
app.use(createVhostProxyMiddleware(host, target, IS_DEV()))
|
app.use(createVhostProxyMiddleware(host, target, IS_DEV()))
|
||||||
})
|
})
|
||||||
|
|
||||||
app.get(`/_api/health`, (req, res, next) => {
|
app.get(`/_api/health`, (req, res, next) => {
|
||||||
|
dbg(`Health check`)
|
||||||
res.json({ status: 'ok' })
|
res.json({ status: 'ok' })
|
||||||
res.end()
|
res.end()
|
||||||
})
|
})
|
||||||
@ -65,19 +66,19 @@ export const firewall = async () => {
|
|||||||
const method = req.method
|
const method = req.method
|
||||||
const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl
|
const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl
|
||||||
|
|
||||||
debug(`${method} ${fullUrl} -> ${`http://localhost:${DAEMON_PORT()}`}`)
|
dbg(`${method} ${fullUrl} -> ${`http://localhost:${DAEMON_PORT()}`}`)
|
||||||
|
|
||||||
handler(req, res, next)
|
handler(req, res, next)
|
||||||
})
|
})
|
||||||
|
|
||||||
const errorHandler: ErrorRequestHandler = (err, req, res, next) => {
|
const errorHandler: ErrorRequestHandler = (err, req, res, next) => {
|
||||||
discordAlert(err.toString())
|
error(err)
|
||||||
res.status(500).send(err.toString())
|
res.status(500).send(err.toString())
|
||||||
}
|
}
|
||||||
app.use(errorHandler)
|
app.use(errorHandler)
|
||||||
|
|
||||||
http.createServer(app).listen(80, () => {
|
http.createServer(app).listen(80, () => {
|
||||||
console.log('SSL redirect server listening on 80')
|
dbg('SSL redirect server listening on 80')
|
||||||
})
|
})
|
||||||
|
|
||||||
// HTTPS server options
|
// HTTPS server options
|
||||||
@ -88,6 +89,6 @@ export const firewall = async () => {
|
|||||||
|
|
||||||
// Create HTTPS server
|
// Create HTTPS server
|
||||||
https.createServer(httpsOptions, app).listen(443, () => {
|
https.createServer(httpsOptions, app).listen(443, () => {
|
||||||
console.log('HTTPS server running on port 443')
|
dbg('HTTPS server running on port 443')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
import { exec } from 'child_process'
|
import { exec } from 'child_process'
|
||||||
import { globSync } from 'glob'
|
import { globSync } from 'glob'
|
||||||
import { DATA_ROOT } from '../../../../core'
|
import { DATA_ROOT } from '../../../../core'
|
||||||
|
import { logger } from '../../../core/ioc'
|
||||||
|
|
||||||
export const compact = async () => {
|
export const compact = async () => {
|
||||||
|
const { info } = logger()
|
||||||
|
|
||||||
const files = [`data`, `logs`].flatMap((db) =>
|
const files = [`data`, `logs`].flatMap((db) =>
|
||||||
globSync(`${DATA_ROOT()}/*/pb_data/${db}.db{-shm,-wal}`),
|
globSync(`${DATA_ROOT()}/*/pb_data/${db}.db{-shm,-wal}`),
|
||||||
)
|
)
|
||||||
|
|
||||||
files.map(async (file) => {
|
files.map(async (file) => {
|
||||||
console.log(`Compacting ${file}`)
|
info(`Compacting ${file}`)
|
||||||
exec(`sqlite3 ${file} ".tables"`)
|
exec(`sqlite3 ${file} ".tables"`)
|
||||||
})
|
})
|
||||||
console.log(`Compaction complete`)
|
info(`Compaction complete`)
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ export const SqliteService = mkSingleton((config: SqliteServiceConfig) => {
|
|||||||
filename: string,
|
filename: string,
|
||||||
): Promise<SqliteServiceApi> => {
|
): Promise<SqliteServiceApi> => {
|
||||||
const _dbLogger = LoggerService().create(`SqliteService`)
|
const _dbLogger = LoggerService().create(`SqliteService`)
|
||||||
_dbLogger.breadcrumb(filename)
|
_dbLogger.breadcrumb({ filename })
|
||||||
const { dbg, error, abort } = _dbLogger
|
const { dbg, error, abort } = _dbLogger
|
||||||
|
|
||||||
trace(`Fetching database`, connections)
|
trace(`Fetching database`, connections)
|
||||||
|
@ -3,16 +3,12 @@
|
|||||||
import { program } from 'commander'
|
import { program } from 'commander'
|
||||||
import EventSource from 'eventsource'
|
import EventSource from 'eventsource'
|
||||||
import {
|
import {
|
||||||
DEBUG,
|
|
||||||
DefaultSettingsService,
|
|
||||||
LogLevelName,
|
LogLevelName,
|
||||||
LoggerService,
|
LoggerService,
|
||||||
PH_PLUGINS,
|
PH_PLUGINS,
|
||||||
SETTINGS,
|
|
||||||
loadPlugins,
|
loadPlugins,
|
||||||
} from '../../core'
|
} from '../../core'
|
||||||
import { version } from '../../package.json'
|
import { version } from '../../package.json'
|
||||||
import { GobotService } from '../services/GobotService'
|
|
||||||
import { EdgeCommand } from './commands/EdgeCommand'
|
import { EdgeCommand } from './commands/EdgeCommand'
|
||||||
import { FirewallCommand } from './commands/FirewallCommand'
|
import { FirewallCommand } from './commands/FirewallCommand'
|
||||||
import { HealthCommand } from './commands/HealthCommand'
|
import { HealthCommand } from './commands/HealthCommand'
|
||||||
@ -20,17 +16,13 @@ import { MothershipCommand } from './commands/MothershipCommand'
|
|||||||
import { PocketBaseCommand } from './commands/PocketBaseCommand'
|
import { PocketBaseCommand } from './commands/PocketBaseCommand'
|
||||||
import { SendMailCommand } from './commands/SendMailCommand'
|
import { SendMailCommand } from './commands/SendMailCommand'
|
||||||
import { ServeCommand } from './commands/ServeCommand'
|
import { ServeCommand } from './commands/ServeCommand'
|
||||||
|
import './ioc'
|
||||||
|
|
||||||
export type GlobalOptions = {
|
export type GlobalOptions = {
|
||||||
logLevel?: LogLevelName
|
logLevel?: LogLevelName
|
||||||
debug: boolean
|
debug: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultSettingsService(SETTINGS)
|
|
||||||
|
|
||||||
LoggerService({ level: DEBUG() ? LogLevelName.Debug : LogLevelName.Info })
|
|
||||||
GobotService({})
|
|
||||||
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
global.EventSource = EventSource
|
global.EventSource = EventSource
|
||||||
|
|
||||||
|
11
packages/pockethost/src/cli/ioc.ts
Normal file
11
packages/pockethost/src/cli/ioc.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { LoggerService } from '../common'
|
||||||
|
import { RegisterEnvSettingsService } from '../constants'
|
||||||
|
import { ioc } from '../core/ioc'
|
||||||
|
import { WinstonLoggerService } from '../core/winston'
|
||||||
|
import { GobotService } from '../services/GobotService'
|
||||||
|
|
||||||
|
ioc.register('logger', WinstonLoggerService({}))
|
||||||
|
|
||||||
|
RegisterEnvSettingsService()
|
||||||
|
LoggerService({})
|
||||||
|
GobotService({})
|
@ -1,16 +1,13 @@
|
|||||||
/// <require "node">
|
/// <require "node">
|
||||||
|
|
||||||
import chalk from 'chalk'
|
import { mkSingleton } from '.'
|
||||||
import stringify from 'json-stringify-safe'
|
import { logger } from '../core/ioc'
|
||||||
import { action, mergeConfig, mkSingleton } from '.'
|
|
||||||
|
|
||||||
export type LoggerConfig = {
|
export type LoggerConfig = {
|
||||||
level: LogLevelName
|
level: LogLevelName
|
||||||
pfx: string[]
|
pfx: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Logger = ReturnType<typeof createLogger>
|
|
||||||
|
|
||||||
export const isLevelLte = (a: LogLevelName, b: LogLevelName) => {
|
export const isLevelLte = (a: LogLevelName, b: LogLevelName) => {
|
||||||
return LogLevels[a] <= LogLevels[b]
|
return LogLevels[a] <= LogLevels[b]
|
||||||
}
|
}
|
||||||
@ -53,118 +50,23 @@ export const LogLevels = {
|
|||||||
[LogLevelName.Abort]: 6,
|
[LogLevelName.Abort]: 6,
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export const createLogger = (config: Partial<LoggerConfig>) => {
|
export type Logger = {
|
||||||
const _config = mergeConfig<LoggerConfig>(
|
raw: (...args: any[]) => void
|
||||||
{
|
dbg: (...args: any[]) => void
|
||||||
level: LogLevelName.Debug,
|
warn: (...args: any[]) => void
|
||||||
pfx: [''],
|
info: (...args: any[]) => void
|
||||||
},
|
error: (...args: any[]) => void
|
||||||
config,
|
criticalError: (...args: any[]) => void
|
||||||
)
|
create: (name: string, configOverride?: Partial<LoggerConfig>) => Logger
|
||||||
const { pfx } = _config
|
child: (name: string) => Logger
|
||||||
|
trace: (...args: any[]) => void
|
||||||
const setLevel = (level: LogLevelName) => {
|
debug: (...args: any[]) => void
|
||||||
_config.level = level
|
breadcrumb: (s: object) => Logger
|
||||||
|
abort: (...args: any[]) => never
|
||||||
|
shutdown: () => void
|
||||||
|
setLevel: (level: LogLevelName) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const _pfx = (s: string) =>
|
|
||||||
[new Date().toISOString(), s, ...pfx]
|
|
||||||
.filter((v) => !!v)
|
|
||||||
.map((p) => `[${p}]`)
|
|
||||||
.join(' ')
|
|
||||||
|
|
||||||
const _log = (levelIn: LogLevelName, ...args: any[]) => {
|
|
||||||
action(`log`, _config.level, levelIn, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
const raw = (...args: any[]) => {
|
|
||||||
_log(LogLevelName.Raw, _pfx('RAW'), ...args)
|
|
||||||
}
|
|
||||||
|
|
||||||
const trace = (...args: any[]) => {
|
|
||||||
_log(LogLevelName.Trace, _pfx(`TRACE`), ...args)
|
|
||||||
}
|
|
||||||
|
|
||||||
const dbg = (...args: any[]) => {
|
|
||||||
_log(LogLevelName.Debug, _pfx(chalk.blueBright('DBG')), ...args)
|
|
||||||
}
|
|
||||||
|
|
||||||
const info = (...args: any[]) => {
|
|
||||||
_log(
|
|
||||||
LogLevelName.Info,
|
|
||||||
_pfx(
|
|
||||||
isLevelGt(LogLevelName.Info, _config.level) ? chalk.gray(`INFO`) : '',
|
|
||||||
),
|
|
||||||
...args,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const warn = (...args: any[]) => {
|
|
||||||
_log(
|
|
||||||
LogLevelName.Warn,
|
|
||||||
_pfx(chalk.yellow(chalk.cyanBright('WARN'))),
|
|
||||||
...args,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const error = (...args: any[]) => {
|
|
||||||
_log(LogLevelName.Error, ...[_pfx(chalk.bgRed(`ERROR`)), ...args])
|
|
||||||
}
|
|
||||||
|
|
||||||
const criticalError = (...args: any[]) => {
|
|
||||||
_log(LogLevelName.Error, ...[_pfx(chalk.bgRed(`ERROR`)), ...args])
|
|
||||||
new Error().stack?.split(/\n/).forEach((line) => {
|
|
||||||
_log(LogLevelName.Debug, _pfx(chalk.bgRed(`ERROR`)), line)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const abort = (...args: any[]): never => {
|
|
||||||
_log(LogLevelName.Abort, true, ...[_pfx(chalk.bgRed(`ABORT`)), ...args])
|
|
||||||
throw new Error(`Fatal error: ${stringify(args)}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const create = (name: string, configOverride?: Partial<LoggerConfig>) =>
|
|
||||||
createLogger({
|
|
||||||
..._config,
|
|
||||||
...configOverride,
|
|
||||||
pfx: [..._config.pfx, name],
|
|
||||||
})
|
|
||||||
|
|
||||||
const breadcrumb = (s: string | object) => {
|
|
||||||
if (typeof s === 'string') {
|
|
||||||
pfx.push(s)
|
|
||||||
} else {
|
|
||||||
Object.entries(s).forEach(([k, v]) => pfx.push(`${k}: ${v}`))
|
|
||||||
}
|
|
||||||
return api
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compatibility func
|
|
||||||
const child = (name: string) => create(name)
|
|
||||||
|
|
||||||
const api = {
|
|
||||||
raw,
|
|
||||||
dbg,
|
|
||||||
warn,
|
|
||||||
info,
|
|
||||||
error,
|
|
||||||
criticalError,
|
|
||||||
create,
|
|
||||||
child,
|
|
||||||
trace,
|
|
||||||
debug: dbg,
|
|
||||||
breadcrumb,
|
|
||||||
abort,
|
|
||||||
shutdown() {
|
|
||||||
dbg(`Logger shutting down`)
|
|
||||||
},
|
|
||||||
setLevel,
|
|
||||||
}
|
|
||||||
return api
|
|
||||||
}
|
|
||||||
|
|
||||||
export type LoggerServiceApi = ReturnType<typeof createLogger>
|
|
||||||
|
|
||||||
export const LoggerService = mkSingleton((config: Partial<LoggerConfig> = {}) =>
|
export const LoggerService = mkSingleton((config: Partial<LoggerConfig> = {}) =>
|
||||||
createLogger(config),
|
logger(),
|
||||||
)
|
)
|
||||||
|
@ -6,15 +6,11 @@ import { default as env } from 'env-var'
|
|||||||
import { mkdirSync, writeFileSync } from 'fs'
|
import { mkdirSync, writeFileSync } from 'fs'
|
||||||
import { dirname, join } from 'path'
|
import { dirname, join } from 'path'
|
||||||
import { fileURLToPath } from 'url'
|
import { fileURLToPath } from 'url'
|
||||||
import { LogEntry } from 'winston'
|
|
||||||
import {
|
import {
|
||||||
InstanceFields,
|
InstanceFields,
|
||||||
InstanceId,
|
InstanceId,
|
||||||
IoCManager,
|
|
||||||
SettingsHandlerFactory,
|
SettingsHandlerFactory,
|
||||||
SettingsService,
|
SettingsService,
|
||||||
UserFields,
|
|
||||||
mkSingleton,
|
|
||||||
} from '../core'
|
} from '../core'
|
||||||
import {
|
import {
|
||||||
mkBoolean,
|
mkBoolean,
|
||||||
@ -23,6 +19,7 @@ import {
|
|||||||
mkPath,
|
mkPath,
|
||||||
mkString,
|
mkString,
|
||||||
} from './core/Settings'
|
} from './core/Settings'
|
||||||
|
import { ioc, settings } from './core/ioc'
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||||
|
|
||||||
@ -147,14 +144,13 @@ export const SETTINGS = {
|
|||||||
PH_GOBOT_ROOT: mkPath(join(_PH_HOME, 'gobot'), { create: true }),
|
PH_GOBOT_ROOT: mkPath(join(_PH_HOME, 'gobot'), { create: true }),
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Settings = ReturnType<typeof DefaultSettingsService>
|
export type Settings = ReturnType<typeof RegisterEnvSettingsService>
|
||||||
export type SettingsDefinition = {
|
export type SettingsDefinition = {
|
||||||
[_ in keyof Settings]: SettingsHandlerFactory<Settings[_]>
|
[_ in keyof Settings]: SettingsHandlerFactory<Settings[_]>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DefaultSettingsService = mkSingleton(
|
export const RegisterEnvSettingsService = () => {
|
||||||
(settings: typeof SETTINGS) => {
|
const _settings = SettingsService(SETTINGS)
|
||||||
const _settings = SettingsService(settings)
|
|
||||||
|
|
||||||
ioc.register('settings', _settings)
|
ioc.register('settings', _settings)
|
||||||
|
|
||||||
@ -163,39 +159,8 @@ export const DefaultSettingsService = mkSingleton(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return _settings
|
return _settings
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
export type MothershipProvider = {
|
|
||||||
getAllInstances(): Promise<InstanceFields[]>
|
|
||||||
getInstanceById(id: InstanceId): Promise<[InstanceFields, UserFields] | []>
|
|
||||||
getInstanceBySubdomain(
|
|
||||||
subdomain: InstanceFields['subdomain'],
|
|
||||||
): Promise<[InstanceFields, UserFields] | []>
|
|
||||||
updateInstance(id: InstanceId, fields: Partial<InstanceFields>): Promise<void>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type UnsubFunc = () => void
|
|
||||||
|
|
||||||
export type InstanceLogProvider = (
|
|
||||||
instanceId: InstanceId,
|
|
||||||
target: string,
|
|
||||||
) => {
|
|
||||||
info(msg: string): void
|
|
||||||
error(msg: string): void
|
|
||||||
tail(linesBack: number, data: (line: LogEntry) => void): UnsubFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ioc = new IoCManager<{
|
|
||||||
settings: Settings
|
|
||||||
mothership: MothershipProvider
|
|
||||||
instanceLogger: InstanceLogProvider
|
|
||||||
}>()
|
|
||||||
|
|
||||||
export const settings = () => ioc.service('settings')
|
|
||||||
export const mothership = () => ioc.service('mothership')
|
|
||||||
export const instanceLogger = () => ioc.service('instanceLogger')
|
|
||||||
|
|
||||||
/** Accessors */
|
/** Accessors */
|
||||||
export const PH_PLUGINS = () => settings().PH_PLUGINS
|
export const PH_PLUGINS = () => settings().PH_PLUGINS
|
||||||
|
|
||||||
|
19
packages/pockethost/src/core/DiscordTransport.ts
Normal file
19
packages/pockethost/src/core/DiscordTransport.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import TransportStream from 'winston-transport'
|
||||||
|
import { discordAlert } from '..'
|
||||||
|
|
||||||
|
export type DiscordTransportType = {
|
||||||
|
webhookUrl: string
|
||||||
|
} & TransportStream.TransportStreamOptions
|
||||||
|
|
||||||
|
export class DiscordTransport extends TransportStream {
|
||||||
|
private url: string
|
||||||
|
constructor(opts: DiscordTransportType) {
|
||||||
|
super(opts)
|
||||||
|
this.url = opts.webhookUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
log(info: any, callback: any) {
|
||||||
|
discordAlert(info)
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
@ -20,8 +20,7 @@ export function SyslogLogger(instanceId: string, target: string) {
|
|||||||
|
|
||||||
const { error, warn } = LoggerService()
|
const { error, warn } = LoggerService()
|
||||||
.create('SyslogLogger')
|
.create('SyslogLogger')
|
||||||
.breadcrumb(instanceId)
|
.breadcrumb({ instanceId, target })
|
||||||
.breadcrumb(target)
|
|
||||||
|
|
||||||
const api = {
|
const api = {
|
||||||
info: (msg: string) => {
|
info: (msg: string) => {
|
||||||
|
35
packages/pockethost/src/core/ioc.ts
Normal file
35
packages/pockethost/src/core/ioc.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { LogEntry } from 'winston'
|
||||||
|
import { InstanceFields, InstanceId, Logger, UserFields } from '../common'
|
||||||
|
import { IoCManager } from '../common/ioc'
|
||||||
|
import { Settings } from '../constants'
|
||||||
|
|
||||||
|
export type MothershipProvider = {
|
||||||
|
getAllInstances(): Promise<InstanceFields[]>
|
||||||
|
getInstanceById(id: InstanceId): Promise<[InstanceFields, UserFields] | []>
|
||||||
|
getInstanceBySubdomain(
|
||||||
|
subdomain: InstanceFields['subdomain'],
|
||||||
|
): Promise<[InstanceFields, UserFields] | []>
|
||||||
|
updateInstance(id: InstanceId, fields: Partial<InstanceFields>): Promise<void>
|
||||||
|
}
|
||||||
|
type UnsubFunc = () => void
|
||||||
|
|
||||||
|
export type InstanceLogProvider = (
|
||||||
|
instanceId: InstanceId,
|
||||||
|
target: string,
|
||||||
|
) => {
|
||||||
|
info(msg: string): void
|
||||||
|
error(msg: string): void
|
||||||
|
tail(linesBack: number, data: (line: LogEntry) => void): UnsubFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ioc = new IoCManager<{
|
||||||
|
settings: Settings
|
||||||
|
mothership: MothershipProvider
|
||||||
|
instanceLogger: InstanceLogProvider
|
||||||
|
logger: Logger
|
||||||
|
}>()
|
||||||
|
|
||||||
|
export const settings = () => ioc.service('settings')
|
||||||
|
export const mothership = () => ioc.service('mothership')
|
||||||
|
export const instanceLogger = () => ioc.service('instanceLogger')
|
||||||
|
export const logger = () => ioc.service('logger')
|
@ -33,7 +33,7 @@ export const tryFetch = async (
|
|||||||
timeoutMs: TRYFETCH_TIMEOUT_MS,
|
timeoutMs: TRYFETCH_TIMEOUT_MS,
|
||||||
...config,
|
...config,
|
||||||
}
|
}
|
||||||
const logger = LoggerService().create(`tryFetch`).breadcrumb(url)
|
const logger = LoggerService().create(`tryFetch`).breadcrumb({ url })
|
||||||
const { dbg } = logger
|
const { dbg } = logger
|
||||||
return new Promise<Response>((resolve, reject) => {
|
return new Promise<Response>((resolve, reject) => {
|
||||||
const again = () => setTimeout(_real_tryFetch, retryMs)
|
const again = () => setTimeout(_real_tryFetch, retryMs)
|
||||||
|
111
packages/pockethost/src/core/winston.ts
Normal file
111
packages/pockethost/src/core/winston.ts
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import { inspect } from 'node:util'
|
||||||
|
import winston from 'winston'
|
||||||
|
import { Logger, mkSingleton } from '../common'
|
||||||
|
import { DEBUG, DISCORD_ALERT_CHANNEL_URL } from '../constants'
|
||||||
|
import { DiscordTransport } from './DiscordTransport'
|
||||||
|
|
||||||
|
const format = winston.format.combine(
|
||||||
|
winston.format.colorize(),
|
||||||
|
winston.format.printf(({ level, message, timestamp, ...meta }) => {
|
||||||
|
const final: string[] = []
|
||||||
|
message.forEach((m: string) => {
|
||||||
|
if (typeof m === 'string' && !!m.match(/\n/)) {
|
||||||
|
final.push(...m.split(/\n/))
|
||||||
|
} else if (typeof m === 'object') {
|
||||||
|
final.push(inspect(m, { depth: null }))
|
||||||
|
} else {
|
||||||
|
final.push(m)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return `${level}: ${final.join(' ')}`
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
export const WinstonLoggerService = mkSingleton<{}, Logger>(() => {
|
||||||
|
const logger = winston.createLogger({
|
||||||
|
format: winston.format.json(),
|
||||||
|
transports: [
|
||||||
|
new winston.transports.Console({
|
||||||
|
level: DEBUG() ? 'debug' : 'info',
|
||||||
|
format,
|
||||||
|
}),
|
||||||
|
new winston.transports.File({
|
||||||
|
filename: 'error.log',
|
||||||
|
level: 'error',
|
||||||
|
maxsize: 100 * 1024 * 1024,
|
||||||
|
maxFiles: 10,
|
||||||
|
tailable: true,
|
||||||
|
}),
|
||||||
|
new winston.transports.File({
|
||||||
|
filename: 'debug.log',
|
||||||
|
level: 'debug',
|
||||||
|
maxsize: 100 * 1024 * 1024,
|
||||||
|
maxFiles: 10,
|
||||||
|
tailable: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
rejectionHandlers: [
|
||||||
|
new winston.transports.Console({
|
||||||
|
level: 'error',
|
||||||
|
format,
|
||||||
|
}),
|
||||||
|
new winston.transports.File({
|
||||||
|
filename: 'rejections.log',
|
||||||
|
maxsize: 100 * 1024 * 1024,
|
||||||
|
maxFiles: 10,
|
||||||
|
tailable: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
exceptionHandlers: [
|
||||||
|
new winston.transports.Console({
|
||||||
|
level: 'error',
|
||||||
|
format,
|
||||||
|
}),
|
||||||
|
new winston.transports.File({
|
||||||
|
filename: 'exceptions.log',
|
||||||
|
maxsize: 100 * 1024 * 1024,
|
||||||
|
maxFiles: 10,
|
||||||
|
tailable: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
defaultMeta: {},
|
||||||
|
})
|
||||||
|
logger.exitOnError = true
|
||||||
|
|
||||||
|
{
|
||||||
|
const url = DISCORD_ALERT_CHANNEL_URL()
|
||||||
|
if (url) {
|
||||||
|
logger.add(new DiscordTransport({ level: 'error', webhookUrl: url }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const createApi = (logger: winston.Logger): Logger => {
|
||||||
|
const api: Logger = {
|
||||||
|
create: (name: string) => {
|
||||||
|
return createApi(logger.child({ ...logger.defaultMeta, name }))
|
||||||
|
},
|
||||||
|
raw: (...args: any[]) => logger.silly(args),
|
||||||
|
dbg: (...args: any[]) => logger.debug(args),
|
||||||
|
warn: (...args: any[]) => logger.warn(args),
|
||||||
|
info: (...args: any[]) => logger.info(args),
|
||||||
|
error: (...args: any[]) => logger.error(args),
|
||||||
|
criticalError: (...args: any[]) => logger.error(args),
|
||||||
|
setLevel: (level) => {},
|
||||||
|
trace: (...args: any[]) => logger.silly(args),
|
||||||
|
debug: (...args: any[]) => logger.debug(args),
|
||||||
|
breadcrumb: (s) => {
|
||||||
|
Object.assign(logger.defaultMeta, s)
|
||||||
|
return api
|
||||||
|
},
|
||||||
|
shutdown: () => {},
|
||||||
|
child: (name) => createApi(logger.child({ name })),
|
||||||
|
abort: (...args) => {
|
||||||
|
logger.error(args)
|
||||||
|
process.exit(1)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
return createApi(logger)
|
||||||
|
})
|
@ -33,7 +33,9 @@ export function InstanceLogger(
|
|||||||
target: string,
|
target: string,
|
||||||
options: Partial<InstanceLoggerOptions> = {},
|
options: Partial<InstanceLoggerOptions> = {},
|
||||||
) {
|
) {
|
||||||
const { dbg, info } = LoggerService().create(instanceId).breadcrumb(target)
|
const { dbg, info } = LoggerService()
|
||||||
|
.create(instanceId)
|
||||||
|
.breadcrumb({ target })
|
||||||
const { ttl } = mergeConfig<InstanceLoggerOptions>({ ttl: 0 }, options)
|
const { ttl } = mergeConfig<InstanceLoggerOptions>({ ttl: 0 }, options)
|
||||||
|
|
||||||
dbg({ ttl })
|
dbg({ ttl })
|
||||||
@ -85,8 +87,7 @@ export function InstanceLogger(
|
|||||||
|
|
||||||
const { error, warn } = LoggerService()
|
const { error, warn } = LoggerService()
|
||||||
.create('InstanceLogger')
|
.create('InstanceLogger')
|
||||||
.breadcrumb(instanceId)
|
.breadcrumb({ instanceId, target })
|
||||||
.breadcrumb(target)
|
|
||||||
|
|
||||||
const resetTtl = (() => {
|
const resetTtl = (() => {
|
||||||
let tid: ReturnType<typeof setTimeout>
|
let tid: ReturnType<typeof setTimeout>
|
||||||
|
@ -72,7 +72,7 @@ export const instanceService = mkSingleton(
|
|||||||
const getInstanceApi = (instance: InstanceFields): Promise<InstanceApi> => {
|
const getInstanceApi = (instance: InstanceFields): Promise<InstanceApi> => {
|
||||||
const _logger = instanceServiceLogger.create(`getInstanceApi`)
|
const _logger = instanceServiceLogger.create(`getInstanceApi`)
|
||||||
const { id, subdomain, version } = instance
|
const { id, subdomain, version } = instance
|
||||||
_logger.breadcrumb(`${subdomain}:${id}:${version}`)
|
_logger.breadcrumb({ subdomain, id, version })
|
||||||
const { dbg, trace } = _logger
|
const { dbg, trace } = _logger
|
||||||
return new Promise<InstanceApi>((resolve, reject) => {
|
return new Promise<InstanceApi>((resolve, reject) => {
|
||||||
let maxTries = instanceApiTimeoutMs / instanceApiCheckIntervalMs
|
let maxTries = instanceApiTimeoutMs / instanceApiCheckIntervalMs
|
||||||
@ -256,7 +256,7 @@ export const instanceService = mkSingleton(
|
|||||||
dbg(`shut down: releasing port`)
|
dbg(`shut down: releasing port`)
|
||||||
releasePort()
|
releasePort()
|
||||||
}, CLEANUP_PRIORITY_LAST)
|
}, CLEANUP_PRIORITY_LAST)
|
||||||
systemInstanceLogger.breadcrumb(`port:${newPort}`)
|
systemInstanceLogger.breadcrumb({ port: newPort })
|
||||||
dbg(`Found port`)
|
dbg(`Found port`)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -94,7 +94,7 @@ export const createPocketbaseService = async (
|
|||||||
dev,
|
dev,
|
||||||
} = _cfg
|
} = _cfg
|
||||||
|
|
||||||
logger.breadcrumb(subdomain).breadcrumb(instanceId)
|
logger.breadcrumb({ subdomain, instanceId })
|
||||||
const iLogger = SyslogLogger(instanceId, 'exec')
|
const iLogger = SyslogLogger(instanceId, 'exec')
|
||||||
cm.add(async () => {
|
cm.add(async () => {
|
||||||
dbg(`Shutting down iLogger`)
|
dbg(`Shutting down iLogger`)
|
||||||
@ -259,7 +259,7 @@ export const createPocketbaseService = async (
|
|||||||
cm.shutdown().catch(error)
|
cm.shutdown().catch(error)
|
||||||
})
|
})
|
||||||
const url = mkInternalUrl(port)
|
const url = mkInternalUrl(port)
|
||||||
logger.breadcrumb(url)
|
logger.breadcrumb({ url })
|
||||||
dbg(`Making exit hook for ${url}`)
|
dbg(`Making exit hook for ${url}`)
|
||||||
const unsub = asyncExitHook(async () => {
|
const unsub = asyncExitHook(async () => {
|
||||||
await api.kill()
|
await api.kill()
|
||||||
|
28
pnpm-lock.yaml
generated
28
pnpm-lock.yaml
generated
@ -479,6 +479,9 @@ importers:
|
|||||||
winston-syslog:
|
winston-syslog:
|
||||||
specifier: ^2.7.0
|
specifier: ^2.7.0
|
||||||
version: 2.7.0(winston@3.11.0)
|
version: 2.7.0(winston@3.11.0)
|
||||||
|
winston-transport:
|
||||||
|
specifier: ^4.7.1
|
||||||
|
version: 4.7.1
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@types/cors':
|
'@types/cors':
|
||||||
specifier: ^2.8.17
|
specifier: ^2.8.17
|
||||||
@ -3894,6 +3897,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==}
|
resolution: {integrity: sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
|
|
||||||
|
logform@2.6.1:
|
||||||
|
resolution: {integrity: sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
|
||||||
lower-case@2.0.2:
|
lower-case@2.0.2:
|
||||||
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
|
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
|
||||||
|
|
||||||
@ -6012,8 +6019,8 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
winston: ^3.8.2
|
winston: ^3.8.2
|
||||||
|
|
||||||
winston-transport@4.6.0:
|
winston-transport@4.7.1:
|
||||||
resolution: {integrity: sha512-wbBA9PbPAHxKiygo7ub7BYRiKxms0tpfU2ljtWzb3SjRjv5yl6Ozuy/TkXf00HTAt+Uylo3gSkNwzc4ME0wiIg==}
|
resolution: {integrity: sha512-wQCXXVgfv/wUPOfb2x0ruxzwkcZfxcktz6JIMUaPLmcNhO4bZTwA/WtDWK74xV3F2dKu8YadrFv0qhwYjVEwhA==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
|
|
||||||
winston@3.11.0:
|
winston@3.11.0:
|
||||||
@ -7159,7 +7166,7 @@ snapshots:
|
|||||||
'@types/glossy': 0.1.3
|
'@types/glossy': 0.1.3
|
||||||
'@types/node': 20.8.10
|
'@types/node': 20.8.10
|
||||||
winston: 3.11.0
|
winston: 3.11.0
|
||||||
winston-transport: 4.6.0
|
winston-transport: 4.7.1
|
||||||
|
|
||||||
JSONStream@1.3.5:
|
JSONStream@1.3.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -9832,6 +9839,15 @@ snapshots:
|
|||||||
safe-stable-stringify: 2.4.3
|
safe-stable-stringify: 2.4.3
|
||||||
triple-beam: 1.4.1
|
triple-beam: 1.4.1
|
||||||
|
|
||||||
|
logform@2.6.1:
|
||||||
|
dependencies:
|
||||||
|
'@colors/colors': 1.6.0
|
||||||
|
'@types/triple-beam': 1.3.4
|
||||||
|
fecha: 4.2.3
|
||||||
|
ms: 2.1.3
|
||||||
|
safe-stable-stringify: 2.4.3
|
||||||
|
triple-beam: 1.4.1
|
||||||
|
|
||||||
lower-case@2.0.2:
|
lower-case@2.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.6.2
|
tslib: 2.6.2
|
||||||
@ -12167,9 +12183,9 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
unix-dgram: 2.0.6
|
unix-dgram: 2.0.6
|
||||||
|
|
||||||
winston-transport@4.6.0:
|
winston-transport@4.7.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
logform: 2.6.0
|
logform: 2.6.1
|
||||||
readable-stream: 3.6.2
|
readable-stream: 3.6.2
|
||||||
triple-beam: 1.4.1
|
triple-beam: 1.4.1
|
||||||
|
|
||||||
@ -12185,7 +12201,7 @@ snapshots:
|
|||||||
safe-stable-stringify: 2.4.3
|
safe-stable-stringify: 2.4.3
|
||||||
stack-trace: 0.0.10
|
stack-trace: 0.0.10
|
||||||
triple-beam: 1.4.1
|
triple-beam: 1.4.1
|
||||||
winston-transport: 4.6.0
|
winston-transport: 4.7.1
|
||||||
|
|
||||||
with@7.0.2:
|
with@7.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user