sentry: Address Sentry JavaScript 7.x deprecations.

https://docs.sentry.io/platforms/javascript/migration/v7-to-v8/

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2024-09-24 20:23:57 -07:00 committed by Tim Abbott
parent e9b031c003
commit a8304fb324
7 changed files with 78 additions and 93 deletions

View File

@ -93,7 +93,7 @@ export function error(msg: string, more_info?: object, original_error?: unknown)
// Note that original_error could be of any type, because you can "raise"
// any type -- something we do see in practice with the error
// object being "dead": https://github.com/zulip/zulip/issues/18374
Sentry.getCurrentHub().captureException(new Error(msg, {cause: original_error}));
Sentry.captureException(new Error(msg, {cause: original_error}));
const args = build_arg_list(msg, more_info);
logger.error(...args);

View File

@ -48,28 +48,32 @@ function call(args: AjaxRequestHandlerOptions): JQuery.jqXHR<unknown> | undefine
return undefined;
}
const existing_span = Sentry.getCurrentHub().getScope().getSpan();
const txn_title = `call ${args.type} ${normalize_path(args.url)}`;
const span_data = {
op: "function",
description: txn_title,
data: {
url: args.url,
method: args.type,
},
};
let span: Sentry.Span | undefined;
/* istanbul ignore if */
if (!shouldCreateSpanForRequest(args.url)) {
// Leave the span unset, so we don't record a transaction
} else {
if (!existing_span) {
span = Sentry.startTransaction({...span_data, name: txn_title});
} else {
/* istanbul ignore next */
span = existing_span.startChild(span_data);
return call_in_span(undefined, args);
}
return Sentry.startSpanManual({...span_data, name: txn_title}, (span) => {
try {
return call_in_span(span, args);
} catch (error) /* istanbul ignore next */ {
span?.end();
throw error;
}
});
}
function call_in_span(
span: Sentry.Span | undefined,
args: AjaxRequestHandlerOptions,
): JQuery.jqXHR<unknown> {
// Remember the number of completed password changes when the
// request was initiated. This allows us to detect race
// situations where a password change occurred before we got a
@ -84,9 +88,10 @@ function call(args: AjaxRequestHandlerOptions): JQuery.jqXHR<unknown> | undefine
// Ignore errors by default
});
args.error = function wrapped_error(xhr, error_type, xhn) {
/* istanbul ignore if */
if (span !== undefined) {
span.setHttpStatus(xhr.status);
span.finish();
Sentry.setHttpStatus(span, xhr.status);
span.end();
}
if (reload_state.is_in_progress()) {
// If we're in the process of reloading the browser,
@ -149,9 +154,10 @@ function call(args: AjaxRequestHandlerOptions): JQuery.jqXHR<unknown> | undefine
// Do nothing by default
});
args.success = function wrapped_success(data, textStatus, jqXHR) {
/* istanbul ignore if */
if (span !== undefined) {
span.setHttpStatus(jqXHR.status);
span.finish();
Sentry.setHttpStatus(span, jqXHR.status);
span.end();
}
if (reload_state.is_in_progress()) {
// If we're in the process of reloading the browser,
@ -165,15 +171,7 @@ function call(args: AjaxRequestHandlerOptions): JQuery.jqXHR<unknown> | undefine
orig_success(data, textStatus, jqXHR);
};
try {
const scope = Sentry.getCurrentHub().pushScope();
if (span !== undefined) {
scope.setSpan(span);
}
return $.ajax(args);
} finally {
Sentry.getCurrentHub().popScope();
}
}
export function get(options: AjaxRequestHandlerOptions): JQuery.jqXHR<unknown> | undefined {

View File

@ -446,23 +446,11 @@ export function show(raw_terms: NarrowTerm[], show_opts: ShowMessageViewOpts): v
...show_opts,
};
const existing_span = Sentry.getCurrentHub().getScope().getSpan();
const span_data = {
op: "function",
description: "narrow",
data: {raw_terms, trigger: opts.trigger},
};
let span;
if (!existing_span) {
span = Sentry.startTransaction({...span_data, name: "narrow"});
} else {
span = existing_span.startChild(span_data);
}
let do_close_span = true;
try {
const scope = Sentry.getCurrentHub().pushScope();
scope.setSpan(span);
void Sentry.startSpan({...span_data, name: "narrow"}, async (span) => {
const id_info: TargetMessageIdInfo = {
target_id: undefined,
local_select_id: undefined,
@ -779,26 +767,16 @@ export function show(raw_terms: NarrowTerm[], show_opts: ShowMessageViewOpts): v
then_select_offset,
);
const post_span = span.startChild({
const post_span_context = {
name: "post-narrow busy time",
op: "function",
description: "post-narrow busy time",
});
do_close_span = false;
span.setStatus("ok");
setTimeout(() => {
};
await Sentry.startSpan(post_span_context, async () => {
span?.setStatus("ok");
await new Promise((resolve) => setTimeout(resolve, 0));
resize.resize_stream_filters_container();
post_span.finish();
span.finish();
}, 0);
} catch (error) {
span.setStatus("unknown_error");
throw error;
} finally {
if (do_close_span) {
span.finish();
}
Sentry.getCurrentHub().popScope();
}
});
});
}
function navigate_to_anchor_message(opts: {

View File

@ -19,7 +19,7 @@ export class MessageState {
server_acked = false;
saw_event = false;
txn: Sentry.Transaction | undefined = undefined;
span: Sentry.Span | undefined = undefined;
event_span: Sentry.Span | undefined = undefined;
constructor(opts: {local_id: string; locally_echoed: boolean}) {
@ -27,17 +27,27 @@ export class MessageState {
this.locally_echoed = opts.locally_echoed;
}
start_send(): Sentry.Transaction {
this.txn = Sentry.startTransaction({
wrap_send(callback: () => void): void {
Sentry.startSpanManual(
{
op: "function",
description: "message send",
name: "message send",
});
this.event_span = this.txn.startChild({
},
(span) => {
try {
this.span = span;
this.event_span = Sentry.startInactiveSpan({
op: "function",
description: "message send (server event loop)",
name: "message send (server event loop)",
});
return this.txn;
callback();
} catch (error) {
this.event_span?.end();
span?.end();
throw error;
}
},
);
}
mark_disparity(): void {
@ -54,22 +64,27 @@ export class MessageState {
return;
}
this.saw_event = true;
this.event_span.finish();
this.event_span?.end();
this.maybe_finish_txn();
}
report_error(): void {
this.event_span?.end();
this.span?.end();
}
maybe_finish_txn(): void {
if (!this.saw_event || !this.server_acked) {
return;
}
const setTag = (name: string, val: boolean): void => {
const str_val = val ? "true" : "false";
this.event_span!.setTag(name, str_val);
this.txn!.setTag(name, str_val);
this.event_span?.setAttribute(name, str_val);
this.span?.setAttribute(name, str_val);
};
setTag("rendered_changed", this.rendered_changed);
setTag("locally_echoed", this.locally_echoed);
this.txn!.finish();
this.span?.end();
messages.delete(this.local_id);
}
}
@ -102,13 +117,13 @@ export function get_message_state(local_id: string): MessageState | undefined {
return state;
}
export function start_send(local_id: string): Sentry.Transaction | undefined {
export function wrap_send(local_id: string, callback: () => void): void {
const state = get_message_state(local_id);
if (!state) {
return undefined;
if (state) {
state.wrap_send(callback);
} else {
callback();
}
return state.start_send();
}
export function mark_disparity(local_id: string): void {

View File

@ -61,9 +61,9 @@ if (sentry_params !== undefined) {
release: "zulip-server@" + ZULIP_VERSION,
integrations: [
new Sentry.BrowserTracing({
startTransactionOnLocationChange: false,
beforeNavigate(context) {
Sentry.browserTracingIntegration({
instrumentNavigation: false,
beforeStartSpan(context) {
return {
...context,
metadata: {source: "custom"},
@ -101,8 +101,5 @@ if (sentry_params !== undefined) {
},
});
} else {
// Always add the tracing extensions, so Sentry doesn't throw runtime errors if one calls
// startTransaction without having created the Sentry.BrowserTracing object.
Sentry.addTracingExtensions();
Sentry.init({});
}

View File

@ -1,5 +1,3 @@
import * as Sentry from "@sentry/browser";
import * as blueslip from "./blueslip";
import * as channel from "./channel";
import * as people from "./people";
@ -17,10 +15,7 @@ export function send_message(request, on_success, error) {
locally_echoed: request.locally_echoed,
});
}
const txn = sent_messages.start_send(request.local_id);
try {
const scope = Sentry.getCurrentHub().pushScope();
scope.setSpan(txn);
sent_messages.wrap_send(request.local_id, () => {
channel.post({
url: "/json/messages",
data: request,
@ -58,6 +53,7 @@ export function send_message(request, on_success, error) {
}
},
error(xhr, error_type) {
sent_messages.get_message_state(request.local_id)?.report_error();
if (error_type !== "timeout" && reload_state.is_pending()) {
// The error might be due to the server changing
reload.initiate({
@ -72,9 +68,7 @@ export function send_message(request, on_success, error) {
error(response, xhr.responseJSON?.code);
},
});
} finally {
Sentry.getCurrentHub().popScope();
}
});
}
export function reply_message(opts) {

View File

@ -14,9 +14,12 @@ const sent_messages = mock_esm("../src/sent_messages", {
start_tracking_message: noop,
get_message_state: () => ({
report_server_ack: noop,
report_error: noop,
saw_event: true,
}),
start_send: noop,
wrap_send(_local_id, callback) {
callback();
},
});
const server_events = mock_esm("../src/server_events");