Skip to content

CaptureContext in captureMessage disallows the level to be set. #2819

Closed
@stuckj

Description

@stuckj

Package + Version

  • @sentry/browser
  • @sentry/node
  • raven-js
  • raven-node (raven for node)
  • other:

Version:

5.21.0

Description

This issue here describes the bug I'm going to explain below.

The change in captureMessage in the node SDK introduced in #2627 changed captureMessage to be able to accept a context to apply to the message. This is handy. However, you can't specify both a context and a severity. I tried to do so by simply specifying the level in the context, but I'm seeing the error in the linked issue above that indicates that the value for level was discarded because it was invalid. I believe it was telling me it was blank (though that wasn't super clear in the error).

I traced through the code a bit and it appears this is because the generated JS parses out EITHER the level or the context and passes them on to your hub function. This is what I see in the generated JS (from your TS) off npm:

function captureMessage(message, captureContext) {
    var syntheticException;
    try {
        throw new Error(message);
    }
    catch (exception) {
        syntheticException = exception;
    }
    // This is necessary to provide explicit scopes upgrade, without changing the original
    // arrity of the `captureMessage(message, level)` method.
    var level = typeof captureContext === 'string' ? captureContext : undefined;
    var context = typeof captureContext !== 'string' ? { captureContext: captureContext } : undefined;
    return callOnHub('captureMessage', message, level, tslib_1.__assign({ originalException: message, syntheticException: syntheticException }, context));
}
exports.captureMessage = captureMessage;

When you pass a context to captureMessage, the callOnHub will get an undefined level and the context. Then in your hub handler (see generated JS below):

    Hub.prototype.captureMessage = function (message, level, hint) {
        var eventId = (this._lastEventId = utils_1.uuid4());
        var finalHint = hint;
        // If there's no explicit hint provided, mimick the same thing that would happen
        // in the minimal itself to create a consistent behavior.
        // We don't do this in the client, as it's the lowest level API, and doing this,
        // would prevent user from having full control over direct calls.
        if (!hint) {
            var syntheticException = void 0;
            try {
                throw new Error(message);
            }
            catch (exception) {
                syntheticException = exception;
            }
            finalHint = {
                originalException: message,
                syntheticException: syntheticException,
            };
        }
        this._invokeClient('captureMessage', message, level, tslib_1.__assign(tslib_1.__assign({}, finalHint), { event_id: eventId }));
        return eventId;
    };

It just passes the level on through to the client. The code's internal at that point, but I'm guessing you're just basically passing that on to your server with the separate level and context and your server is using the passed level and ignoring the level in the context.

I think you can fix this either in the server code (to use the context if the passed level is undefined) or in the node code by populating the level from the context if there is a level in the context (e.g, either in your hub method or the API method).

I can work around it for now by just wrapping the call with a withScope, it'd be nice to fix though since that was kinda the point of #2627. :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions