@temporalio/workflow
Version:
Temporal.io SDK Workflow sub-package
93 lines • 4.49 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.log = void 0;
exports.executeWithLifecycleLogging = executeWithLifecycleLogging;
exports.workflowLogAttributes = workflowLogAttributes;
const interceptors_1 = require("@temporalio/common/lib/interceptors");
const common_1 = require("@temporalio/common");
const stack_helpers_1 = require("./stack-helpers");
const sinks_1 = require("./sinks");
const errors_1 = require("./errors");
const interfaces_1 = require("./interfaces");
const global_attributes_1 = require("./global-attributes");
const loggerSink = (0, sinks_1.proxySinks)().__temporal_logger;
/**
* Symbol used by the SDK logger to extract a timestamp from log attributes.
* Also defined in `worker/logger.ts` - intentionally not shared.
*/
const LogTimestamp = Symbol.for('log_timestamp');
/**
* Default workflow logger.
*
* This logger is replay-aware and will omit log messages on workflow replay. Messages emitted by this logger are
* funnelled through a sink that forwards them to the logger registered on {@link Runtime.logger}.
*
* Attributes from the current Workflow Execution context are automatically included as metadata on every log
* entries. An extra `sdkComponent` metadata attribute is also added, with value `workflow`; this can be used for
* fine-grained filtering of log entries further downstream.
*
* To customize log attributes, register a {@link WorkflowOutboundCallsInterceptor} that intercepts the
* `getLogAttributes()` method.
*
* Notice that since sinks are used to power this logger, any log attributes must be transferable via the
* {@link https://nodejs.org/api/worker_threads.html#worker_threads_port_postmessage_value_transferlist | postMessage}
* API.
*
* NOTE: Specifying a custom logger through {@link defaultSink} or by manually registering a sink named
* `defaultWorkerLogger` has been deprecated. Please use {@link Runtime.logger} instead.
*/
exports.log = Object.fromEntries(['trace', 'debug', 'info', 'warn', 'error'].map((level) => {
return [
level,
(message, attrs) => {
const activator = (0, global_attributes_1.assertInWorkflowContext)('Workflow.log(...) may only be used from workflow context.');
const getLogAttributes = (0, interceptors_1.composeInterceptors)(activator.interceptors.outbound, 'getLogAttributes', (a) => a);
return loggerSink[level](message, {
// Inject the call time in nanosecond resolution as expected by the worker logger.
[LogTimestamp]: activator.getTimeOfDay(),
sdkComponent: common_1.SdkComponent.workflow,
...getLogAttributes(workflowLogAttributes(activator.info)),
...attrs,
});
},
];
}));
function executeWithLifecycleLogging(fn) {
exports.log.debug('Workflow started', { sdkComponent: common_1.SdkComponent.worker });
const p = fn().then((res) => {
exports.log.debug('Workflow completed', { sdkComponent: common_1.SdkComponent.worker });
return res;
}, (error) => {
// Avoid using instanceof checks in case the modules they're defined in loaded more than once,
// e.g. by jest or when multiple versions are installed.
if (typeof error === 'object' && error != null) {
if ((0, errors_1.isCancellation)(error)) {
exports.log.debug('Workflow completed as cancelled', { sdkComponent: common_1.SdkComponent.worker });
throw error;
}
else if (error instanceof interfaces_1.ContinueAsNew) {
exports.log.debug('Workflow continued as new', { sdkComponent: common_1.SdkComponent.worker });
throw error;
}
}
exports.log.warn('Workflow failed', { error, sdkComponent: common_1.SdkComponent.worker });
throw error;
});
// Avoid showing this interceptor in stack trace query
(0, stack_helpers_1.untrackPromise)(p);
return p;
}
/**
* Returns a map of attributes to be set _by default_ on log messages for a given Workflow.
* Note that this function may be called from outside of the Workflow context (eg. by the worker itself).
*/
function workflowLogAttributes(info) {
return {
namespace: info.namespace,
taskQueue: info.taskQueue,
workflowId: info.workflowId,
runId: info.runId,
workflowType: info.workflowType,
};
}
//# sourceMappingURL=logs.js.map
;