diff --git a/grafana-plugin/package.json b/grafana-plugin/package.json index d9f5f62f..3bbfb033 100644 --- a/grafana-plugin/package.json +++ b/grafana-plugin/package.json @@ -61,7 +61,9 @@ "@babel/preset-typescript": "^7.18.6", "@grafana/data": "^9.2.4", "@grafana/eslint-config": "^5.0.0", - "@grafana/faro-react": "^1.0.0-beta3", + "@grafana/faro-core": "1.0.0-beta4", + "@grafana/faro-web-sdk": "1.0.0-beta4", + "@grafana/faro-web-tracing": "1.0.0-beta4", "@grafana/runtime": "9.3.0-beta1", "@grafana/toolkit": "^9.2.4", "@grafana/ui": "^9.2.4", @@ -111,9 +113,6 @@ "node": ">=14" }, "dependencies": { - "@grafana/faro-core": "^1.0.0-beta3", - "@grafana/faro-web-sdk": "^1.0.0-beta3", - "@grafana/faro-web-tracing": "^1.0.0-beta3", "@opentelemetry/api": "^1.3.0", "array-move": "^4.0.0", "change-case": "^4.1.1", diff --git a/grafana-plugin/src/network/index.ts b/grafana-plugin/src/network/index.ts index 1e2c5025..a73950a3 100644 --- a/grafana-plugin/src/network/index.ts +++ b/grafana-plugin/src/network/index.ts @@ -1,4 +1,5 @@ import { SpanStatusCode } from '@opentelemetry/api'; +import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import axios from 'axios'; import qs from 'query-string'; @@ -41,7 +42,14 @@ export const makeRequest = async (path: string, config: RequestConfig) if (FaroHelper.faro && otel) { const tracer = otel.trace.getTracer('default'); - let span = otel.trace.getActiveSpan() ?? tracer.startSpan('http-request'); + 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 () => { diff --git a/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx b/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx index 4bf791cd..3eaa6d5d 100644 --- a/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx +++ b/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx @@ -23,7 +23,6 @@ import { routes } from 'pages/routes'; import { rootStore } from 'state'; import { useStore } from 'state/useStore'; import { isUserActionAllowed } from 'utils/authorization'; -import FaroHelper from 'utils/faro'; import { useQueryParams, useQueryPath } from 'utils/hooks'; dayjs.extend(utc); @@ -70,8 +69,6 @@ export const Root = observer((props: AppRootProps) => { document.head.appendChild(link); - FaroHelper.initializeFaro(); - return () => { document.head.removeChild(link); }; diff --git a/grafana-plugin/src/state/plugin/index.ts b/grafana-plugin/src/state/plugin/index.ts index aea010af..55326cd0 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; @@ -206,6 +207,10 @@ class PluginState { return startSyncResponse; } + if (!FaroHelper.faro) { + FaroHelper.initializeFaro(); + } + return await this.pollOnCallDataSyncStatus(onCallApiUrl, onCallApiUrlIsConfiguredThroughEnvVar); } catch (e) { return this.getHumanReadableErrorFromOnCallError(e, onCallApiUrl, 'sync', onCallApiUrlIsConfiguredThroughEnvVar); diff --git a/grafana-plugin/src/utils/faro.ts b/grafana-plugin/src/utils/faro.ts index a6b4f997..f1e98484 100644 --- a/grafana-plugin/src/utils/faro.ts +++ b/grafana-plugin/src/utils/faro.ts @@ -1,9 +1,15 @@ import { Faro } from '@grafana/faro-core'; import { initializeFaro, getWebInstrumentations } from '@grafana/faro-web-sdk'; -import { TracingInstrumentation, getDefaultOTELInstrumentations } from '@grafana/faro-web-tracing'; +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\\).)*$/]; + class FaroHelper { faro: Faro; @@ -24,7 +30,12 @@ class FaroHelper { captureConsole: true, }), new TracingInstrumentation({ - instrumentations: [...getDefaultOTELInstrumentations([/^((?!\/{0,1}a\/grafana\-oncall\-app\\).)*$/])], + instrumentations: [ + new DocumentLoadInstrumentation(), + new FetchInstrumentation({ ignoreUrls: IGNORE_URLS }), + new XMLHttpRequestInstrumentation({}), + new UserInteractionInstrumentation(), + ], }), ], session: (window as any).__PRELOADED_STATE__?.faro?.session, diff --git a/grafana-plugin/webpack.config.js b/grafana-plugin/webpack.config.js index fddc69a5..17763bf9 100644 --- a/grafana-plugin/webpack.config.js +++ b/grafana-plugin/webpack.config.js @@ -120,6 +120,13 @@ module.exports.getWebpackConfig = (config, options) => { 'sass-loader', ], }, + + { + test: /\.m?js/, + resolve: { + fullySpecified: false, + }, + }, ], }, diff --git a/grafana-plugin/yarn.lock b/grafana-plugin/yarn.lock index bc444e77..757e45e4 100644 --- a/grafana-plugin/yarn.lock +++ b/grafana-plugin/yarn.lock @@ -1594,6 +1594,15 @@ eslint-plugin-react-hooks "4.3.0" typescript "4.6.4" +"@grafana/faro-core@1.0.0-beta4", "@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-core@^1.0.0-beta2": version "1.0.0-beta2" resolved "https://registry.yarnpkg.com/@grafana/faro-core/-/faro-core-1.0.0-beta2.tgz#97636677c1d687b0b238642a3978334652f263a5" @@ -1604,25 +1613,6 @@ "@opentelemetry/otlp-transformer" "^0.33.0" fast-deep-equal "^3.1.3" -"@grafana/faro-core@^1.0.0-beta3": - version "1.0.0-beta3" - resolved "https://registry.yarnpkg.com/@grafana/faro-core/-/faro-core-1.0.0-beta3.tgz#705f561790b6f1d8b65a0a3507a1955519d393f8" - integrity sha512-P+mp2CMIYovmFFLJx7fvds65m+u0NB9l6RI0kKEPQHiMoR7cnHhe/dK049mk8widK0Z5Vmz1QBaNWxn3jO52cg== - dependencies: - "@opentelemetry/api" "^1.3.0" - "@opentelemetry/api-metrics" "^0.33.0" - "@opentelemetry/otlp-transformer" "^0.34.0" - fast-deep-equal "^3.1.3" - -"@grafana/faro-react@^1.0.0-beta3": - version "1.0.0-beta3" - resolved "https://registry.yarnpkg.com/@grafana/faro-react/-/faro-react-1.0.0-beta3.tgz#f28ba2fba136cd6d0417f6894218f359a5cdc88e" - integrity sha512-E8aI8FPqzs9NgOa3ApfeCNtmhakgMgfg1xu0snNz7Gt0KHssoHyIYrOHlI/C45BhkSXRMetIvhJv/YQkE9Ua7Q== - dependencies: - "@grafana/faro-web-sdk" "^1.0.0-beta3" - "@grafana/faro-web-tracing" "^1.0.0-beta3" - hoist-non-react-statics "^3.3.2" - "@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" @@ -1632,21 +1622,21 @@ ua-parser-js "^1.0.32" web-vitals "^3.0.4" -"@grafana/faro-web-sdk@^1.0.0-beta3": - version "1.0.0-beta3" - resolved "https://registry.yarnpkg.com/@grafana/faro-web-sdk/-/faro-web-sdk-1.0.0-beta3.tgz#b26e0a3888228d59555a36ae4dcda4d711d4102f" - integrity sha512-vtU53oPrDXt655ggkusvogrTpDHHBm5JO0MbYlrYqvJprUpGaTsEgnb6lDRpXht3Vy6nk9h0+q0tBzgryZtY/w== +"@grafana/faro-web-sdk@1.0.0-beta4", "@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-beta3" + "@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-beta3": - version "1.0.0-beta3" - resolved "https://registry.yarnpkg.com/@grafana/faro-web-tracing/-/faro-web-tracing-1.0.0-beta3.tgz#a2b760f0f6beb64417e8e5f54706ae7ac1ae63c7" - integrity sha512-PIa3M8NNn6lIwr1zaJ3BIr/TAAZcNGipcPs7TZGEFgNenrCHIKghW7o2v6VW+ttSRTc4zaymphy5zCoXy5Hvug== +"@grafana/faro-web-tracing@1.0.0-beta4": + version "1.0.0-beta4" + resolved "https://registry.yarnpkg.com/@grafana/faro-web-tracing/-/faro-web-tracing-1.0.0-beta4.tgz#c65ace7ccf0c00da901e5532ce83bb07e6713627" + integrity sha512-a+SM+Wm2uONUCtGVFjxrz1O+tHKaQy10YBcqPZZcPDpanf8YMbo1bdYv9mFICvzg4rrvB/OI7mRO0Unr4+zGMQ== dependencies: - "@grafana/faro-core" "^1.0.0-beta3" + "@grafana/faro-web-sdk" "^1.0.0-beta4" "@opentelemetry/api" "^1.3.0" "@opentelemetry/context-zone" "^1.8.0" "@opentelemetry/core" "^1.8.0"