diff --git a/packages/spotlight/_fixtures/metrics/trace_metric_envelope.bin b/packages/spotlight/_fixtures/metrics/trace_metric_envelope.bin new file mode 100644 index 000000000..7d61b004e --- /dev/null +++ b/packages/spotlight/_fixtures/metrics/trace_metric_envelope.bin @@ -0,0 +1,3 @@ +{"sdk":{"name":"sentry.javascript.react","version":"10.34.0"}} +{"type":"trace_metric","item_count":12,"content_type":"application/vnd.sentry.items.trace-metric+json"} +{"items":[{"timestamp":1769353796.9620998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","name":"frontend.button.clicked","type":"counter","value":1,"attributes":{"component":{"value":"SentryMetrics","type":"string"},"sentry.environment":{"value":"development","type":"string"},"sentry.sdk.name":{"value":"sentry.javascript.react","type":"string"},"sentry.sdk.version":{"value":"10.34.0","type":"string"},"sentry.replay_id":{"value":"e88e195d7a5249a2a0df5b3f2123816d","type":"string"}}},{"timestamp":1769353796.9625998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","name":"frontend.button2.clicked","type":"counter","value":1,"attributes":{"component":{"value":"SentryMetrics","type":"string"},"sentry.environment":{"value":"development","type":"string"},"sentry.sdk.name":{"value":"sentry.javascript.react","type":"string"},"sentry.sdk.version":{"value":"10.34.0","type":"string"},"sentry.replay_id":{"value":"e88e195d7a5249a2a0df5b3f2123816d","type":"string"}}},{"timestamp":1769353797.2412999,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","name":"frontend.button.clicked","type":"counter","value":1,"attributes":{"component":{"value":"SentryMetrics","type":"string"},"sentry.environment":{"value":"development","type":"string"},"sentry.sdk.name":{"value":"sentry.javascript.react","type":"string"},"sentry.sdk.version":{"value":"10.34.0","type":"string"},"sentry.replay_id":{"value":"e88e195d7a5249a2a0df5b3f2123816d","type":"string"}}},{"timestamp":1769353797.2414,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","name":"frontend.button2.clicked","type":"counter","value":1,"attributes":{"component":{"value":"SentryMetrics","type":"string"},"sentry.environment":{"value":"development","type":"string"},"sentry.sdk.name":{"value":"sentry.javascript.react","type":"string"},"sentry.sdk.version":{"value":"10.34.0","type":"string"},"sentry.replay_id":{"value":"e88e195d7a5249a2a0df5b3f2123816d","type":"string"}}},{"timestamp":1769353797.5262,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","name":"frontend.button.clicked","type":"counter","value":1,"attributes":{"component":{"value":"SentryMetrics","type":"string"},"sentry.environment":{"value":"development","type":"string"},"sentry.sdk.name":{"value":"sentry.javascript.react","type":"string"},"sentry.sdk.version":{"value":"10.34.0","type":"string"},"sentry.replay_id":{"value":"e88e195d7a5249a2a0df5b3f2123816d","type":"string"}}},{"timestamp":1769353797.5263999,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","name":"frontend.button2.clicked","type":"counter","value":1,"attributes":{"component":{"value":"SentryMetrics","type":"string"},"sentry.environment":{"value":"development","type":"string"},"sentry.sdk.name":{"value":"sentry.javascript.react","type":"string"},"sentry.sdk.version":{"value":"10.34.0","type":"string"},"sentry.replay_id":{"value":"e88e195d7a5249a2a0df5b3f2123816d","type":"string"}}},{"timestamp":1769353798.102,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","name":"frontend.random.value","type":"gauge","value":60,"attributes":{"component":{"value":"SentryMetrics","type":"string"},"sentry.environment":{"value":"development","type":"string"},"sentry.sdk.name":{"value":"sentry.javascript.react","type":"string"},"sentry.sdk.version":{"value":"10.34.0","type":"string"},"sentry.replay_id":{"value":"e88e195d7a5249a2a0df5b3f2123816d","type":"string"}}},{"timestamp":1769353798.3725,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","name":"frontend.random.value","type":"gauge","value":69,"attributes":{"component":{"value":"SentryMetrics","type":"string"},"sentry.environment":{"value":"development","type":"string"},"sentry.sdk.name":{"value":"sentry.javascript.react","type":"string"},"sentry.sdk.version":{"value":"10.34.0","type":"string"},"sentry.replay_id":{"value":"e88e195d7a5249a2a0df5b3f2123816d","type":"string"}}},{"timestamp":1769353799.0937998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","name":"frontend.response.time","type":"distribution","unit":"millisecond","value":125.4894445940432,"attributes":{"component":{"value":"SentryMetrics","type":"string"},"sentry.environment":{"value":"development","type":"string"},"sentry.sdk.name":{"value":"sentry.javascript.react","type":"string"},"sentry.sdk.version":{"value":"10.34.0","type":"string"},"sentry.replay_id":{"value":"e88e195d7a5249a2a0df5b3f2123816d","type":"string"}}},{"timestamp":1769353799.2722998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","name":"frontend.response.time","type":"distribution","unit":"millisecond","value":880.0890658738737,"attributes":{"component":{"value":"SentryMetrics","type":"string"},"sentry.environment":{"value":"development","type":"string"},"sentry.sdk.name":{"value":"sentry.javascript.react","type":"string"},"sentry.sdk.version":{"value":"10.34.0","type":"string"},"sentry.replay_id":{"value":"e88e195d7a5249a2a0df5b3f2123816d","type":"string"}}},{"timestamp":1769353799.5245998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","name":"frontend.response.time","type":"distribution","unit":"millisecond","value":350.38026520290623,"attributes":{"component":{"value":"SentryMetrics","type":"string"},"sentry.environment":{"value":"development","type":"string"},"sentry.sdk.name":{"value":"sentry.javascript.react","type":"string"},"sentry.sdk.version":{"value":"10.34.0","type":"string"},"sentry.replay_id":{"value":"e88e195d7a5249a2a0df5b3f2123816d","type":"string"}}},{"timestamp":1769353799.7902,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","name":"frontend.response.time","type":"distribution","unit":"millisecond","value":854.05904566557,"attributes":{"component":{"value":"SentryMetrics","type":"string"},"sentry.environment":{"value":"development","type":"string"},"sentry.sdk.name":{"value":"sentry.javascript.react","type":"string"},"sentry.sdk.version":{"value":"10.34.0","type":"string"},"sentry.replay_id":{"value":"e88e195d7a5249a2a0df5b3f2123816d","type":"string"}}}]} diff --git a/packages/spotlight/_fixtures/metrics/transaction_envelope.bin b/packages/spotlight/_fixtures/metrics/transaction_envelope.bin new file mode 100644 index 000000000..dbfc501b7 --- /dev/null +++ b/packages/spotlight/_fixtures/metrics/transaction_envelope.bin @@ -0,0 +1,3 @@ +{"event_id":"d794078088734aea9722f94912b4654d","sent_at":"2026-01-25T15:09:55.489Z","sdk":{"name":"sentry.javascript.react","version":"10.34.0"},"trace":{"environment":"development","trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","replay_id":"e88e195d7a5249a2a0df5b3f2123816d","sampled":"true","sample_rand":"0.7282764264866799","sample_rate":"1"}} +{"type":"transaction"} +{"contexts":{"trace":{"span_id":"92502bdd1423ef77","trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","data":{"sentry.origin":"auto.pageload.browser","sentry.op":"pageload","sentry.source":"url","sentry.sample_rate":1,"effectiveConnectionType":"4g","deviceMemory":"8 GB","hardwareConcurrency":"10","performance.timeOrigin":1769353794.3253999,"performance.activationStart":0,"lcp.element":"body","lcp.loadTime":0,"lcp.renderTime":156,"lcp.size":25488,"cls.source.1":"button.bg-gradient-to-r.from-blue-500.to-purple-600.text-white.font-semibold.py-3.px-8.rounded-lg.hover:from-blue-600.hover:to-purple-700.transition-all.duration-300.transform.hover:scale-105.shadow-lg","cls.source.2":"button.bg-gray-700.text-white.font-semibold.py-3.px-8.rounded-lg.hover:bg-gray-600.transition-all.duration-300.transform.hover:scale-105.shadow-lg.disabled:opacity-50.disabled:cursor-not-allowed.disabled:transform-none","cls.source.3":"div.container.mx-auto.px-4.py-8 > div.text-center.mt-12.text-gray-500","sentry.idle_span_finish_reason":"idleTimeout"},"op":"pageload","status":"ok","origin":"auto.pageload.browser"},"react":{"version":"19.2.3"}},"spans":[{"data":{"sentry.origin":"auto.http.browser","sentry.op":"http.client","url":"http://localhost:5001/api/users","type":"xhr","http.method":"GET","http.url":"http://localhost:5001/api/users","server.address":"localhost:5001","http.response.status_code":200,"network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.446,"http.request.domain_lookup_start":0,"http.request.domain_lookup_end":0,"http.request.connect_start":0,"http.request.secure_connection_start":0,"http.request.connection_end":0,"http.request.request_start":0,"http.request.response_start":0,"http.request.response_end":1769353794.4685998,"http.request.time_to_first_byte":0},"description":"GET http://localhost:5001/api/users","op":"http.client","parent_span_id":"92502bdd1423ef77","span_id":"a24a75d723981772","start_timestamp":1769353794.4442,"status":"ok","timestamp":1769353794.4731,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.http.browser"},{"data":{"sentry.origin":"auto.http.browser","sentry.op":"http.client","url":"http://localhost:5001/api/users","type":"xhr","http.method":"GET","http.url":"http://localhost:5001/api/users","server.address":"localhost:5001","http.response.status_code":200,"network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.446,"http.request.domain_lookup_start":0,"http.request.domain_lookup_end":0,"http.request.connect_start":0,"http.request.secure_connection_start":0,"http.request.connection_end":0,"http.request.request_start":0,"http.request.response_start":0,"http.request.response_end":1769353794.4685998,"http.request.time_to_first_byte":0},"description":"GET http://localhost:5001/api/users","op":"http.client","parent_span_id":"92502bdd1423ef77","span_id":"a6569f507f12e8e2","start_timestamp":1769353794.4459,"status":"ok","timestamp":1769353794.4737,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.http.browser"},{"data":{"sentry.origin":"auto.ui.browser.metrics","sentry.op":"browser.unloadEvent"},"description":"http://localhost:5174/","op":"browser.unloadEvent","parent_span_id":"92502bdd1423ef77","span_id":"8d390bd66408fe11","start_timestamp":1769353794.3560998,"timestamp":1769353794.3560998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.ui.browser.metrics"},{"data":{"sentry.origin":"auto.ui.browser.metrics","sentry.op":"browser.domContentLoadedEvent"},"description":"http://localhost:5174/","op":"browser.domContentLoadedEvent","parent_span_id":"92502bdd1423ef77","span_id":"be6875c0349d2822","start_timestamp":1769353794.4278,"timestamp":1769353794.4278,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.ui.browser.metrics"},{"data":{"sentry.origin":"auto.ui.browser.metrics","sentry.op":"browser.loadEvent"},"description":"http://localhost:5174/","op":"browser.loadEvent","parent_span_id":"92502bdd1423ef77","span_id":"a8129b816b26b367","start_timestamp":1769353794.4733999,"timestamp":1769353794.4734998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.ui.browser.metrics"},{"data":{"sentry.origin":"auto.ui.browser.metrics","sentry.op":"browser.connect"},"description":"http://localhost:5174/","op":"browser.connect","parent_span_id":"92502bdd1423ef77","span_id":"893ccf803cd4ca7c","start_timestamp":1769353794.3286998,"timestamp":1769353794.3286998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.ui.browser.metrics"},{"data":{"sentry.origin":"auto.ui.browser.metrics","sentry.op":"browser.cache"},"description":"http://localhost:5174/","op":"browser.cache","parent_span_id":"92502bdd1423ef77","span_id":"b20485298a323dd9","start_timestamp":1769353794.3286998,"timestamp":1769353794.3286998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.ui.browser.metrics"},{"data":{"sentry.origin":"auto.ui.browser.metrics","sentry.op":"browser.DNS"},"description":"http://localhost:5174/","op":"browser.DNS","parent_span_id":"92502bdd1423ef77","span_id":"b3afa17a7132be06","start_timestamp":1769353794.3286998,"timestamp":1769353794.3286998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.ui.browser.metrics"},{"data":{"sentry.origin":"auto.ui.browser.metrics","sentry.op":"browser.request"},"description":"http://localhost:5174/","op":"browser.request","parent_span_id":"92502bdd1423ef77","span_id":"9c03f0cae6e73414","start_timestamp":1769353794.3328,"timestamp":1769353794.3479,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.ui.browser.metrics"},{"data":{"sentry.origin":"auto.ui.browser.metrics","sentry.op":"browser.response"},"description":"http://localhost:5174/","op":"browser.response","parent_span_id":"92502bdd1423ef77","span_id":"a46a7e3dd03cdd13","start_timestamp":1769353794.3463998,"timestamp":1769353794.3479,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.ui.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":300,"http.response_content_length":5667,"http.decoded_response_content_length":5667,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.3588998,"http.request.domain_lookup_start":1769353794.3588998,"http.request.domain_lookup_end":1769353794.3588998,"http.request.connect_start":1769353794.3588998,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.3588998,"http.request.request_start":1769353794.3745,"http.request.response_start":1769353794.375,"http.request.response_end":1769353794.3755999,"http.request.time_to_first_byte":0.04960000000149012},"description":"/src/main.tsx","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"9babd76aafe89aaa","start_timestamp":1769353794.3588998,"timestamp":1769353794.3755999,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":300,"http.response_content_length":178928,"http.decoded_response_content_length":178928,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.3588998,"http.request.domain_lookup_start":1769353794.3588998,"http.request.domain_lookup_end":1769353794.3588998,"http.request.connect_start":1769353794.3588998,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.3588998,"http.request.request_start":1769353794.3744,"http.request.response_start":1769353794.3748999,"http.request.response_end":1769353794.3760998,"http.request.time_to_first_byte":0.0495},"description":"/@vite/client","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"89b3f5cb048f2008","start_timestamp":1769353794.3588998,"timestamp":1769353794.3760998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":300,"http.response_content_length":111894,"http.decoded_response_content_length":111894,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.3777997,"http.request.domain_lookup_start":1769353794.3777997,"http.request.domain_lookup_end":1769353794.3777997,"http.request.connect_start":1769353794.3777997,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.3777997,"http.request.request_start":1769353794.3809,"http.request.response_start":1769353794.3813999,"http.request.response_end":1769353794.3835998,"http.request.time_to_first_byte":0.056},"description":"/@react-refresh","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"8dd4c0a53285770f","start_timestamp":1769353794.3778,"timestamp":1769353794.3836,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":0,"http.response_content_length":1024,"http.decoded_response_content_length":1024,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.378,"http.request.domain_lookup_start":1769353794.378,"http.request.domain_lookup_end":1769353794.378,"http.request.connect_start":1769353794.378,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.378,"http.request.request_start":1769353794.3805,"http.request.response_start":1769353794.381,"http.request.response_end":1769353794.3815,"http.request.time_to_first_byte":0.05560000000149012},"description":"/node_modules/.vite/deps/react.js?v=19ab71f5","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"b0c3de1cfa26f293","start_timestamp":1769353794.3779998,"timestamp":1769353794.3814998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":0,"http.response_content_length":12375,"http.decoded_response_content_length":12375,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.378,"http.request.domain_lookup_start":1769353794.378,"http.request.domain_lookup_end":1769353794.378,"http.request.connect_start":1769353794.378,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.378,"http.request.request_start":1769353794.3804,"http.request.response_start":1769353794.381,"http.request.response_end":1769353794.3817,"http.request.time_to_first_byte":0.05560000000149012},"description":"/node_modules/.vite/deps/react_jsx-dev-runtime.js?v=19ab71f5","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"8f858beb286fb766","start_timestamp":1769353794.3779998,"timestamp":1769353794.3816998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":300,"http.response_content_length":42197,"http.decoded_response_content_length":42197,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.378,"http.request.domain_lookup_start":1769353794.378,"http.request.domain_lookup_end":1769353794.378,"http.request.connect_start":1769353794.378,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.378,"http.request.request_start":1769353794.3841999,"http.request.response_start":1769353794.385,"http.request.response_end":1769353794.3855,"http.request.time_to_first_byte":0.059600000001490114},"description":"/src/index.css","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"afa109ed4593da93","start_timestamp":1769353794.3779998,"timestamp":1769353794.3854997,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":0,"http.response_content_length":1005279,"http.decoded_response_content_length":1005279,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.378,"http.request.domain_lookup_start":1769353794.378,"http.request.domain_lookup_end":1769353794.378,"http.request.connect_start":1769353794.378,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.378,"http.request.request_start":1769353794.3805,"http.request.response_start":1769353794.381,"http.request.response_end":1769353794.386,"http.request.time_to_first_byte":0.05560000000149012},"description":"/node_modules/.vite/deps/react-dom_client.js?v=19ab71f5","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"a22f858b5d6164b5","start_timestamp":1769353794.3779998,"timestamp":1769353794.3859997,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":0,"http.response_content_length":1021181,"http.decoded_response_content_length":1021181,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.378,"http.request.domain_lookup_start":1769353794.378,"http.request.domain_lookup_end":1769353794.378,"http.request.connect_start":1769353794.378,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.378,"http.request.request_start":1769353794.3812997,"http.request.response_start":1769353794.3818998,"http.request.response_end":1769353794.3862,"http.request.time_to_first_byte":0.0565},"description":"/node_modules/.vite/deps/@sentry_react.js?v=19ab71f5","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"a3b4637cf5e2b28f","start_timestamp":1769353794.3779998,"timestamp":1769353794.3861997,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":300,"http.response_content_length":3478,"http.decoded_response_content_length":3478,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.3781,"http.request.domain_lookup_start":1769353794.3781,"http.request.domain_lookup_end":1769353794.3781,"http.request.connect_start":1769353794.3781,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.3781,"http.request.request_start":1769353794.3832998,"http.request.response_start":1769353794.3841,"http.request.response_end":1769353794.3847997,"http.request.time_to_first_byte":0.058699999995529654},"description":"/node_modules/vite/dist/client/env.mjs","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"93f0a10fe4d009c4","start_timestamp":1769353794.3781,"timestamp":1769353794.3848,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":300,"http.response_content_length":30288,"http.decoded_response_content_length":30288,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.3781,"http.request.domain_lookup_start":1769353794.3781,"http.request.domain_lookup_end":1769353794.3781,"http.request.connect_start":1769353794.3781,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.3781,"http.request.request_start":1769353794.3835,"http.request.response_start":1769353794.3844,"http.request.response_end":1769353794.3853,"http.request.time_to_first_byte":0.059},"description":"/src/App.tsx","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"b0c1ef7c03a50c09","start_timestamp":1769353794.3781,"timestamp":1769353794.3853,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":0,"http.response_content_length":7968,"http.decoded_response_content_length":7968,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.3822,"http.request.domain_lookup_start":1769353794.3822,"http.request.domain_lookup_end":1769353794.3822,"http.request.connect_start":1769353794.3822,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.3822,"http.request.request_start":1769353794.3827999,"http.request.response_start":1769353794.3839,"http.request.response_end":1769353794.3841999,"http.request.time_to_first_byte":0.0585},"description":"/node_modules/.vite/deps/chunk-G3PMV62Z.js?v=19ab71f5","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"81d1a564ee02d472","start_timestamp":1769353794.3821998,"timestamp":1769353794.3841999,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":0,"http.response_content_length":45564,"http.decoded_response_content_length":45564,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.3822,"http.request.domain_lookup_start":1769353794.3822,"http.request.domain_lookup_end":1769353794.3822,"http.request.connect_start":1769353794.3822,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.3822,"http.request.request_start":1769353794.3827,"http.request.response_start":1769353794.384,"http.request.response_end":1769353794.3847997,"http.request.time_to_first_byte":0.05860000000149011},"description":"/node_modules/.vite/deps/chunk-WUR7D6NS.js?v=19ab71f5","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"b4a651295e99196a","start_timestamp":1769353794.3821998,"timestamp":1769353794.3847997,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":300,"http.response_content_length":14990,"http.decoded_response_content_length":14990,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.3874,"http.request.domain_lookup_start":1769353794.3874,"http.request.domain_lookup_end":1769353794.3874,"http.request.connect_start":1769353794.3874,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.3874,"http.request.request_start":1769353794.389,"http.request.response_start":1769353794.39,"http.request.response_end":1769353794.3906,"http.request.time_to_first_byte":0.06460000000149012},"description":"/src/components/UserForm.tsx","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"b62b881a7c8042ed","start_timestamp":1769353794.3874,"timestamp":1769353794.3906,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":300,"http.response_content_length":14132,"http.decoded_response_content_length":14132,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.3875,"http.request.domain_lookup_start":1769353794.3875,"http.request.domain_lookup_end":1769353794.3875,"http.request.connect_start":1769353794.3875,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.3875,"http.request.request_start":1769353794.3897998,"http.request.response_start":1769353794.3907998,"http.request.response_end":1769353794.391,"http.request.time_to_first_byte":0.06539999999850989},"description":"/src/components/UserList.tsx","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"9f5f788a44a9d2c2","start_timestamp":1769353794.3874998,"timestamp":1769353794.3909998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":300,"http.response_content_length":46144,"http.decoded_response_content_length":46144,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.3875,"http.request.domain_lookup_start":1769353794.3875,"http.request.domain_lookup_end":1769353794.3875,"http.request.connect_start":1769353794.3875,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.3875,"http.request.request_start":1769353794.3900998,"http.request.response_start":1769353794.3909,"http.request.response_end":1769353794.3913999,"http.request.time_to_first_byte":0.0655},"description":"/src/components/SpotlightDemo.tsx","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"a8860080d6075077","start_timestamp":1769353794.3874998,"timestamp":1769353794.3913999,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":300,"http.response_content_length":52769,"http.decoded_response_content_length":52769,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.3875,"http.request.domain_lookup_start":1769353794.3875,"http.request.domain_lookup_end":1769353794.3875,"http.request.connect_start":1769353794.3875,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.3875,"http.request.request_start":1769353794.3897,"http.request.response_start":1769353794.3904,"http.request.response_end":1769353794.3912997,"http.request.time_to_first_byte":0.065},"description":"/src/components/SentryMetrics.tsx","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"8677e4257206a32a","start_timestamp":1769353794.3874998,"timestamp":1769353794.3912997,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":300,"http.response_content_length":4518,"http.decoded_response_content_length":4518,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.3876,"http.request.domain_lookup_start":1769353794.3899,"http.request.domain_lookup_end":1769353794.3899,"http.request.connect_start":1769353794.3899,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.3900998,"http.request.request_start":1769353794.3902,"http.request.response_start":1769353794.3911,"http.request.response_end":1769353794.3915,"http.request.time_to_first_byte":0.06569999999552965},"description":"/src/services/api.ts","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"88bf8dc10558040c","start_timestamp":1769353794.3876,"timestamp":1769353794.3915,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":0,"http.response_content_length":84037,"http.decoded_response_content_length":84037,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.3917997,"http.request.domain_lookup_start":1769353794.3917997,"http.request.domain_lookup_end":1769353794.3917997,"http.request.connect_start":1769353794.3917997,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.3917997,"http.request.request_start":1769353794.3922,"http.request.response_start":1769353794.3923,"http.request.response_end":1769353794.3927999,"http.request.time_to_first_byte":0.06689999999850989},"description":"/node_modules/.vite/deps/axios.js?v=19ab71f5","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"92d60ba3c9cfde2e","start_timestamp":1769353794.3918,"timestamp":1769353794.3927999,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.script","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":0,"http.response_content_length":16214,"http.decoded_response_content_length":16214,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.3927999,"http.request.domain_lookup_start":1769353794.3927999,"http.request.domain_lookup_end":1769353794.3927999,"http.request.connect_start":1769353794.3927999,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.3927999,"http.request.request_start":1769353794.3932,"http.request.response_start":1769353794.3935,"http.request.response_end":1769353794.3935997,"http.request.time_to_first_byte":0.06810000000149012},"description":"/node_modules/.vite/deps/chunk-YF4B4G2L.js?v=19ab71f5","op":"resource.script","parent_span_id":"92502bdd1423ef77","span_id":"b69091fd7079ed93","start_timestamp":1769353794.3927999,"timestamp":1769353794.3935997,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"mark"},"description":"sentry-tracing-init","op":"mark","parent_span_id":"92502bdd1423ef77","span_id":"b2e81248312cecd1","start_timestamp":1769353794.4206998,"timestamp":1769353794.4206998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"measure","sentry.browser.measure.detail.devtools":"{\"properties\":[[\"Method name\",\"root.render()\"]],\"track\":\"Blocking\",\"trackGroup\":\"Scheduler ⚛\",\"color\":\"primary-light\"}"},"description":"Update","op":"measure","parent_span_id":"92502bdd1423ef77","span_id":"938173f29acbe3d9","start_timestamp":1769353794.4276,"timestamp":1769353794.4318,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"measure","sentry.browser.measure.detail.devtools":"{\"properties\":[[\"Component name\",\"App\"],[\"Method name\",\"setState()\"]],\"track\":\"Blocking\",\"trackGroup\":\"Scheduler ⚛\",\"color\":\"error\"}"},"description":"Cascading Update","op":"measure","parent_span_id":"92502bdd1423ef77","span_id":"8cbf5aea35aba23a","start_timestamp":1769353794.4459999,"timestamp":1769353794.4464,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"mark"},"description":"@grammarly-extension:checkScriptInitStart","op":"mark","parent_span_id":"92502bdd1423ef77","span_id":"b071c1501c1d4c2a","start_timestamp":1769353794.4680998,"timestamp":1769353794.4680998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"measure","sentry.browser.measure.detail.devtools":"{\"properties\":[[\"Component name\",\"App\"],[\"Method name\",\"setState()\"]],\"track\":\"Blocking\",\"trackGroup\":\"Scheduler ⚛\",\"color\":\"primary-light\"}"},"description":"Update","op":"measure","parent_span_id":"92502bdd1423ef77","span_id":"914b81c2de10c586","start_timestamp":1769353794.4733,"timestamp":1769353794.4743,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"resource.other","url.scheme":"http","server.address":"localhost:5174","url.same_origin":true,"http.response.status_code":200,"http.response_transfer_size":300,"http.response_content_length":1497,"http.decoded_response_content_length":1497,"resource.render_blocking_status":"non-blocking","http.response_delivery_type":"cache","network.protocol.version":"unknown","network.protocol.name":"","http.request.redirect_start":0,"http.request.redirect_end":0,"http.request.worker_start":0,"http.request.fetch_start":1769353794.4775999,"http.request.domain_lookup_start":1769353794.4775999,"http.request.domain_lookup_end":1769353794.4775999,"http.request.connect_start":1769353794.4775999,"http.request.secure_connection_start":0,"http.request.connection_end":1769353794.4775999,"http.request.request_start":1769353794.4787998,"http.request.response_start":1769353794.4805999,"http.request.response_end":1769353794.4812999,"http.request.time_to_first_byte":0.15519999999552966},"description":"/vite.svg","op":"resource.other","parent_span_id":"92502bdd1423ef77","span_id":"ad54d62e785dd752","start_timestamp":1769353794.4775999,"timestamp":1769353794.4812999,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"mark"},"description":"@grammarly-extension:checkScriptInitEnd","op":"mark","parent_span_id":"92502bdd1423ef77","span_id":"a78a12517f33855d","start_timestamp":1769353794.4798,"timestamp":1769353794.4798,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"paint"},"description":"first-paint","op":"paint","parent_span_id":"92502bdd1423ef77","span_id":"b18cd4ce7905262b","start_timestamp":1769353794.4813998,"timestamp":1769353794.4813998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"},{"data":{"sentry.origin":"auto.resource.browser.metrics","sentry.op":"paint"},"description":"first-contentful-paint","op":"paint","parent_span_id":"92502bdd1423ef77","span_id":"819bd573ac8a4df6","start_timestamp":1769353794.4813998,"timestamp":1769353794.4813998,"trace_id":"5becd2182ebd4b4bb5afe9fbc6b95866","origin":"auto.resource.browser.metrics"}],"start_timestamp":1769353794.3253999,"timestamp":1769353794.4813998,"transaction":"/","type":"transaction","request":{"url":"http://localhost:5174/","headers":{"Referer":"http://localhost:5174/","User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36"}},"transaction_info":{"source":"url"},"measurements":{"ttfb":{"value":21,"unit":"millisecond"},"lcp":{"value":156,"unit":"millisecond"},"cls":{"value":0.003798351872800402,"unit":""},"fp":{"value":156,"unit":"millisecond"},"fcp":{"value":156,"unit":"millisecond"},"connection.rtt":{"value":150,"unit":"millisecond"},"ttfb.requestTime":{"value":13.600000001490116,"unit":"millisecond"}},"platform":"javascript","event_id":"d794078088734aea9722f94912b4654d","environment":"development","sdk":{"integrations":["InboundFilters","FunctionToString","BrowserApiErrors","Breadcrumbs","GlobalHandlers","LinkedErrors","Dedupe","HttpContext","BrowserSession","SpotlightBrowser","BrowserTracing","Replay","ConsoleLogs"],"name":"sentry.javascript.react","version":"10.34.0","packages":[{"name":"npm:@sentry/react","version":"10.34.0"}],"settings":{"infer_ip":"never"}},"breadcrumbs":[{"timestamp":1769353794.472,"category":"xhr","data":{"method":"GET","url":"http://localhost:5001/api/users","status_code":200,"response_body_size":195},"type":"http"},{"timestamp":1769353794.473,"category":"xhr","data":{"method":"GET","url":"http://localhost:5001/api/users","status_code":200,"response_body_size":195},"type":"http"}],"tags":{"replayId":"e88e195d7a5249a2a0df5b3f2123816d"}} \ No newline at end of file diff --git a/packages/spotlight/package.json b/packages/spotlight/package.json index 15a353d31..611d310d9 100644 --- a/packages/spotlight/package.json +++ b/packages/spotlight/package.json @@ -32,9 +32,7 @@ "test:e2e:electron": "playwright test tests/electron.test.ts", "sample": "node ./_fixtures/send_to_sidecar.cjs" }, - "files": [ - "dist" - ], + "files": ["dist"], "bin": { "spotlight": "./dist/run.js" }, @@ -79,9 +77,9 @@ "@radix-ui/react-dropdown-menu": "^2.1.15", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-tooltip": "^1.2.7", - "@sentry/browser": "^10.31.0", + "@sentry/browser": "^10.36.0", "@sentry/electron": "^7.5.0", - "@sentry/react": "^10.31.0", + "@sentry/react": "^10.36.0", "@sentry/vite-plugin": "^2.22.5", "@shikijs/transformers": "^3.13.0", "@tailwindcss/vite": "catalog:", diff --git a/packages/spotlight/src/server/cli/tail.ts b/packages/spotlight/src/server/cli/tail.ts index 073752d43..c36fb829d 100644 --- a/packages/spotlight/src/server/cli/tail.ts +++ b/packages/spotlight/src/server/cli/tail.ts @@ -28,6 +28,7 @@ export const NAME_TO_TYPE_MAPPING: Record = Object.freeze({ traces: ["transaction", "span"], // profiles: ["profile"], logs: ["log"], + metrics: ["trace_metric"], attachments: ["attachment"], errors: ["event"], // sessions: ["session"], diff --git a/packages/spotlight/src/server/formatters/human/index.ts b/packages/spotlight/src/server/formatters/human/index.ts index a18039ad2..0fda0fbc2 100644 --- a/packages/spotlight/src/server/formatters/human/index.ts +++ b/packages/spotlight/src/server/formatters/human/index.ts @@ -1,11 +1,13 @@ -import { isErrorEvent, isLogEvent, isTraceEvent } from "../../parser/helpers.ts"; +import { isErrorEvent, isLogEvent, isMetricEvent, isTraceEvent } from "../../parser/helpers.ts"; import type { FormatterRegistry } from "../types.ts"; import { formatError } from "./errors.ts"; import { formatLog } from "./logs.ts"; +import { formatMetric } from "./metrics.ts"; import { formatTrace } from "./traces.ts"; export const formatters: FormatterRegistry = { event: { typeGuard: isErrorEvent, format: formatError }, log: { typeGuard: isLogEvent, format: formatLog }, + metric: { typeGuard: isMetricEvent, format: formatMetric }, transaction: { typeGuard: isTraceEvent, format: formatTrace }, }; diff --git a/packages/spotlight/src/server/formatters/human/metrics.ts b/packages/spotlight/src/server/formatters/human/metrics.ts new file mode 100644 index 000000000..fc15a4e4e --- /dev/null +++ b/packages/spotlight/src/server/formatters/human/metrics.ts @@ -0,0 +1,41 @@ +import type { Envelope } from "@sentry/core"; +import type { SentryMetricEvent, SentryMetricPayload } from "../../parser/index.ts"; +import { formatTimestamp } from "../utils.ts"; + +function formatSingleMetric(metric: SentryMetricPayload): string { + const parts: string[] = []; + + parts.push(`name=${metric.name}`); + parts.push(`type=${metric.type}`); + parts.push(`value=${metric.value}`); + + if (metric.unit) { + parts.push(`unit=${metric.unit}`); + } + + if (metric.trace_id) { + parts.push(`trace_id=${metric.trace_id}`); + } + + if (metric.span_id) { + parts.push(`span_id=${metric.span_id}`); + } + + if (metric.attributes) { + for (const [key, attr] of Object.entries(metric.attributes)) { + if (attr.value !== undefined && attr.value !== null) { + parts.push(`${key}=${attr.value}`); + } + } + } + + // Use metric timestamp as primary timestamp + const ts = formatTimestamp(metric.timestamp); + parts.push(`@${ts}`); + + return parts.join(" "); +} + +export function formatMetric(event: SentryMetricEvent, _envelopeHeader: Envelope[0]): string[] { + return event.items.map(formatSingleMetric); +} diff --git a/packages/spotlight/src/server/formatters/json/index.ts b/packages/spotlight/src/server/formatters/json/index.ts index a18039ad2..0fda0fbc2 100644 --- a/packages/spotlight/src/server/formatters/json/index.ts +++ b/packages/spotlight/src/server/formatters/json/index.ts @@ -1,11 +1,13 @@ -import { isErrorEvent, isLogEvent, isTraceEvent } from "../../parser/helpers.ts"; +import { isErrorEvent, isLogEvent, isMetricEvent, isTraceEvent } from "../../parser/helpers.ts"; import type { FormatterRegistry } from "../types.ts"; import { formatError } from "./errors.ts"; import { formatLog } from "./logs.ts"; +import { formatMetric } from "./metrics.ts"; import { formatTrace } from "./traces.ts"; export const formatters: FormatterRegistry = { event: { typeGuard: isErrorEvent, format: formatError }, log: { typeGuard: isLogEvent, format: formatLog }, + metric: { typeGuard: isMetricEvent, format: formatMetric }, transaction: { typeGuard: isTraceEvent, format: formatTrace }, }; diff --git a/packages/spotlight/src/server/formatters/json/metrics.ts b/packages/spotlight/src/server/formatters/json/metrics.ts new file mode 100644 index 000000000..3dc341b32 --- /dev/null +++ b/packages/spotlight/src/server/formatters/json/metrics.ts @@ -0,0 +1,6 @@ +import type { Envelope } from "@sentry/core"; +import type { SentryMetricEvent } from "../../parser/index.ts"; + +export function formatMetric(event: SentryMetricEvent, _envelopeHeader: Envelope[0]): string[] { + return [JSON.stringify(event)]; +} diff --git a/packages/spotlight/src/server/formatters/logfmt/index.ts b/packages/spotlight/src/server/formatters/logfmt/index.ts index a18039ad2..0fda0fbc2 100644 --- a/packages/spotlight/src/server/formatters/logfmt/index.ts +++ b/packages/spotlight/src/server/formatters/logfmt/index.ts @@ -1,11 +1,13 @@ -import { isErrorEvent, isLogEvent, isTraceEvent } from "../../parser/helpers.ts"; +import { isErrorEvent, isLogEvent, isMetricEvent, isTraceEvent } from "../../parser/helpers.ts"; import type { FormatterRegistry } from "../types.ts"; import { formatError } from "./errors.ts"; import { formatLog } from "./logs.ts"; +import { formatMetric } from "./metrics.ts"; import { formatTrace } from "./traces.ts"; export const formatters: FormatterRegistry = { event: { typeGuard: isErrorEvent, format: formatError }, log: { typeGuard: isLogEvent, format: formatLog }, + metric: { typeGuard: isMetricEvent, format: formatMetric }, transaction: { typeGuard: isTraceEvent, format: formatTrace }, }; diff --git a/packages/spotlight/src/server/formatters/logfmt/metrics.ts b/packages/spotlight/src/server/formatters/logfmt/metrics.ts new file mode 100644 index 000000000..06b54cb0a --- /dev/null +++ b/packages/spotlight/src/server/formatters/logfmt/metrics.ts @@ -0,0 +1,38 @@ +import type { Envelope } from "@sentry/core"; +import logfmt from "logfmt"; +import type { SentryMetricEvent, SentryMetricPayload } from "../../parser/index.ts"; +import { formatTimestamp } from "../utils.ts"; + +function formatSingleMetric(metric: SentryMetricPayload): string { + const data: Record = { + timestamp: formatTimestamp(metric.timestamp), + type: "trace_metric", + name: metric.name, + metric_type: metric.type, + value: metric.value, + }; + + if (metric.unit) { + data.unit = metric.unit; + } + + if (metric.trace_id) { + data.trace_id = metric.trace_id; + } + + if (metric.span_id) { + data.span_id = metric.span_id; + } + + if (metric.attributes) { + for (const [key, attr] of Object.entries(metric.attributes)) { + data[`attr.${key}`] = attr.value; + } + } + + return logfmt.stringify(data); +} + +export function formatMetric(event: SentryMetricEvent, _envelopeHeader: Envelope[0]): string[] { + return event.items.map(formatSingleMetric); +} diff --git a/packages/spotlight/src/server/formatters/md/index.ts b/packages/spotlight/src/server/formatters/md/index.ts index a18039ad2..0fda0fbc2 100644 --- a/packages/spotlight/src/server/formatters/md/index.ts +++ b/packages/spotlight/src/server/formatters/md/index.ts @@ -1,11 +1,13 @@ -import { isErrorEvent, isLogEvent, isTraceEvent } from "../../parser/helpers.ts"; +import { isErrorEvent, isLogEvent, isMetricEvent, isTraceEvent } from "../../parser/helpers.ts"; import type { FormatterRegistry } from "../types.ts"; import { formatError } from "./errors.ts"; import { formatLog } from "./logs.ts"; +import { formatMetric } from "./metrics.ts"; import { formatTrace } from "./traces.ts"; export const formatters: FormatterRegistry = { event: { typeGuard: isErrorEvent, format: formatError }, log: { typeGuard: isLogEvent, format: formatLog }, + metric: { typeGuard: isMetricEvent, format: formatMetric }, transaction: { typeGuard: isTraceEvent, format: formatTrace }, }; diff --git a/packages/spotlight/src/server/formatters/md/metrics.ts b/packages/spotlight/src/server/formatters/md/metrics.ts new file mode 100644 index 000000000..5a5ba1768 --- /dev/null +++ b/packages/spotlight/src/server/formatters/md/metrics.ts @@ -0,0 +1,32 @@ +import type { Envelope } from "@sentry/core"; +import type { SentryMetricEvent, SentryMetricPayload } from "../../parser/index.ts"; +import { formatTimestamp } from "../utils.ts"; + +function formatMetricRow(metric: SentryMetricPayload): string { + const timestamp = formatTimestamp(metric.timestamp); + const attributes = + metric.attributes && Object.keys(metric.attributes).length > 0 + ? Object.entries(metric.attributes) + .map(([key, attr]) => `${key}=${attr.value}`) + .join(", ") + : ""; + + const traceInfo = metric.trace_id ? metric.trace_id.substring(0, 8) : ""; + + return `| ${timestamp} | ${metric.name} | ${metric.type} | ${metric.value} | ${metric.unit ?? ""} | ${traceInfo} | ${attributes} |`; +} + +export function formatMetric(event: SentryMetricEvent, _envelopeHeader: Envelope[0]): string[] { + const lines: string[] = []; + + lines.push("## Metrics"); + lines.push(""); + lines.push("| Timestamp | Name | Type | Value | Unit | Trace | Attributes |"); + lines.push("|-----------|------|------|-------|------|-------|------------|"); + + for (const metric of event.items) { + lines.push(formatMetricRow(metric)); + } + + return lines; +} diff --git a/packages/spotlight/src/server/formatters/types.ts b/packages/spotlight/src/server/formatters/types.ts index be1e7109f..26e33b40e 100644 --- a/packages/spotlight/src/server/formatters/types.ts +++ b/packages/spotlight/src/server/formatters/types.ts @@ -1,11 +1,18 @@ import type { Envelope } from "@sentry/core"; -import type { SentryErrorEvent, SentryEvent, SentryLogEvent, SentryTransactionEvent } from "../parser/types.ts"; +import type { + SentryErrorEvent, + SentryEvent, + SentryLogEvent, + SentryMetricEvent, + SentryTransactionEvent, +} from "../parser/types.ts"; /** * Strongly-typed formatter functions (no type guards needed in implementation) */ export type ErrorFormatterFn = (event: SentryErrorEvent, envelopeHeader: Envelope[0]) => string[]; export type LogFormatterFn = (event: SentryLogEvent, envelopeHeader: Envelope[0]) => string[]; +export type MetricFormatterFn = (event: SentryMetricEvent, envelopeHeader: Envelope[0]) => string[]; export type TraceFormatterFn = (event: SentryTransactionEvent, envelopeHeader: Envelope[0]) => string[]; /** @@ -22,6 +29,7 @@ export type FormatterEntry = { export type FormatterRegistry = { event: FormatterEntry; log: FormatterEntry; + metric: FormatterEntry; transaction: FormatterEntry; }; diff --git a/packages/spotlight/src/server/mcp/constants.ts b/packages/spotlight/src/server/mcp/constants.ts index 9f2c92521..91a395579 100644 --- a/packages/spotlight/src/server/mcp/constants.ts +++ b/packages/spotlight/src/server/mcp/constants.ts @@ -75,3 +75,45 @@ export const NO_LOGS_CONTENT: CallToolResult = { }, ], }; + +export const NO_METRICS_CONTENT: CallToolResult = { + content: [ + { + type: "text", + text: `**No metrics detected in Spotlight** + +**This means:** +- Application hasn't generated any metrics in the recent timeframe +- No counter, gauge, or distribution metrics were captured +- Application might not be instrumented with Sentry metrics SDK + +**Next debugging steps:** + +1. **If investigating application metrics:** + - Ensure your Sentry SDK has metrics enabled (JavaScript 10.25.0+, Python 2.44.0+) + - Verify metrics are being sent via \`trace_metric\` envelope items + - Check that Spotlight is correctly capturing metric envelopes + +2. **If checking for specific functionality:** + - Trigger the feature or workflow you're investigating + - Look for custom metric instrumentation in your code + - Consider adding metrics to critical paths if needed + +3. **If monitoring general health:** + - Check that metrics SDK is properly configured + - Verify that metrics are being emitted (check SDK logs) + - Test with known metric-generating actions (API calls, database operations) + +4. **Expand search timeframe:** + - Use a longer duration (300+ seconds) to capture older metrics + - Consider that some operations might generate metrics less frequently + +**Metric Types Available:** +- **COUNTER**: Incrementing counts (e.g., request counts) +- **GAUGE**: Fluctuating values (e.g., queue depth) +- **DISTRIBUTION**: Statistical distributions (e.g., response times) + +**Pro tip:** Metrics are trace-connected in Sentry - every metric can be linked to a trace for enhanced debugging. This is Sentry's key differentiator for metrics!`, + }, + ], +}; diff --git a/packages/spotlight/src/server/mcp/mcp.ts b/packages/spotlight/src/server/mcp/mcp.ts index feee555c2..485f0f78d 100644 --- a/packages/spotlight/src/server/mcp/mcp.ts +++ b/packages/spotlight/src/server/mcp/mcp.ts @@ -11,7 +11,8 @@ import { renderSpanTree, } from "../formatters/md/traces.ts"; import { getBuffer } from "../utils/index.ts"; -import { NO_ERRORS_CONTENT, NO_LOGS_CONTENT } from "./constants.ts"; +import { NO_ERRORS_CONTENT, NO_LOGS_CONTENT, NO_METRICS_CONTENT } from "./constants.ts"; +import { queryMetrics } from "./tools/metrics.ts"; const inputSchema = { filters: z.union([ @@ -439,5 +440,127 @@ get_traces({ traceId: "71a8c5e41ae1044dee67f50a07538fe7" }) }, ); + mcp.registerTool( + "query_metrics", + { + title: "Query Metrics", + description: `**Purpose:** Query metrics from collected telemetry. Returns all metrics when called without filters, or filter by name, type, trace ID, or time window. + +**Returns:** +• List of metric samples (all or filtered) +• Full metric payloads with attributes +• Trace correlation information + +**When to use:** +- Getting all available metrics (no filters) +- Finding metrics by name or type +- Filtering metrics by trace ID +- Getting metrics within a time window + +**Example calls:** +\`\`\`json +// Get all metrics +query_metrics({}) + +// Query by name +query_metrics({ name: "api.response_time" }) + +// Query by type +query_metrics({ type: "distribution" }) + +// Query by trace ID +query_metrics({ traceId: "71a8c5e4" }) + +// Query with time window (last 5 minutes) +query_metrics({ timeWindow: 300 }) + +// Combined filters +query_metrics({ name: "api", type: "counter", limit: 10 }) +\`\`\` + +**Parameter hints:** +• name: Metric name (exact or partial match) +• type: Metric type (counter, gauge, distribution) +• traceId: Trace ID to filter by +• timeWindow: Seconds to look back (60 = 1 min, 300 = 5 min) +• limit: Maximum number of results to return`, + inputSchema: { + name: z.string().optional().describe("Metric name to filter by (exact or partial match)"), + type: z.enum(["counter", "gauge", "distribution"]).optional().describe("Metric type to filter by"), + traceId: z.string().optional().describe("Trace ID to filter metrics by"), + timeWindow: z + .number() + .optional() + .describe("Number of seconds to look back from now. Examples: 60 = last minute, 300 = last 5 minutes"), + limit: z.number().optional().describe("Maximum number of results to return"), + }, + }, + async args => { + try { + const metrics = queryMetrics({ + name: args.name, + type: args.type, + traceId: args.traceId, + timeWindow: args.timeWindow, + limit: args.limit, + }); + + if (metrics.length === 0) { + return NO_METRICS_CONTENT; + } + + const content: TextContent[] = [ + { + type: "text", + text: `# Metrics Query Results (${metrics.length} found)\n\n`, + }, + ]; + + for (const metric of metrics) { + const timestamp = new Date(metric.timestamp * 1000).toISOString(); + let metricText = `## ${metric.name}\n`; + metricText += `- **Type:** ${metric.type}\n`; + const valueStr = + metric.unit && metric.unit !== "none" + ? `${metric.value.toLocaleString()} ${metric.unit}` + : metric.value.toLocaleString(); + metricText += `- **Value:** ${valueStr}\n`; + metricText += `- **Timestamp:** ${timestamp}\n`; + if (metric.trace_id) { + metricText += `- **Trace ID:** ${metric.trace_id}\n`; + } + if (metric.span_id) { + metricText += `- **Span ID:** ${metric.span_id}\n`; + } + if (metric.attributes && Object.keys(metric.attributes).length > 0) { + metricText += "- **Attributes:**\n"; + for (const [key, attr] of Object.entries(metric.attributes)) { + const value = typeof attr === "object" && "value" in attr ? attr.value : attr; + metricText += ` - ${key}: ${value}\n`; + } + } + metricText += "\n"; + + content.push({ + type: "text", + text: metricText, + }); + } + + return { content }; + } catch (err) { + captureException(err, { extra: { context: "Error querying metrics in MCP" } }); + return { + content: [ + { + type: "text", + text: `Error querying metrics: ${err instanceof Error ? err.message : String(err)}`, + }, + ], + }; + } + }, + ); + return mcp; } diff --git a/packages/spotlight/src/server/mcp/tools/metrics.ts b/packages/spotlight/src/server/mcp/tools/metrics.ts new file mode 100644 index 000000000..4e70d2577 --- /dev/null +++ b/packages/spotlight/src/server/mcp/tools/metrics.ts @@ -0,0 +1,74 @@ +import type { SentryMetricPayload } from "../../parser/types.ts"; +import { getBuffer } from "../../utils/index.ts"; +import type { EventContainer } from "../../utils/index.ts"; + +/** + * Extract all metrics from envelopes + */ +function extractMetricsFromEnvelopes(envelopes: EventContainer[]): SentryMetricPayload[] { + const allMetrics: SentryMetricPayload[] = []; + + for (const envelope of envelopes) { + const parsed = envelope.getParsedEnvelope(); + if (!parsed) continue; + + const [, items] = parsed.envelope; + for (const [itemHeader, itemData] of items) { + if (itemHeader.type === "trace_metric" && itemData && typeof itemData === "object") { + const payload = itemData as { items?: SentryMetricPayload[] }; + if (payload.items && Array.isArray(payload.items)) { + allMetrics.push(...payload.items); + } + } + } + } + + return allMetrics; +} + +/** + * Query metrics with filters + */ +export function queryMetrics(filters: { + name?: string; + type?: string; + traceId?: string; + timeWindow?: number; + limit?: number; +}): SentryMetricPayload[] { + const envelopes = getBuffer().read( + filters.timeWindow + ? { + timeWindow: filters.timeWindow, + } + : { all: true }, + ); + + const allMetrics = extractMetricsFromEnvelopes(envelopes); + + // Apply filters + let filtered = allMetrics; + + if (filters.name) { + const nameFilter = filters.name; + filtered = filtered.filter(m => m.name === nameFilter || m.name.includes(nameFilter)); + } + + if (filters.type) { + filtered = filtered.filter(m => m.type === filters.type); + } + + if (filters.traceId) { + const traceIdFilter = filters.traceId; + filtered = filtered.filter(m => m.trace_id === traceIdFilter || (m.trace_id?.startsWith(traceIdFilter) ?? false)); + } + + // Sort by timestamp (newest first) and apply limit + filtered.sort((a, b) => b.timestamp - a.timestamp); + + if (filters.limit) { + filtered = filtered.slice(0, filters.limit); + } + + return filtered; +} diff --git a/packages/spotlight/src/server/parser/helpers.ts b/packages/spotlight/src/server/parser/helpers.ts index de08b3b5a..66e6945dc 100644 --- a/packages/spotlight/src/server/parser/helpers.ts +++ b/packages/spotlight/src/server/parser/helpers.ts @@ -2,6 +2,7 @@ import type { SentryErrorEvent, SentryEvent, SentryLogEvent, + SentryMetricEvent, SentryProfileV1Event, SentryTransactionEvent, } from "./types.ts"; @@ -10,11 +11,13 @@ export const ERROR_EVENT_TYPES = new Set(["event", "error"]); export const TRACE_EVENT_TYPES = new Set(["transaction"]); export const PROFILE_EVENT_TYPES = new Set(["profile"]); export const LOG_EVENT_TYPES = new Set(["log"]); +export const METRIC_EVENT_TYPES = new Set(["trace_metric"]); export const SUPPORTED_EVENT_TYPES = new Set([ ...ERROR_EVENT_TYPES, ...TRACE_EVENT_TYPES, ...PROFILE_EVENT_TYPES, ...LOG_EVENT_TYPES, + ...METRIC_EVENT_TYPES, ]); export function isErrorEvent(event: SentryEvent): event is SentryErrorEvent { @@ -35,3 +38,7 @@ export function isTraceEvent(event: SentryEvent): event is SentryTransactionEven export function isLogEvent(event: SentryEvent): event is SentryLogEvent { return !!event.type && LOG_EVENT_TYPES.has(event.type); } + +export function isMetricEvent(event: SentryEvent): event is SentryMetricEvent { + return !!event.type && METRIC_EVENT_TYPES.has(event.type); +} diff --git a/packages/spotlight/src/server/parser/types.ts b/packages/spotlight/src/server/parser/types.ts index 74a40f54f..595476cd1 100644 --- a/packages/spotlight/src/server/parser/types.ts +++ b/packages/spotlight/src/server/parser/types.ts @@ -1,4 +1,4 @@ -import type { EventEnvelopeHeaders, Measurements, SerializedLog } from "@sentry/core"; +import type { EventEnvelopeHeaders, Measurements, SerializedLog, SerializedMetric } from "@sentry/core"; export type RawEventContext = { /** @@ -289,9 +289,19 @@ export type SentryLogEvent = CommonEventAttrs & { items: Array; }; +export type SentryMetricPayload = SerializedMetric & { + id: string; +}; + +export type SentryMetricEvent = CommonEventAttrs & { + type: "trace_metric"; + items: SentryMetricPayload[]; +}; + export type SentryEvent = | SentryErrorEvent | SentryTransactionEvent | SentryProfileV1Event | SentryProfileV2ChunkEvent - | SentryLogEvent; + | SentryLogEvent + | SentryMetricEvent; diff --git a/packages/spotlight/src/ui/telemetry/components/TelemetrySidebar.tsx b/packages/spotlight/src/ui/telemetry/components/TelemetrySidebar.tsx index ccaeb800a..fda5bb191 100644 --- a/packages/spotlight/src/ui/telemetry/components/TelemetrySidebar.tsx +++ b/packages/spotlight/src/ui/telemetry/components/TelemetrySidebar.tsx @@ -14,6 +14,7 @@ interface TelemetrySidebarProps { errorCount: number; traceCount: number; logCount: number; + metricCount: number; isOnline: boolean; } @@ -45,7 +46,13 @@ function NavigationLink({ ); } -export default function TelemetrySidebar({ errorCount, traceCount, logCount, isOnline }: TelemetrySidebarProps) { +export default function TelemetrySidebar({ + errorCount, + traceCount, + logCount, + metricCount, + isOnline, +}: TelemetrySidebarProps) { const location = useLocation(); const pathname = location.pathname; const { getSidecarUrl } = useSpotlightContext(); @@ -122,6 +129,12 @@ export default function TelemetrySidebar({ errorCount, traceCount, logCount, isO isActive={isActive("errors")} /> + {/* Insights section */} + )} + + + + + + + + Filter by Metric Name + + {allMetricNames.map(name => ( + toggleNameFilter(name)} + className="truncate" + > + {name} + + ))} + + + + + {hasActiveFilters && ( +
+ {Array.from(selectedNames).map(name => ( + + {name} + + + ))} + +
+ )} + + + + {metricGroups.length === 0 ? ( + + ) : ( + metricGroups.map(group => { + const isExpanded = expandedSections.has(group.name); + + return ( + toggleSection(group.name)} + traceId={traceId} + selectedMetricId={metricId ? decodeURIComponent(metricId) : undefined} + selectedRef={selectedRef} + /> + ); + }) + )} + + {metricId && } + + ); +} + +function MetricSection({ + group, + isExpanded, + onToggle, + traceId, + selectedMetricId, + selectedRef, +}: { + group: MetricGroup; + isExpanded: boolean; + onToggle: () => void; + traceId?: string; + selectedMetricId?: string; + selectedRef: React.RefObject; +}) { + return ( +
+ + + {isExpanded && ( +
+
+ +
+ + {group.samples.map(sample => { + const isSelected = selectedMetricId === sample.id; + const ref = isSelected ? selectedRef : null; + + return ( +
+ +
+ ); + })} +
+ )} +
+ ); +} + +function MetricSampleItem({ + sample, + traceId, + isSelected, +}: { + sample: SentryMetricPayload; + traceId?: string; + isSelected: boolean; +}) { + const route = traceId + ? `/telemetry/traces/${traceId}/metrics/${encodeURIComponent(sample.id)}` + : `/telemetry/metrics/${encodeURIComponent(sample.id)}`; + + return ( + +
+ +
+ +
{getFormattedNumber(sample.value)}
+ +
+ {sample.trace_id && !traceId && ( + e.stopPropagation()} + className="text-primary-400 hover:text-primary-100 underline font-mono" + > + {truncateId(sample.trace_id)} + + )} + {sample.span_id && span {truncateId(sample.span_id)}} +
+ + ); +} + +function AggregateSummary({ group }: { group: MetricGroup }) { + const { aggregate, percentiles, type } = group; + const showPercentiles = (type === "gauge" || type === "distribution") && percentiles.size > 0; + + return ( +
+
+ Count: + {aggregate.count} +
+ {aggregate.sum !== undefined && ( +
+ Sum: + {getFormattedNumber(aggregate.sum)} +
+ )} + {aggregate.avg !== undefined && ( +
+ Avg: + {getFormattedNumber(aggregate.avg)} +
+ )} + {aggregate.min !== undefined && ( +
+ Min: + {getFormattedNumber(aggregate.min)} +
+ )} + {aggregate.max !== undefined && ( +
+ Max: + {getFormattedNumber(aggregate.max)} +
+ )} + {showPercentiles && ( + <> +
+ P50: + {getFormattedNumber(percentiles.get(50) ?? 0)} +
+
+ P90: + {getFormattedNumber(percentiles.get(90) ?? 0)} +
+
+ P95: + {getFormattedNumber(percentiles.get(95) ?? 0)} +
+ + )} +
+ ); +} diff --git a/packages/spotlight/src/ui/telemetry/components/metrics/components/MetricTypeBadge.tsx b/packages/spotlight/src/ui/telemetry/components/metrics/components/MetricTypeBadge.tsx new file mode 100644 index 000000000..1de15be4b --- /dev/null +++ b/packages/spotlight/src/ui/telemetry/components/metrics/components/MetricTypeBadge.tsx @@ -0,0 +1,21 @@ +import type { MetricType } from "@sentry/core"; +import { cn } from "@spotlight/ui/lib/cn"; + +export default function MetricTypeBadge({ type }: { type: MetricType }) { + const colors: Record = { + counter: "bg-blue-600/30 text-blue-300 border-blue-500/30", + gauge: "bg-green-600/30 text-green-300 border-green-500/30", + distribution: "bg-purple-600/30 text-purple-300 border-purple-500/30", + }; + + return ( + + {type} + + ); +} diff --git a/packages/spotlight/src/ui/telemetry/components/traces/TraceDetails/index.tsx b/packages/spotlight/src/ui/telemetry/components/traces/TraceDetails/index.tsx index a47d6b6ed..21bb2c962 100644 --- a/packages/spotlight/src/ui/telemetry/components/traces/TraceDetails/index.tsx +++ b/packages/spotlight/src/ui/telemetry/components/traces/TraceDetails/index.tsx @@ -13,6 +13,7 @@ import EventList from "../../events/EventList"; import AITraceSplitView from "../../insights/aiTraces/AITraceSplitView"; import { hasAISpans } from "../../insights/aiTraces/sdks/aiLibraries"; import LogsList from "../../log/LogsList"; +import MetricsList from "../../metrics/MetricsList"; import DateTime from "../../shared/DateTime"; import EmptyState from "../../shared/EmptyState"; import TraceProfileTree from "./components/TraceProfileTree"; @@ -88,6 +89,8 @@ export default function TraceDetails({ trace, aiConfig }: TraceDetailsProps) { const events = useSentryEvents(trace.trace_id); const profile = useSentryStore.getState().getProfileByTraceId(trace.trace_id); + const getMetricsByTraceId = useSentryStore.getState().getMetricsByTraceId; + const metrics = getMetricsByTraceId(trace.trace_id); const errorCount = useMemo(() => events.reduce((len, e) => (isErrorEvent(e) ? len + 1 : len), 0), [events]); const tabs = [ @@ -99,6 +102,11 @@ export default function TraceDetails({ trace, aiConfig }: TraceDetailsProps) { severe: errorCount > 0, }, }), + createTab("metrics", "Metrics", { + notificationCount: { + count: metrics.length, + }, + }), ]; if (profile) { @@ -118,6 +126,8 @@ export default function TraceDetails({ trace, aiConfig }: TraceDetailsProps) { } /> } /> } /> + } /> + } /> {profile && } />} {/* Default tab */} } /> diff --git a/packages/spotlight/src/ui/telemetry/constants/sentry.ts b/packages/spotlight/src/ui/telemetry/constants/sentry.ts index f42d06300..e97a75b4a 100644 --- a/packages/spotlight/src/ui/telemetry/constants/sentry.ts +++ b/packages/spotlight/src/ui/telemetry/constants/sentry.ts @@ -2,10 +2,12 @@ export const ERROR_EVENT_TYPES = new Set(["event", "error"]); export const TRACE_EVENT_TYPES = new Set(["transaction"]); export const PROFILE_EVENT_TYPES = new Set(["profile", "profile_chunk"]); export const LOG_EVENT_TYPES = new Set(["log"]); +export const METRIC_EVENT_TYPES = new Set(["trace_metric"]); export const ATTACHMENT_EVENT_TYPES = new Set(["attachment"]); export const SUPPORTED_EVENT_TYPES = new Set([ ...ERROR_EVENT_TYPES, ...TRACE_EVENT_TYPES, ...PROFILE_EVENT_TYPES, ...LOG_EVENT_TYPES, + ...METRIC_EVENT_TYPES, ]); diff --git a/packages/spotlight/src/ui/telemetry/store/slices/eventsSlice.ts b/packages/spotlight/src/ui/telemetry/store/slices/eventsSlice.ts index 79a8341e5..88fe91a99 100644 --- a/packages/spotlight/src/ui/telemetry/store/slices/eventsSlice.ts +++ b/packages/spotlight/src/ui/telemetry/store/slices/eventsSlice.ts @@ -1,12 +1,20 @@ import { generateUuidv4 } from "@spotlight/ui/lib/uuid"; import type { StateCreator } from "zustand"; import { graftProfileSpans } from "../../data/profiles"; -import type { SentryEvent, SentryLogEventItem } from "../../types"; +import type { SentryEvent, SentryLogEventItem, SentryMetricPayload } from "../../types"; import type { SentryTransactionEvent } from "../../types"; -import { isErrorEvent, isLogEvent, isProfileChunkEvent, isProfileEvent, isTraceEvent } from "../../utils/sentry"; +import { + isErrorEvent, + isLogEvent, + isMetricEvent, + isProfileChunkEvent, + isProfileEvent, + isTraceEvent, +} from "../../utils/sentry"; import type { EventsSliceActions, EventsSliceState, SentryProfileWithTraceMeta, SentryStore } from "../types"; import { toTimestamp } from "../utils"; import { processLogItems } from "../utils/logProcessor"; +import { processMetricItems } from "../utils/metricProcessor"; import { mergeChunksToProfile, processProfileChunkEvent } from "../utils/profileChunkProcessor"; import { processProfileEvent } from "../utils/profileProcessor"; import { initializeTrace } from "../utils/traceInitializer"; @@ -64,6 +72,31 @@ export const createEventsSlice: StateCreator(); + metricSet.add(metric); + newMetricsByTraceId.set(metric.trace_id, metricSet); + } + + const metricsWithName = newMetricsByName.get(metric.name) || []; + metricsWithName.push(metric); + newMetricsByName.set(metric.name, metricsWithName); + } + + set({ metricsById: newMetricsById, metricsByTraceId: newMetricsByTraceId, metricsByName: newMetricsByName }); + } + const { eventsById } = get(); const newEventIds = new Map(eventsById); newEventIds.set(event.event_id, event); diff --git a/packages/spotlight/src/ui/telemetry/store/slices/metricsSlice.ts b/packages/spotlight/src/ui/telemetry/store/slices/metricsSlice.ts new file mode 100644 index 000000000..3fd94c754 --- /dev/null +++ b/packages/spotlight/src/ui/telemetry/store/slices/metricsSlice.ts @@ -0,0 +1,25 @@ +import type { StateCreator } from "zustand"; +import type { MetricsSliceActions, MetricsSliceState, SentryStore } from "../types"; + +const initialMetricsState: MetricsSliceState = { + metricsById: new Map(), + metricsByTraceId: new Map(), + metricsByName: new Map(), +}; + +export const createMetricsSlice: StateCreator = ( + _set, + get, +) => ({ + ...initialMetricsState, + getMetricById: (id: string) => get().metricsById.get(id), + getMetrics: () => Array.from(get().metricsById.values()), + getMetricsByTraceId: (traceId: string) => { + const metricsByTraceId = get().metricsByTraceId.get(traceId); + return metricsByTraceId ? Array.from(metricsByTraceId) : []; + }, + getMetricsByName: (name: string) => { + return get().metricsByName.get(name) || []; + }, + getMetricNames: () => Array.from(get().metricsByName.keys()), +}); diff --git a/packages/spotlight/src/ui/telemetry/store/slices/sharedSlice.ts b/packages/spotlight/src/ui/telemetry/store/slices/sharedSlice.ts index 29a8dedbf..7de60df8b 100644 --- a/packages/spotlight/src/ui/telemetry/store/slices/sharedSlice.ts +++ b/packages/spotlight/src/ui/telemetry/store/slices/sharedSlice.ts @@ -64,6 +64,9 @@ export const createSharedSlice: StateCreator()((...a) => ({ ...createEnvelopesSlice(...a), ...createSDKsSlice(...a), ...createLogsSlice(...a), + ...createMetricsSlice(...a), ...createSharedSlice(...a), })); diff --git a/packages/spotlight/src/ui/telemetry/store/types.ts b/packages/spotlight/src/ui/telemetry/store/types.ts index b0159a92d..b928f08f8 100644 --- a/packages/spotlight/src/ui/telemetry/store/types.ts +++ b/packages/spotlight/src/ui/telemetry/store/types.ts @@ -5,6 +5,7 @@ import type { SentryErrorEvent, SentryEvent, SentryLogEventItem, + SentryMetricPayload, SentryProcessedProfile, Trace, } from "../types"; @@ -91,6 +92,20 @@ export interface LogsSliceActions { getLogsByTraceId: (traceId: string) => SentryLogEventItem[]; } +export interface MetricsSliceState { + metricsById: Map; + metricsByTraceId: Map>; + metricsByName: Map; +} + +export interface MetricsSliceActions { + getMetricById: (id: string) => SentryMetricPayload | undefined; + getMetrics: () => SentryMetricPayload[]; + getMetricsByTraceId: (traceId: string) => SentryMetricPayload[]; + getMetricsByName: (name: string) => SentryMetricPayload[]; + getMetricNames: () => string[]; +} + export interface SDKsSliceActions { inferSdkFromEvent: (event: SentryEvent) => Sdk; storeSdkRecord: (sdk: Sdk) => Sdk; @@ -112,6 +127,7 @@ export type SentryStoreState = EventsSliceState & SettingsSliceState & EnvelopesSliceState & LogsSliceState & + MetricsSliceState & SDKsSliceState; export type SentryStoreActions = EventsSliceActions & @@ -121,6 +137,7 @@ export type SentryStoreActions = EventsSliceActions & SettingsSliceActions & EnvelopesSliceActions & LogsSliceActions & + MetricsSliceActions & SDKsSliceActions & SharedSliceActions; diff --git a/packages/spotlight/src/ui/telemetry/store/utils/metricProcessor.ts b/packages/spotlight/src/ui/telemetry/store/utils/metricProcessor.ts new file mode 100644 index 000000000..2eaef2717 --- /dev/null +++ b/packages/spotlight/src/ui/telemetry/store/utils/metricProcessor.ts @@ -0,0 +1,31 @@ +import { generateUuidv4 } from "@spotlight/ui/lib/uuid"; +import type { SentryMetricEvent, SentryMetricPayload } from "../../types"; + +export interface MetricProcessingResult { + processedMetrics: SentryMetricPayload[]; +} + +/** + * Processes metric items from a metric event, adding id fields for UI tracking. + * @param event The metric event to process + * @returns Processed metric items ready to be stored + */ +export function processMetricItems(event: SentryMetricEvent): MetricProcessingResult { + const processedMetrics: SentryMetricPayload[] = []; + + if (!event.items?.length) { + return { processedMetrics }; + } + + for (const metric of event.items) { + // Generate a unique ID for each metric if not present + const metricId = metric.id || generateUuidv4(); + + processedMetrics.push({ + ...metric, + id: metricId, + }); + } + + return { processedMetrics }; +} diff --git a/packages/spotlight/src/ui/telemetry/tabs/MetricsTab.tsx b/packages/spotlight/src/ui/telemetry/tabs/MetricsTab.tsx new file mode 100644 index 000000000..58e99b8f9 --- /dev/null +++ b/packages/spotlight/src/ui/telemetry/tabs/MetricsTab.tsx @@ -0,0 +1,18 @@ +import { Route, Routes } from "react-router-dom"; +import MetricsList from "../components/metrics/MetricsList"; +import { SentryEventsContextProvider } from "../data/sentryEventsContext"; + +export default function MetricsTab() { + return ( + +
+
+ + } /> + } /> + +
+
+
+ ); +} diff --git a/packages/spotlight/src/ui/telemetry/types.ts b/packages/spotlight/src/ui/telemetry/types.ts index 0ad878de1..daea1d96c 100644 --- a/packages/spotlight/src/ui/telemetry/types.ts +++ b/packages/spotlight/src/ui/telemetry/types.ts @@ -1,4 +1,4 @@ -import type { EnvelopeItem, EventEnvelopeHeaders, Measurements, SerializedLog } from "@sentry/core"; +import type { EnvelopeItem, EventEnvelopeHeaders, Measurements, SerializedLog, SerializedMetric } from "@sentry/core"; import type { ColorValue } from "nanovis"; export type TraceId = string; @@ -276,12 +276,22 @@ export type SentryLogEvent = CommonEventAttrs & { items: Array; }; +export type SentryMetricPayload = SerializedMetric & { + id: string; +}; + +export type SentryMetricEvent = CommonEventAttrs & { + type: "trace_metric"; + items: SentryMetricPayload[]; +}; + export type SentryEvent = | SentryErrorEvent | SentryTransactionEvent | SentryProfileV1Event | SentryProfileV2ChunkEvent - | SentryLogEvent; + | SentryLogEvent + | SentryMetricEvent; export type Trace = TraceContext & { trace_id: string; diff --git a/packages/spotlight/src/ui/telemetry/utils/metrics.ts b/packages/spotlight/src/ui/telemetry/utils/metrics.ts new file mode 100644 index 000000000..559400252 --- /dev/null +++ b/packages/spotlight/src/ui/telemetry/utils/metrics.ts @@ -0,0 +1,86 @@ +import type { MetricType } from "@sentry/core"; +import type { SentryMetricPayload } from "../types"; + +/** + * Aggregate metrics by type (sum for counters, avg for distributions, etc.) + */ +export function aggregateMetrics( + metrics: SentryMetricPayload[], + type: MetricType, +): { + sum?: number; + avg?: number; + min?: number; + max?: number; + count: number; +} { + if (metrics.length === 0) { + return { count: 0 }; + } + + const values = metrics.map(m => m.value); + + switch (type) { + case "counter": + return { + sum: values.reduce((a, b) => a + b, 0), + count: metrics.length, + }; + case "gauge": + case "distribution": + return { + sum: values.reduce((a, b) => a + b, 0), + avg: values.reduce((a, b) => a + b, 0) / values.length, + min: Math.min(...values), + max: Math.max(...values), + count: metrics.length, + }; + default: + return { count: metrics.length }; + } +} + +/** + * Calculate percentiles for a distribution of values + */ +export function calculatePercentiles(values: number[], percentiles: number[]): Map { + if (values.length === 0) { + return new Map(); + } + + const sorted = [...values].sort((a, b) => a - b); + const result = new Map(); + + for (const percentile of percentiles) { + if (percentile < 0 || percentile > 100) continue; + + const index = (percentile / 100) * (sorted.length - 1); + const lower = Math.floor(index); + const upper = Math.ceil(index); + const weight = index - lower; + + if (lower === upper) { + result.set(percentile, sorted[lower] ?? 0); + } else { + const value = (sorted[lower] ?? 0) * (1 - weight) + (sorted[upper] ?? 0) * weight; + result.set(percentile, value); + } + } + + return result; +} + +/** + * Get metrics grouped by name + */ +export function groupMetricsByName(metrics: SentryMetricPayload[]): Map { + const groups = new Map(); + + for (const metric of metrics) { + const existing = groups.get(metric.name) || []; + existing.push(metric); + groups.set(metric.name, existing); + } + + return groups; +} diff --git a/packages/spotlight/src/ui/telemetry/utils/sentry.ts b/packages/spotlight/src/ui/telemetry/utils/sentry.ts index d75980038..8b17b1e54 100644 --- a/packages/spotlight/src/ui/telemetry/utils/sentry.ts +++ b/packages/spotlight/src/ui/telemetry/utils/sentry.ts @@ -1,8 +1,15 @@ -import { ERROR_EVENT_TYPES, LOG_EVENT_TYPES, PROFILE_EVENT_TYPES, TRACE_EVENT_TYPES } from "../constants/sentry"; +import { + ERROR_EVENT_TYPES, + LOG_EVENT_TYPES, + METRIC_EVENT_TYPES, + PROFILE_EVENT_TYPES, + TRACE_EVENT_TYPES, +} from "../constants/sentry"; import type { SentryErrorEvent, SentryEvent, SentryLogEvent, + SentryMetricEvent, SentryProfileV1Event, SentryProfileV2ChunkEvent, SentryTransactionEvent, @@ -27,3 +34,7 @@ export function isTraceEvent(event: SentryEvent): event is SentryTransactionEven export function isLogEvent(event: SentryEvent): event is SentryLogEvent { return !!event.type && LOG_EVENT_TYPES.has(event.type); } + +export function isMetricEvent(event: SentryEvent): event is SentryMetricEvent { + return !!event.type && METRIC_EVENT_TYPES.has(event.type); +} diff --git a/packages/spotlight/tests/e2e/ui/metrics.e2e.test.ts b/packages/spotlight/tests/e2e/ui/metrics.e2e.test.ts new file mode 100644 index 000000000..abc761237 --- /dev/null +++ b/packages/spotlight/tests/e2e/ui/metrics.e2e.test.ts @@ -0,0 +1,221 @@ +import { expect, test } from "./fixtures"; + +// Metric fixture paths +const METRIC_ENVELOPE = "metrics/trace_metric_envelope.bin"; +const TRANSACTION_WITH_METRICS = "metrics/transaction_envelope.bin"; + +test.describe("Metrics Display UI Tests", () => { + test("should display metrics list with types and values", async ({ page, sidecar, sendTestEnvelope }) => { + await page.goto(sidecar.baseURL); + // Send metric envelope + await sendTestEnvelope(METRIC_ENVELOPE); + + // Navigate to Metrics tab + const metricsTab = page + .locator('[data-test-id="tab-metrics"], a[href*="metrics"], button:has-text("Metrics")') + .first(); + await metricsTab.click(); + // Wait for metric sections (expandable buttons) to appear + await page.waitForSelector('button:has-text("▶"), a[href*="/telemetry/metrics/"]', { + timeout: 10000, + }); + + // Verify metrics are displayed with numeric values + const pageContent = page.locator("body"); + const text = await pageContent.textContent(); + expect(text).not.toBe(""); + // Should contain numeric values + const hasNumbers = /\d+/.test(text || ""); + expect(hasNumbers).toBe(true); + }); + + test("should display grouped metrics by name", async ({ page, sidecar, sendTestEnvelope }) => { + await page.goto(sidecar.baseURL); + // Send metric envelope multiple times to get multiple samples + await sendTestEnvelope(METRIC_ENVELOPE); + await sendTestEnvelope(METRIC_ENVELOPE); + + // Navigate to Metrics tab + const metricsTab = page + .locator('[data-test-id="tab-metrics"], a[href*="metrics"], button:has-text("Metrics")') + .first(); + await metricsTab.click(); + // Wait for metrics to appear + await page.waitForSelector('button:has-text("▶"), a[href*="/telemetry/metrics/"]', { + timeout: 10000, + }); + + // Verify metrics are displayed (grouped by name) + const pageContent = page.locator("body"); + const text = await pageContent.textContent(); + expect(text).not.toBe(""); + // Verify multiple metric sections exist (indicating grouping) + const sectionButtons = page.locator('button:has-text("▶")'); + const sectionCount = await sectionButtons.count(); + expect(sectionCount).toBeGreaterThan(0); + }); + + test("should expand metric sections", async ({ page, sidecar, sendTestEnvelope }) => { + await page.goto(sidecar.baseURL); + // Send metric envelope + await sendTestEnvelope(METRIC_ENVELOPE); + + // Navigate to Metrics tab + const metricsTab = page + .locator('[data-test-id="tab-metrics"], a[href*="metrics"], button:has-text("Metrics")') + .first(); + await metricsTab.click(); + // Wait for metric sections to appear + await page.waitForSelector('button:has-text("▶")', { + timeout: 10000, + }); + + // Click on a metric section to expand it + const sectionButton = page.locator('button:has-text("▶")').first(); + await sectionButton.click({ timeout: 2000 }); + + // Wait for expanded content (metric sample links) + await page + .waitForSelector('a[href*="/telemetry/metrics/"]', { + timeout: 3000, + }) + .catch(() => { + // Might not have samples or already visible + }); + + // Verify content is displayed + const pageContent = page.locator("body"); + const text = await pageContent.textContent(); + expect(text).not.toBe(""); + }); + + test("should display metric details on click", async ({ page, sidecar, sendTestEnvelope }) => { + await page.goto(sidecar.baseURL); + // Send metric envelope + await sendTestEnvelope(METRIC_ENVELOPE); + + // Navigate to Metrics tab + const metricsTab = page + .locator('[data-test-id="tab-metrics"], a[href*="metrics"], button:has-text("Metrics")') + .first(); + await metricsTab.click(); + // Wait for metrics to appear + await page.waitForSelector('button:has-text("▶")', { + timeout: 10000, + }); + + // Expand a section first + const sectionButton = page.locator('button:has-text("▶")').first(); + await sectionButton.click({ timeout: 2000 }).catch(() => {}); + + // Wait for metric sample links + await page + .waitForSelector('a[href*="/telemetry/metrics/"]', { + timeout: 5000, + }) + .catch(() => { + // If no samples, that's okay + }); + + // Try to click on a metric sample link + const metricLink = page.locator('a[href*="/telemetry/metrics/"]').first(); + const hasMetricLink = await metricLink.isVisible().catch(() => false); + + if (hasMetricLink) { + await metricLink.click({ timeout: 2000 }); + // Wait for side panel to appear + await page.waitForTimeout(500); + } + + // Verify details are shown (side panel or expanded view) + const pageContent = page.locator("body"); + const text = await pageContent.textContent(); + expect(text).not.toBe(""); + }); + + test("should handle metric filtering", async ({ page, sidecar, sendTestEnvelope }) => { + await page.goto(sidecar.baseURL); + // Send metric envelope + await sendTestEnvelope(METRIC_ENVELOPE); + + // Navigate to Metrics tab + const metricsTab = page + .locator('[data-test-id="tab-metrics"], a[href*="metrics"], button:has-text("Metrics")') + .first(); + await metricsTab.click(); + // Wait for metrics to appear + await page.waitForSelector('button:has-text("▶"), input[type="text"]', { + timeout: 10000, + }); + + // Verify filter controls are available (search input, filter button) + const filterInput = page.locator('input[type="text"], input[placeholder*="Search"]').first(); + await filterInput.isVisible().catch(() => { + // Filter controls might not be visible, that's okay + }); + + // Should at least have metric content + const pageContent = page.locator("body"); + const text = await pageContent.textContent(); + expect(text).not.toBe(""); + }); + + test("should display metrics with trace context", async ({ page, sidecar, sendTestEnvelope }) => { + await page.goto(sidecar.baseURL); + // Send transaction envelope (may or may not include metrics) + await sendTestEnvelope(TRANSACTION_WITH_METRICS); + // Also send a metric envelope to ensure metrics are available + await sendTestEnvelope(METRIC_ENVELOPE); + + // Navigate to Traces tab first to verify transaction is received + const tracesTab = page.locator('[data-test-id="tab-traces"], a[href*="traces"], button:has-text("Traces")').first(); + await tracesTab.click(); + // Wait for traces to appear + await page + .waitForSelector('a[href*="/telemetry/traces/"]', { + timeout: 5000, + }) + .catch(() => { + // No traces, that's okay - test will still verify metrics tab works + }); + + // Navigate to Metrics tab + const metricsTab = page + .locator('[data-test-id="tab-metrics"], a[href*="metrics"], button:has-text("Metrics")') + .first(); + await metricsTab.click(); + // Wait for metrics to appear (either from transaction or metric envelope) + await page.waitForSelector('button:has-text("▶"), a[href*="/telemetry/metrics/"]', { + timeout: 10000, + }); + + // Verify content is displayed + const pageContent = page.locator("body"); + const text = await pageContent.textContent(); + expect(text).not.toBe(""); + }); + + test("should handle empty metrics state", async ({ page, sidecar }) => { + await page.goto(sidecar.baseURL); + + // Navigate to Metrics tab without sending any metrics + const metricsTab = page + .locator('[data-test-id="tab-metrics"], a[href*="metrics"], button:has-text("Metrics")') + .first(); + await metricsTab.click(); + // Wait for either metrics to appear OR "No metrics" message + await Promise.race([ + page.waitForSelector('button:has-text("▶"), a[href*="/telemetry/metrics/"]', { + timeout: 3000, + }), + page.waitForSelector("text=/No metrics/i", { timeout: 3000 }), + ]).catch(() => { + // Either state is fine + }); + + // Verify content is displayed (either metrics or empty state) + const pageContent = page.locator("body"); + const text = await pageContent.textContent(); + expect(text).not.toBe(""); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 884ebfe03..49e8dd087 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,14 +10,14 @@ catalogs: specifier: ^5.1.0 version: 5.2.5 '@sentry/astro': - specifier: ^10.31.0 - version: 10.32.1 + specifier: ^10.36.0 + version: 10.36.0 '@sentry/core': - specifier: ^10.31.0 - version: 10.32.1 + specifier: ^10.36.0 + version: 10.36.0 '@sentry/node': - specifier: ^10.31.0 - version: 10.32.1 + specifier: ^10.36.0 + version: 10.36.0 '@tailwindcss/vite': specifier: ^4.1.11 version: 4.1.11 @@ -105,10 +105,10 @@ importers: version: 1.25.2(hono@4.11.7)(zod@4.1.13) '@sentry/core': specifier: 'catalog:' - version: 10.32.1 + version: 10.36.0 '@sentry/node': specifier: 'catalog:' - version: 10.32.1 + version: 10.36.0 anser: specifier: ^2.3.3 version: 2.3.3 @@ -168,14 +168,14 @@ importers: specifier: ^1.2.7 version: 1.2.7(@types/react-dom@18.3.7(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@sentry/browser': - specifier: ^10.31.0 - version: 10.32.1 + specifier: ^10.36.0 + version: 10.36.0 '@sentry/electron': specifier: ^7.5.0 version: 7.5.0 '@sentry/react': - specifier: ^10.31.0 - version: 10.32.1(react@18.3.1) + specifier: ^10.36.0 + version: 10.36.0(react@18.3.1) '@sentry/vite-plugin': specifier: ^2.22.5 version: 2.23.0 @@ -358,7 +358,7 @@ importers: version: 5.2.5 '@sentry/astro': specifier: 'catalog:' - version: 10.32.1(astro@5.15.9(@types/node@24.10.1)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.53.3)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.2)) + version: 10.36.0(astro@5.15.9(@types/node@24.10.1)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.53.3)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.2)) '@tailwindcss/vite': specifier: 'catalog:' version: 4.1.11(vite@6.4.1(@types/node@24.10.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.2)) @@ -1753,10 +1753,18 @@ packages: '@one-ini/wasm@0.1.1': resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} + '@opentelemetry/api-logs@0.207.0': + resolution: {integrity: sha512-lAb0jQRVyleQQGiuuvCOTDVspc14nx6XJjP4FspJ1sNARo3Regq4ZZbrc3rN4b1TYSuUCvgH+UXUPug4SLOqEQ==} + engines: {node: '>=8.0.0'} + '@opentelemetry/api-logs@0.208.0': resolution: {integrity: sha512-CjruKY9V6NMssL/T1kAFgzosF1v9o6oeN+aX5JB/C/xPNtmgIJqcXHG7fA82Ou1zCpWGl4lROQUKwUNE1pMCyg==} engines: {node: '>=8.0.0'} + '@opentelemetry/api-logs@0.210.0': + resolution: {integrity: sha512-CMtLxp+lYDriveZejpBND/2TmadrrhUfChyxzmkFtHaMDdSKfP59MAYyA0ICBvEBdm3iXwLcaj/8Ic/pnGw9Yg==} + engines: {node: '>=8.0.0'} + '@opentelemetry/api@1.9.0': resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} engines: {node: '>=8.0.0'} @@ -1767,150 +1775,312 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/context-async-hooks@2.5.0': + resolution: {integrity: sha512-uOXpVX0ZjO7heSVjhheW2XEPrhQAWr2BScDPoZ9UDycl5iuHG+Usyc3AIfG6kZeC1GyLpMInpQ6X5+9n69yOFw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/core@2.2.0': resolution: {integrity: sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/core@2.4.0': + resolution: {integrity: sha512-KtcyFHssTn5ZgDu6SXmUznS80OFs/wN7y6MyFRRcKU6TOw8hNcGxKvt8hsdaLJfhzUszNSjURetq5Qpkad14Gw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/core@2.5.0': + resolution: {integrity: sha512-ka4H8OM6+DlUhSAZpONu0cPBtPPTQKxbxVzC4CzVx5+K4JnroJVBtDzLAMx4/3CDTJXRvVFhpFjtl4SaiTNoyQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/instrumentation-amqplib@0.55.0': resolution: {integrity: sha512-5ULoU8p+tWcQw5PDYZn8rySptGSLZHNX/7srqo2TioPnAAcvTy6sQFQXsNPrAnyRRtYGMetXVyZUy5OaX1+IfA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-amqplib@0.57.0': + resolution: {integrity: sha512-hgHnbcopDXju7164mwZu7+6mLT/+O+6MsyedekrXL+HQAYenMqeG7cmUOE0vI6s/9nW08EGHXpD+Q9GhLU1smA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-connect@0.52.0': resolution: {integrity: sha512-GXPxfNB5szMbV3I9b7kNWSmQBoBzw7MT0ui6iU/p+NIzVx3a06Ri2cdQO7tG9EKb4aKSLmfX9Cw5cKxXqX6Ohg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-connect@0.53.0': + resolution: {integrity: sha512-SoFqipWLUEYVIxvz0VYX9uWLJhatJG4cqXpRe1iophLofuEtqFUn8YaEezjz2eJK74eTUQ0f0dJVOq7yMXsJGQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-dataloader@0.26.0': resolution: {integrity: sha512-P2BgnFfTOarZ5OKPmYfbXfDFjQ4P9WkQ1Jji7yH5/WwB6Wm/knynAoA1rxbjWcDlYupFkyT0M1j6XLzDzy0aCA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-dataloader@0.27.0': + resolution: {integrity: sha512-8e7n8edfTN28nJDpR/H59iW3RbW1fvpt0xatGTfSbL8JS4FLizfjPxO7JLbyWh9D3DSXxrTnvOvXpt6V5pnxJg==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-express@0.57.0': resolution: {integrity: sha512-HAdx/o58+8tSR5iW+ru4PHnEejyKrAy9fYFhlEI81o10nYxrGahnMAHWiSjhDC7UQSY3I4gjcPgSKQz4rm/asg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-express@0.58.0': + resolution: {integrity: sha512-UuGst6/1XPcswrIm5vmhuUwK/9qx9+fmNB+4xNk3lfpgQlnQxahy20xmlo3I+LIyA5ZA3CR2CDXslxAMqwminA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-fs@0.28.0': resolution: {integrity: sha512-FFvg8fq53RRXVBRHZViP+EMxMR03tqzEGpuq55lHNbVPyFklSVfQBN50syPhK5UYYwaStx0eyCtHtbRreusc5g==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-fs@0.29.0': + resolution: {integrity: sha512-JXPygU1RbrHNc5kD+626v3baV5KamB4RD4I9m9nUTd/HyfLZQSA3Z2z3VOebB3ChJhRDERmQjLiWvwJMHecKPg==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-generic-pool@0.52.0': resolution: {integrity: sha512-ISkNcv5CM2IwvsMVL31Tl61/p2Zm2I2NAsYq5SSBgOsOndT0TjnptjufYVScCnD5ZLD1tpl4T3GEYULLYOdIdQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-generic-pool@0.53.0': + resolution: {integrity: sha512-h49axGXGlvWzyQ4exPyd0qG9EUa+JP+hYklFg6V+Gm4ZC2Zam1QeJno/TQ8+qrLvsVvaFnBjTdS53hALpR3h3Q==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-graphql@0.56.0': resolution: {integrity: sha512-IPvNk8AFoVzTAM0Z399t34VDmGDgwT6rIqCUug8P9oAGerl2/PEIYMPOl/rerPGu+q8gSWdmbFSjgg7PDVRd3Q==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-graphql@0.57.0': + resolution: {integrity: sha512-wjtSavcp9MsGcnA1hj8ArgsL3EkHIiTLGMwqVohs5pSnMGeao0t2mgAuMiv78KdoR3kO3DUjks8xPO5Q6uJekg==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-hapi@0.55.0': resolution: {integrity: sha512-prqAkRf9e4eEpy4G3UcR32prKE8NLNlA90TdEU1UsghOTg0jUvs40Jz8LQWFEs5NbLbXHYGzB4CYVkCI8eWEVQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-hapi@0.56.0': + resolution: {integrity: sha512-HgLxgO0G8V9y/6yW2pS3Fv5M3hz9WtWUAdbuszQDZ8vXDQSd1sI9FYHLdZW+td/8xCLApm8Li4QIeCkRSpHVTg==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-http@0.208.0': resolution: {integrity: sha512-rhmK46DRWEbQQB77RxmVXGyjs6783crXCnFjYQj+4tDH/Kpv9Rbg3h2kaNyp5Vz2emF1f9HOQQvZoHzwMWOFZQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-http@0.210.0': + resolution: {integrity: sha512-dICO+0D0VBnrDOmDXOvpmaP0gvai6hNhJ5y6+HFutV0UoXc7pMgJlJY3O7AzT725cW/jP38ylmfHhQa7M0Nhww==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-ioredis@0.56.0': resolution: {integrity: sha512-XSWeqsd3rKSsT3WBz/JKJDcZD4QYElZEa0xVdX8f9dh4h4QgXhKRLorVsVkK3uXFbC2sZKAS2Ds+YolGwD83Dg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-ioredis@0.58.0': + resolution: {integrity: sha512-2tEJFeoM465A0FwPB0+gNvdM/xPBRIqNtC4mW+mBKy+ZKF9CWa7rEqv87OODGrigkEDpkH8Bs1FKZYbuHKCQNQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-kafkajs@0.18.0': resolution: {integrity: sha512-KCL/1HnZN5zkUMgPyOxfGjLjbXjpd4odDToy+7c+UsthIzVLFf99LnfIBE8YSSrYE4+uS7OwJMhvhg3tWjqMBg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-kafkajs@0.19.0': + resolution: {integrity: sha512-PMJePP4PVv+NSvWFuKADEVemsbNK8tnloHnrHOiRXMmBnyqcyOTmJyPy6eeJ0au90QyiGB2rzD8smmu2Y0CC7A==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-knex@0.53.0': resolution: {integrity: sha512-xngn5cH2mVXFmiT1XfQ1aHqq1m4xb5wvU6j9lSgLlihJ1bXzsO543cpDwjrZm2nMrlpddBf55w8+bfS4qDh60g==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-knex@0.54.0': + resolution: {integrity: sha512-XYXKVUH+0/Ur29jMPnyxZj32MrZkWSXHhCteTkt/HzynKnvIASmaAJ6moMOgBSRoLuDJFqPew68AreRylIzhhg==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-koa@0.57.0': resolution: {integrity: sha512-3JS8PU/D5E3q295mwloU2v7c7/m+DyCqdu62BIzWt+3u9utjxC9QS7v6WmUNuoDN3RM+Q+D1Gpj13ERo+m7CGg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.9.0 + '@opentelemetry/instrumentation-koa@0.58.0': + resolution: {integrity: sha512-602W6hEFi3j2QrQQBKWuBUSlHyrwSCc1IXpmItC991i9+xJOsS4n4mEktEk/7N6pavBX35J9OVkhPDXjbFk/1A==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.9.0 + '@opentelemetry/instrumentation-lru-memoizer@0.53.0': resolution: {integrity: sha512-LDwWz5cPkWWr0HBIuZUjslyvijljTwmwiItpMTHujaULZCxcYE9eU44Qf/pbVC8TulT0IhZi+RoGvHKXvNhysw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-lru-memoizer@0.54.0': + resolution: {integrity: sha512-LPji0Qwpye5e1TNAUkHt7oij2Lrtpn2DRTUr4CU69VzJA13aoa2uzP3NutnFoLDUjmuS6vi/lv08A2wo9CfyTA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-mongodb@0.61.0': resolution: {integrity: sha512-OV3i2DSoY5M/pmLk+68xr5RvkHU8DRB3DKMzYJdwDdcxeLs62tLbkmRyqJZsYf3Ht7j11rq35pHOWLuLzXL7pQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-mongodb@0.63.0': + resolution: {integrity: sha512-EvJb3aLiq1QedAZO4vqXTG0VJmKUpGU37r11thLPuL5HNa08sUS9DbF69RB8YoXVby2pXkFPMnbG0Pky0JMlKA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-mongoose@0.55.0': resolution: {integrity: sha512-5afj0HfF6aM6Nlqgu6/PPHFk8QBfIe3+zF9FGpX76jWPS0/dujoEYn82/XcLSaW5LPUDW8sni+YeK0vTBNri+w==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-mongoose@0.56.0': + resolution: {integrity: sha512-1xBjUpDSJFZS4qYc4XXef0pzV38iHyKymY4sKQ3xPv7dGdka4We1PsuEg6Z8K21f1d2Yg5eU0OXXRSPVmowKfA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-mysql2@0.55.0': resolution: {integrity: sha512-0cs8whQG55aIi20gnK8B7cco6OK6N+enNhW0p5284MvqJ5EPi+I1YlWsWXgzv/V2HFirEejkvKiI4Iw21OqDWg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-mysql2@0.56.0': + resolution: {integrity: sha512-rW0hIpoaCFf55j0F1oqw6+Xv9IQeqJGtw9MudT3LCuhqld9S3DF0UEj8o3CZuPhcYqD+HAivZQdrsO5XMWyFqw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-mysql@0.54.0': resolution: {integrity: sha512-bqC1YhnwAeWmRzy1/Xf9cDqxNG2d/JDkaxnqF5N6iJKN1eVWI+vg7NfDkf52/Nggp3tl1jcC++ptC61BD6738A==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-mysql@0.56.0': + resolution: {integrity: sha512-osdGMB3vc4bm1Kos04zfVmYAKoKVbKiF/Ti5/R0upDEOsCnrnUm9xvLeaKKbbE2WgJoaFz3VS8c99wx31efytQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-pg@0.61.0': resolution: {integrity: sha512-UeV7KeTnRSM7ECHa3YscoklhUtTQPs6V6qYpG283AB7xpnPGCUCUfECFT9jFg6/iZOQTt3FHkB1wGTJCNZEvPw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-pg@0.62.0': + resolution: {integrity: sha512-/ZSMRCyFRMjQVx7Wf+BIAOMEdN/XWBbAGTNLKfQgGYs1GlmdiIFkUy8Z8XGkToMpKrgZju0drlTQpqt4Ul7R6w==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-redis@0.57.0': resolution: {integrity: sha512-bCxTHQFXzrU3eU1LZnOZQ3s5LURxQPDlU3/upBzlWY77qOI1GZuGofazj3jtzjctMJeBEJhNwIFEgRPBX1kp/Q==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-redis@0.58.0': + resolution: {integrity: sha512-tOGxw+6HZ5LDpMP05zYKtTw5HPqf3PXYHaOuN+pkv6uIgrZ+gTT75ELkd49eXBpjg3t36p8bYpsLgYcpIPqWqA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-tedious@0.27.0': resolution: {integrity: sha512-jRtyUJNZppPBjPae4ZjIQ2eqJbcRaRfJkr0lQLHFmOU/no5A6e9s1OHLd5XZyZoBJ/ymngZitanyRRA5cniseA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-tedious@0.29.0': + resolution: {integrity: sha512-Jtnayb074lk7DQL25pOOpjvg4zjJMFjFWOLlKzTF5i1KxMR4+GlR/DSYgwDRfc0a4sfPXzdb/yYw7jRSX/LdFg==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-undici@0.19.0': resolution: {integrity: sha512-Pst/RhR61A2OoZQZkn6OLpdVpXp6qn3Y92wXa6umfJe9rV640r4bc6SWvw4pPN6DiQqPu2c8gnSSZPDtC6JlpQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.7.0 + '@opentelemetry/instrumentation-undici@0.20.0': + resolution: {integrity: sha512-VGBQ89Bza1pKtV12Lxgv3uMrJ1vNcf1cDV6LAXp2wa6hnl6+IN6lbEmPn6WNWpguZTZaFEvugyZgN8FJuTjLEA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.7.0 + + '@opentelemetry/instrumentation@0.207.0': + resolution: {integrity: sha512-y6eeli9+TLKnznrR8AZlQMSJT7wILpXH+6EYq5Vf/4Ao+huI7EedxQHwRgVUOMLFbe7VFDvHJrX9/f4lcwnJsA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation@0.208.0': resolution: {integrity: sha512-Eju0L4qWcQS+oXxi6pgh7zvE2byogAkcsVv0OjHF/97iOz1N/aKE6etSGowYkie+YA1uo6DNwdSxaaNnLvcRlA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation@0.210.0': + resolution: {integrity: sha512-sLMhyHmW9katVaLUOKpfCnxSGhZq2t1ReWgwsu2cSgxmDVMB690H9TanuexanpFI94PJaokrqbp8u9KYZDUT5g==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/redis-common@0.38.2': resolution: {integrity: sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA==} engines: {node: ^18.19.0 || >=20.6.0} @@ -1921,12 +2091,24 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/resources@2.5.0': + resolution: {integrity: sha512-F8W52ApePshpoSrfsSk1H2yJn9aKjCrbpQF1M9Qii0GHzbfVeFUB+rc3X4aggyZD8x9Gu3Slua+s6krmq6Dt8g==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/sdk-trace-base@2.2.0': resolution: {integrity: sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/sdk-trace-base@2.5.0': + resolution: {integrity: sha512-VzRf8LzotASEyNDUxTdaJ9IRJ1/h692WyArDBInf5puLCjxbICD6XkHgpuudis56EndyS7LYFmtTMny6UABNdQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/semantic-conventions@1.37.0': resolution: {integrity: sha512-JD6DerIKdJGmRp4jQyX5FlrQjA4tjOw1cvfsPAZXfOOEErMUHjPcPSICS+6WnM0nB0efSFARh0KAZss+bvExOA==} engines: {node: '>=14'} @@ -1985,6 +2167,11 @@ packages: peerDependencies: '@opentelemetry/api': ^1.8 + '@prisma/instrumentation@7.2.0': + resolution: {integrity: sha512-Rh9Z4x5kEj1OdARd7U18AtVrnL6rmLSI0qYShaB4W7Wx5BKbgzndWF+QnuzMb7GLfVdlT5aYCXoPQVYuYtVu0g==} + peerDependencies: + '@opentelemetry/api': ^1.8 + '@radix-ui/primitive@1.1.2': resolution: {integrity: sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==} @@ -2444,36 +2631,36 @@ packages: resolution: {integrity: sha512-M3kycMY6f3KY9a8jDYac+yG0E3ZgWVWSxlOEC5MhYyX+g7mqxkwrb3LFQyuxSm/m+CCgMTCaPOOaB2twXP6EQg==} engines: {node: '>=18'} - '@sentry-internal/browser-utils@10.32.1': - resolution: {integrity: sha512-sjLLep1es3rTkbtAdTtdpc/a6g7v7bK5YJiZJsUigoJ4NTiFeMI5uIDCxbH/tjJ1q23YE1LzVn7T96I+qBRjHA==} + '@sentry-internal/browser-utils@10.36.0': + resolution: {integrity: sha512-WILVR8HQBWOxbqLRuTxjzRCMIACGsDTo6jXvzA8rz6ezElElLmIrn3CFAswrESLqEEUa4CQHl5bLgSVJCRNweA==} engines: {node: '>=18'} '@sentry-internal/feedback@10.29.0': resolution: {integrity: sha512-Y7IRsNeS99cEONu1mZWZc3HvbjNnu59Hgymm0swFFKbdgbCgdT6l85kn2oLsuq4Ew8Dw/pL/Sgpwsl9UgYFpUg==} engines: {node: '>=18'} - '@sentry-internal/feedback@10.32.1': - resolution: {integrity: sha512-O24G8jxbfBY1RE/v2qFikPJISVMOrd/zk8FKyl+oUVYdOxU2Ucjk2cR3EQruBFlc7irnL6rT3GPfRZ/kBgLkmQ==} + '@sentry-internal/feedback@10.36.0': + resolution: {integrity: sha512-zPjz7AbcxEyx8AHj8xvp28fYtPTPWU1XcNtymhAHJLS9CXOblqSC7W02Jxz6eo3eR1/pLyOo6kJBUjvLe9EoFA==} engines: {node: '>=18'} '@sentry-internal/replay-canvas@10.29.0': resolution: {integrity: sha512-typY4JrpAQQGPuSyd/BD8+nNCbvTV2UVvKzr+iKgI0m1qc4Dz8tHZ4Nfais2Z8eYn/pL1kqVQN5ERTmJoYFdIw==} engines: {node: '>=18'} - '@sentry-internal/replay-canvas@10.32.1': - resolution: {integrity: sha512-/XGTzWNWVc+B691fIVekV2KeoHFEDA5KftrLFAhEAW7uWOwk/xy3aQX4TYM0LcPm2PBKvoumlAD+Sd/aXk63oA==} + '@sentry-internal/replay-canvas@10.36.0': + resolution: {integrity: sha512-DLGIwmT2LX+O6TyYPtOQL5GiTm2rN0taJPDJ/Lzg2KEJZrdd5sKkzTckhh2x+vr4JQyeaLmnb8M40Ch1hvG/vQ==} engines: {node: '>=18'} '@sentry-internal/replay@10.29.0': resolution: {integrity: sha512-45NVw9PwB9TQ8z+xJ6G6Za+wmQ1RTA35heBSzR6U4bknj8LmA04k2iwnobvxCBEQXeLfcJEO1vFgagMoqMZMBw==} engines: {node: '>=18'} - '@sentry-internal/replay@10.32.1': - resolution: {integrity: sha512-KKmLUgIaLRM0VjrMA1ByQTawZyRDYSkG2evvEOVpEtR9F0sumidAQdi7UY71QEKE1RYe/Jcp/3WoaqsMh8tbnQ==} + '@sentry-internal/replay@10.36.0': + resolution: {integrity: sha512-nLMkJgvHq+uCCrQKV2KgSdVHxTsmDk0r2hsAoTcKCbzUpXyW5UhCziMRS6ULjBlzt5sbxoIIplE25ZpmIEeNgg==} engines: {node: '>=18'} - '@sentry/astro@10.32.1': - resolution: {integrity: sha512-/fUn27a+DAlqMjhRhdUcGvpE3H5q17JOLW42XCi3gOhtnE7zVqd3JJ1TbA4Q3G6BlaSAIsX1xqNOL9HGXhuLYQ==} + '@sentry/astro@10.36.0': + resolution: {integrity: sha512-H8iwYLKaF0CtOrrPMlHvt1F5SFkOSs1Sw4KHFknO5JndqyZmkOsGgHnsYFw8Z11oRjd4VImogwoWeI2TskdIMA==} engines: {node: '>=18.19.1'} peerDependencies: astro: '>=3.x || >=4.0.0-beta || >=5.x' @@ -2482,24 +2669,24 @@ packages: resolution: {integrity: sha512-+uLqaCKeYmH/W2YUV1XHkFEtpHdx/aFjCQahPVsvXyqg13dfkR6jaygPL4DB5DJtUSmPFCUE3MEk9ZO5JlhJYg==} engines: {node: '>= 14'} - '@sentry/babel-plugin-component-annotate@4.6.1': - resolution: {integrity: sha512-aSIk0vgBqv7PhX6/Eov+vlI4puCE0bRXzUG5HdCsHBpAfeMkI8Hva6kSOusnzKqs8bf04hU7s3Sf0XxGTj/1AA==} + '@sentry/babel-plugin-component-annotate@4.7.0': + resolution: {integrity: sha512-MkyajDiO17/GaHHFgOmh05ZtOwF5hmm9KRjVgn9PXHIdpz+TFM5mkp1dABmR6Y75TyNU98Z1aOwPOgyaR5etJw==} engines: {node: '>= 14'} '@sentry/browser@10.29.0': resolution: {integrity: sha512-XdbyIR6F4qoR9Z1JCWTgunVcTJjS9p2Th+v4wYs4ME+ZdLC4tuKKmRgYg3YdSIWCn1CBfIgdI6wqETSf7H6Njw==} engines: {node: '>=18'} - '@sentry/browser@10.32.1': - resolution: {integrity: sha512-NPNCXTZ05ZGTFyJdKNqjykpFm+urem0ebosILQiw3C4BxNVNGH4vfYZexyl6prRhmg91oB6GjVNiVDuJiap1gg==} + '@sentry/browser@10.36.0': + resolution: {integrity: sha512-yHhXbgdGY1s+m8CdILC9U/II7gb6+s99S2Eh8VneEn/JG9wHc+UOzrQCeFN0phFP51QbLkjkiQbbanjT1HP8UQ==} engines: {node: '>=18'} '@sentry/bundler-plugin-core@2.23.0': resolution: {integrity: sha512-Qbw+jZFK63w+V193l0eCFKLzGba2Iu93Fx8kCRzZ3uqjky002H8U3pu4mKgcc11J+u8QTjfNZGUyXsxz0jv2mg==} engines: {node: '>= 14'} - '@sentry/bundler-plugin-core@4.6.1': - resolution: {integrity: sha512-WPeRbnMXm927m4Kr69NTArPfI+p5/34FHftdCRI3LFPMyhZDzz6J3wLy4hzaVUgmMf10eLzmq2HGEMvpQmdynA==} + '@sentry/bundler-plugin-core@4.7.0': + resolution: {integrity: sha512-gFdEtiup/7qYhN3vp1v2f0WL9AG9OorWLtIpfSBYbWjtzklVNg1sizvNyZ8nEiwtnb25LzvvCUbOP1SyP6IodQ==} engines: {node: '>= 14'} '@sentry/cli-darwin@2.39.1': @@ -2604,8 +2791,8 @@ packages: resolution: {integrity: sha512-olQ2DU9dA/Bwsz3PtA9KNXRMqBWRQSkPw+MxwWEoU1K1qtiM9L0j6lbEFb5iSY3d7WYD5MB+1d5COugjSBrHtw==} engines: {node: '>=18'} - '@sentry/core@10.32.1': - resolution: {integrity: sha512-PH2ldpSJlhqsMj2vCTyU0BI2Fx1oIDhm7Izo5xFALvjVCS0gmlqHt1udu6YlKn8BtpGH6bGzssvv5APrk+OdPQ==} + '@sentry/core@10.36.0': + resolution: {integrity: sha512-EYJjZvofI+D93eUsPLDIUV0zQocYqiBRyXS6CCV6dHz64P/Hob5NJQOwPa8/v6nD+UvJXvwsFfvXOHhYZhZJOQ==} engines: {node: '>=18'} '@sentry/electron@7.5.0': @@ -2628,24 +2815,24 @@ packages: '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 || ^2.2.0 '@opentelemetry/semantic-conventions': ^1.37.0 - '@sentry/node-core@10.32.1': - resolution: {integrity: sha512-w56rxdBanBKc832zuwnE+zNzUQ19fPxfHEtOhK8JGPu3aSwQYcIxwz9z52lOx3HN7k/8Fj5694qlT3x/PokhRw==} + '@sentry/node-core@10.36.0': + resolution: {integrity: sha512-3K2SJCPiQGQMYSVSF3GuPIAilJPlXOWxyvrmnxY9Zw3ZbXaLynhYCJ5TjL38hS7XoMby/0lN2fY/kbXH/GlNeg==} engines: {node: '>=18'} peerDependencies: '@opentelemetry/api': ^1.9.0 - '@opentelemetry/context-async-hooks': ^1.30.1 || ^2.1.0 || ^2.2.0 - '@opentelemetry/core': ^1.30.1 || ^2.1.0 || ^2.2.0 + '@opentelemetry/context-async-hooks': ^1.30.1 || ^2.1.0 + '@opentelemetry/core': ^1.30.1 || ^2.1.0 '@opentelemetry/instrumentation': '>=0.57.1 <1' - '@opentelemetry/resources': ^1.30.1 || ^2.1.0 || ^2.2.0 - '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 || ^2.2.0 + '@opentelemetry/resources': ^1.30.1 || ^2.1.0 + '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 '@opentelemetry/semantic-conventions': ^1.37.0 '@sentry/node@10.29.0': resolution: {integrity: sha512-9j8VzV06VCj+H8tlxpfa7BNN4HzH5exv68WOufdMTXzzWLOXnzrdNDoYplm1G2S3LMvWsc1SVI3a8A0yBY7oWg==} engines: {node: '>=18'} - '@sentry/node@10.32.1': - resolution: {integrity: sha512-oxlybzt8QW0lx/QaEj1DcvZDRXkgouewFelu/10dyUwv5So3YvipfvWInda+yMLmn25OggbloDQ0gyScA2jU3g==} + '@sentry/node@10.36.0': + resolution: {integrity: sha512-c7kYTZ9WcOYqod65PpA4iY+wEGJqLbFy10v4lIG6B5XrO+PFEXh1CrvGPLDJVogbB/4NE0r2jgeFQ+jz8aZUhw==} engines: {node: '>=18'} '@sentry/opentelemetry@10.29.0': @@ -2658,18 +2845,18 @@ packages: '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 || ^2.2.0 '@opentelemetry/semantic-conventions': ^1.37.0 - '@sentry/opentelemetry@10.32.1': - resolution: {integrity: sha512-YLssSz5Y+qPvufrh2cDaTXDoXU8aceOhB+YTjT8/DLF6SOj7Tzen52aAcjNaifawaxEsLCC8O+B+A2iA+BllvA==} + '@sentry/opentelemetry@10.36.0': + resolution: {integrity: sha512-TPOSiHBk45exA/LGFELSuzmBrWe1MG7irm7NkUXCZfdXuLLPeUtp1Y+rWDCWWNMrraAdizDN0d/l1GSLpxzpPg==} engines: {node: '>=18'} peerDependencies: '@opentelemetry/api': ^1.9.0 - '@opentelemetry/context-async-hooks': ^1.30.1 || ^2.1.0 || ^2.2.0 - '@opentelemetry/core': ^1.30.1 || ^2.1.0 || ^2.2.0 - '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 || ^2.2.0 + '@opentelemetry/context-async-hooks': ^1.30.1 || ^2.1.0 + '@opentelemetry/core': ^1.30.1 || ^2.1.0 + '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 '@opentelemetry/semantic-conventions': ^1.37.0 - '@sentry/react@10.32.1': - resolution: {integrity: sha512-/tX0HeACbAmVP57x8txTrGk/U3fa9pDBaoAtlOrnPv5VS/aC5SGkehXWeTGSAa+ahlOWwp3IF8ILVXRiOoG/Vg==} + '@sentry/react@10.36.0': + resolution: {integrity: sha512-k2GwMKgepJLXvEQffQymQyxsTVjsLiY6YXG0bcceM3vulii9Sy29uqGhpqwaPOfM4bPQzUXJzAxS/c9S7n5hTw==} engines: {node: '>=18'} peerDependencies: react: ^16.14.0 || 17.x || 18.x || 19.x @@ -2678,8 +2865,8 @@ packages: resolution: {integrity: sha512-iLbqxan3DUkFJqbx7DOtJ2fTd6g+TmNS1PIdaDFfpvVG4Lg9AYp4Xege6BBCrGQYl+wUE3poWfNhASfch/s51Q==} engines: {node: '>= 14'} - '@sentry/vite-plugin@4.6.1': - resolution: {integrity: sha512-Qvys1y3o8/bfL3ikrHnJS9zxdjt0z3POshdBl3967UcflrTqBmnGNkcVk53SlmtJWIfh85fgmrLvGYwZ2YiqNg==} + '@sentry/vite-plugin@4.7.0': + resolution: {integrity: sha512-eQXDghOQLsYwnHutJo8TCzhG4gp0KLNq3h96iqFMhsbjnNnfYeCX1lIw1pJEh/az3cDwSyPI/KGkvf8hr0dZmQ==} engines: {node: '>= 14'} '@shikijs/core@1.29.2': @@ -3082,6 +3269,9 @@ packages: '@types/pg-pool@2.0.6': resolution: {integrity: sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==} + '@types/pg-pool@2.0.7': + resolution: {integrity: sha512-U4CwmGVQcbEuqpyju8/ptOKg6gEC+Tqsvj2xS9o1g71bUh8twxnC6ZL5rZKCsGN0iyH0CwgUyc9VR5owNQF9Ng==} + '@types/pg@8.15.6': resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==} @@ -3530,8 +3720,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.9.18: - resolution: {integrity: sha512-e23vBV1ZLfjb9apvfPk4rHVu2ry6RIr2Wfs+O324okSidrX7pTAnEJPCh/O5BtRlr7QtZI7ktOP3vsqr7Z5XoA==} + baseline-browser-mapping@2.9.14: + resolution: {integrity: sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==} hasBin: true bcp-47-match@2.0.3: @@ -3670,8 +3860,8 @@ packages: caniuse-lite@1.0.30001751: resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==} - caniuse-lite@1.0.30001766: - resolution: {integrity: sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==} + caniuse-lite@1.0.30001764: + resolution: {integrity: sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -3729,6 +3919,9 @@ packages: cjs-module-lexer@1.4.3: resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} + cjs-module-lexer@2.2.0: + resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} + class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} @@ -4188,8 +4381,8 @@ packages: electron-to-chromium@1.5.145: resolution: {integrity: sha512-pZ5EcTWRq/055MvSBgoFEyKf2i4apwfoqJbK/ak2jnFq8oHjZ+vzc3AhRcz37Xn+ZJfL58R666FLJx0YOK9yTw==} - electron-to-chromium@1.5.279: - resolution: {integrity: sha512-0bblUU5UNdOt5G7XqGiJtpZMONma6WAfq9vsFmtn9x1+joAObr6x1chfqyxFSDCAFwFhCQDrqeAr6MYdpwJ9Hg==} + electron-to-chromium@1.5.267: + resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} electron-updater@6.6.2: resolution: {integrity: sha512-Cr4GDOkbAUqRHP5/oeOmH/L2Bn6+FQPxVLZtPbcmKZC63a1F3uu5EefYOssgZXG3u/zBlubbJ5PJdITdMVggbw==} @@ -4808,9 +5001,6 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true - hoist-non-react-statics@3.3.2: - resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} - hono-rate-limiter@0.4.2: resolution: {integrity: sha512-AAtFqgADyrmbDijcRTT/HJfwqfvhalya2Zo+MgfdrMPas3zSMD8SU03cv+ZsYwRU1swv7zgVt0shwN059yzhjw==} peerDependencies: @@ -4905,6 +5095,9 @@ packages: import-in-the-middle@2.0.0: resolution: {integrity: sha512-yNZhyQYqXpkT0AKq3F3KLasUSK4fHvebNH5hOsKQw2dhGSALvQ4U0BqUc5suziKvydO5u5hgN2hy1RJaho8U5A==} + import-in-the-middle@2.0.5: + resolution: {integrity: sha512-0InH9/4oDCBRzWXhpOqusspLBrVfK1vPvbn9Wxl8DAQ8yyx5fWJRETICSwkiAMaYntjJAMBP1R4B6cQnEUYVEA==} + import-lazy@4.0.0: resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} engines: {node: '>=8'} @@ -8806,21 +8999,43 @@ snapshots: '@one-ini/wasm@0.1.1': {} + '@opentelemetry/api-logs@0.207.0': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs@0.208.0': dependencies: '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs@0.210.0': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api@1.9.0': {} '@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 + '@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/core@2.4.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.37.0 + + '@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/instrumentation-amqplib@0.55.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8829,6 +9044,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-amqplib@0.57.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-connect@0.52.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8839,6 +9063,16 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-connect@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + '@types/connect': 3.4.38 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-dataloader@0.26.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8846,6 +9080,13 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-dataloader@0.27.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-express@0.57.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8855,6 +9096,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-express@0.58.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-fs@0.28.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8863,6 +9113,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-fs@0.29.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-generic-pool@0.52.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8870,6 +9128,13 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-generic-pool@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-graphql@0.56.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8877,6 +9142,13 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-graphql@0.57.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-hapi@0.55.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8886,6 +9158,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-hapi@0.56.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-http@0.208.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8896,6 +9177,16 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-http@0.210.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.4.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + forwarded-parse: 2.1.2 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-ioredis@0.56.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8904,6 +9195,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-ioredis@0.58.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/redis-common': 0.38.2 + '@opentelemetry/semantic-conventions': 1.37.0 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-kafkajs@0.18.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8912,6 +9212,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-kafkajs@0.19.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-knex@0.53.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8920,6 +9228,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-knex@0.54.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-koa@0.57.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8929,6 +9245,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-koa@0.58.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-lru-memoizer@0.53.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8936,6 +9261,13 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-lru-memoizer@0.54.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-mongodb@0.61.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8943,6 +9275,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-mongodb@0.63.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-mongoose@0.55.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8951,6 +9291,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-mongoose@0.56.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-mysql2@0.55.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8960,6 +9309,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-mysql2@0.56.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-mysql@0.54.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8968,6 +9326,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-mysql@0.56.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + '@types/mysql': 2.15.27 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-pg@0.61.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8980,6 +9347,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-pg@0.62.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.0) + '@types/pg': 8.15.6 + '@types/pg-pool': 2.0.7 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-redis@0.57.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8989,6 +9368,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-redis@0.58.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/redis-common': 0.38.2 + '@opentelemetry/semantic-conventions': 1.37.0 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-tedious@0.27.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8997,6 +9385,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-tedious@0.29.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + '@types/tedious': 4.0.14 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation-undici@0.19.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -9006,6 +9403,24 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation-undici@0.20.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation@0.207.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.207.0 + import-in-the-middle: 2.0.5 + require-in-the-middle: 8.0.1 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation@0.208.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -9015,6 +9430,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/instrumentation@0.210.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.210.0 + import-in-the-middle: 2.0.5 + require-in-the-middle: 8.0.1 + transitivePeerDependencies: + - supports-color + '@opentelemetry/redis-common@0.38.2': {} '@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0)': @@ -9023,6 +9447,12 @@ snapshots: '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/resources@2.5.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -9030,6 +9460,13 @@ snapshots: '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions@1.37.0': {} '@opentelemetry/sql-common@0.41.2(@opentelemetry/api@1.9.0)': @@ -9072,6 +9509,13 @@ snapshots: transitivePeerDependencies: - supports-color + '@prisma/instrumentation@7.2.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.207.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + '@radix-ui/primitive@1.1.2': {} '@radix-ui/react-arrow@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': @@ -9471,44 +9915,44 @@ snapshots: dependencies: '@sentry/core': 10.29.0 - '@sentry-internal/browser-utils@10.32.1': + '@sentry-internal/browser-utils@10.36.0': dependencies: - '@sentry/core': 10.32.1 + '@sentry/core': 10.36.0 '@sentry-internal/feedback@10.29.0': dependencies: '@sentry/core': 10.29.0 - '@sentry-internal/feedback@10.32.1': + '@sentry-internal/feedback@10.36.0': dependencies: - '@sentry/core': 10.32.1 + '@sentry/core': 10.36.0 '@sentry-internal/replay-canvas@10.29.0': dependencies: '@sentry-internal/replay': 10.29.0 '@sentry/core': 10.29.0 - '@sentry-internal/replay-canvas@10.32.1': + '@sentry-internal/replay-canvas@10.36.0': dependencies: - '@sentry-internal/replay': 10.32.1 - '@sentry/core': 10.32.1 + '@sentry-internal/replay': 10.36.0 + '@sentry/core': 10.36.0 '@sentry-internal/replay@10.29.0': dependencies: '@sentry-internal/browser-utils': 10.29.0 '@sentry/core': 10.29.0 - '@sentry-internal/replay@10.32.1': + '@sentry-internal/replay@10.36.0': dependencies: - '@sentry-internal/browser-utils': 10.32.1 - '@sentry/core': 10.32.1 + '@sentry-internal/browser-utils': 10.36.0 + '@sentry/core': 10.36.0 - '@sentry/astro@10.32.1(astro@5.15.9(@types/node@24.10.1)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.53.3)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.2))': + '@sentry/astro@10.36.0(astro@5.15.9(@types/node@24.10.1)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.53.3)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.2))': dependencies: - '@sentry/browser': 10.32.1 - '@sentry/core': 10.32.1 - '@sentry/node': 10.32.1 - '@sentry/vite-plugin': 4.6.1 + '@sentry/browser': 10.36.0 + '@sentry/core': 10.36.0 + '@sentry/node': 10.36.0 + '@sentry/vite-plugin': 4.7.0 astro: 5.15.9(@types/node@24.10.1)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.53.3)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.2) transitivePeerDependencies: - encoding @@ -9516,7 +9960,7 @@ snapshots: '@sentry/babel-plugin-component-annotate@2.23.0': {} - '@sentry/babel-plugin-component-annotate@4.6.1': {} + '@sentry/babel-plugin-component-annotate@4.7.0': {} '@sentry/browser@10.29.0': dependencies: @@ -9526,13 +9970,13 @@ snapshots: '@sentry-internal/replay-canvas': 10.29.0 '@sentry/core': 10.29.0 - '@sentry/browser@10.32.1': + '@sentry/browser@10.36.0': dependencies: - '@sentry-internal/browser-utils': 10.32.1 - '@sentry-internal/feedback': 10.32.1 - '@sentry-internal/replay': 10.32.1 - '@sentry-internal/replay-canvas': 10.32.1 - '@sentry/core': 10.32.1 + '@sentry-internal/browser-utils': 10.36.0 + '@sentry-internal/feedback': 10.36.0 + '@sentry-internal/replay': 10.36.0 + '@sentry-internal/replay-canvas': 10.36.0 + '@sentry/core': 10.36.0 '@sentry/bundler-plugin-core@2.23.0': dependencies: @@ -9548,10 +9992,10 @@ snapshots: - encoding - supports-color - '@sentry/bundler-plugin-core@4.6.1': + '@sentry/bundler-plugin-core@4.7.0': dependencies: '@babel/core': 7.27.1 - '@sentry/babel-plugin-component-annotate': 4.6.1 + '@sentry/babel-plugin-component-annotate': 4.7.0 '@sentry/cli': 2.58.2 dotenv: 16.5.0 find-up: 5.0.0 @@ -9648,7 +10092,7 @@ snapshots: '@sentry/core@10.29.0': {} - '@sentry/core@10.32.1': {} + '@sentry/core@10.36.0': {} '@sentry/electron@7.5.0': dependencies: @@ -9674,19 +10118,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@sentry/node-core@10.32.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.208.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.37.0)': + '@sentry/node-core@10.36.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.210.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.37.0)': dependencies: '@apm-js-collab/tracing-hooks': 0.3.1 '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.208.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/context-async-hooks': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.5.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.37.0 - '@sentry/core': 10.32.1 - '@sentry/opentelemetry': 10.32.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.37.0) - import-in-the-middle: 2.0.0 + '@sentry/core': 10.36.0 + '@sentry/opentelemetry': 10.36.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.37.0) + import-in-the-middle: 2.0.5 transitivePeerDependencies: - supports-color @@ -9730,42 +10174,42 @@ snapshots: transitivePeerDependencies: - supports-color - '@sentry/node@10.32.1': + '@sentry/node@10.36.0': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.208.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-amqplib': 0.55.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-connect': 0.52.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-dataloader': 0.26.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-express': 0.57.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-fs': 0.28.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-generic-pool': 0.52.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-graphql': 0.56.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-hapi': 0.55.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-http': 0.208.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-ioredis': 0.56.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-kafkajs': 0.18.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-knex': 0.53.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-koa': 0.57.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-lru-memoizer': 0.53.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mongodb': 0.61.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mongoose': 0.55.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mysql': 0.54.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mysql2': 0.55.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-pg': 0.61.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-redis': 0.57.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-tedious': 0.27.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-undici': 0.19.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/context-async-hooks': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-amqplib': 0.57.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-connect': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-dataloader': 0.27.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-express': 0.58.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-fs': 0.29.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-generic-pool': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-graphql': 0.57.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-hapi': 0.56.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-http': 0.210.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-ioredis': 0.58.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-kafkajs': 0.19.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-knex': 0.54.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-koa': 0.58.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-lru-memoizer': 0.54.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mongodb': 0.63.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mongoose': 0.56.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mysql': 0.56.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mysql2': 0.56.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-pg': 0.62.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-redis': 0.58.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-tedious': 0.29.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-undici': 0.20.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.5.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.37.0 - '@prisma/instrumentation': 6.19.0(@opentelemetry/api@1.9.0) - '@sentry/core': 10.32.1 - '@sentry/node-core': 10.32.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.208.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.37.0) - '@sentry/opentelemetry': 10.32.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.37.0) - import-in-the-middle: 2.0.0 + '@prisma/instrumentation': 7.2.0(@opentelemetry/api@1.9.0) + '@sentry/core': 10.36.0 + '@sentry/node-core': 10.36.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.210.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.37.0) + '@sentry/opentelemetry': 10.36.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.37.0) + import-in-the-middle: 2.0.5 minimatch: 9.0.5 transitivePeerDependencies: - supports-color @@ -9779,20 +10223,19 @@ snapshots: '@opentelemetry/semantic-conventions': 1.37.0 '@sentry/core': 10.29.0 - '@sentry/opentelemetry@10.32.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.37.0)': + '@sentry/opentelemetry@10.36.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.37.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/context-async-hooks': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.5.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.37.0 - '@sentry/core': 10.32.1 + '@sentry/core': 10.36.0 - '@sentry/react@10.32.1(react@18.3.1)': + '@sentry/react@10.36.0(react@18.3.1)': dependencies: - '@sentry/browser': 10.32.1 - '@sentry/core': 10.32.1 - hoist-non-react-statics: 3.3.2 + '@sentry/browser': 10.36.0 + '@sentry/core': 10.36.0 react: 18.3.1 '@sentry/vite-plugin@2.23.0': @@ -9803,9 +10246,9 @@ snapshots: - encoding - supports-color - '@sentry/vite-plugin@4.6.1': + '@sentry/vite-plugin@4.7.0': dependencies: - '@sentry/bundler-plugin-core': 4.6.1 + '@sentry/bundler-plugin-core': 4.7.0 unplugin: 1.0.1 transitivePeerDependencies: - encoding @@ -10266,6 +10709,10 @@ snapshots: dependencies: '@types/pg': 8.15.6 + '@types/pg-pool@2.0.7': + dependencies: + '@types/pg': 8.15.6 + '@types/pg@8.15.6': dependencies: '@types/node': 24.10.1 @@ -10894,7 +11341,7 @@ snapshots: autoprefixer@10.4.23(postcss@8.5.6): dependencies: browserslist: 4.28.1 - caniuse-lite: 1.0.30001766 + caniuse-lite: 1.0.30001764 fraction.js: 5.3.4 picocolors: 1.1.1 postcss: 8.5.6 @@ -10923,7 +11370,7 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.9.18: {} + baseline-browser-mapping@2.9.14: {} bcp-47-match@2.0.3: {} @@ -11014,9 +11461,9 @@ snapshots: browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.9.18 - caniuse-lite: 1.0.30001766 - electron-to-chromium: 1.5.279 + baseline-browser-mapping: 2.9.14 + caniuse-lite: 1.0.30001764 + electron-to-chromium: 1.5.267 node-releases: 2.0.27 update-browserslist-db: 1.2.3(browserslist@4.28.1) @@ -11104,7 +11551,7 @@ snapshots: caniuse-lite@1.0.30001751: {} - caniuse-lite@1.0.30001766: {} + caniuse-lite@1.0.30001764: {} ccount@2.0.1: {} @@ -11163,6 +11610,8 @@ snapshots: cjs-module-lexer@1.4.3: {} + cjs-module-lexer@2.2.0: {} + class-variance-authority@0.7.1: dependencies: clsx: 2.1.1 @@ -11631,7 +12080,7 @@ snapshots: electron-to-chromium@1.5.145: {} - electron-to-chromium@1.5.279: {} + electron-to-chromium@1.5.267: {} electron-updater@6.6.2: dependencies: @@ -12624,10 +13073,6 @@ snapshots: he@1.2.0: {} - hoist-non-react-statics@3.3.2: - dependencies: - react-is: 16.13.1 - hono-rate-limiter@0.4.2(hono@4.11.7): dependencies: hono: 4.11.7 @@ -12727,6 +13172,13 @@ snapshots: cjs-module-lexer: 1.4.3 module-details-from-path: 1.0.4 + import-in-the-middle@2.0.5: + dependencies: + acorn: 8.15.0 + acorn-import-attributes: 1.9.5(acorn@8.15.0) + cjs-module-lexer: 2.2.0 + module-details-from-path: 1.0.4 + import-lazy@4.0.0: {} import-meta-resolve@4.2.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 10904e364..40c98f635 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,5 @@ packages: - - 'packages/*' + - "packages/*" catalog: "@fontsource/raleway": ^5.1.0 @@ -7,9 +7,9 @@ catalog: "@types/node": ^22.15.21 "@types/react": ^18.3.11 "@types/react-dom": ^18.3.0 - "@sentry/astro": ^10.31.0 - "@sentry/core": ^10.31.0 - "@sentry/node": ^10.31.0 + "@sentry/astro": ^10.36.0 + "@sentry/core": ^10.36.0 + "@sentry/node": ^10.36.0 react: ^18.3.1 react-dom: ^18.3.1 tailwindcss: ^4.1.10