diff --git a/grafana-plugin/.env.example b/grafana-plugin/.env.example new file mode 100644 index 00000000..e69de29b diff --git a/grafana-plugin/.eslintrc.js b/grafana-plugin/.eslintrc.js index a25b9cf3..9a8d2b07 100644 --- a/grafana-plugin/.eslintrc.js +++ b/grafana-plugin/.eslintrc.js @@ -64,5 +64,6 @@ module.exports = { */ 'react-hooks/exhaustive-deps': 'off', 'rulesdir/no-relative-import-paths': ['error', { allowSameFolder: true }], + '@typescript-eslint/explicit-member-accessibility': 'off', }, }; diff --git a/grafana-plugin/package.json b/grafana-plugin/package.json index 0c74a2a9..ee4efd6f 100644 --- a/grafana-plugin/package.json +++ b/grafana-plugin/package.json @@ -54,11 +54,8 @@ "@babel/preset-env": "^7.18.10", "@babel/preset-react": "^7.18.6", "@babel/preset-typescript": "^7.18.6", - "@grafana/data": "^9.2.4", "@grafana/eslint-config": "^5.0.0", - "@grafana/runtime": "9.3.0-beta1", "@grafana/toolkit": "^9.2.4", - "@grafana/ui": "^9.2.4", "@jest/globals": "^27.5.1", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "12", @@ -78,6 +75,7 @@ "babel-plugin-dynamic-import-node": "^2.3.3", "copy-webpack-plugin": "^11.0.0", "dompurify": "^2.3.12", + "dotenv": "^16.0.3", "eslint": "^8.25.0", "eslint-plugin-jsdoc": "^39.3.14", "eslint-plugin-react": "^7.31.10", @@ -104,6 +102,12 @@ "node": ">=14" }, "dependencies": { + "@grafana/data": "^9.2.4", + "@grafana/faro-web-sdk": "^1.0.0-beta4", + "@grafana/faro-web-tracing": "^1.0.0-beta4", + "@grafana/runtime": "9.3.0-beta1", + "@grafana/ui": "^9.2.4", + "@opentelemetry/api": "^1.3.0", "array-move": "^4.0.0", "change-case": "^4.1.1", "circular-dependency-plugin": "^5.2.2", diff --git a/grafana-plugin/src/network/index.ts b/grafana-plugin/src/network/index.ts index bfb7068e..e9c1930e 100644 --- a/grafana-plugin/src/network/index.ts +++ b/grafana-plugin/src/network/index.ts @@ -1,6 +1,10 @@ +import { SpanStatusCode } from '@opentelemetry/api'; +import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import axios from 'axios'; import qs from 'query-string'; +import FaroHelper from 'utils/faro'; + export const API_HOST = `${window.location.protocol}//${window.location.host}/`; export const API_PROXY_PREFIX = 'api/plugin-proxy/grafana-oncall-app'; export const API_PATH_PREFIX = '/api/internal/v1'; @@ -34,14 +38,60 @@ export const makeRequest = async (path: string, config: RequestConfig) const { method = 'GET', params, data, validateStatus } = config; const url = `${API_PROXY_PREFIX}${API_PATH_PREFIX}${path}`; + const otel = FaroHelper.faro?.api?.getOTEL(); - const response = await instance({ + if (FaroHelper.faro && otel) { + const tracer = otel.trace.getTracer('default'); + let span = otel.trace.getActiveSpan(); + + if (!span) { + span = tracer.startSpan('http-request'); + span.setAttribute('page_url', document.URL.split('//')[1]); + span.setAttribute(SemanticAttributes.HTTP_URL, url); + span.setAttribute(SemanticAttributes.HTTP_METHOD, method); + } + + return new Promise((resolve, reject) => { + otel.context.with(otel.trace.setSpan(otel.context.active(), span), async () => { + FaroHelper.faro.api.pushEvent('Sending request', { url }); + + instance({ + method, + url, + params, + data, + validateStatus, + }) + .then((response) => { + FaroHelper.faro.api.pushEvent('Request completed', { url }); + span.end(); + resolve(response.data as RT); + }) + .catch((ex) => { + FaroHelper.faro.api.pushEvent('Request failed', { url }); + FaroHelper.faro.api.pushError(ex); + span.setStatus({ code: SpanStatusCode.ERROR }); + span.end(); + reject(ex); + }); + }); + }); + } + + return instance({ method, url, params, data, validateStatus, - }); - - return response.data as RT; + }) + .then((response) => { + FaroHelper.faro?.api.pushEvent('Request completed', { url }); + return response.data as RT; + }) + .catch((ex) => { + FaroHelper.faro?.api.pushEvent('Request failed', { url }); + FaroHelper.faro?.api.pushError(ex); + return Promise.reject(ex); + }); }; diff --git a/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.test.tsx b/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.test.tsx index dcfe429e..c016b0f6 100644 --- a/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.test.tsx +++ b/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.test.tsx @@ -20,6 +20,14 @@ const outgoingWebhookStore = () => ({ }, {}), }); +jest.mock('@grafana/faro-web-sdk', () => ({ + initializeFaro: jest.fn(), + TracingInstrumentation: undefined, +})); +jest.mock('@grafana/faro-web-tracing', () => ({ + TracingInstrumentation: undefined, +})); + jest.mock('plugin/GrafanaPluginRootPage.helpers', () => ({ isTopNavbar: () => false, })); diff --git a/grafana-plugin/src/state/plugin/index.ts b/grafana-plugin/src/state/plugin/index.ts index c0920900..454fee84 100644 --- a/grafana-plugin/src/state/plugin/index.ts +++ b/grafana-plugin/src/state/plugin/index.ts @@ -3,6 +3,7 @@ import axios from 'axios'; import { OnCallAppPluginMeta, OnCallPluginMetaJSONData, OnCallPluginMetaSecureJSONData } from 'types'; import { makeRequest } from 'network'; +import FaroHelper from 'utils/faro'; export type UpdateGrafanaPluginSettingsProps = { jsonData?: Partial; @@ -201,12 +202,15 @@ class PluginState { ): Promise => { try { const startSyncResponse = await makeRequest(`${this.ONCALL_BASE_URL}/sync`, { method: 'POST' }); - if (typeof startSyncResponse === 'string') { // an error occured trying to initiate the sync return startSyncResponse; } + if (!FaroHelper.faro) { + FaroHelper.initializeFaro(onCallApiUrl); + } + return await this.pollOnCallDataSyncStatus(onCallApiUrl, onCallApiUrlIsConfiguredThroughEnvVar); } catch (e) { return this.getHumanReadableErrorFromOnCallError(e, onCallApiUrl, 'sync', onCallApiUrlIsConfiguredThroughEnvVar); diff --git a/grafana-plugin/src/utils/faro.test.disabled b/grafana-plugin/src/utils/faro.test.disabled new file mode 100644 index 00000000..6a3c0553 --- /dev/null +++ b/grafana-plugin/src/utils/faro.test.disabled @@ -0,0 +1,89 @@ +import 'jest/matchMedia.ts'; +import { describe, test } from '@jest/globals'; + +import FaroHelper from 'utils/faro'; + +import '@testing-library/jest-dom'; + +jest.mock('@grafana/faro-web-sdk', () => ({ + initializeFaro: jest.fn().mockReturnValue({ + api: { + pushLog: jest.fn(), + }, + }), + getWebInstrumentations: () => [], +})); + +jest.mock('@grafana/faro-web-tracing', () => ({ + TracingInstrumentation: jest.fn(), +})); +jest.mock('@opentelemetry/instrumentation-document-load', () => ({ + DocumentLoadInstrumentation: jest.fn(), +})); +jest.mock('@opentelemetry/instrumentation-fetch', () => ({ + FetchInstrumentation: jest.fn(), +})); + +describe('Faro', () => { + const OLD_ENV = process.env; + + beforeEach(() => { + jest.resetModules(); + process.env = { ...OLD_ENV }; + FaroHelper.faro = undefined; + jest.clearAllMocks(); + }); + + const getDefaultValues = () => ({ + faroUrl: 'localhost:12345/collect', + apiKey: 'secret', + enabled: 'true', + }); + + const getProcessEnv = (config: { faroUrl?: string; apiKey?: string; enabled?: string } = {}) => { + const configObject = { + ...getDefaultValues(), + ...config, + }; + + const { faroUrl, apiKey, enabled } = configObject; + + return { + FARO_URL: faroUrl, + FARO_API_KEY: apiKey, + FARO_ENABLED: enabled, + }; + }; + + test('It initializes without api key', () => { + process.env = getProcessEnv({ apiKey: '' }); + const faro = FaroHelper.initializeFaro(); + expect(faro).toBeDefined(); + }); + + test('It initializes faro ENABLED === true', () => { + process.env = getProcessEnv(); + const faro = FaroHelper.initializeFaro(); + + expect(faro).toBeDefined(); + expect(faro.api.pushLog).toHaveBeenCalledTimes(1); + }); + + test('It does not initialize faro if ENABLED != true', () => { + process.env = getProcessEnv({ enabled: 'some-other-value-here' }); + const faro = FaroHelper.initializeFaro(); + expect(faro).toBeUndefined(); + }); + + test('It skips initializing if values are missing', () => { + let faro; + + process.env = getProcessEnv({ faroUrl: undefined }); + faro = FaroHelper.initializeFaro(); + expect(faro).toBeUndefined(); + + process.env = getProcessEnv({ enabled: undefined }); + faro = FaroHelper.initializeFaro(); + expect(faro).toBeUndefined(); + }); +}); diff --git a/grafana-plugin/src/utils/faro.ts b/grafana-plugin/src/utils/faro.ts new file mode 100644 index 00000000..357b9e94 --- /dev/null +++ b/grafana-plugin/src/utils/faro.ts @@ -0,0 +1,81 @@ +import { Faro, initializeFaro, getWebInstrumentations } from '@grafana/faro-web-sdk'; +import { TracingInstrumentation } from '@grafana/faro-web-tracing'; +import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load'; +import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch'; +import { UserInteractionInstrumentation } from '@opentelemetry/instrumentation-user-interaction'; +import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request'; + +import plugin from '../../package.json'; // eslint-disable-line + +const IGNORE_URLS = [/^((?!\/{0,1}a\/grafana\-oncall\-app\\).)*$/]; + +interface FaroConfig { + url: string; + enabled: boolean; + environment: string; +} + +class FaroHelper { + faro: Faro; + + initializeFaro(onCallApiUrl: string) { + const faroConfig: FaroConfig = { + url: 'https://faro-collector-prod-us-central-0.grafana.net/collect/f3a038193e7802cf47531ca94cfbada7', + enabled: false, + environment: undefined, + }; + + if (onCallApiUrl === 'https://oncall-prod-us-central-0.grafana.net/oncall') { + faroConfig.enabled = true; + faroConfig.environment = 'prod'; + } else if (onCallApiUrl === 'https://oncall-ops-us-east-0.grafana.net/oncall') { + faroConfig.enabled = true; + faroConfig.environment = 'ops'; + } else if (onCallApiUrl === 'https://oncall-dev-us-central-0.grafana.net/oncall') { + faroConfig.enabled = true; + faroConfig.environment = 'dev'; + } else { + // This opensource, don't send traces + /* faroConfig.enabled = true; + faroConfig.environment = 'local'; */ + } + + if (!faroConfig?.enabled || !faroConfig?.url || this.faro) { + return undefined; + } + + try { + const faroOptions = { + url: faroConfig.url, + isolate: true, + instrumentations: [ + ...getWebInstrumentations({ + captureConsole: true, + }), + new TracingInstrumentation({ + instrumentations: [ + new DocumentLoadInstrumentation(), + new FetchInstrumentation({ ignoreUrls: IGNORE_URLS }), + new XMLHttpRequestInstrumentation({}), + new UserInteractionInstrumentation(), + ], + }), + ], + session: (window as any).__PRELOADED_STATE__?.faro?.session, + app: { + name: 'grafana-oncall', + version: plugin?.version, + environment: faroConfig.environment, + }, + }; + + this.faro = initializeFaro(faroOptions); + + this.faro.api.pushLog([`Faro was initialized for ${faroConfig.environment}`]); + } catch (ex) {} + + return this.faro; + } +} + +export default new FaroHelper(); diff --git a/grafana-plugin/webpack.config.js b/grafana-plugin/webpack.config.js index 934c1717..4e895287 100644 --- a/grafana-plugin/webpack.config.js +++ b/grafana-plugin/webpack.config.js @@ -1,5 +1,6 @@ const webpack = require('webpack'); const path = require('path'); +const dotenv = require('dotenv'); const CircularDependencyPlugin = require('circular-dependency-plugin'); @@ -9,6 +10,8 @@ Object.defineProperty(RegExp.prototype, 'toJSON', { value: RegExp.prototype.toString, }); +dotenv.config({ path: path.resolve(__dirname, '.env') }); + module.exports.getWebpackConfig = (config, options) => { const cssLoader = config.module.rules.find((rule) => rule.test.toString() === '/\\.css$/'); @@ -144,6 +147,9 @@ module.exports.getWebpackConfig = (config, options) => { ONCALL_API_URL: null, MOBILE_APP_QR_INTERVAL_QUEUE: null, }), + new webpack.DefinePlugin({ + 'process.env': JSON.stringify(dotenv.config().parsed), + }), ], resolve: { diff --git a/grafana-plugin/yarn.lock b/grafana-plugin/yarn.lock index 4b06ee8c..68b6f8de 100644 --- a/grafana-plugin/yarn.lock +++ b/grafana-plugin/yarn.lock @@ -1604,6 +1604,15 @@ "@opentelemetry/otlp-transformer" "^0.33.0" fast-deep-equal "^3.1.3" +"@grafana/faro-core@^1.0.0-beta4": + version "1.0.0-beta4" + resolved "https://registry.yarnpkg.com/@grafana/faro-core/-/faro-core-1.0.0-beta4.tgz#2f38e18764c0a3c3f1af889d510a2896bcb742ab" + integrity sha512-tB7705aYCByw4CNWt3WNoV39+sZCudBMiStmiEKHzM17VRRLBjPcrMQTkVYu4zMkEAdWMuAdYhT3xjzHlQpXIA== + dependencies: + "@opentelemetry/api" "^1.3.0" + "@opentelemetry/api-metrics" "^0.33.0" + "@opentelemetry/otlp-transformer" "^0.34.0" + "@grafana/faro-web-sdk@1.0.0-beta2": version "1.0.0-beta2" resolved "https://registry.yarnpkg.com/@grafana/faro-web-sdk/-/faro-web-sdk-1.0.0-beta2.tgz#d096a350d6366a108428a205753c797802eb480d" @@ -1613,6 +1622,36 @@ ua-parser-js "^1.0.32" web-vitals "^3.0.4" +"@grafana/faro-web-sdk@^1.0.0-beta4": + version "1.0.0-beta4" + resolved "https://registry.yarnpkg.com/@grafana/faro-web-sdk/-/faro-web-sdk-1.0.0-beta4.tgz#de9ec9b1201b4f02e3746f31dc0e7a3f77df47b3" + integrity sha512-yEBprcLn+L4zy/qYwrTEoSRpdbiN29EnesHlonYP5rj+K1G9CU+Oa0BL7PyS1oTEYZ2xOOv/gGYjiyi3PX9PEg== + dependencies: + "@grafana/faro-core" "^1.0.0-beta4" + ua-parser-js "^1.0.32" + web-vitals "^3.1.0" + +"@grafana/faro-web-tracing@^1.0.0-beta4": + version "1.0.0-beta5" + resolved "https://registry.yarnpkg.com/@grafana/faro-web-tracing/-/faro-web-tracing-1.0.0-beta5.tgz#855f2714131bbc6855f3b2fd81c7e1b0995fc922" + integrity sha512-wHTv5F1eKUzf46dFKJRi4KBXHC1VRALhtgWbR+IeiXZboJn7hvRF7lwvelJzX++RcnApycFdjLi3RVEpbinZOA== + dependencies: + "@grafana/faro-web-sdk" "^1.0.0-beta4" + "@opentelemetry/api" "^1.3.0" + "@opentelemetry/context-zone" "^1.8.0" + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/exporter-trace-otlp-http" "^0.34.0" + "@opentelemetry/instrumentation" "^0.34.0" + "@opentelemetry/instrumentation-document-load" "^0.31.0" + "@opentelemetry/instrumentation-fetch" "^0.34.0" + "@opentelemetry/instrumentation-user-interaction" "^0.32.0" + "@opentelemetry/instrumentation-xml-http-request" "^0.34.0" + "@opentelemetry/otlp-transformer" "^0.34.0" + "@opentelemetry/resources" "^1.8.0" + "@opentelemetry/sdk-trace-base" "^1.8.0" + "@opentelemetry/sdk-trace-web" "^1.8.0" + "@opentelemetry/semantic-conventions" "^1.8.0" + "@grafana/runtime@9.3.0-beta1": version "9.3.0-beta1" resolved "https://registry.yarnpkg.com/@grafana/runtime/-/runtime-9.3.0-beta1.tgz#4bcd5d8c24c1e810b254f113598cbb1cb759ee16" @@ -2360,11 +2399,24 @@ dependencies: "@opentelemetry/api" "^1.0.0" -"@opentelemetry/api@^1.0.0", "@opentelemetry/api@^1.1.0": +"@opentelemetry/api@^1.0.0", "@opentelemetry/api@^1.1.0", "@opentelemetry/api@^1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.3.0.tgz#27c6f776ac3c1c616651e506a89f438a0ed6a055" integrity sha512-YveTnGNsFFixTKJz09Oi4zYkiLT5af3WpZDu4aIUM7xX+2bHAkOJayFTVQd6zB8kkWPpbua4Ha6Ql00grdLlJQ== +"@opentelemetry/context-zone-peer-dep@1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/context-zone-peer-dep/-/context-zone-peer-dep-1.8.0.tgz#79e38b7f1d6b10424a628723eeb6fe7d80082692" + integrity sha512-j8hnrH9OOU9Rw4NN15fwXvaKtdXdsk0vj48YqC/c0mngf0xWroDvruOyOu2i43N+0mBRAv7YOcf52hFD4YQDng== + +"@opentelemetry/context-zone@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/context-zone/-/context-zone-1.8.0.tgz#41c3b60b59bec1d195f63937919b9c233b359e2d" + integrity sha512-IcDyvP3qSQq2ekH7CPYG6qeDHHi5edRK3bmf19gAi/kmr+pEzQL70/66BDLXThHPEWyklu0OfMFPypOrA1roMQ== + dependencies: + "@opentelemetry/context-zone-peer-dep" "1.8.0" + zone.js "^0.11.0" + "@opentelemetry/core@1.7.0": version "1.7.0" resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.7.0.tgz#83bdd1b7a4ceafcdffd6590420657caec5f7b34c" @@ -2372,6 +2424,90 @@ dependencies: "@opentelemetry/semantic-conventions" "1.7.0" +"@opentelemetry/core@1.8.0", "@opentelemetry/core@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.8.0.tgz#cca18594dd48ded6dc0d08c7e789c79af0315934" + integrity sha512-6SDjwBML4Am0AQmy7z1j6HGrWDgeK8awBRUvl1PGw6HayViMk4QpnUXvv4HTHisecgVBy43NE/cstWprm8tIfw== + dependencies: + "@opentelemetry/semantic-conventions" "1.8.0" + +"@opentelemetry/exporter-trace-otlp-http@^0.34.0": + version "0.34.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.34.0.tgz#baca4cebb1666ed801288e24215d96a65f2e8ae5" + integrity sha512-MBtUwMvgpdoRo9iqK2eDJ8SP2xKYWeBCSu99s4cc1kg4HKKOpenXLE/6daGsSZ+QTPwd8j+9xMSd+hhBg+Bvzw== + dependencies: + "@opentelemetry/core" "1.8.0" + "@opentelemetry/otlp-exporter-base" "0.34.0" + "@opentelemetry/otlp-transformer" "0.34.0" + "@opentelemetry/resources" "1.8.0" + "@opentelemetry/sdk-trace-base" "1.8.0" + +"@opentelemetry/instrumentation-document-load@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-document-load/-/instrumentation-document-load-0.31.0.tgz#8e6117b68e420fe962963baf7526d97c861b4c36" + integrity sha512-IlbJxUOyvJiatNerKuTii6cEW8iX/9F42zGmyqi8WjgxCZtncRAhkl9argG0xlQvpIoOWEotWB9S+++CjJfvfw== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.34.0" + "@opentelemetry/sdk-trace-base" "^1.0.0" + "@opentelemetry/sdk-trace-web" "^1.8.0" + "@opentelemetry/semantic-conventions" "^1.0.0" + +"@opentelemetry/instrumentation-fetch@^0.34.0": + version "0.34.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fetch/-/instrumentation-fetch-0.34.0.tgz#059b2a389acaa1cf8af509fe3c5302c0d480710a" + integrity sha512-5ihgQiRG7UGDcj0JnsLZmN/VbZj1vcKaw1frGjsEnMzvjbulYXPwmUbtxzZGxe0lpX6u6zQIpo28Ccdzxt1pJg== + dependencies: + "@opentelemetry/core" "1.8.0" + "@opentelemetry/instrumentation" "0.34.0" + "@opentelemetry/sdk-trace-web" "1.8.0" + "@opentelemetry/semantic-conventions" "1.8.0" + +"@opentelemetry/instrumentation-user-interaction@^0.32.0": + version "0.32.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-user-interaction/-/instrumentation-user-interaction-0.32.0.tgz#f4f2f9836d0374a51f97833e34d6a5d7aff9c40d" + integrity sha512-FW/N4Wu2EHv06sXyl2j57lMTAHkBb9b47+YVcUgDU+g2hpz1zC07Ajo1eZQF99tYtRy/25XX2lMOriLrrviyQg== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.34.0" + "@opentelemetry/sdk-trace-web" "^1.8.0" + +"@opentelemetry/instrumentation-xml-http-request@^0.34.0": + version "0.34.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-xml-http-request/-/instrumentation-xml-http-request-0.34.0.tgz#349818aecd967196bb2568af7496980a9ecb6498" + integrity sha512-STJuL7smHN09Q1cqN6cfQmg/9FDjPnzbIzmFV7UIWcZnHH38x2v6s8kPRZrsN8HJEH9SkS4SKbrtPW8fHX+Blw== + dependencies: + "@opentelemetry/core" "1.8.0" + "@opentelemetry/instrumentation" "0.34.0" + "@opentelemetry/sdk-trace-web" "1.8.0" + "@opentelemetry/semantic-conventions" "1.8.0" + +"@opentelemetry/instrumentation@0.34.0", "@opentelemetry/instrumentation@^0.34.0": + version "0.34.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.34.0.tgz#bae86da46ea4466594689975cd10f0c3720b4071" + integrity sha512-VET/bOh4StOQV4vf1sAvn2JD67BhW2vPZ/ynl2gHXyafme2yB8Hs9+tr1TLzFwNGo7jwMFviFQkZjCYxMuK0AA== + dependencies: + require-in-the-middle "^5.0.3" + semver "^7.3.2" + shimmer "^1.2.1" + +"@opentelemetry/otlp-exporter-base@0.34.0": + version "0.34.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.34.0.tgz#c6020b63590d4b8ac3833eda345a6f582fa014b1" + integrity sha512-xVNvQm7oXeQogeI21iTZRnBrBYS0OVekPutEJgb7jQtHg7x2GWuCBQK9sDo84FRWNXBpNOgSYqsf8/+PxIJ2vA== + dependencies: + "@opentelemetry/core" "1.8.0" + +"@opentelemetry/otlp-transformer@0.34.0", "@opentelemetry/otlp-transformer@^0.34.0": + version "0.34.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-transformer/-/otlp-transformer-0.34.0.tgz#71023706233c7bc6c3cdcf954c749fea9338084c" + integrity sha512-NghPJvn3pVoWBuhWyBe1n/nWIrj1D1EFUH/bIkWEp0CMVWFLux6R+BkRPZQo5klTcj8xFhCZZIZsL/ubkYPryg== + dependencies: + "@opentelemetry/core" "1.8.0" + "@opentelemetry/resources" "1.8.0" + "@opentelemetry/sdk-metrics" "1.8.0" + "@opentelemetry/sdk-trace-base" "1.8.0" + "@opentelemetry/otlp-transformer@^0.33.0": version "0.33.0" resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-transformer/-/otlp-transformer-0.33.0.tgz#6fd3ddc944f017da08d445f142cad1779770e0e0" @@ -2391,6 +2527,14 @@ "@opentelemetry/core" "1.7.0" "@opentelemetry/semantic-conventions" "1.7.0" +"@opentelemetry/resources@1.8.0", "@opentelemetry/resources@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.8.0.tgz#260be9742cf7bceccc0db928d8ca8d64391acfe3" + integrity sha512-KSyMH6Jvss/PFDy16z5qkCK0ERlpyqixb1xwb73wLMvVq+j7i89lobDjw3JkpCcd1Ws0J6jAI4fw28Zufj2ssg== + dependencies: + "@opentelemetry/core" "1.8.0" + "@opentelemetry/semantic-conventions" "1.8.0" + "@opentelemetry/sdk-metrics@0.33.0": version "0.33.0" resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-0.33.0.tgz#c4e51decc6e3bb0e1e97c7b081955d357e46c2fe" @@ -2401,6 +2545,15 @@ "@opentelemetry/resources" "1.7.0" lodash.merge "4.6.2" +"@opentelemetry/sdk-metrics@1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-1.8.0.tgz#d061060f03861ab3f345d0f924922bc1a6396157" + integrity sha512-+KYb+uj0vHhl8xzJO+oChS4oP1e+/2Wl3SXoHoIdcEjd1TQfDV+lxOm4oqxWq6wykXvI35/JHyejxSoT+qxGmg== + dependencies: + "@opentelemetry/core" "1.8.0" + "@opentelemetry/resources" "1.8.0" + lodash.merge "4.6.2" + "@opentelemetry/sdk-trace-base@1.7.0": version "1.7.0" resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.7.0.tgz#b498424e0c6340a9d80de63fd408c5c2130a60a5" @@ -2410,11 +2563,34 @@ "@opentelemetry/resources" "1.7.0" "@opentelemetry/semantic-conventions" "1.7.0" +"@opentelemetry/sdk-trace-base@1.8.0", "@opentelemetry/sdk-trace-base@^1.0.0", "@opentelemetry/sdk-trace-base@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.8.0.tgz#70713aab90978a16dea188c8335209f857be7384" + integrity sha512-iH41m0UTddnCKJzZx3M85vlhKzRcmT48pUeBbnzsGrq4nIay1oWVHKM5nhB5r8qRDGvd/n7f/YLCXClxwM0tvA== + dependencies: + "@opentelemetry/core" "1.8.0" + "@opentelemetry/resources" "1.8.0" + "@opentelemetry/semantic-conventions" "1.8.0" + +"@opentelemetry/sdk-trace-web@1.8.0", "@opentelemetry/sdk-trace-web@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-web/-/sdk-trace-web-1.8.0.tgz#78432fe77567cbf46846169f9f7b7643f421965b" + integrity sha512-SfotgAOOy6WTDtIxo97DjE+4l+hCiMqI0A3/TbJjixMPpk4ir/32uFqU9urhH/+zRybwwGYkQ6eILeuyZUi0ZQ== + dependencies: + "@opentelemetry/core" "1.8.0" + "@opentelemetry/sdk-trace-base" "1.8.0" + "@opentelemetry/semantic-conventions" "1.8.0" + "@opentelemetry/semantic-conventions@1.7.0": version "1.7.0" resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.7.0.tgz#af80a1ef7cf110ea3a68242acd95648991bcd763" integrity sha512-FGBx/Qd09lMaqQcogCHyYrFEpTx4cAjeS+48lMIR12z7LdH+zofGDVQSubN59nL6IpubfKqTeIDu9rNO28iHVA== +"@opentelemetry/semantic-conventions@1.8.0", "@opentelemetry/semantic-conventions@^1.0.0", "@opentelemetry/semantic-conventions@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.8.0.tgz#fe2aa90e6df050a11cd57f5c0f47b0641fd2cad3" + integrity sha512-TYh1MRcm4JnvpqtqOwT9WYaBYY4KERHdToxs/suDTLviGRsQkIjS5yYROTYTSJQUnYLOn/TuOh5GoMwfLSU+Ew== + "@petamoriken/float16@^3.4.7": version "3.6.6" resolved "https://registry.yarnpkg.com/@petamoriken/float16/-/float16-3.6.6.tgz#641f73913a6be402b34e4bdfca98d6832ed55586" @@ -5912,6 +6088,11 @@ dot-case@^3.0.4: no-case "^3.0.4" tslib "^2.0.3" +dotenv@^16.0.3: + version "16.0.3" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" + integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== + duplexer@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" @@ -9360,6 +9541,11 @@ mobx@5.13.0: resolved "https://registry.yarnpkg.com/mobx/-/mobx-5.13.0.tgz#0fd68f10aa5ff2d146a4ed9e145b53337cfbca59" integrity sha512-eSAntMSMNj0PFL705rgv+aB/z1RjNqDnFEpBe18yQVreXTWiVgIrmBUXzjnJfuba+eo4eAk6zi+/gXQkSUea8A== +module-details-from-path@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" + integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== + moment-timezone@0.5.35: version "0.5.35" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.35.tgz#6fa2631bdbe8ff04f6b8753f7199516be6dc9839" @@ -11778,6 +11964,15 @@ require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +require-in-the-middle@^5.0.3: + version "5.2.0" + resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-5.2.0.tgz#4b71e3cc7f59977100af9beb76bf2d056a5a6de2" + integrity sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg== + dependencies: + debug "^4.1.1" + module-details-from-path "^1.0.3" + resolve "^1.22.1" + requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" @@ -11835,7 +12030,7 @@ resolve.exports@^1.1.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.1: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -12142,6 +12337,11 @@ shell-quote@^1.7.3: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.4.tgz#33fe15dee71ab2a81fcbd3a52106c5cfb9fb75d8" integrity sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw== +shimmer@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" + integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -13505,7 +13705,7 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" -web-vitals@^3.0.4: +web-vitals@^3.0.4, web-vitals@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-3.1.0.tgz#a6f5156cb6c7fee562da46078540265ac2cd2d16" integrity sha512-zCeQ+bOjWjJbXv5ZL0r8Py3XP2doCQMZXNKlBGfUjPAVZWokApdeF/kFlK1peuKlCt8sL9TFkKzyXE9/cmNJQA== @@ -13775,6 +13975,13 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +zone.js@^0.11.0: + version "0.11.8" + resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.11.8.tgz#40dea9adc1ad007b5effb2bfed17f350f1f46a21" + integrity sha512-82bctBg2hKcEJ21humWIkXRlLBBmrc3nN7DFh5LGGhcyycO2S7FN8NmdvlcKaGFDNVL4/9kFLmwmInTavdJERA== + dependencies: + tslib "^2.3.0" + zwitch@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"