Skip to content

Commit

Permalink
UBERF-5795: Improve logging capabilities (hcengineering#4813)
Browse files Browse the repository at this point in the history
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
Signed-off-by: Tiago Cruz <tcruz@netic.io>
  • Loading branch information
haiodo authored and tjaoc committed Mar 5, 2024
1 parent 0f03efe commit 45fda63
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 22 deletions.
44 changes: 33 additions & 11 deletions packages/core/src/measurements/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,35 @@ export class MeasureMetricsContext implements MeasureContext {
this.name = name
this.params = params
this.metrics = metrics
this.done = measure(metrics, params, fullParams)
this.done = measure(metrics, params, fullParams, (spend) => {
this.logger.logOperation(this.name, spend, { ...params, ...fullParams })
})

this.logger = logger ?? {
info: (msg, args) => {
console.info(msg, ...args)
console.info(msg, ...Object.entries(args ?? {}).map((it) => `${it[0]}=${JSON.stringify(it[1])}`))
},
error: (msg, args) => {
console.error(msg, ...args)
}
console.error(msg, ...Object.entries(args ?? {}).map((it) => `${it[0]}=${JSON.stringify(it[1])}`))
},
close: async () => {},
logOperation: (operation, time, params) => {}
}
}

measure (name: string, value: number): void {
const c = new MeasureMetricsContext('#' + name, {}, {}, childMetrics(this.metrics, ['#' + name]))
const c = new MeasureMetricsContext('#' + name, {}, {}, childMetrics(this.metrics, ['#' + name]), this.logger)
c.done(value)
}

newChild (name: string, params: ParamsType, fullParams?: FullParamsType, logger?: MeasureLogger): MeasureContext {
return new MeasureMetricsContext(name, params, fullParams ?? {}, childMetrics(this.metrics, [name]), logger)
return new MeasureMetricsContext(
name,
params,
fullParams ?? {},
childMetrics(this.metrics, [name]),
logger ?? this.logger
)
}

async with<T>(
Expand All @@ -50,7 +60,7 @@ export class MeasureMetricsContext implements MeasureContext {
op: (ctx: MeasureContext) => T | Promise<T>,
fullParams?: ParamsType
): Promise<T> {
const c = this.newChild(name, params, fullParams)
const c = this.newChild(name, params, fullParams, this.logger)
try {
let value = op(c)
if (value instanceof Promise) {
Expand All @@ -64,12 +74,24 @@ export class MeasureMetricsContext implements MeasureContext {
}
}

async error (message: string, ...args: any[]): Promise<void> {
this.logger.error(message, args)
async withLog<T>(
name: string,
params: ParamsType,
op: (ctx: MeasureContext) => T | Promise<T>,
fullParams?: ParamsType
): Promise<T> {
const st = Date.now()
const r = await this.with(name, params, op, fullParams)
this.logger.logOperation(name, Date.now() - st, { ...params, ...fullParams })
return r
}

async error (message: string, args?: Record<string, any>): Promise<void> {
this.logger.error(message, { ...this.params, ...args })
}

async info (message: string, ...args: any[]): Promise<void> {
this.logger.info(message, args)
async info (message: string, args?: Record<string, any>): Promise<void> {
this.logger.info(message, { ...this.params, ...args })
}

end (): void {
Expand Down
8 changes: 7 additions & 1 deletion packages/core/src/measurements/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,12 @@ function getUpdatedTopResult (
* Measure with tree expansion. Operation counter will be added only to leaf's.
* @public
*/
export function measure (metrics: Metrics, params: ParamsType, fullParams: FullParamsType = {}): () => void {
export function measure (
metrics: Metrics,
params: ParamsType,
fullParams: FullParamsType = {},
endOp?: (spend: number) => void
): () => void {
const st = Date.now()
return (value?: number) => {
const ed = Date.now()
Expand Down Expand Up @@ -75,6 +80,7 @@ export function measure (metrics: Metrics, params: ParamsType, fullParams: FullP
metrics.operations++

metrics.topResult = getUpdatedTopResult(metrics.topResult, ed - st, fullParams)
endOp?.(ed - st)
}
}

Expand Down
21 changes: 17 additions & 4 deletions packages/core/src/measurements/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,14 @@ export interface Metrics extends MetricsData {
* @public
*/
export interface MeasureLogger {
info: (message: string, ...args: any[]) => void
error: (message: string, ...args: any[]) => void
info: (message: string, obj?: Record<string, any>) => void
error: (message: string, obj?: Record<string, any>) => void

logOperation: (operation: string, time: number, params: ParamsType) => void

childLogger?: (name: string, params: Record<string, any>) => MeasureLogger

close: () => Promise<void>
}
/**
* @public
Expand All @@ -54,13 +60,20 @@ export interface MeasureContext {
fullParams?: FullParamsType
) => Promise<T>

withLog: <T>(
name: string,
params: ParamsType,
op: (ctx: MeasureContext) => T | Promise<T>,
fullParams?: FullParamsType
) => Promise<T>

logger: MeasureLogger

measure: (name: string, value: number) => void

// Capture error
error: (message: string, ...args: any[]) => Promise<void>
info: (message: string, ...args: any[]) => Promise<void>
error: (message: string, obj?: Record<string, any>) => Promise<void>
info: (message: string, obj?: Record<string, any>) => Promise<void>

// Mark current context as complete
// If no value is passed, time difference will be used.
Expand Down
27 changes: 21 additions & 6 deletions server/server/src/apm.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MeasureContext, MeasureLogger, ParamType } from '@hcengineering/core'
import { MeasureContext, MeasureLogger, ParamType, ParamsType } from '@hcengineering/core'
import apm, { Agent, Span, Transaction } from 'elastic-apm-node'

/**
Expand Down Expand Up @@ -37,11 +37,13 @@ export class APMMeasureContext implements MeasureContext {
this.parent = parent
this.logger = {
info: (msg, args) => {
agent.logger.info(msg, args)
agent.logger.info({ message: msg, ...args })
},
error: (msg, args) => {
agent.logger.error(msg, args)
}
agent.logger.error({ message: msg, ...args })
},
logOperation (operation, time, params) {},
close: async () => {}
}
if (!(noTransaction ?? false)) {
if (this.parent === undefined) {
Expand All @@ -63,8 +65,9 @@ export class APMMeasureContext implements MeasureContext {

async with<T>(
name: string,
params: Record<string, ParamType>,
op: (ctx: MeasureContext) => T | Promise<T>
params: ParamsType,
op: (ctx: MeasureContext) => T | Promise<T>,
fullParams?: ParamsType
): Promise<T> {
const c = this.newChild(name, params)
try {
Expand All @@ -80,6 +83,18 @@ export class APMMeasureContext implements MeasureContext {
}
}

async withLog<T>(
name: string,
params: ParamsType,
op: (ctx: MeasureContext) => T | Promise<T>,
fullParams?: ParamsType
): Promise<T> {
const st = Date.now()
const r = await this.with(name, params, op, fullParams)
this.logger.logOperation(name, Date.now() - st, { ...params, ...fullParams })
return r
}

async error (message: string, ...args: any[]): Promise<void> {
this.logger.error(message, args)

Expand Down

0 comments on commit 45fda63

Please sign in to comment.