Skip to content

Commit

Permalink
Merge pull request #622 from nats-io/stacks
Browse files Browse the repository at this point in the history
[FEAT] disable async trace extra information
  • Loading branch information
aricart authored Oct 26, 2023
2 parents 17a02a6 + 6b9c2e0 commit 41e3118
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 19 deletions.
5 changes: 4 additions & 1 deletion jetstream/jsmsg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,10 @@ export class JsMsgImpl implements JsMsg {
if (this.msg.reply) {
const mi = this.msg as MsgImpl;
const proto = mi.publisher as unknown as ProtocolHandler;
const r = new RequestOne(proto.muxSubscriptions, this.msg.reply);
const trace = !(proto.options?.noAsyncTraces || false);
const r = new RequestOne(proto.muxSubscriptions, this.msg.reply, {
timeout: 1000,
}, trace);
proto.request(r);
try {
proto.publish(
Expand Down
6 changes: 6 additions & 0 deletions nats-base-client/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1355,6 +1355,12 @@ export interface ConnectionOptions {
* This option should be used with care as it will disable this behaviour when true
*/
ignoreAuthErrorAbort?: boolean;

/**
* When true, the client will not augment timeout and other error traces with
* additional context as to where the operation was started.
*/
noAsyncTraces?: boolean;
}

/**
Expand Down
24 changes: 18 additions & 6 deletions nats-base-client/nats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ export class NatsConnectionImpl implements NatsConnection {
data: Payload = Empty,
opts: Partial<RequestManyOptions> = { maxWait: 1000, maxMessages: -1 },
): Promise<QueuedIterator<Msg>> {
const asyncTraces = !(this.protocol.options.noAsyncTraces || false);

try {
this._check(subject, true, true);
} catch (err) {
Expand Down Expand Up @@ -200,7 +202,7 @@ export class NatsConnectionImpl implements NatsConnection {

if (opts.noMux) {
// we setup a subscription and manage it
const stack = new Error().stack;
const stack = asyncTraces ? new Error().stack : null;
let max = typeof opts.maxMessages === "number" && opts.maxMessages > 0
? opts.maxMessages
: -1;
Expand All @@ -217,7 +219,9 @@ export class NatsConnectionImpl implements NatsConnection {
// augment any error with the current stack to provide context
// for the error on the suer code
if (err) {
err.stack += `\n\n${stack}`;
if (stack) {
err.stack += `\n\n${stack}`;
}
cancel(err);
return;
}
Expand Down Expand Up @@ -335,6 +339,7 @@ export class NatsConnectionImpl implements NatsConnection {
} catch (err) {
return Promise.reject(err);
}
const asyncTraces = !(this.protocol.options.noAsyncTraces || false);
opts.timeout = opts.timeout || 1000;
if (opts.timeout < 1) {
return Promise.reject(new NatsError("timeout", ErrorCode.InvalidOption));
Expand All @@ -353,7 +358,7 @@ export class NatsConnectionImpl implements NatsConnection {
? opts.reply
: createInbox(this.options.inboxPrefix);
const d = deferred<Msg>();
const errCtx = new Error();
const errCtx = asyncTraces ? new Error() : null;
const sub = this.subscribe(
inbox,
{
Expand All @@ -362,15 +367,17 @@ export class NatsConnectionImpl implements NatsConnection {
callback: (err, msg) => {
if (err) {
// timeouts from `timeout()` will have the proper stack
if (err.code !== ErrorCode.Timeout) {
if (errCtx && err.code !== ErrorCode.Timeout) {
err.stack += `\n\n${errCtx.stack}`;
}
d.reject(err);
} else {
err = isRequestError(msg);
if (err) {
// if we failed here, help the developer by showing what failed
err.stack += `\n\n${errCtx.stack}`;
if (errCtx) {
err.stack += `\n\n${errCtx.stack}`;
}
d.reject(err);
} else {
d.resolve(msg);
Expand All @@ -386,7 +393,12 @@ export class NatsConnectionImpl implements NatsConnection {
});
return d;
} else {
const r = new RequestOne(this.protocol.muxSubscriptions, subject, opts);
const r = new RequestOne(
this.protocol.muxSubscriptions,
subject,
opts,
asyncTraces,
);
this.protocol.request(r);

try {
Expand Down
4 changes: 3 additions & 1 deletion nats-base-client/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,10 @@ export class SubscriptionImpl extends QueuedIteratorImpl<Msg>
this.noIterator = typeof opts.callback === "function";
this.closed = deferred();

const asyncTraces = !(protocol.options?.noAsyncTraces || false);

if (opts.timeout) {
this.timer = timeout<void>(opts.timeout);
this.timer = timeout<void>(opts.timeout, asyncTraces);
this.timer
.then(() => {
// timer was cancelled
Expand Down
22 changes: 15 additions & 7 deletions nats-base-client/request.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 The NATS Authors
* Copyright 2020-2023 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand Down Expand Up @@ -28,19 +28,22 @@ import {
export class BaseRequest {
token: string;
received: number;
ctx: Error;
ctx?: Error;
requestSubject: string;
mux: MuxSubscription;

constructor(
mux: MuxSubscription,
requestSubject: string,
asyncTraces = true,
) {
this.mux = mux;
this.requestSubject = requestSubject;
this.received = 0;
this.token = nuid.next();
this.ctx = new Error();
if (asyncTraces) {
this.ctx = new Error();
}
}
}

Expand Down Expand Up @@ -96,7 +99,9 @@ export class RequestMany extends BaseRequest implements Request {

resolver(err: Error | null, msg: Msg): void {
if (err) {
err.stack += `\n\n${this.ctx.stack}`;
if (this.ctx) {
err.stack += `\n\n${this.ctx.stack}`;
}
this.cancel(err as NatsError);
} else {
this.callback(null, msg);
Expand Down Expand Up @@ -132,19 +137,22 @@ export class RequestOne extends BaseRequest implements Request {
mux: MuxSubscription,
requestSubject: string,
opts: RequestOptions = { timeout: 1000 },
asyncTraces = true,
) {
super(mux, requestSubject);
super(mux, requestSubject, asyncTraces);
// extend(this, opts);
this.deferred = deferred();
this.timer = timeout<Msg>(opts.timeout);
this.timer = timeout<Msg>(opts.timeout, asyncTraces);
}

resolver(err: Error | null, msg: Msg): void {
if (this.timer) {
this.timer.cancel();
}
if (err) {
err.stack += `\n\n${this.ctx.stack}`;
if (this.ctx) {
err.stack += `\n\n${this.ctx.stack}`;
}
this.deferred.reject(err);
} else {
this.deferred.resolve(msg);
Expand Down
12 changes: 8 additions & 4 deletions nats-base-client/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2021 The NATS Authors
* Copyright 2018-2023 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand Down Expand Up @@ -64,9 +64,9 @@ export interface Timeout<T> extends Promise<T> {
cancel: () => void;
}

export function timeout<T>(ms: number): Timeout<T> {
export function timeout<T>(ms: number, asyncTraces = true): Timeout<T> {
// by generating the stack here to help identify what timed out
const err = NatsError.errorForCode(ErrorCode.Timeout);
const err = asyncTraces ? NatsError.errorForCode(ErrorCode.Timeout) : null;
let methods;
let timer: number;
const p = new Promise((_resolve, reject) => {
Expand All @@ -78,7 +78,11 @@ export function timeout<T>(ms: number): Timeout<T> {
methods = { cancel };
// @ts-ignore: node is not a number
timer = setTimeout(() => {
reject(err);
if (err === null) {
reject(NatsError.errorForCode(ErrorCode.Timeout));
} else {
reject(err);
}
}, ms);
});
// noinspection JSUnusedAssignment
Expand Down

0 comments on commit 41e3118

Please sign in to comment.