From 6796e66fb8be0b7528e1e64f933e1e7cff581e6c Mon Sep 17 00:00:00 2001
From: Joey <90795735+joey-grafana@users.noreply.github.com>
Date: Tue, 16 Jan 2024 12:46:15 +0000
Subject: [PATCH] Pyroscope: Add standalone build (#80222)
* Pyroscope standalone build
* Fix for tests
* Add missing packages
* Remove import
* Update trace to profiles
* Update test
---
.betterer.results | 3 +
.eslintrc | 2 +
.golangci.toml | 2 +
package.json | 1 +
.../x/GrafanaPyroscopeDataQuery_types.gen.ts | 2 +-
.../api/plugins/data/expectedListResp.json | 6 +-
.../standalone/datasource.go | 51 +++++++++++
.../standalone/main.go | 23 +++++
.../TraceToProfilesSettings.tsx | 20 ++---
.../SpanDetail/SpanFlameGraph.tsx | 5 +-
.../app/features/plugins/built_in_plugins.ts | 2 +-
.../grafana-pyroscope-datasource/CHANGELOG.md | 1 +
.../datasource.ts | 3 +-
.../grafana-pyroscope-datasource/package.json | 49 +++++++++++
.../grafana-pyroscope-datasource/plugin.json | 7 +-
.../tsconfig.json | 4 +
.../grafana-pyroscope-datasource/utils.ts | 84 +++++++++++++++++++
.../webpack.config.ts | 15 ++++
yarn.lock | 58 +++++++++++++
19 files changed, 316 insertions(+), 22 deletions(-)
create mode 100644 pkg/tsdb/grafana-pyroscope-datasource/standalone/datasource.go
create mode 100644 pkg/tsdb/grafana-pyroscope-datasource/standalone/main.go
create mode 100644 public/app/plugins/datasource/grafana-pyroscope-datasource/CHANGELOG.md
create mode 100644 public/app/plugins/datasource/grafana-pyroscope-datasource/package.json
create mode 100644 public/app/plugins/datasource/grafana-pyroscope-datasource/tsconfig.json
create mode 100644 public/app/plugins/datasource/grafana-pyroscope-datasource/utils.ts
create mode 100644 public/app/plugins/datasource/grafana-pyroscope-datasource/webpack.config.ts
diff --git a/.betterer.results b/.betterer.results
index 83dbdd6ada5..d1d169aa96e 100644
--- a/.betterer.results
+++ b/.betterer.results
@@ -4972,6 +4972,9 @@ exports[`better eslint`] = {
[0, 0, 0, "Styles should be written using objects.", "0"],
[0, 0, 0, "Styles should be written using objects.", "1"]
],
+ "public/app/plugins/datasource/grafana-pyroscope-datasource/utils.ts:5381": [
+ [0, 0, 0, "Do not use any type assertions.", "0"]
+ ],
"public/app/plugins/datasource/grafana-testdata-datasource/QueryEditor.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
diff --git a/.eslintrc b/.eslintrc
index c0854901c88..33b751f17f0 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -96,6 +96,8 @@
},
{
"files": [
+ "public/app/plugins/datasource/grafana-pyroscope-datasource/*.{ts,tsx}",
+ "public/app/plugins/datasource/grafana-pyroscope-datasource/**/*.{ts,tsx}",
"public/app/plugins/datasource/grafana-testdata-datasource/*.{ts,tsx}",
"public/app/plugins/datasource/grafana-testdata-datasource/**/*.{ts,tsx}",
"public/app/plugins/datasource/azuremonitor/*.{ts,tsx}",
diff --git a/.golangci.toml b/.golangci.toml
index ad6a6ecb380..67a9c683e9f 100644
--- a/.golangci.toml
+++ b/.golangci.toml
@@ -55,6 +55,8 @@ deny = [
{ pkg = "github.com/grafana/grafana/pkg/tsdb/intervalv2", desc = "Core plugins are not allowed to depend on Grafana core packages" },
]
files = [
+ "**/pkg/tsdb/grafana-pyroscope-datasource/*",
+ "**/pkg/tsdb/grafana-pyroscope-datasource/**/*",
"**/pkg/tsdb/grafana-testdata-datasource/*",
"**/pkg/tsdb/grafana-testdata-datasource/**/*",
"**/pkg/tsdb/azuremonitor/*",
diff --git a/package.json b/package.json
index 3bbdcde63f0..ae0807e7c40 100644
--- a/package.json
+++ b/package.json
@@ -244,6 +244,7 @@
"@floating-ui/react": "0.26.6",
"@glideapps/glide-data-grid": "^5.2.1",
"@grafana-plugins/grafana-azure-monitor-datasource": "workspace:*",
+ "@grafana-plugins/grafana-pyroscope-datasource": "workspace:*",
"@grafana-plugins/grafana-testdata-datasource": "workspace:*",
"@grafana-plugins/parca": "workspace:*",
"@grafana-plugins/tempo": "workspace:*",
diff --git a/packages/grafana-schema/src/raw/composable/grafanapyroscope/dataquery/x/GrafanaPyroscopeDataQuery_types.gen.ts b/packages/grafana-schema/src/raw/composable/grafanapyroscope/dataquery/x/GrafanaPyroscopeDataQuery_types.gen.ts
index 8860cd51842..2be0dcface6 100644
--- a/packages/grafana-schema/src/raw/composable/grafanapyroscope/dataquery/x/GrafanaPyroscopeDataQuery_types.gen.ts
+++ b/packages/grafana-schema/src/raw/composable/grafanapyroscope/dataquery/x/GrafanaPyroscopeDataQuery_types.gen.ts
@@ -11,7 +11,7 @@
import * as common from '@grafana/schema';
-export const pluginVersion = "10.4.0-pre";
+export const pluginVersion = "%VERSION%";
export type PyroscopeQueryType = ('metrics' | 'profile' | 'both');
diff --git a/pkg/tests/api/plugins/data/expectedListResp.json b/pkg/tests/api/plugins/data/expectedListResp.json
index 5f2ceae5fdf..93c276966b7 100644
--- a/pkg/tests/api/plugins/data/expectedListResp.json
+++ b/pkg/tests/api/plugins/data/expectedListResp.json
@@ -160,7 +160,7 @@
"updated": ""
},
"dependencies": {
- "grafanaDependency": ">=10.3.0",
+ "grafanaDependency": "\u003e=10.3.0",
"grafanaVersion": "*",
"plugins": []
},
@@ -688,7 +688,7 @@
"updated": ""
},
"dependencies": {
- "grafanaDependency": "",
+ "grafanaDependency": "\u003e=10.3.0-0",
"grafanaVersion": "*",
"plugins": []
},
@@ -1896,4 +1896,4 @@
"signatureOrg": "",
"angularDetected": false
}
-]
\ No newline at end of file
+]
diff --git a/pkg/tsdb/grafana-pyroscope-datasource/standalone/datasource.go b/pkg/tsdb/grafana-pyroscope-datasource/standalone/datasource.go
new file mode 100644
index 00000000000..fc00c805d31
--- /dev/null
+++ b/pkg/tsdb/grafana-pyroscope-datasource/standalone/datasource.go
@@ -0,0 +1,51 @@
+package main
+
+import (
+ "context"
+
+ "github.com/grafana/grafana-plugin-sdk-go/backend"
+ "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
+ "github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
+ pyroscope "github.com/grafana/grafana/pkg/tsdb/grafana-pyroscope-datasource"
+)
+
+var (
+ _ backend.QueryDataHandler = (*Datasource)(nil)
+ _ backend.CheckHealthHandler = (*Datasource)(nil)
+ _ backend.CallResourceHandler = (*Datasource)(nil)
+ _ backend.StreamHandler = (*Datasource)(nil)
+)
+
+func NewDatasource(context.Context, backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
+ return &Datasource{
+ Service: pyroscope.ProvideService(httpclient.NewProvider()),
+ }, nil
+}
+
+type Datasource struct {
+ Service *pyroscope.Service
+}
+
+func (d *Datasource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
+ return d.Service.QueryData(ctx, req)
+}
+
+func (d *Datasource) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
+ return d.Service.CallResource(ctx, req, sender)
+}
+
+func (d *Datasource) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
+ return d.Service.CheckHealth(ctx, req)
+}
+
+func (d *Datasource) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
+ return d.Service.SubscribeStream(ctx, req)
+}
+
+func (d *Datasource) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
+ return d.Service.PublishStream(ctx, req)
+}
+
+func (d *Datasource) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
+ return d.Service.RunStream(ctx, req, sender)
+}
diff --git a/pkg/tsdb/grafana-pyroscope-datasource/standalone/main.go b/pkg/tsdb/grafana-pyroscope-datasource/standalone/main.go
new file mode 100644
index 00000000000..345f2493715
--- /dev/null
+++ b/pkg/tsdb/grafana-pyroscope-datasource/standalone/main.go
@@ -0,0 +1,23 @@
+package main
+
+import (
+ "os"
+
+ "github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
+ "github.com/grafana/grafana-plugin-sdk-go/backend/log"
+)
+
+func main() {
+ // Start listening to requests sent from Grafana. This call is blocking so
+ // it won't finish until Grafana shuts down the process or the plugin choose
+ // to exit by itself using os.Exit. Manage automatically manages life cycle
+ // of datasource instances. It accepts datasource instance factory as first
+ // argument. This factory will be automatically called on incoming request
+ // from Grafana to create different instances of SampleDatasource (per datasource
+ // ID). When datasource configuration changed Dispose method will be called and
+ // new datasource instance created using NewSampleDatasource factory.
+ if err := datasource.Manage("grafana-pyroscope-datasource", NewDatasource, datasource.ManageOpts{}); err != nil {
+ log.DefaultLogger.Error(err.Error())
+ os.Exit(1)
+ }
+}
diff --git a/public/app/core/components/TraceToProfiles/TraceToProfilesSettings.tsx b/public/app/core/components/TraceToProfiles/TraceToProfilesSettings.tsx
index 880da29f195..c5381ceb6c6 100644
--- a/public/app/core/components/TraceToProfiles/TraceToProfilesSettings.tsx
+++ b/public/app/core/components/TraceToProfiles/TraceToProfilesSettings.tsx
@@ -9,11 +9,10 @@ import {
updateDatasourcePluginJsonDataOption,
} from '@grafana/data';
import { ConfigDescriptionLink, ConfigSection } from '@grafana/experimental';
-import { getDataSourceSrv } from '@grafana/runtime';
+import { DataSourceWithBackend, getDataSourceSrv } from '@grafana/runtime';
import { InlineField, InlineFieldRow, Input, InlineSwitch } from '@grafana/ui';
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
import { ProfileTypesCascader } from 'app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/ProfileTypesCascader';
-import { PyroscopeDataSource } from 'app/plugins/datasource/grafana-pyroscope-datasource/datasource';
import { ProfileTypeMessage } from 'app/plugins/datasource/grafana-pyroscope-datasource/types';
import { TagMappingInput } from '../TraceToLogs/TagMappingInput';
@@ -47,20 +46,19 @@ export function TraceToProfilesSettings({ options, onOptionsChange }: Props) {
return await getDataSourceSrv().get(options.jsonData.tracesToProfiles?.datasourceUid);
}, [options.jsonData.tracesToProfiles?.datasourceUid]);
- useEffect(() => {
+ const { value: pTypes } = useAsync(async () => {
if (
- dataSource &&
- dataSource instanceof PyroscopeDataSource &&
+ dataSource instanceof DataSourceWithBackend &&
supportedDataSourceTypes.includes(dataSource.type) &&
dataSource.uid === options.jsonData.tracesToProfiles?.datasourceUid
) {
- dataSource.getAllProfileTypes().then((profileTypes) => {
- setProfileTypes(profileTypes);
- });
- } else {
- setProfileTypes([]);
+ return await dataSource?.getResource('profileTypes');
}
- }, [dataSource, onOptionsChange, options, supportedDataSourceTypes]);
+ }, [dataSource]);
+
+ useEffect(() => {
+ setProfileTypes(pTypes ?? []);
+ }, [pTypes]);
return (
diff --git a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/SpanFlameGraph.tsx b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/SpanFlameGraph.tsx
index 7f91ea24592..631fef72849 100644
--- a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/SpanFlameGraph.tsx
+++ b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/SpanFlameGraph.tsx
@@ -13,12 +13,11 @@ import {
TimeZone,
} from '@grafana/data';
import { FlameGraph } from '@grafana/flamegraph';
-import { config, getTemplateSrv } from '@grafana/runtime';
+import { config, DataSourceWithBackend, getTemplateSrv } from '@grafana/runtime';
import { useStyles2 } from '@grafana/ui';
import { TraceToProfilesOptions } from 'app/core/components/TraceToProfiles/TraceToProfilesSettings';
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
import { PyroscopeQueryType } from 'app/plugins/datasource/grafana-pyroscope-datasource/dataquery.gen';
-import { PyroscopeDataSource } from 'app/plugins/datasource/grafana-pyroscope-datasource/datasource';
import { Query } from 'app/plugins/datasource/grafana-pyroscope-datasource/types';
import {
@@ -79,7 +78,7 @@ export default function SpanFlameGraph(props: SpanFlameGraphProps) {
const getFlameGraphData = async (request: DataQueryRequest
, datasourceUid: string) => {
const ds = await getDatasourceSrv().get(datasourceUid);
- if (ds instanceof PyroscopeDataSource) {
+ if (ds instanceof DataSourceWithBackend) {
const result = await lastValueFrom(ds.query(request));
const frame = result.data.find((x: DataFrame) => {
return x.name === 'response';
diff --git a/public/app/features/plugins/built_in_plugins.ts b/public/app/features/plugins/built_in_plugins.ts
index 6b08e910458..f0d9857e419 100644
--- a/public/app/features/plugins/built_in_plugins.ts
+++ b/public/app/features/plugins/built_in_plugins.ts
@@ -37,7 +37,7 @@ const tempoPlugin = async () => await import(/* webpackChunkName: "tempoPlugin"
const alertmanagerPlugin = async () =>
await import(/* webpackChunkName: "alertmanagerPlugin" */ 'app/plugins/datasource/alertmanager/module');
const pyroscopePlugin = async () =>
- await import(/* webpackChunkName: "pyroscopePlugin" */ 'app/plugins/datasource/grafana-pyroscope-datasource/module');
+ await import(/* webpackChunkName: "pyroscopePlugin" */ '@grafana-plugins/grafana-pyroscope-datasource/module');
const parcaPlugin = async () => await import(/* webpackChunkName: "parcaPlugin" */ '@grafana-plugins/parca/module');
import * as alertGroupsPanel from 'app/plugins/panel/alertGroups/module';
diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/CHANGELOG.md b/public/app/plugins/datasource/grafana-pyroscope-datasource/CHANGELOG.md
new file mode 100644
index 00000000000..825c32f0d03
--- /dev/null
+++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/CHANGELOG.md
@@ -0,0 +1 @@
+# Changelog
diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/datasource.ts b/public/app/plugins/datasource/grafana-pyroscope-datasource/datasource.ts
index efcc5cb97cb..460f32b10fe 100644
--- a/public/app/plugins/datasource/grafana-pyroscope-datasource/datasource.ts
+++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/datasource.ts
@@ -11,11 +11,10 @@ import {
} from '@grafana/data';
import { DataSourceWithBackend, getTemplateSrv, TemplateSrv } from '@grafana/runtime';
-import { extractLabelMatchers, toPromLikeExpr } from '../prometheus/language_utils';
-
import { VariableSupport } from './VariableSupport';
import { defaultGrafanaPyroscope, defaultPyroscopeQueryType } from './dataquery.gen';
import { PyroscopeDataSourceOptions, Query, ProfileTypeMessage } from './types';
+import { extractLabelMatchers, toPromLikeExpr } from './utils';
export class PyroscopeDataSource extends DataSourceWithBackend {
constructor(
diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json b/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json
new file mode 100644
index 00000000000..f47a58f03b2
--- /dev/null
+++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "@grafana-plugins/grafana-pyroscope-datasource",
+ "description": "Continuous profiling for analysis of CPU and memory usage, down to the line number and throughout time. Saving infrastructure cost, improving performance, and increasing reliability.",
+ "private": true,
+ "version": "10.4.0-pre",
+ "dependencies": {
+ "@emotion/css": "11.11.2",
+ "@grafana/data": "10.4.0-pre",
+ "@grafana/runtime": "10.4.0-pre",
+ "@grafana/schema": "10.4.0-pre",
+ "@grafana/ui": "10.4.0-pre",
+ "fast-deep-equal": "^3.1.3",
+ "lodash": "4.17.21",
+ "monaco-editor": "0.34.0",
+ "prismjs": "1.29.0",
+ "react": "18.2.0",
+ "react-dom": "18.2.0",
+ "react-use": "17.4.0",
+ "rxjs": "7.8.1",
+ "tslib": "2.6.0"
+ },
+ "devDependencies": {
+ "@grafana/plugin-configs": "10.4.0-pre",
+ "@testing-library/jest-dom": "6.1.4",
+ "@testing-library/react": "14.0.0",
+ "@testing-library/user-event": "14.5.1",
+ "@types/jest": "29.5.4",
+ "@types/lodash": "4.14.195",
+ "@types/prismjs": "1.26.0",
+ "@types/react": "18.2.15",
+ "@types/react-dom": "18.2.7",
+ "@types/testing-library__jest-dom": "5.14.8",
+ "css-loader": "6.8.1",
+ "jest": "29.7.0",
+ "style-loader": "3.3.3",
+ "ts-node": "10.9.1",
+ "typescript": "5.2.2",
+ "webpack": "5.89.0"
+ },
+ "peerDependencies": {
+ "@grafana/runtime": "*"
+ },
+ "scripts": {
+ "build": "webpack -c ./webpack.config.ts --env production",
+ "build:commit": "webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)",
+ "dev": "webpack -w -c ./webpack.config.ts --env development"
+ },
+ "packageManager": "yarn@3.6.0"
+}
diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/plugin.json b/public/app/plugins/datasource/grafana-pyroscope-datasource/plugin.json
index ba90841a3e8..9aef1503eda 100644
--- a/public/app/plugins/datasource/grafana-pyroscope-datasource/plugin.json
+++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/plugin.json
@@ -2,6 +2,7 @@
"type": "datasource",
"name": "Grafana Pyroscope",
"id": "grafana-pyroscope-datasource",
+ "executable": "gpx_grafana-pyroscope-datasource",
"aliasIDs": ["phlare"],
"category": "profiling",
@@ -29,6 +30,10 @@
"name": "GitHub Project",
"url": "https://github.com/grafana/pyroscope"
}
- ]
+ ],
+ "version": "%VERSION%"
+ },
+ "dependencies": {
+ "grafanaDependency": ">=10.3.0-0"
}
}
diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/tsconfig.json b/public/app/plugins/datasource/grafana-pyroscope-datasource/tsconfig.json
new file mode 100644
index 00000000000..7daf2ee8aba
--- /dev/null
+++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "extends": "@grafana/plugin-configs/tsconfig.json",
+ "include": ["."]
+}
diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/utils.ts b/public/app/plugins/datasource/grafana-pyroscope-datasource/utils.ts
new file mode 100644
index 00000000000..f811fbe4ebc
--- /dev/null
+++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/utils.ts
@@ -0,0 +1,84 @@
+import { invert } from 'lodash';
+import { Token } from 'prismjs';
+
+import { AbstractLabelMatcher, AbstractLabelOperator, AbstractQuery } from '@grafana/data';
+
+export function extractLabelMatchers(tokens: Array): AbstractLabelMatcher[] {
+ const labelMatchers: AbstractLabelMatcher[] = [];
+
+ for (const token of tokens) {
+ if (!(token instanceof Token)) {
+ continue;
+ }
+
+ if (token.type === 'context-labels') {
+ let labelKey = '';
+ let labelValue = '';
+ let labelOperator = '';
+
+ const contentTokens = Array.isArray(token.content) ? token.content : [token.content];
+
+ for (let currentToken of contentTokens) {
+ if (typeof currentToken === 'string') {
+ let currentStr: string;
+ currentStr = currentToken;
+ if (currentStr === '=' || currentStr === '!=' || currentStr === '=~' || currentStr === '!~') {
+ labelOperator = currentStr;
+ }
+ } else if (currentToken instanceof Token) {
+ switch (currentToken.type) {
+ case 'label-key':
+ labelKey = getMaybeTokenStringContent(currentToken);
+ break;
+ case 'label-value':
+ labelValue = getMaybeTokenStringContent(currentToken);
+ labelValue = labelValue.substring(1, labelValue.length - 1);
+ const labelComparator = FromPromLikeMap[labelOperator];
+ if (labelComparator) {
+ labelMatchers.push({ name: labelKey, operator: labelComparator, value: labelValue });
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return labelMatchers;
+}
+
+export function toPromLikeExpr(labelBasedQuery: AbstractQuery): string {
+ const expr = labelBasedQuery.labelMatchers
+ .map((selector: AbstractLabelMatcher) => {
+ const operator = ToPromLikeMap[selector.operator];
+ if (operator) {
+ return `${selector.name}${operator}"${selector.value}"`;
+ } else {
+ return '';
+ }
+ })
+ .filter((e: string) => e !== '')
+ .join(', ');
+
+ return expr ? `{${expr}}` : '';
+}
+
+function getMaybeTokenStringContent(token: Token): string {
+ if (typeof token.content === 'string') {
+ return token.content;
+ }
+
+ return '';
+}
+
+const FromPromLikeMap: Record = {
+ '=': AbstractLabelOperator.Equal,
+ '!=': AbstractLabelOperator.NotEqual,
+ '=~': AbstractLabelOperator.EqualRegEx,
+ '!~': AbstractLabelOperator.NotEqualRegEx,
+};
+
+const ToPromLikeMap: Record = invert(FromPromLikeMap) as Record<
+ AbstractLabelOperator,
+ string
+>;
diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/webpack.config.ts b/public/app/plugins/datasource/grafana-pyroscope-datasource/webpack.config.ts
new file mode 100644
index 00000000000..8e03497ddb2
--- /dev/null
+++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/webpack.config.ts
@@ -0,0 +1,15 @@
+import config from '@grafana/plugin-configs/webpack.config';
+
+const configWithFallback = async (env: Record) => {
+ const response = await config(env);
+ if (response !== undefined && response.resolve !== undefined) {
+ response.resolve.fallback = {
+ ...response.resolve.fallback,
+ stream: false,
+ string_decoder: false,
+ };
+ }
+ return response;
+};
+
+export default configWithFallback;
diff --git a/yarn.lock b/yarn.lock
index 6a07b08ce0f..7b8b1b50fb0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2970,6 +2970,45 @@ __metadata:
languageName: unknown
linkType: soft
+"@grafana-plugins/grafana-pyroscope-datasource@workspace:*, @grafana-plugins/grafana-pyroscope-datasource@workspace:public/app/plugins/datasource/grafana-pyroscope-datasource":
+ version: 0.0.0-use.local
+ resolution: "@grafana-plugins/grafana-pyroscope-datasource@workspace:public/app/plugins/datasource/grafana-pyroscope-datasource"
+ dependencies:
+ "@emotion/css": "npm:11.11.2"
+ "@grafana/data": "npm:10.4.0-pre"
+ "@grafana/plugin-configs": "npm:10.4.0-pre"
+ "@grafana/runtime": "npm:10.4.0-pre"
+ "@grafana/schema": "npm:10.4.0-pre"
+ "@grafana/ui": "npm:10.4.0-pre"
+ "@testing-library/jest-dom": "npm:6.1.4"
+ "@testing-library/react": "npm:14.0.0"
+ "@testing-library/user-event": "npm:14.5.1"
+ "@types/jest": "npm:29.5.4"
+ "@types/lodash": "npm:4.14.195"
+ "@types/prismjs": "npm:1.26.0"
+ "@types/react": "npm:18.2.15"
+ "@types/react-dom": "npm:18.2.7"
+ "@types/testing-library__jest-dom": "npm:5.14.8"
+ css-loader: "npm:6.8.1"
+ fast-deep-equal: "npm:^3.1.3"
+ jest: "npm:29.7.0"
+ lodash: "npm:4.17.21"
+ monaco-editor: "npm:0.34.0"
+ prismjs: "npm:1.29.0"
+ react: "npm:18.2.0"
+ react-dom: "npm:18.2.0"
+ react-use: "npm:17.4.0"
+ rxjs: "npm:7.8.1"
+ style-loader: "npm:3.3.3"
+ ts-node: "npm:10.9.1"
+ tslib: "npm:2.6.0"
+ typescript: "npm:5.2.2"
+ webpack: "npm:5.89.0"
+ peerDependencies:
+ "@grafana/runtime": "*"
+ languageName: unknown
+ linkType: soft
+
"@grafana-plugins/grafana-testdata-datasource@workspace:*, @grafana-plugins/grafana-testdata-datasource@workspace:public/app/plugins/datasource/grafana-testdata-datasource":
version: 0.0.0-use.local
resolution: "@grafana-plugins/grafana-testdata-datasource@workspace:public/app/plugins/datasource/grafana-testdata-datasource"
@@ -7943,6 +7982,15 @@ __metadata:
languageName: node
linkType: hard
+"@testing-library/user-event@npm:14.5.1":
+ version: 14.5.1
+ resolution: "@testing-library/user-event@npm:14.5.1"
+ peerDependencies:
+ "@testing-library/dom": ">=7.21.4"
+ checksum: 696e1328c230b0a7063a41d82b5350c6be926696106809a4d79d446d190ff56bebb850fe564ff0952cb74ae81e59a6f10534a88ecbb3792083271a249e04e728
+ languageName: node
+ linkType: hard
+
"@testing-library/user-event@npm:14.5.2":
version: 14.5.2
resolution: "@testing-library/user-event@npm:14.5.2"
@@ -9415,6 +9463,15 @@ __metadata:
languageName: node
linkType: hard
+"@types/testing-library__jest-dom@npm:5.14.8":
+ version: 5.14.8
+ resolution: "@types/testing-library__jest-dom@npm:5.14.8"
+ dependencies:
+ "@types/jest": "npm:*"
+ checksum: 26d768b3de5c71ecef683aa0e968ec2bb7f4626d78718132fa5a9c2064f9237836135e2551aa048c728407760d51d985a9d58a14528f2679a35d18d5ca200f08
+ languageName: node
+ linkType: hard
+
"@types/testing-library__jest-dom@npm:5.14.9":
version: 5.14.9
resolution: "@types/testing-library__jest-dom@npm:5.14.9"
@@ -17143,6 +17200,7 @@ __metadata:
"@floating-ui/react": "npm:0.26.6"
"@glideapps/glide-data-grid": "npm:^5.2.1"
"@grafana-plugins/grafana-azure-monitor-datasource": "workspace:*"
+ "@grafana-plugins/grafana-pyroscope-datasource": "workspace:*"
"@grafana-plugins/grafana-testdata-datasource": "workspace:*"
"@grafana-plugins/parca": "workspace:*"
"@grafana-plugins/tempo": "workspace:*"