mirror of https://github.com/grafana/grafana
Pyroscope: Add standalone build (#80222)
* Pyroscope standalone build * Fix for tests * Add missing packages * Remove import * Update trace to profiles * Update testpull/81063/head^2
parent
96010eb21e
commit
6796e66fb8
@ -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) |
||||
} |
@ -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) |
||||
} |
||||
} |
@ -0,0 +1 @@ |
||||
# Changelog |
@ -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" |
||||
} |
@ -0,0 +1,4 @@ |
||||
{ |
||||
"extends": "@grafana/plugin-configs/tsconfig.json", |
||||
"include": ["."] |
||||
} |
@ -0,0 +1,84 @@ |
||||
import { invert } from 'lodash'; |
||||
import { Token } from 'prismjs'; |
||||
|
||||
import { AbstractLabelMatcher, AbstractLabelOperator, AbstractQuery } from '@grafana/data'; |
||||
|
||||
export function extractLabelMatchers(tokens: Array<string | Token>): 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<string, AbstractLabelOperator> = { |
||||
'=': AbstractLabelOperator.Equal, |
||||
'!=': AbstractLabelOperator.NotEqual, |
||||
'=~': AbstractLabelOperator.EqualRegEx, |
||||
'!~': AbstractLabelOperator.NotEqualRegEx, |
||||
}; |
||||
|
||||
const ToPromLikeMap: Record<AbstractLabelOperator, string> = invert(FromPromLikeMap) as Record< |
||||
AbstractLabelOperator, |
||||
string |
||||
>; |
@ -0,0 +1,15 @@ |
||||
import config from '@grafana/plugin-configs/webpack.config'; |
||||
|
||||
const configWithFallback = async (env: Record<string, unknown>) => { |
||||
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; |
Loading…
Reference in new issue