mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-21 13:50:20 +08:00
Merge pull request #22233 from dannon/feature/sentry-upgrade
Upgrade Sentry JS SDK to v10, add opt-in session replay
This commit is contained in:
+1
-2
@@ -47,8 +47,7 @@
|
||||
"@johmun/vue-tags-input": "^2.1.0",
|
||||
"@monaco-editor/loader": "^1.5.0",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@sentry/browser": "^7.74.1",
|
||||
"@sentry/vue": "^7.114.0",
|
||||
"@sentry/vue": "^10.45.0",
|
||||
"@vueuse/core": "^10.5.0",
|
||||
"@vueuse/math": "^10.9.0",
|
||||
"@vueuse/shared": "^10.5.0",
|
||||
|
||||
Generated
+53
-102
@@ -64,12 +64,9 @@ importers:
|
||||
'@popperjs/core':
|
||||
specifier: ^2.11.8
|
||||
version: 2.11.8
|
||||
'@sentry/browser':
|
||||
specifier: ^7.74.1
|
||||
version: 7.114.0
|
||||
'@sentry/vue':
|
||||
specifier: ^7.114.0
|
||||
version: 7.114.0(vue@2.7.16)
|
||||
specifier: ^10.45.0
|
||||
version: 10.45.0(pinia@2.3.1(typescript@5.8.3)(vue@2.7.16))(vue@2.7.16)
|
||||
'@vueuse/core':
|
||||
specifier: ^10.5.0
|
||||
version: 10.5.0(vue@2.7.16)
|
||||
@@ -1184,47 +1181,42 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@sentry-internal/feedback@7.114.0':
|
||||
resolution: {integrity: sha512-kUiLRUDZuh10QE9JbSVVLgqxFoD9eDPOzT0MmzlPuas8JlTmJuV4FtSANNcqctd5mBuLt2ebNXH0MhRMwyae4A==}
|
||||
engines: {node: '>=12'}
|
||||
'@sentry-internal/browser-utils@10.45.0':
|
||||
resolution: {integrity: sha512-ZPZpeIarXKScvquGx2AfNKcYiVNDA4wegMmjyGVsTA2JPmP0TrJoO3UybJS6KGDeee8V3I3EfD/ruauMm7jOFQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry-internal/replay-canvas@7.114.0':
|
||||
resolution: {integrity: sha512-6rTiqmKi/FYtesdM2TM2U+rh6BytdPjLP65KTUodtxohJ+r/3m+termj2o4BhIYPE1YYOZNmbZfwebkuQPmWeg==}
|
||||
engines: {node: '>=12'}
|
||||
'@sentry-internal/feedback@10.45.0':
|
||||
resolution: {integrity: sha512-vCSurazFVq7RUeYiM5X326jA5gOVrWYD6lYX2fbjBOMcyCEhDnveNxMT62zKkZDyNT/jyD194nz/cjntBUkyWA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry-internal/tracing@7.114.0':
|
||||
resolution: {integrity: sha512-dOuvfJN7G+3YqLlUY4HIjyWHaRP8vbOgF+OsE5w2l7ZEn1rMAaUbPntAR8AF9GBA6j2zWNoSo8e7GjbJxVofSg==}
|
||||
engines: {node: '>=8'}
|
||||
'@sentry-internal/replay-canvas@10.45.0':
|
||||
resolution: {integrity: sha512-nvq/AocdZTuD7y0KSiWi3gVaY0s5HOFy86mC/v1kDZmT/jsBAzN5LDkk/f1FvsWma1peqQmpUqxvhC+YIW294Q==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/browser@7.114.0':
|
||||
resolution: {integrity: sha512-ijJ0vOEY6U9JJADVYGkUbLrAbpGSQgA4zV+KW3tcsBLX9M1jaWq4BV1PWHdzDPPDhy4OgfOjIfaMb5BSPn1U+g==}
|
||||
engines: {node: '>=8'}
|
||||
'@sentry-internal/replay@10.45.0':
|
||||
resolution: {integrity: sha512-vjosRoGA1bzhVAEO1oce+CsRdd70quzBeo7WvYqpcUnoLe/Rv8qpOMqWX3j26z7XfFHMExWQNQeLxmtYOArvlw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/core@7.114.0':
|
||||
resolution: {integrity: sha512-YnanVlmulkjgZiVZ9BfY9k6I082n+C+LbZo52MTvx3FY6RE5iyiPMpaOh67oXEZRWcYQEGm+bKruRxLVP6RlbA==}
|
||||
engines: {node: '>=8'}
|
||||
'@sentry/browser@10.45.0':
|
||||
resolution: {integrity: sha512-e/a8UMiQhqqv706McSIcG6XK+AoQf9INthi2pD+giZfNRTzXTdqHzUT5OIO5hg8Am6eF63nDJc+vrYNPhzs51Q==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/integrations@7.114.0':
|
||||
resolution: {integrity: sha512-BJIBWXGKeIH0ifd7goxOS29fBA8BkEgVVCahs6xIOXBjX1IRS6PmX0zYx/GP23nQTfhJiubv2XPzoYOlZZmDxg==}
|
||||
engines: {node: '>=8'}
|
||||
'@sentry/core@10.45.0':
|
||||
resolution: {integrity: sha512-s69UXxvefeQxuZ5nY7/THtTrIEvJxNVCp3ns4kwoCw1qMpgpvn/296WCKVmM7MiwnaAdzEKnAvLAwaxZc2nM7Q==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/replay@7.114.0':
|
||||
resolution: {integrity: sha512-UvEajoLIX9n2poeW3R4Ybz7D0FgCGXoFr/x/33rdUEMIdTypknxjJWxg6fJngIduzwrlrvWpvP8QiZXczYQy2Q==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
'@sentry/types@7.114.0':
|
||||
resolution: {integrity: sha512-tsqkkyL3eJtptmPtT0m9W/bPLkU7ILY7nvwpi1hahA5jrM7ppoU0IMaQWAgTD+U3rzFH40IdXNBFb8Gnqcva4w==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
'@sentry/utils@7.114.0':
|
||||
resolution: {integrity: sha512-319N90McVpupQ6vws4+tfCy/03AdtsU0MurIE4+W5cubHME08HtiEWlfacvAxX+yuKFhvdsO4K4BB/dj54ideg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
'@sentry/vue@7.114.0':
|
||||
resolution: {integrity: sha512-tHydxMJFpUcsmNCbXo59SqeNImX+3mMO+j3T0eLsDZy1NY2fSDFP6PFvuc72RsqiwCKeCKQmQDtAVa5Vt5ZlQA==}
|
||||
engines: {node: '>=8'}
|
||||
'@sentry/vue@10.45.0':
|
||||
resolution: {integrity: sha512-p6ghTgQtiCBZ+Yw0B2xmC69S8AdCRRsYvbTHW7MJYspwNnJDs7rqgCBqOxNhvr3tsKdDuEOEHLtf/5hbKi+8xQ==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@tanstack/vue-router': ^1.64.0
|
||||
pinia: 2.x || 3.x
|
||||
vue: 2.7.16
|
||||
peerDependenciesMeta:
|
||||
'@tanstack/vue-router':
|
||||
optional: true
|
||||
pinia:
|
||||
optional: true
|
||||
|
||||
'@socket.io/component-emitter@3.1.2':
|
||||
resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
|
||||
@@ -3046,9 +3038,6 @@ packages:
|
||||
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
lie@3.1.1:
|
||||
resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==}
|
||||
|
||||
lie@3.3.0:
|
||||
resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
|
||||
|
||||
@@ -3063,9 +3052,6 @@ packages:
|
||||
linkifyjs@4.3.2:
|
||||
resolution: {integrity: sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==}
|
||||
|
||||
localforage@1.10.0:
|
||||
resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==}
|
||||
|
||||
locate-path@6.0.0:
|
||||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -5188,68 +5174,41 @@ snapshots:
|
||||
'@rollup/rollup-win32-x64-msvc@4.53.3':
|
||||
optional: true
|
||||
|
||||
'@sentry-internal/feedback@7.114.0':
|
||||
'@sentry-internal/browser-utils@10.45.0':
|
||||
dependencies:
|
||||
'@sentry/core': 7.114.0
|
||||
'@sentry/types': 7.114.0
|
||||
'@sentry/utils': 7.114.0
|
||||
'@sentry/core': 10.45.0
|
||||
|
||||
'@sentry-internal/replay-canvas@7.114.0':
|
||||
'@sentry-internal/feedback@10.45.0':
|
||||
dependencies:
|
||||
'@sentry/core': 7.114.0
|
||||
'@sentry/replay': 7.114.0
|
||||
'@sentry/types': 7.114.0
|
||||
'@sentry/utils': 7.114.0
|
||||
'@sentry/core': 10.45.0
|
||||
|
||||
'@sentry-internal/tracing@7.114.0':
|
||||
'@sentry-internal/replay-canvas@10.45.0':
|
||||
dependencies:
|
||||
'@sentry/core': 7.114.0
|
||||
'@sentry/types': 7.114.0
|
||||
'@sentry/utils': 7.114.0
|
||||
'@sentry-internal/replay': 10.45.0
|
||||
'@sentry/core': 10.45.0
|
||||
|
||||
'@sentry/browser@7.114.0':
|
||||
'@sentry-internal/replay@10.45.0':
|
||||
dependencies:
|
||||
'@sentry-internal/feedback': 7.114.0
|
||||
'@sentry-internal/replay-canvas': 7.114.0
|
||||
'@sentry-internal/tracing': 7.114.0
|
||||
'@sentry/core': 7.114.0
|
||||
'@sentry/integrations': 7.114.0
|
||||
'@sentry/replay': 7.114.0
|
||||
'@sentry/types': 7.114.0
|
||||
'@sentry/utils': 7.114.0
|
||||
'@sentry-internal/browser-utils': 10.45.0
|
||||
'@sentry/core': 10.45.0
|
||||
|
||||
'@sentry/core@7.114.0':
|
||||
'@sentry/browser@10.45.0':
|
||||
dependencies:
|
||||
'@sentry/types': 7.114.0
|
||||
'@sentry/utils': 7.114.0
|
||||
'@sentry-internal/browser-utils': 10.45.0
|
||||
'@sentry-internal/feedback': 10.45.0
|
||||
'@sentry-internal/replay': 10.45.0
|
||||
'@sentry-internal/replay-canvas': 10.45.0
|
||||
'@sentry/core': 10.45.0
|
||||
|
||||
'@sentry/integrations@7.114.0':
|
||||
'@sentry/core@10.45.0': {}
|
||||
|
||||
'@sentry/vue@10.45.0(pinia@2.3.1(typescript@5.8.3)(vue@2.7.16))(vue@2.7.16)':
|
||||
dependencies:
|
||||
'@sentry/core': 7.114.0
|
||||
'@sentry/types': 7.114.0
|
||||
'@sentry/utils': 7.114.0
|
||||
localforage: 1.10.0
|
||||
|
||||
'@sentry/replay@7.114.0':
|
||||
dependencies:
|
||||
'@sentry-internal/tracing': 7.114.0
|
||||
'@sentry/core': 7.114.0
|
||||
'@sentry/types': 7.114.0
|
||||
'@sentry/utils': 7.114.0
|
||||
|
||||
'@sentry/types@7.114.0': {}
|
||||
|
||||
'@sentry/utils@7.114.0':
|
||||
dependencies:
|
||||
'@sentry/types': 7.114.0
|
||||
|
||||
'@sentry/vue@7.114.0(vue@2.7.16)':
|
||||
dependencies:
|
||||
'@sentry/browser': 7.114.0
|
||||
'@sentry/core': 7.114.0
|
||||
'@sentry/types': 7.114.0
|
||||
'@sentry/utils': 7.114.0
|
||||
'@sentry/browser': 10.45.0
|
||||
'@sentry/core': 10.45.0
|
||||
vue: 2.7.16
|
||||
optionalDependencies:
|
||||
pinia: 2.3.1(typescript@5.8.3)(vue@2.7.16)
|
||||
|
||||
'@socket.io/component-emitter@3.1.2': {}
|
||||
|
||||
@@ -7371,10 +7330,6 @@ snapshots:
|
||||
prelude-ls: 1.2.1
|
||||
type-check: 0.4.0
|
||||
|
||||
lie@3.1.1:
|
||||
dependencies:
|
||||
immediate: 3.0.6
|
||||
|
||||
lie@3.3.0:
|
||||
dependencies:
|
||||
immediate: 3.0.6
|
||||
@@ -7389,10 +7344,6 @@ snapshots:
|
||||
|
||||
linkifyjs@4.3.2: {}
|
||||
|
||||
localforage@1.10.0:
|
||||
dependencies:
|
||||
lie: 3.1.1
|
||||
|
||||
locate-path@6.0.0:
|
||||
dependencies:
|
||||
p-locate: 5.0.0
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import * as Sentry from "@sentry/vue";
|
||||
import Vue from "vue";
|
||||
|
||||
/**
|
||||
* Initializes Sentry, one of the few functions that should actually be
|
||||
* in a global init. Transplanted here from js-app.mako
|
||||
*
|
||||
* @param {object} config Galaxy configuration object
|
||||
*/
|
||||
export async function initSentry(Galaxy, router) {
|
||||
console.log("initSentry");
|
||||
const config = Galaxy.config;
|
||||
if (config.sentry_dsn_public) {
|
||||
const sentry_dsn_public = config.sentry_dsn_public;
|
||||
const email = Galaxy.user.get("email");
|
||||
let release = Galaxy.config.version_major;
|
||||
if (Galaxy.config.version_minor) {
|
||||
release += `.${Galaxy.config.version_minor}`;
|
||||
}
|
||||
Sentry.init({
|
||||
Vue,
|
||||
dsn: sentry_dsn_public,
|
||||
integrations: [Sentry.browserTracingIntegration({ router })],
|
||||
release: release,
|
||||
beforeSend(event, hint) {
|
||||
const error = hint.originalException;
|
||||
if (["AdminRequired", "RegisteredUserRequired"].includes(error?.name)) {
|
||||
// ignore these error events
|
||||
return null;
|
||||
}
|
||||
return event;
|
||||
},
|
||||
});
|
||||
if (email) {
|
||||
Sentry.configureScope((scope) => {
|
||||
scope.setUser({
|
||||
email: email,
|
||||
});
|
||||
});
|
||||
}
|
||||
Galaxy.Sentry = Sentry;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import * as Sentry from "@sentry/vue";
|
||||
import Vue from "vue";
|
||||
import type VueRouter from "vue-router";
|
||||
|
||||
interface GalaxyConfig {
|
||||
sentry_dsn_public?: string;
|
||||
sentry_client_traces_sample_rate?: number;
|
||||
version_major: string;
|
||||
version_minor?: string;
|
||||
}
|
||||
|
||||
interface GalaxyUser {
|
||||
get(attr: string): string | undefined;
|
||||
attributes?: {
|
||||
preferences?: {
|
||||
extra_user_preferences?: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
interface GalaxyInstance {
|
||||
config: GalaxyConfig;
|
||||
user?: GalaxyUser;
|
||||
}
|
||||
|
||||
function isReplayEnabled(user?: GalaxyUser): boolean {
|
||||
try {
|
||||
const prefsJson = user?.attributes?.preferences?.extra_user_preferences;
|
||||
if (!prefsJson) {
|
||||
return false;
|
||||
}
|
||||
const prefs = JSON.parse(prefsJson);
|
||||
const value = prefs["sentry_replay|enabled"];
|
||||
return value === true || value === "true";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function initSentry(Galaxy: GalaxyInstance, router: VueRouter): void {
|
||||
const config = Galaxy.config;
|
||||
if (!config.sentry_dsn_public) {
|
||||
return;
|
||||
}
|
||||
|
||||
const email = Galaxy.user?.get("email");
|
||||
let release = config.version_major;
|
||||
if (config.version_minor) {
|
||||
release += `.${config.version_minor}`;
|
||||
}
|
||||
|
||||
const replayEnabled = isReplayEnabled(Galaxy.user);
|
||||
const integrations = [Sentry.browserTracingIntegration({ router })];
|
||||
if (replayEnabled) {
|
||||
integrations.push(
|
||||
Sentry.replayIntegration({
|
||||
maskAllText: true,
|
||||
blockAllMedia: true,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Sentry.init({
|
||||
Vue,
|
||||
dsn: config.sentry_dsn_public,
|
||||
integrations,
|
||||
release,
|
||||
tracesSampleRate: config.sentry_client_traces_sample_rate ?? 0,
|
||||
replaysSessionSampleRate: 0,
|
||||
replaysOnErrorSampleRate: replayEnabled ? 1.0 : 0,
|
||||
beforeSend(event, hint) {
|
||||
const error = hint.originalException;
|
||||
if (error instanceof Error && ["AdminRequired", "RegisteredUserRequired"].includes(error.name)) {
|
||||
return null;
|
||||
}
|
||||
return event;
|
||||
},
|
||||
});
|
||||
|
||||
if (email) {
|
||||
Sentry.setUser({ email });
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ window.addEventListener("load", async () => {
|
||||
const router = getRouter(Galaxy);
|
||||
|
||||
// Initialize globals
|
||||
await initSentry(Galaxy, router);
|
||||
initSentry(Galaxy, router);
|
||||
await initWebhooks(Galaxy);
|
||||
|
||||
// Mount application
|
||||
|
||||
@@ -3300,6 +3300,19 @@
|
||||
:Type: float
|
||||
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
``sentry_client_traces_sample_rate``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description:
|
||||
Sample rate for client-side (browser) performance tracing, between
|
||||
0 and 1. Controls what fraction of page loads and navigations
|
||||
generate performance traces sent to Sentry. Independent of
|
||||
sentry_traces_sample_rate, which controls server-side tracing.
|
||||
:Default: ``0.0``
|
||||
:Type: float
|
||||
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
``sentry_ca_certs``
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -1911,6 +1911,12 @@ galaxy:
|
||||
# to Sentry. A value higher than 0 is required to analyze performance.
|
||||
#sentry_traces_sample_rate: 0.0
|
||||
|
||||
# Sample rate for client-side (browser) performance tracing, between 0
|
||||
# and 1. Controls what fraction of page loads and navigations generate
|
||||
# performance traces sent to Sentry. Independent of
|
||||
# sentry_traces_sample_rate, which controls server-side tracing.
|
||||
#sentry_client_traces_sample_rate: 0.0
|
||||
|
||||
# Use this option to provide the path to location of the CA
|
||||
# (Certificate Authority) certificate file if the sentry server uses a
|
||||
# self-signed certificate.
|
||||
|
||||
@@ -125,7 +125,7 @@ preferences:
|
||||
label: Creator name to associate with new records (formatted as "Last name, First name"). If left blank "Anonymous Galaxy User" will be used. You can always change this by editing your record directly.
|
||||
type: text
|
||||
required: False
|
||||
|
||||
|
||||
dataverse:
|
||||
description: Your Dataverse Integration Settings
|
||||
inputs:
|
||||
@@ -170,6 +170,15 @@ preferences:
|
||||
required: False
|
||||
value: False
|
||||
|
||||
sentry_replay:
|
||||
description: Session Replay for error diagnostics
|
||||
inputs:
|
||||
- name: enabled
|
||||
label: Allow session replay recordings to be sent when errors occur. These recordings help administrators diagnose issues but may capture screen content.
|
||||
type: boolean
|
||||
required: False
|
||||
value: False
|
||||
|
||||
# Used in file_sources_conf.yml
|
||||
elabftw:
|
||||
description: Your eLabFTW Integration Settings
|
||||
|
||||
@@ -2431,6 +2431,16 @@ mapping:
|
||||
will have that percentage chance of being sent to Sentry. A value higher than 0
|
||||
is required to analyze performance.
|
||||
|
||||
sentry_client_traces_sample_rate:
|
||||
type: float
|
||||
default: 0.0
|
||||
required: false
|
||||
desc: |
|
||||
Sample rate for client-side (browser) performance tracing, between 0
|
||||
and 1. Controls what fraction of page loads and navigations generate
|
||||
performance traces sent to Sentry. Independent of
|
||||
sentry_traces_sample_rate, which controls server-side tracing.
|
||||
|
||||
sentry_ca_certs:
|
||||
type: str
|
||||
required: False
|
||||
|
||||
@@ -245,6 +245,7 @@ class ConfigSerializer(base.ModelSerializer):
|
||||
"install_resolver_dependencies": _use_config,
|
||||
"enable_tool_generated_tours": _use_config,
|
||||
"sentry_dsn_public": lambda item, key, **context: item.sentry_dsn_public,
|
||||
"sentry_client_traces_sample_rate": _use_config,
|
||||
"enable_webhooks": lambda item, key, **context: hasattr(self.app, "webhooks_registry")
|
||||
and bool(self.app.webhooks_registry.webhooks),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user