@perses-dev/prometheus-plugin 0.45.0 → 0.46.0-rc0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,7 +27,6 @@ const _model = require("../../model");
27
27
  const _utils = require("../../utils");
28
28
  const _types = require("../types");
29
29
  const getTimeSeriesData = async (spec, context)=>{
30
- var _response_data;
31
30
  if (spec.query === undefined || spec.query === null || spec.query === '') {
32
31
  // Do not make a request to the backend, instead return an empty TimeSeriesData
33
32
  return {
@@ -72,15 +71,26 @@ const getTimeSeriesData = async (spec, context)=>{
72
71
  // Get the datasource, using the default Prom Datasource if one isn't specified in the query
73
72
  const client = await context.datasourceStore.getDatasourceClient((_spec_datasource1 = spec.datasource) !== null && _spec_datasource1 !== void 0 ? _spec_datasource1 : _model.DEFAULT_PROM);
74
73
  // Make the request to Prom
75
- const response = await client.rangeQuery({
76
- query,
77
- start,
78
- end,
79
- step
80
- });
81
- var _response_data_result;
74
+ let response;
75
+ switch(context.mode){
76
+ case 'instant':
77
+ response = await client.instantQuery({
78
+ query,
79
+ time: end
80
+ });
81
+ break;
82
+ case 'range':
83
+ default:
84
+ response = await client.rangeQuery({
85
+ query,
86
+ start,
87
+ end,
88
+ step
89
+ });
90
+ break;
91
+ }
82
92
  // TODO: What about error responses from Prom that have a response body?
83
- const result = (_response_data_result = (_response_data = response.data) === null || _response_data === void 0 ? void 0 : _response_data.result) !== null && _response_data_result !== void 0 ? _response_data_result : [];
93
+ const result = response.data;
84
94
  // Custom display for response header warnings, configurable error responses display coming next
85
95
  const notices = [];
86
96
  if (response.status === 'success') {
@@ -103,17 +113,7 @@ const getTimeSeriesData = async (spec, context)=>{
103
113
  end: (0, _datefns.fromUnixTime)(end)
104
114
  },
105
115
  stepMs: step * 1000,
106
- series: result.map((value)=>{
107
- const { metric, values } = value;
108
- // Account for seriesNameFormat from query editor when determining name to show in legend, tooltip, etc.
109
- const { name, formattedName } = (0, _utils.getFormattedPrometheusSeriesName)(query, metric, seriesNameFormat);
110
- return {
111
- name,
112
- values: values.map(_model.parseValueTuple),
113
- formattedName,
114
- labels: metric
115
- };
116
- }),
116
+ series: buildTimeSeries(result, query, seriesNameFormat),
117
117
  metadata: {
118
118
  notices,
119
119
  executedQueryString: query
@@ -121,3 +121,60 @@ const getTimeSeriesData = async (spec, context)=>{
121
121
  };
122
122
  return chartData;
123
123
  };
124
+ function buildVectorData(data, query, seriesNameFormat) {
125
+ return data.result.map((res)=>{
126
+ const { metric, value } = res;
127
+ // Account for seriesNameFormat from query editor when determining name to show in legend, tooltip, etc.
128
+ const { name, formattedName } = (0, _utils.getFormattedPrometheusSeriesName)(query, metric, seriesNameFormat);
129
+ return {
130
+ name,
131
+ values: [
132
+ (0, _model.parseValueTuple)(value)
133
+ ],
134
+ formattedName,
135
+ labels: metric
136
+ };
137
+ });
138
+ }
139
+ function buildMatrixData(data, query, seriesNameFormat) {
140
+ return data.result.map((res)=>{
141
+ const { metric, values } = res;
142
+ // Account for seriesNameFormat from query editor when determining name to show in legend, tooltip, etc.
143
+ const { name, formattedName } = (0, _utils.getFormattedPrometheusSeriesName)(query, metric, seriesNameFormat);
144
+ return {
145
+ name,
146
+ values: values.map(_model.parseValueTuple),
147
+ formattedName,
148
+ labels: metric
149
+ };
150
+ });
151
+ }
152
+ function buildScalarData(data, query, seriesNameFormat) {
153
+ const { name, formattedName } = (0, _utils.getFormattedPrometheusSeriesName)(query, {}, seriesNameFormat);
154
+ return [
155
+ {
156
+ name,
157
+ values: [
158
+ (0, _model.parseValueTuple)(data.result)
159
+ ],
160
+ formattedName
161
+ }
162
+ ];
163
+ }
164
+ function buildTimeSeries(data, query, seriesNameFormat) {
165
+ if (!data) {
166
+ return [];
167
+ }
168
+ const resultType = data.resultType;
169
+ switch(resultType){
170
+ case 'vector':
171
+ return buildVectorData(data, query, seriesNameFormat);
172
+ case 'matrix':
173
+ return buildMatrixData(data, query, seriesNameFormat);
174
+ case 'scalar':
175
+ return buildScalarData(data, query, seriesNameFormat);
176
+ default:
177
+ console.warn('Unknown result type', resultType, data);
178
+ return [];
179
+ }
180
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"get-time-series-data.d.ts","sourceRoot":"","sources":["../../../src/plugins/prometheus-time-series-query/get-time-series-data.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,qBAAqB,EAAqD,MAAM,2BAA2B,CAAC;AAYrH,OAAO,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAE1E,eAAO,MAAM,iBAAiB,EAAE,qBAAqB,CAAC,6BAA6B,CAAC,CAAC,mBAAmB,CA0GvG,CAAC"}
1
+ {"version":3,"file":"get-time-series-data.d.ts","sourceRoot":"","sources":["../../../src/plugins/prometheus-time-series-query/get-time-series-data.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,qBAAqB,EAAqD,MAAM,2BAA2B,CAAC;AAerH,OAAO,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAE1E,eAAO,MAAM,iBAAiB,EAAE,qBAAqB,CAAC,6BAA6B,CAAC,CAAC,mBAAmB,CA0GvG,CAAC"}
@@ -17,7 +17,6 @@ import { parseValueTuple, getDurationStringSeconds, getPrometheusTimeRange, getR
17
17
  import { getFormattedPrometheusSeriesName } from '../../utils';
18
18
  import { DEFAULT_SCRAPE_INTERVAL } from '../types';
19
19
  export const getTimeSeriesData = async (spec, context)=>{
20
- var _response_data;
21
20
  if (spec.query === undefined || spec.query === null || spec.query === '') {
22
21
  // Do not make a request to the backend, instead return an empty TimeSeriesData
23
22
  return {
@@ -62,15 +61,26 @@ export const getTimeSeriesData = async (spec, context)=>{
62
61
  // Get the datasource, using the default Prom Datasource if one isn't specified in the query
63
62
  const client = await context.datasourceStore.getDatasourceClient((_spec_datasource1 = spec.datasource) !== null && _spec_datasource1 !== void 0 ? _spec_datasource1 : DEFAULT_PROM);
64
63
  // Make the request to Prom
65
- const response = await client.rangeQuery({
66
- query,
67
- start,
68
- end,
69
- step
70
- });
71
- var _response_data_result;
64
+ let response;
65
+ switch(context.mode){
66
+ case 'instant':
67
+ response = await client.instantQuery({
68
+ query,
69
+ time: end
70
+ });
71
+ break;
72
+ case 'range':
73
+ default:
74
+ response = await client.rangeQuery({
75
+ query,
76
+ start,
77
+ end,
78
+ step
79
+ });
80
+ break;
81
+ }
72
82
  // TODO: What about error responses from Prom that have a response body?
73
- const result = (_response_data_result = (_response_data = response.data) === null || _response_data === void 0 ? void 0 : _response_data.result) !== null && _response_data_result !== void 0 ? _response_data_result : [];
83
+ const result = response.data;
74
84
  // Custom display for response header warnings, configurable error responses display coming next
75
85
  const notices = [];
76
86
  if (response.status === 'success') {
@@ -93,17 +103,7 @@ export const getTimeSeriesData = async (spec, context)=>{
93
103
  end: fromUnixTime(end)
94
104
  },
95
105
  stepMs: step * 1000,
96
- series: result.map((value)=>{
97
- const { metric, values } = value;
98
- // Account for seriesNameFormat from query editor when determining name to show in legend, tooltip, etc.
99
- const { name, formattedName } = getFormattedPrometheusSeriesName(query, metric, seriesNameFormat);
100
- return {
101
- name,
102
- values: values.map(parseValueTuple),
103
- formattedName,
104
- labels: metric
105
- };
106
- }),
106
+ series: buildTimeSeries(result, query, seriesNameFormat),
107
107
  metadata: {
108
108
  notices,
109
109
  executedQueryString: query
@@ -111,5 +111,62 @@ export const getTimeSeriesData = async (spec, context)=>{
111
111
  };
112
112
  return chartData;
113
113
  };
114
+ function buildVectorData(data, query, seriesNameFormat) {
115
+ return data.result.map((res)=>{
116
+ const { metric, value } = res;
117
+ // Account for seriesNameFormat from query editor when determining name to show in legend, tooltip, etc.
118
+ const { name, formattedName } = getFormattedPrometheusSeriesName(query, metric, seriesNameFormat);
119
+ return {
120
+ name,
121
+ values: [
122
+ parseValueTuple(value)
123
+ ],
124
+ formattedName,
125
+ labels: metric
126
+ };
127
+ });
128
+ }
129
+ function buildMatrixData(data, query, seriesNameFormat) {
130
+ return data.result.map((res)=>{
131
+ const { metric, values } = res;
132
+ // Account for seriesNameFormat from query editor when determining name to show in legend, tooltip, etc.
133
+ const { name, formattedName } = getFormattedPrometheusSeriesName(query, metric, seriesNameFormat);
134
+ return {
135
+ name,
136
+ values: values.map(parseValueTuple),
137
+ formattedName,
138
+ labels: metric
139
+ };
140
+ });
141
+ }
142
+ function buildScalarData(data, query, seriesNameFormat) {
143
+ const { name, formattedName } = getFormattedPrometheusSeriesName(query, {}, seriesNameFormat);
144
+ return [
145
+ {
146
+ name,
147
+ values: [
148
+ parseValueTuple(data.result)
149
+ ],
150
+ formattedName
151
+ }
152
+ ];
153
+ }
154
+ function buildTimeSeries(data, query, seriesNameFormat) {
155
+ if (!data) {
156
+ return [];
157
+ }
158
+ const resultType = data.resultType;
159
+ switch(resultType){
160
+ case 'vector':
161
+ return buildVectorData(data, query, seriesNameFormat);
162
+ case 'matrix':
163
+ return buildMatrixData(data, query, seriesNameFormat);
164
+ case 'scalar':
165
+ return buildScalarData(data, query, seriesNameFormat);
166
+ default:
167
+ console.warn('Unknown result type', resultType, data);
168
+ return [];
169
+ }
170
+ }
114
171
 
115
172
  //# sourceMappingURL=get-time-series-data.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/plugins/prometheus-time-series-query/get-time-series-data.ts"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport {\n DatasourceSpec,\n DurationString,\n formatDuration,\n msToPrometheusDuration,\n Notice,\n parseDurationString,\n TimeSeriesData,\n} from '@perses-dev/core';\nimport { TimeSeriesQueryPlugin, replaceTemplateVariables, replaceTemplateVariable } from '@perses-dev/plugin-system';\nimport { fromUnixTime, milliseconds } from 'date-fns';\nimport {\n parseValueTuple,\n PrometheusClient,\n getDurationStringSeconds,\n getPrometheusTimeRange,\n getRangeStep,\n DEFAULT_PROM,\n} from '../../model';\nimport { getFormattedPrometheusSeriesName } from '../../utils';\nimport { DEFAULT_SCRAPE_INTERVAL, PrometheusDatasourceSpec } from '../types';\nimport { PrometheusTimeSeriesQuerySpec } from './time-series-query-model';\n\nexport const getTimeSeriesData: TimeSeriesQueryPlugin<PrometheusTimeSeriesQuerySpec>['getTimeSeriesData'] = async (\n spec,\n context\n) => {\n if (spec.query === undefined || spec.query === null || spec.query === '') {\n // Do not make a request to the backend, instead return an empty TimeSeriesData\n return { series: [] };\n }\n\n const datasource = (await context.datasourceStore.getDatasource(\n spec.datasource ?? DEFAULT_PROM\n )) as DatasourceSpec<PrometheusDatasourceSpec>;\n const datasourceScrapeInterval = Math.trunc(\n milliseconds(parseDurationString(datasource.plugin.spec.scrapeInterval ?? DEFAULT_SCRAPE_INTERVAL)) / 1000\n );\n\n const minStep =\n getDurationStringSeconds(\n // resolve any variable that may have been provided\n // TODO add a validation check to make sure the variable is a DurationString, to avoid the back & forth cast here\n replaceTemplateVariables(spec.minStep as string, context.variableState) as DurationString\n ) ?? datasourceScrapeInterval;\n const timeRange = getPrometheusTimeRange(context.timeRange);\n const step = getRangeStep(timeRange, minStep, undefined, context.suggestedStepMs); // TODO: resolution\n\n // Align the time range so that it's a multiple of the step\n let { start, end } = timeRange;\n const utcOffsetSec = new Date().getTimezoneOffset() * 60;\n\n const alignedEnd = Math.floor((end + utcOffsetSec) / step) * step - utcOffsetSec;\n const alignedStart = Math.floor((start + utcOffsetSec) / step) * step - utcOffsetSec;\n start = alignedStart;\n end = alignedEnd;\n\n // Replace template variable placeholders in PromQL query\n const intervalMs = context.suggestedStepMs ?? step * 1000; // Step is in seconds\n let query = replaceTemplateVariable(spec.query, '__interval_ms', intervalMs.toString());\n query = replaceTemplateVariable(spec.query, '__interval', formatDuration(msToPrometheusDuration(intervalMs)));\n\n const scrapeIntervalMs = minStep * 1000;\n // The $__rate_interval variable is meant to be used in the rate function.\n // It is defined as max($__interval + Scrape interval, 4 * Scrape interval), where Scrape interval is the Min step setting (a setting per PromQL query),\n // if any is set, and otherwise the Scrape interval as set in the Prometheus datasource\n const rateIntervalMs = Math.max(intervalMs + scrapeIntervalMs, 4 * scrapeIntervalMs);\n query = replaceTemplateVariable(query, '__rate_interval', formatDuration(msToPrometheusDuration(rateIntervalMs)));\n query = replaceTemplateVariables(query, context.variableState);\n\n let seriesNameFormat = spec.seriesNameFormat;\n // if series name format is defined, replace template variable placeholders in series name format\n if (seriesNameFormat) {\n seriesNameFormat = replaceTemplateVariables(seriesNameFormat, context.variableState);\n }\n\n // Get the datasource, using the default Prom Datasource if one isn't specified in the query\n const client: PrometheusClient = await context.datasourceStore.getDatasourceClient(spec.datasource ?? DEFAULT_PROM);\n\n // Make the request to Prom\n const response = await client.rangeQuery({\n query,\n start,\n end,\n step,\n });\n\n // TODO: What about error responses from Prom that have a response body?\n const result = response.data?.result ?? [];\n\n // Custom display for response header warnings, configurable error responses display coming next\n const notices: Notice[] = [];\n if (response.status === 'success') {\n const warnings = response.warnings ?? [];\n const warningMessage = warnings[0] ?? '';\n if (warningMessage !== '') {\n notices.push({\n type: 'warning',\n message: warningMessage,\n });\n }\n }\n\n // Transform response\n const chartData: TimeSeriesData = {\n // Return the time range and step we actually used for the query\n timeRange: { start: fromUnixTime(start), end: fromUnixTime(end) },\n stepMs: step * 1000,\n\n series: result.map((value) => {\n const { metric, values } = value;\n\n // Account for seriesNameFormat from query editor when determining name to show in legend, tooltip, etc.\n const { name, formattedName } = getFormattedPrometheusSeriesName(query, metric, seriesNameFormat);\n\n return {\n name,\n values: values.map(parseValueTuple),\n formattedName,\n labels: metric,\n };\n }),\n metadata: {\n notices,\n executedQueryString: query,\n },\n };\n\n return chartData;\n};\n"],"names":["formatDuration","msToPrometheusDuration","parseDurationString","replaceTemplateVariables","replaceTemplateVariable","fromUnixTime","milliseconds","parseValueTuple","getDurationStringSeconds","getPrometheusTimeRange","getRangeStep","DEFAULT_PROM","getFormattedPrometheusSeriesName","DEFAULT_SCRAPE_INTERVAL","getTimeSeriesData","spec","context","response","query","undefined","series","datasource","datasourceStore","getDatasource","datasourceScrapeInterval","Math","trunc","plugin","scrapeInterval","minStep","variableState","timeRange","step","suggestedStepMs","start","end","utcOffsetSec","Date","getTimezoneOffset","alignedEnd","floor","alignedStart","intervalMs","toString","scrapeIntervalMs","rateIntervalMs","max","seriesNameFormat","client","getDatasourceClient","rangeQuery","result","data","notices","status","warnings","warningMessage","push","type","message","chartData","stepMs","map","value","metric","values","name","formattedName","labels","metadata","executedQueryString"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/plugins/prometheus-time-series-query/get-time-series-data.ts"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport {\n DatasourceSpec,\n DurationString,\n formatDuration,\n msToPrometheusDuration,\n Notice,\n parseDurationString,\n TimeSeries,\n TimeSeriesData,\n} from '@perses-dev/core';\nimport { TimeSeriesQueryPlugin, replaceTemplateVariables, replaceTemplateVariable } from '@perses-dev/plugin-system';\nimport { fromUnixTime, milliseconds } from 'date-fns';\nimport {\n parseValueTuple,\n PrometheusClient,\n getDurationStringSeconds,\n getPrometheusTimeRange,\n getRangeStep,\n DEFAULT_PROM,\n MatrixData,\n VectorData,\n ScalarData,\n} from '../../model';\nimport { getFormattedPrometheusSeriesName } from '../../utils';\nimport { DEFAULT_SCRAPE_INTERVAL, PrometheusDatasourceSpec } from '../types';\nimport { PrometheusTimeSeriesQuerySpec } from './time-series-query-model';\n\nexport const getTimeSeriesData: TimeSeriesQueryPlugin<PrometheusTimeSeriesQuerySpec>['getTimeSeriesData'] = async (\n spec,\n context\n) => {\n if (spec.query === undefined || spec.query === null || spec.query === '') {\n // Do not make a request to the backend, instead return an empty TimeSeriesData\n return { series: [] };\n }\n\n const datasource = (await context.datasourceStore.getDatasource(\n spec.datasource ?? DEFAULT_PROM\n )) as DatasourceSpec<PrometheusDatasourceSpec>;\n const datasourceScrapeInterval = Math.trunc(\n milliseconds(parseDurationString(datasource.plugin.spec.scrapeInterval ?? DEFAULT_SCRAPE_INTERVAL)) / 1000\n );\n\n const minStep =\n getDurationStringSeconds(\n // resolve any variable that may have been provided\n // TODO add a validation check to make sure the variable is a DurationString, to avoid the back & forth cast here\n replaceTemplateVariables(spec.minStep as string, context.variableState) as DurationString\n ) ?? datasourceScrapeInterval;\n const timeRange = getPrometheusTimeRange(context.timeRange);\n const step = getRangeStep(timeRange, minStep, undefined, context.suggestedStepMs); // TODO: resolution\n\n // Align the time range so that it's a multiple of the step\n let { start, end } = timeRange;\n const utcOffsetSec = new Date().getTimezoneOffset() * 60;\n\n const alignedEnd = Math.floor((end + utcOffsetSec) / step) * step - utcOffsetSec;\n const alignedStart = Math.floor((start + utcOffsetSec) / step) * step - utcOffsetSec;\n start = alignedStart;\n end = alignedEnd;\n\n // Replace template variable placeholders in PromQL query\n const intervalMs = context.suggestedStepMs ?? step * 1000; // Step is in seconds\n let query = replaceTemplateVariable(spec.query, '__interval_ms', intervalMs.toString());\n query = replaceTemplateVariable(spec.query, '__interval', formatDuration(msToPrometheusDuration(intervalMs)));\n\n const scrapeIntervalMs = minStep * 1000;\n // The $__rate_interval variable is meant to be used in the rate function.\n // It is defined as max($__interval + Scrape interval, 4 * Scrape interval), where Scrape interval is the Min step setting (a setting per PromQL query),\n // if any is set, and otherwise the Scrape interval as set in the Prometheus datasource\n const rateIntervalMs = Math.max(intervalMs + scrapeIntervalMs, 4 * scrapeIntervalMs);\n query = replaceTemplateVariable(query, '__rate_interval', formatDuration(msToPrometheusDuration(rateIntervalMs)));\n query = replaceTemplateVariables(query, context.variableState);\n\n let seriesNameFormat = spec.seriesNameFormat;\n // if series name format is defined, replace template variable placeholders in series name format\n if (seriesNameFormat) {\n seriesNameFormat = replaceTemplateVariables(seriesNameFormat, context.variableState);\n }\n\n // Get the datasource, using the default Prom Datasource if one isn't specified in the query\n const client: PrometheusClient = await context.datasourceStore.getDatasourceClient(spec.datasource ?? DEFAULT_PROM);\n\n // Make the request to Prom\n let response;\n switch (context.mode) {\n case 'instant':\n response = await client.instantQuery({\n query,\n time: end,\n });\n break;\n case 'range':\n default:\n response = await client.rangeQuery({\n query,\n start,\n end,\n step,\n });\n break;\n }\n\n // TODO: What about error responses from Prom that have a response body?\n const result = response.data;\n\n // Custom display for response header warnings, configurable error responses display coming next\n const notices: Notice[] = [];\n if (response.status === 'success') {\n const warnings = response.warnings ?? [];\n const warningMessage = warnings[0] ?? '';\n if (warningMessage !== '') {\n notices.push({\n type: 'warning',\n message: warningMessage,\n });\n }\n }\n\n // Transform response\n const chartData: TimeSeriesData = {\n // Return the time range and step we actually used for the query\n timeRange: { start: fromUnixTime(start), end: fromUnixTime(end) },\n stepMs: step * 1000,\n\n series: buildTimeSeries(result, query, seriesNameFormat),\n metadata: {\n notices,\n executedQueryString: query,\n },\n };\n\n return chartData;\n};\n\nfunction buildVectorData(data: VectorData, query: string, seriesNameFormat: string | undefined): TimeSeries[] {\n return data.result.map((res) => {\n const { metric, value } = res;\n\n // Account for seriesNameFormat from query editor when determining name to show in legend, tooltip, etc.\n const { name, formattedName } = getFormattedPrometheusSeriesName(query, metric, seriesNameFormat);\n\n return {\n name,\n values: [parseValueTuple(value)],\n formattedName,\n labels: metric,\n };\n });\n}\n\nfunction buildMatrixData(data: MatrixData, query: string, seriesNameFormat: string | undefined): TimeSeries[] {\n return data.result.map((res) => {\n const { metric, values } = res;\n\n // Account for seriesNameFormat from query editor when determining name to show in legend, tooltip, etc.\n const { name, formattedName } = getFormattedPrometheusSeriesName(query, metric, seriesNameFormat);\n\n return {\n name,\n values: values.map(parseValueTuple),\n formattedName,\n labels: metric,\n };\n });\n}\n\nfunction buildScalarData(data: ScalarData, query: string, seriesNameFormat: string | undefined): TimeSeries[] {\n const { name, formattedName } = getFormattedPrometheusSeriesName(query, {}, seriesNameFormat);\n return [\n {\n name,\n values: [parseValueTuple(data.result)],\n formattedName,\n },\n ];\n}\n\nfunction buildTimeSeries(\n data: MatrixData | VectorData | ScalarData | undefined,\n query: string,\n seriesNameFormat?: string\n): TimeSeries[] {\n if (!data) {\n return [];\n }\n\n const resultType = data.resultType;\n\n switch (resultType) {\n case 'vector':\n return buildVectorData(data, query, seriesNameFormat);\n case 'matrix':\n return buildMatrixData(data, query, seriesNameFormat);\n case 'scalar':\n return buildScalarData(data, query, seriesNameFormat);\n default:\n console.warn('Unknown result type', resultType, data);\n return [];\n }\n}\n"],"names":["formatDuration","msToPrometheusDuration","parseDurationString","replaceTemplateVariables","replaceTemplateVariable","fromUnixTime","milliseconds","parseValueTuple","getDurationStringSeconds","getPrometheusTimeRange","getRangeStep","DEFAULT_PROM","getFormattedPrometheusSeriesName","DEFAULT_SCRAPE_INTERVAL","getTimeSeriesData","spec","context","query","undefined","series","datasource","datasourceStore","getDatasource","datasourceScrapeInterval","Math","trunc","plugin","scrapeInterval","minStep","variableState","timeRange","step","suggestedStepMs","start","end","utcOffsetSec","Date","getTimezoneOffset","alignedEnd","floor","alignedStart","intervalMs","toString","scrapeIntervalMs","rateIntervalMs","max","seriesNameFormat","client","getDatasourceClient","response","mode","instantQuery","time","rangeQuery","result","data","notices","status","warnings","warningMessage","push","type","message","chartData","stepMs","buildTimeSeries","metadata","executedQueryString","buildVectorData","map","res","metric","value","name","formattedName","values","labels","buildMatrixData","buildScalarData","resultType","console","warn"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perses-dev/prometheus-plugin",
3
- "version": "0.45.0",
3
+ "version": "0.46.0-rc0",
4
4
  "description": "Prometheus plugin for Perses",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/perses/perses/blob/main/README.md",
@@ -31,9 +31,9 @@
31
31
  "dependencies": {
32
32
  "@lezer/highlight": "^1.0.0",
33
33
  "@lezer/lr": "^1.2.0",
34
- "@perses-dev/components": "0.45.0",
35
- "@perses-dev/core": "0.45.0",
36
- "@perses-dev/plugin-system": "0.45.0",
34
+ "@perses-dev/components": "0.46.0-rc0",
35
+ "@perses-dev/core": "0.46.0-rc0",
36
+ "@perses-dev/plugin-system": "0.46.0-rc0",
37
37
  "@prometheus-io/codemirror-promql": "^0.43.0",
38
38
  "@uiw/react-codemirror": "^4.19.1",
39
39
  "date-fns": "^2.28.0",
package/plugin.json CHANGED
@@ -41,7 +41,7 @@
41
41
  "pluginType": "TimeSeriesQuery",
42
42
  "kind": "PrometheusTimeSeriesQuery",
43
43
  "display": {
44
- "name": "Prometheus Range Query",
44
+ "name": "Prometheus Query",
45
45
  "description": ""
46
46
  }
47
47
  },