How to send logs from Activities in TypeScript
Activities run in the standard Node.js environment and can use any Node.js logger.
Inject Activity context via interceptor and log all Activity executions
instrumentation/src/activities/interceptors.ts
- TypeScript
- JavaScript
import { Context } from '@temporalio/activity';
import { ActivityInboundCallsInterceptor, ActivityExecuteInput, Next } from '@temporalio/worker';
import { Logger } from 'winston';
/** An Activity Context with an attached logger */
export interface ContextWithLogger extends Context {
logger: Logger;
}
/** Get the current Activity context with an attached logger */
export function getContext(): ContextWithLogger {
return Context.current() as ContextWithLogger;
}
/** Logs Activity executions and their duration */
export class ActivityInboundLogInterceptor implements ActivityInboundCallsInterceptor {
public readonly logger: Logger;
constructor(ctx: Context, logger: Logger) {
this.logger = logger.child({
activity: ctx.info,
});
// Set a logger instance on the current Activity Context to provide
// contextual logging information to each log entry generated by the Activity.
(ctx as ContextWithLogger).logger = this.logger;
}
async execute(input: ActivityExecuteInput, next: Next<ActivityInboundCallsInterceptor, 'execute'>): Promise<unknown> {
let error: any = undefined;
const startTime = process.hrtime.bigint();
try {
return await next(input);
} catch (err: any) {
error = err;
throw err;
} finally {
const durationNanos = process.hrtime.bigint() - startTime;
const durationMs = Number(durationNanos / 1_000_000n);
if (error) {
this.logger.error('activity failed', { error, durationMs });
} else {
this.logger.debug('activity completed', { durationMs });
}
}
}
}
import { Context } from '@temporalio/activity';
/** Get the current Activity context with an attached logger */
export function getContext() {
return Context.current();
}
/** Logs Activity executions and their duration */
export class ActivityInboundLogInterceptor {
logger;
constructor(ctx, logger) {
this.logger = logger.child({
activity: ctx.info,
});
// Set a logger instance on the current Activity Context to provide
// contextual logging information to each log entry generated by the Activity.
ctx.logger = this.logger;
}
async execute(input, next) {
let error = undefined;
const startTime = process.hrtime.bigint();
try {
return await next(input);
}
catch (err) {
error = err;
throw err;
}
finally {
const durationNanos = process.hrtime.bigint() - startTime;
const durationMs = Number(durationNanos / 1000000n);
if (error) {
this.logger.error('activity failed', { error, durationMs });
}
else {
this.logger.debug('activity completed', { durationMs });
}
}
}
}
Use the injected logger from an Activity
instrumentation/src/activities/index.ts
- TypeScript
- JavaScript
import { getContext } from './interceptors';
export async function greet(name: string): Promise<string> {
const { logger } = getContext();
logger.info('Log from activity', { name });
return `Hello, ${name}!`;
}
import { getContext } from './interceptors';
export async function greet(name) {
const { logger } = getContext();
logger.info('Log from activity', { name });
return `Hello, ${name}!`;
}