Merge branch 'main' into giuseppe/enable-tracing-feature-flag
This commit is contained in:
+24
-76
@@ -4374,12 +4374,9 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "8"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "9"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "10"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "11"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "12"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "13"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "14"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "15"]
|
||||
[0, 0, 0, "Do not use any type assertions.", "10"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "11"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "12"]
|
||||
],
|
||||
"public/app/features/trails/SelectMetricTrailView.tsx:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
@@ -5947,24 +5944,16 @@ 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/tempo/traceql/autocomplete.test.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/plugins/datasource/zipkin/ConfigEditor.tsx:5381": [
|
||||
[0, 0, 0, "Styles should be written using objects.", "0"]
|
||||
],
|
||||
"public/app/plugins/datasource/zipkin/QueryField.tsx:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/plugins/datasource/zipkin/datasource.ts:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "4"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/plugins/datasource/zipkin/utils/testResponse.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
@@ -6003,8 +5992,7 @@ exports[`better eslint`] = {
|
||||
],
|
||||
"public/app/plugins/panel/alertlist/AlertListMigrationHandler.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/plugins/panel/alertlist/UnifiedAlertList.tsx:5381": [
|
||||
[0, 0, 0, "Styles should be written using objects.", "0"],
|
||||
@@ -6036,18 +6024,11 @@ exports[`better eslint`] = {
|
||||
],
|
||||
"public/app/plugins/panel/annolist/AnnoListPanel.test.tsx:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/plugins/panel/annolist/AnnoListPanel.tsx:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "2"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "3"]
|
||||
],
|
||||
"public/app/plugins/panel/annolist/module.tsx:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "1"]
|
||||
],
|
||||
"public/app/plugins/panel/barchart/BarChartPanel.tsx:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
@@ -6094,9 +6075,6 @@ exports[`better eslint`] = {
|
||||
"public/app/plugins/panel/canvas/globalStyles.ts:5381": [
|
||||
[0, 0, 0, "Styles should be written using objects.", "0"]
|
||||
],
|
||||
"public/app/plugins/panel/dashlist/migrations.test.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/plugins/panel/dashlist/styles.ts:5381": [
|
||||
[0, 0, 0, "Styles should be written using objects.", "0"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "1"],
|
||||
@@ -6117,8 +6095,7 @@ exports[`better eslint`] = {
|
||||
],
|
||||
"public/app/plugins/panel/debug/EventBusLogger.tsx:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/plugins/panel/gauge/GaugeMigrations.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
@@ -6168,8 +6145,7 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/plugins/panel/geomap/utils/layers.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/plugins/panel/geomap/utils/tooltip.ts:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||
@@ -6246,9 +6222,7 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Do not use any type assertions.", "16"]
|
||||
],
|
||||
"public/app/plugins/panel/histogram/Histogram.tsx:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||
],
|
||||
"public/app/plugins/panel/live/LiveChannelEditor.tsx:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
@@ -6330,13 +6304,6 @@ 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/panel/nodeGraph/usePanning.ts:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||
],
|
||||
"public/app/plugins/panel/nodeGraph/utils.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/plugins/panel/piechart/PieChart.tsx:5381": [
|
||||
[0, 0, 0, "Styles should be written using objects.", "0"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "1"],
|
||||
@@ -6349,8 +6316,7 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/plugins/panel/stat/StatMigrations.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/plugins/panel/state-timeline/migrations.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
@@ -6403,14 +6369,7 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "8"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "9"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "10"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "11"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "12"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "13"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "14"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "15"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "16"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "17"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "18"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "11"]
|
||||
],
|
||||
"public/app/plugins/panel/table-old/renderer.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
@@ -6485,17 +6444,15 @@ exports[`better eslint`] = {
|
||||
],
|
||||
"public/app/plugins/panel/timeseries/migrations.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "2"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "4"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "6"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "8"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "9"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "10"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "11"]
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "3"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "4"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "5"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "7"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "8"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "9"]
|
||||
],
|
||||
"public/app/plugins/panel/timeseries/plugins/ThresholdDragHandle.tsx:5381": [
|
||||
[0, 0, 0, "Styles should be written using objects.", "0"],
|
||||
@@ -6569,14 +6526,6 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"]
|
||||
],
|
||||
"public/app/plugins/panel/xychart/dims.ts:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "2"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "4"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "5"]
|
||||
],
|
||||
"public/app/plugins/panel/xychart/scatter.ts:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"],
|
||||
@@ -6693,8 +6642,7 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "8"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "9"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "10"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "11"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "10"]
|
||||
]
|
||||
}`
|
||||
};
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
"history", // we should bump this together with react-router-dom (see https://github.com/grafana/grafana/issues/76744)
|
||||
"react-router-dom", // we should bump this together with history (see https://github.com/grafana/grafana/issues/76744)
|
||||
"monaco-editor", // due to us exposing this via @grafana/ui/CodeEditor's props bumping can break plugins
|
||||
"react-hook-form", // due to us exposing these hooks via @grafana/ui form components bumping can break plugins
|
||||
],
|
||||
"includePaths": ["package.json", "packages/**", "public/app/plugins/**"],
|
||||
"ignorePaths": ["emails/**", "plugins-bundled/**", "**/mocks/**", "packages/grafana-e2e/**"],
|
||||
@@ -15,10 +14,10 @@
|
||||
"postUpdateOptions": ["yarnDedupeHighest"],
|
||||
"packageRules": [
|
||||
{
|
||||
"automerge": true,
|
||||
"matchCurrentVersion": "!/^0/",
|
||||
"matchUpdateTypes": ["patch"],
|
||||
"excludePackagePatterns": ["^@?storybook", "^@locker"],
|
||||
"extends": ["schedule:monthly"],
|
||||
"groupName": "Monthly patch updates"
|
||||
"excludePackagePatterns": ["^@?storybook", "^@locker"]
|
||||
},
|
||||
{
|
||||
"matchPackagePatterns": ["^@?storybook"],
|
||||
|
||||
@@ -91,9 +91,9 @@ To troubleshoot configuration and other issues, check the log file located at `/
|
||||
|
||||
### Derived fields
|
||||
|
||||
Derived Fields are used to extract new fields from a log message and create a link from the value of the field.
|
||||
Derived Fields are used to extract new fields from your logs and create a link from the value of the field.
|
||||
|
||||
For example, you can link to your tracing backend directly from your logs, or link to a user profile page if the log line contains a corresponding userId.
|
||||
For example, you can link to your tracing backend directly from your logs, or link to a user profile page if the log line contains a corresponding `userId`.
|
||||
These links appear in the [log details][].
|
||||
|
||||
You can add multiple derived fields.
|
||||
@@ -106,7 +106,11 @@ Each derived field consists of the following:
|
||||
|
||||
- **Name** - Sets the field name. Displayed as a label in the log details.
|
||||
|
||||
- **Regex** - Defines a regular expression to parse a part of the log message and capture it as the value of the new field. Can contain only one capture group.
|
||||
- **Type** - Defines the type of the derived field. It can be either:
|
||||
|
||||
- **Regex**: A regular expression to parse a part of the log message and capture it as the value of the new field. Can contain only one capture group.
|
||||
|
||||
- **Label**: A label from the selected log line. This can be any type of label - indexed, parsed or structured metadata. The label's value will be used as the value of the derived field.
|
||||
|
||||
- **URL/query** Sets the full link URL if the link is external, or a query for the target data source if the link is internal. You can interpolate the value from the field with the `${__value.raw}` macro.
|
||||
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@
|
||||
"@betterer/betterer": "5.4.0",
|
||||
"@betterer/cli": "5.4.0",
|
||||
"@betterer/eslint": "5.4.0",
|
||||
"@cypress/webpack-preprocessor": "6.0.0",
|
||||
"@cypress/webpack-preprocessor": "6.0.1",
|
||||
"@emotion/eslint-plugin": "11.11.0",
|
||||
"@grafana/eslint-config": "6.0.1",
|
||||
"@grafana/eslint-plugin": "link:./packages/grafana-eslint-rules",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { css, CSSObject, cx } from '@emotion/css';
|
||||
import { css, cx } from '@emotion/css';
|
||||
import React, { AnchorHTMLAttributes, ButtonHTMLAttributes } from 'react';
|
||||
|
||||
import { GrafanaTheme2, ThemeRichColor } from '@grafana/data';
|
||||
@@ -224,7 +224,7 @@ export const getButtonStyles = (props: StyleProps) => {
|
||||
};
|
||||
};
|
||||
|
||||
function getButtonVariantStyles(theme: GrafanaTheme2, color: ThemeRichColor, fill: ButtonFill): CSSObject {
|
||||
function getButtonVariantStyles(theme: GrafanaTheme2, color: ThemeRichColor, fill: ButtonFill) {
|
||||
let outlineBorderColor = color.border;
|
||||
let borderColor = 'transparent';
|
||||
let hoverBorderColor = 'transparent';
|
||||
@@ -293,7 +293,7 @@ function getButtonVariantStyles(theme: GrafanaTheme2, color: ThemeRichColor, fil
|
||||
}
|
||||
|
||||
function getPropertiesForDisabled(theme: GrafanaTheme2, variant: ButtonVariant, fill: ButtonFill) {
|
||||
const disabledStyles: CSSObject = {
|
||||
const disabledStyles = {
|
||||
cursor: 'not-allowed',
|
||||
boxShadow: 'none',
|
||||
color: theme.colors.text.disabled,
|
||||
|
||||
@@ -13,7 +13,7 @@ export default function resetSelectStyles(theme: GrafanaTheme2) {
|
||||
groupHeading: () => ({}),
|
||||
indicatorsContainer: () => ({}),
|
||||
indicatorSeparator: () => ({}),
|
||||
input: function (originalStyles: CSSObjectWithLabel): CSSObjectWithLabel {
|
||||
input: function (originalStyles: CSSObjectWithLabel) {
|
||||
return {
|
||||
...originalStyles,
|
||||
color: 'inherit',
|
||||
@@ -37,7 +37,7 @@ export default function resetSelectStyles(theme: GrafanaTheme2) {
|
||||
multiValueRemove: () => ({}),
|
||||
noOptionsMessage: () => ({}),
|
||||
option: () => ({}),
|
||||
placeholder: (originalStyles: CSSObjectWithLabel): CSSObjectWithLabel => ({
|
||||
placeholder: (originalStyles: CSSObjectWithLabel) => ({
|
||||
...originalStyles,
|
||||
color: theme.colors.text.secondary,
|
||||
}),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { css, CSSObject } from '@emotion/react';
|
||||
import { css } from '@emotion/react';
|
||||
|
||||
import { GrafanaTheme2, ThemeTypographyVariant } from '@grafana/data';
|
||||
|
||||
@@ -144,7 +144,7 @@ export function getElementStyles(theme: GrafanaTheme2) {
|
||||
});
|
||||
}
|
||||
|
||||
export function getVariantStyles(variant: ThemeTypographyVariant): CSSObject {
|
||||
export function getVariantStyles(variant: ThemeTypographyVariant) {
|
||||
return {
|
||||
margin: 0,
|
||||
fontSize: variant.fontSize,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { CSSObject } from '@emotion/css';
|
||||
import tinycolor from 'tinycolor2';
|
||||
|
||||
import { GrafanaTheme, GrafanaTheme2 } from '@grafana/data';
|
||||
@@ -55,14 +54,14 @@ export const focusCss = (theme: GrafanaTheme | GrafanaTheme2) => {
|
||||
transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1);`;
|
||||
};
|
||||
|
||||
export function getMouseFocusStyles(theme: GrafanaTheme | GrafanaTheme2): CSSObject {
|
||||
export function getMouseFocusStyles(theme: GrafanaTheme | GrafanaTheme2) {
|
||||
return {
|
||||
outline: 'none',
|
||||
boxShadow: `none`,
|
||||
};
|
||||
}
|
||||
|
||||
export function getFocusStyles(theme: GrafanaTheme2): CSSObject {
|
||||
export function getFocusStyles(theme: GrafanaTheme2) {
|
||||
return {
|
||||
outline: '2px dotted transparent',
|
||||
outlineOffset: '2px',
|
||||
@@ -74,7 +73,7 @@ export function getFocusStyles(theme: GrafanaTheme2): CSSObject {
|
||||
}
|
||||
|
||||
// max-width is set up based on .grafana-tooltip class that's used in dashboard
|
||||
export const getTooltipContainerStyles = (theme: GrafanaTheme2): CSSObject => ({
|
||||
export const getTooltipContainerStyles = (theme: GrafanaTheme2) => ({
|
||||
overflow: 'hidden',
|
||||
background: theme.colors.background.secondary,
|
||||
boxShadow: theme.shadows.z2,
|
||||
|
||||
@@ -51,7 +51,7 @@ func (s *Service) externalPluginSources() []plugins.PluginSource {
|
||||
|
||||
var pluginDirs []string
|
||||
for _, dir := range d {
|
||||
if dir.IsDir() {
|
||||
if dir.IsDir() || dir.Type()&os.ModeSymlink == os.ModeSymlink {
|
||||
pluginDirs = append(pluginDirs, filepath.Join(pluginsPath, dir.Name()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,4 +78,41 @@ func TestSources_List(t *testing.T) {
|
||||
require.False(t, exists)
|
||||
require.Equal(t, plugins.Signature{}, sig)
|
||||
})
|
||||
|
||||
t.Run("Plugin sources are populated with symbolic links", func(t *testing.T) {
|
||||
testdata, err := filepath.Abs("../testdata")
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := &setting.Cfg{
|
||||
StaticRootPath: testdata,
|
||||
PluginsPath: filepath.Join(testdata, "symbolic-plugin-dirs"),
|
||||
BundledPluginsPath: filepath.Join(testdata, "unsigned-panel"),
|
||||
}
|
||||
s := ProvideService(cfg)
|
||||
ctx := context.Background()
|
||||
srcs := s.List(ctx)
|
||||
uris := map[plugins.Class]map[string]struct{}{}
|
||||
for _, s := range srcs {
|
||||
class := s.PluginClass(ctx)
|
||||
if _, exists := uris[class]; !exists {
|
||||
uris[class] = map[string]struct{}{}
|
||||
}
|
||||
for _, uri := range s.PluginURIs(ctx) {
|
||||
uris[class][uri] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
require.Equal(t, uris[plugins.ClassCore], map[string]struct{}{
|
||||
filepath.Join(testdata, "app", "plugins", "datasource"): {},
|
||||
filepath.Join(testdata, "app", "plugins", "panel"): {},
|
||||
}, "should include core plugins")
|
||||
|
||||
require.Equal(t, uris[plugins.ClassBundled], map[string]struct{}{
|
||||
filepath.Join(testdata, "unsigned-panel"): {},
|
||||
}, "should include bundle plugin")
|
||||
|
||||
require.Equal(t, uris[plugins.ClassExternal], map[string]struct{}{
|
||||
filepath.Join(testdata, "symbolic-plugin-dirs", "plugin"): {},
|
||||
}, "should include external symlinked plugin")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ func (api *Api) updateProviderSettings(c *contextmodel.ReqContext) response.Resp
|
||||
return response.ErrOrFallback(http.StatusInternalServerError, "Failed to update provider settings", err)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusNoContent, nil)
|
||||
return response.Empty(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// swagger:route DELETE /v1/sso-settings/{key} sso_settings removeProviderSettings
|
||||
@@ -209,7 +209,7 @@ func (api *Api) removeProviderSettings(c *contextmodel.ReqContext) response.Resp
|
||||
return response.Error(http.StatusInternalServerError, "Failed to delete provider settings", err)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusNoContent, nil)
|
||||
return response.Empty(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// swagger:parameters getProviderSettings
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/experimental"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/tsdb/sqleng"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
var updateGoldenFiles = false
|
||||
|
||||
// These tests require a real postgres database:
|
||||
// - make devenv sources=potgres_tests
|
||||
// - either set the env variable GRAFANA_TEST_DB = postgres
|
||||
// - or set `forceRun := true` below
|
||||
//
|
||||
// The tests require a PostgreSQL db named grafanadstest and a user/password grafanatest/grafanatest!
|
||||
// Use the docker/blocks/postgres_tests/docker-compose.yaml to spin up a
|
||||
// preconfigured Postgres server suitable for running these tests.
|
||||
func TestIntegrationPostgresSnapshots(t *testing.T) {
|
||||
// the logic in this function is copied from postgres_tests.go
|
||||
shouldRunTest := func() bool {
|
||||
if testing.Short() {
|
||||
return false
|
||||
}
|
||||
|
||||
testDbName, present := os.LookupEnv("GRAFANA_TEST_DB")
|
||||
|
||||
if present && testDbName == "postgres" {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
if !shouldRunTest() {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
openDB := func() *sql.DB {
|
||||
host := os.Getenv("POSTGRES_HOST")
|
||||
if host == "" {
|
||||
host = "localhost"
|
||||
}
|
||||
port := os.Getenv("POSTGRES_PORT")
|
||||
if port == "" {
|
||||
port = "5432"
|
||||
}
|
||||
|
||||
connStr := fmt.Sprintf("user=grafanatest password=grafanatest host=%s port=%s dbname=grafanadstest sslmode=disable",
|
||||
host, port)
|
||||
|
||||
db, err := sql.Open("postgres", connStr)
|
||||
require.NoError(t, err)
|
||||
return db
|
||||
}
|
||||
|
||||
sqlQueryCommentRe := regexp.MustCompile(`^-- (.+)\n`)
|
||||
|
||||
readSqlFile := func(path string) (string, string) {
|
||||
// the file-path is not coming from the outside,
|
||||
// it is hardcoded in this file.
|
||||
//nolint:gosec
|
||||
sqlBytes, err := os.ReadFile(path)
|
||||
require.NoError(t, err)
|
||||
|
||||
sql := string(sqlBytes)
|
||||
|
||||
// first line of the file contains the sql query to run, commented out
|
||||
match := sqlQueryCommentRe.FindStringSubmatch(sql)
|
||||
require.Len(t, match, 2)
|
||||
|
||||
rawSQL := strings.TrimSpace(match[1])
|
||||
|
||||
return rawSQL, sql
|
||||
}
|
||||
|
||||
makeQuery := func(rawSQL string, format string) backend.QueryDataRequest {
|
||||
queryData := map[string]string{
|
||||
"rawSql": rawSQL,
|
||||
"format": format,
|
||||
}
|
||||
|
||||
queryBytes, err := json.Marshal(queryData)
|
||||
require.NoError(t, err)
|
||||
|
||||
return backend.QueryDataRequest{
|
||||
Queries: []backend.DataQuery{
|
||||
{
|
||||
JSON: queryBytes,
|
||||
RefID: "A",
|
||||
TimeRange: backend.TimeRange{
|
||||
From: time.Date(2023, 12, 24, 14, 15, 0, 0, time.UTC),
|
||||
To: time.Date(2023, 12, 24, 14, 45, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
format string
|
||||
}{
|
||||
{format: "time_series", name: "simple"},
|
||||
{format: "time_series", name: "7x_compat_metric_label"},
|
||||
{format: "time_series", name: "convert_to_float64"},
|
||||
{format: "time_series", name: "fill_null"},
|
||||
{format: "time_series", name: "fill_previous"},
|
||||
{format: "time_series", name: "fill_value"},
|
||||
{format: "table", name: "simple"},
|
||||
{format: "table", name: "types_numeric"},
|
||||
{format: "table", name: "types_char"},
|
||||
{format: "table", name: "types_datetime"},
|
||||
{format: "table", name: "types_other"},
|
||||
{format: "table", name: "timestamp_convert_bigint"},
|
||||
{format: "table", name: "timestamp_convert_integer"},
|
||||
}
|
||||
|
||||
for _, test := range tt {
|
||||
require.True(t, test.format == "table" || test.format == "time_series")
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
origInterpolate := sqleng.Interpolate
|
||||
t.Cleanup(func() {
|
||||
sqleng.Interpolate = origInterpolate
|
||||
})
|
||||
|
||||
sqleng.Interpolate = func(query backend.DataQuery, timeRange backend.TimeRange, timeInterval string, sql string) (string, error) {
|
||||
return sql, nil
|
||||
}
|
||||
|
||||
db := openDB()
|
||||
|
||||
t.Cleanup((func() {
|
||||
_, err := db.Exec("DROP TABLE tbl")
|
||||
require.NoError(t, err)
|
||||
err = db.Close()
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
cfg.DataPath = t.TempDir()
|
||||
|
||||
jsonData := sqleng.JsonData{
|
||||
MaxOpenConns: 0,
|
||||
MaxIdleConns: 2,
|
||||
ConnMaxLifetime: 14400,
|
||||
Timescaledb: false,
|
||||
ConfigurationMethod: "file-path",
|
||||
}
|
||||
|
||||
dsInfo := sqleng.DataSourceInfo{
|
||||
JsonData: jsonData,
|
||||
DecryptedSecureJSONData: map[string]string{},
|
||||
}
|
||||
|
||||
config := sqleng.DataPluginConfiguration{
|
||||
DSInfo: dsInfo,
|
||||
MetricColumnTypes: []string{"UNKNOWN", "TEXT", "VARCHAR", "CHAR"},
|
||||
RowLimit: 1000000,
|
||||
}
|
||||
|
||||
queryResultTransformer := postgresQueryResultTransformer{}
|
||||
|
||||
logger := log.New()
|
||||
handler, err := sqleng.NewQueryDataHandler(cfg, db, config, &queryResultTransformer, newPostgresMacroEngine(dsInfo.JsonData.Timescaledb),
|
||||
logger)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
sqlFilePath := filepath.Join("testdata", test.format, test.name+".sql")
|
||||
goldenFileName := filepath.Join(test.format, test.name+".golden")
|
||||
|
||||
rawSQL, sql := readSqlFile(sqlFilePath)
|
||||
|
||||
_, err = db.Exec(sql)
|
||||
require.NoError(t, err)
|
||||
|
||||
query := makeQuery(rawSQL, test.format)
|
||||
|
||||
result, err := handler.QueryData(context.Background(), &query)
|
||||
require.Len(t, result.Responses, 1)
|
||||
response, found := result.Responses["A"]
|
||||
require.True(t, found)
|
||||
require.NoError(t, err)
|
||||
experimental.CheckGoldenJSONResponse(t, "testdata", goldenFileName, &response, updateGoldenFiles)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
//
|
||||
// Frame[0] {
|
||||
// "typeVersion": [
|
||||
// 0,
|
||||
// 0
|
||||
// ],
|
||||
// "executedQueryString": "SELECT * FROM tbl"
|
||||
// }
|
||||
// Name:
|
||||
// Dimensions: 3 Fields by 10 Rows
|
||||
// +-------------------------------+------------------+-----------------+
|
||||
// | Name: time | Name: v | Name: c |
|
||||
// | Labels: | Labels: | Labels: |
|
||||
// | Type: []*time.Time | Type: []*float64 | Type: []*string |
|
||||
// +-------------------------------+------------------+-----------------+
|
||||
// | 2023-12-24 14:30:03 +0000 UTC | 10 | a |
|
||||
// | 2023-12-24 14:30:03 +0000 UTC | 110 | b |
|
||||
// | 2023-12-24 14:31:03 +0000 UTC | 20 | a |
|
||||
// | 2023-12-24 14:31:03 +0000 UTC | 120 | b |
|
||||
// | 2023-12-24 14:32:03 +0000 UTC | 30 | a |
|
||||
// | 2023-12-24 14:32:03 +0000 UTC | 130 | b |
|
||||
// | 2023-12-24 14:33:03 +0000 UTC | 40 | a |
|
||||
// | 2023-12-24 14:33:03 +0000 UTC | 140 | b |
|
||||
// | 2023-12-24 14:34:03 +0000 UTC | 50 | a |
|
||||
// | 2023-12-24 14:34:03 +0000 UTC | 150 | b |
|
||||
// +-------------------------------+------------------+-----------------+
|
||||
//
|
||||
//
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
{
|
||||
"status": 200,
|
||||
"frames": [
|
||||
{
|
||||
"schema": {
|
||||
"meta": {
|
||||
"typeVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"executedQueryString": "SELECT * FROM tbl"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "time",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "c",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"values": [
|
||||
[
|
||||
1703428203000,
|
||||
1703428203000,
|
||||
1703428263000,
|
||||
1703428263000,
|
||||
1703428323000,
|
||||
1703428323000,
|
||||
1703428383000,
|
||||
1703428383000,
|
||||
1703428443000,
|
||||
1703428443000
|
||||
],
|
||||
[
|
||||
10,
|
||||
110,
|
||||
20,
|
||||
120,
|
||||
30,
|
||||
130,
|
||||
40,
|
||||
140,
|
||||
50,
|
||||
150
|
||||
],
|
||||
[
|
||||
"a",
|
||||
"b",
|
||||
"a",
|
||||
"b",
|
||||
"a",
|
||||
"b",
|
||||
"a",
|
||||
"b",
|
||||
"a",
|
||||
"b"
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
-- SELECT * FROM tbl
|
||||
CREATE TEMPORARY TABLE tbl (
|
||||
"time" timestamp with time zone,
|
||||
v double precision,
|
||||
c text
|
||||
);
|
||||
|
||||
INSERT INTO tbl ("time", v, c) VALUES
|
||||
('2023-12-24 14:30:03 UTC', 10, 'a'),
|
||||
('2023-12-24 14:30:03 UTC', 110, 'b'),
|
||||
('2023-12-24 14:31:03 UTC', 20, 'a'),
|
||||
('2023-12-24 14:31:03 UTC', 120, 'b'),
|
||||
('2023-12-24 14:32:03 UTC', 30, 'a'),
|
||||
('2023-12-24 14:32:03 UTC', 130, 'b'),
|
||||
('2023-12-24 14:33:03 UTC', 40, 'a'),
|
||||
('2023-12-24 14:33:03 UTC', 140, 'b'),
|
||||
('2023-12-24 14:34:03 UTC', 50, 'a'),
|
||||
('2023-12-24 14:34:03 UTC', 150, 'b');
|
||||
Vendored
+113
@@ -0,0 +1,113 @@
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
//
|
||||
// Frame[0] {
|
||||
// "typeVersion": [
|
||||
// 0,
|
||||
// 0
|
||||
// ],
|
||||
// "executedQueryString": "SELECT * FROM tbl"
|
||||
// }
|
||||
// Name:
|
||||
// Dimensions: 4 Fields by 4 Rows
|
||||
// +--------------------------------------+-----------------------------------+---------------------+-----------------------------------+
|
||||
// | Name: reallyt | Name: time | Name: n | Name: timeend |
|
||||
// | Labels: | Labels: | Labels: | Labels: |
|
||||
// | Type: []*time.Time | Type: []*time.Time | Type: []*int64 | Type: []*time.Time |
|
||||
// +--------------------------------------+-----------------------------------+---------------------+-----------------------------------+
|
||||
// | 2023-12-24 14:21:27 +0000 UTC | 2023-12-21 13:21:27 +0100 CET | 1703161287 | 2023-12-21 13:21:52 +0100 CET |
|
||||
// | 2023-12-24 14:21:27.724 +0000 UTC | 2023-12-21 13:21:27.724 +0100 CET | 1703161287724 | 2023-12-21 13:21:52.522 +0100 CET |
|
||||
// | 2023-12-24 14:21:27.724919 +0000 UTC | 2023-12-21 13:21:27.724 +0100 CET | 1703161287724919000 | 2023-12-21 13:21:52.522 +0100 CET |
|
||||
// | null | null | null | null |
|
||||
// +--------------------------------------+-----------------------------------+---------------------+-----------------------------------+
|
||||
//
|
||||
//
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
{
|
||||
"status": 200,
|
||||
"frames": [
|
||||
{
|
||||
"schema": {
|
||||
"meta": {
|
||||
"typeVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"executedQueryString": "SELECT * FROM tbl"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "reallyt",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "time",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "n",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "int64",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "timeend",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"values": [
|
||||
[
|
||||
1703427687000,
|
||||
1703427687724,
|
||||
1703427687724,
|
||||
null
|
||||
],
|
||||
[
|
||||
1703161287000,
|
||||
1703161287724,
|
||||
1703161287724,
|
||||
null
|
||||
],
|
||||
[
|
||||
1703161287,
|
||||
1703161287724,
|
||||
1703161287724919000,
|
||||
null
|
||||
],
|
||||
[
|
||||
1703161312000,
|
||||
1703161312522,
|
||||
1703161312522,
|
||||
null
|
||||
]
|
||||
],
|
||||
"nanos": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
919000,
|
||||
0
|
||||
],
|
||||
null,
|
||||
null,
|
||||
null
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
-- SELECT * FROM tbl
|
||||
-- the time-field and time-end field gets converted to time.Time
|
||||
CREATE TEMPORARY TABLE tbl (
|
||||
reallyt timestamp with time zone, -- reference real timestamp
|
||||
"time" bigint,
|
||||
n bigint, -- normal number, it should not get converted to a timestamp
|
||||
timeend bigint
|
||||
);
|
||||
|
||||
INSERT INTO tbl (reallyt, "time", n, timeend) VALUES
|
||||
('2023-12-24T14:21:27 UTC', 1703161287, 1703161287, 1703161312),
|
||||
('2023-12-24T14:21:27.724 UTC', 1703161287724, 1703161287724, 1703161312522),
|
||||
('2023-12-24T14:21:27.724919 UTC', 1703161287724919000, 1703161287724919000, 1703161312522186000),
|
||||
(NULL, NULL, NULL, NULL);
|
||||
Vendored
+92
@@ -0,0 +1,92 @@
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
//
|
||||
// Frame[0] {
|
||||
// "typeVersion": [
|
||||
// 0,
|
||||
// 0
|
||||
// ],
|
||||
// "executedQueryString": "SELECT * FROM tbl"
|
||||
// }
|
||||
// Name:
|
||||
// Dimensions: 4 Fields by 2 Rows
|
||||
// +-------------------------------+-------------------------------+----------------+-------------------------------+
|
||||
// | Name: reallyt | Name: time | Name: n | Name: timeend |
|
||||
// | Labels: | Labels: | Labels: | Labels: |
|
||||
// | Type: []*time.Time | Type: []*time.Time | Type: []*int32 | Type: []*time.Time |
|
||||
// +-------------------------------+-------------------------------+----------------+-------------------------------+
|
||||
// | 2023-12-24 14:21:27 +0000 UTC | 2023-12-21 13:21:27 +0100 CET | 1703161287 | 2023-12-21 13:21:52 +0100 CET |
|
||||
// | null | null | null | null |
|
||||
// +-------------------------------+-------------------------------+----------------+-------------------------------+
|
||||
//
|
||||
//
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
{
|
||||
"status": 200,
|
||||
"frames": [
|
||||
{
|
||||
"schema": {
|
||||
"meta": {
|
||||
"typeVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"executedQueryString": "SELECT * FROM tbl"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "reallyt",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "time",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "n",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "int32",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "timeend",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"values": [
|
||||
[
|
||||
1703427687000,
|
||||
null
|
||||
],
|
||||
[
|
||||
1703161287000,
|
||||
null
|
||||
],
|
||||
[
|
||||
1703161287,
|
||||
null
|
||||
],
|
||||
[
|
||||
1703161312000,
|
||||
null
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
-- SELECT * FROM tbl
|
||||
-- the time-field and time-end field gets converted to time.Time
|
||||
CREATE TEMPORARY TABLE tbl (
|
||||
reallyt timestamp with time zone, -- reference real timestamp
|
||||
"time" integer, -- 32bits, seconds-as-number is highest we can go, milliseconds-as-number does not fit
|
||||
n integer, -- normal number, it should not get converted to a timestamp
|
||||
timeend integer
|
||||
);
|
||||
|
||||
INSERT INTO tbl (reallyt, "time", n, timeend) VALUES
|
||||
('2023-12-24T14:21:27 UTC', 1703161287, 1703161287, 1703161312),
|
||||
(NULL, NULL, NULL, NULL);
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
//
|
||||
// Frame[0] {
|
||||
// "typeVersion": [
|
||||
// 0,
|
||||
// 0
|
||||
// ],
|
||||
// "executedQueryString": "SELECT * FROM tbl"
|
||||
// }
|
||||
// Name:
|
||||
// Dimensions: 8 Fields by 2 Rows
|
||||
// +-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+
|
||||
// | Name: cv | Name: cvnn | Name: c | Name: cnn | Name: bpc | Name: bpcnn | Name: t | Name: tnn |
|
||||
// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: |
|
||||
// | Type: []*string | Type: []*string | Type: []*string | Type: []*string | Type: []*string | Type: []*string | Type: []*string | Type: []*string |
|
||||
// +-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+
|
||||
// | one | two | three | four | five | six | seven | eight |
|
||||
// | null | xtwo | null | xfour | null | xsix | null | xeight |
|
||||
// +-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+
|
||||
//
|
||||
//
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
{
|
||||
"status": 200,
|
||||
"frames": [
|
||||
{
|
||||
"schema": {
|
||||
"meta": {
|
||||
"typeVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"executedQueryString": "SELECT * FROM tbl"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "cv",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cvnn",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "c",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cnn",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bpc",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bpcnn",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "t",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tnn",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"values": [
|
||||
[
|
||||
"one",
|
||||
null
|
||||
],
|
||||
[
|
||||
"two",
|
||||
"xtwo"
|
||||
],
|
||||
[
|
||||
"three ",
|
||||
null
|
||||
],
|
||||
[
|
||||
"four ",
|
||||
"xfour "
|
||||
],
|
||||
[
|
||||
"five",
|
||||
null
|
||||
],
|
||||
[
|
||||
"six",
|
||||
"xsix"
|
||||
],
|
||||
[
|
||||
"seven",
|
||||
null
|
||||
],
|
||||
[
|
||||
"eight",
|
||||
"xeight"
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
-- SELECT * FROM tbl
|
||||
-- test all character-based postgres data types
|
||||
CREATE TEMPORARY TABLE tbl (
|
||||
cv character varying(10),
|
||||
cvnn character varying(10) NOT NULL,
|
||||
c character(10),
|
||||
cnn character(10) NOT NULL,
|
||||
bpc bpchar,
|
||||
bpcnn bpchar NOT NULL,
|
||||
t text,
|
||||
tnn text NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO tbl (cv, cvnn, c, cnn, bpc, bpcnn, t, tnn) VALUES
|
||||
('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight'),
|
||||
(NULL, 'xtwo', NULL, 'xfour', NULL, 'xsix', NULL, 'xeight');
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
//
|
||||
// Frame[0] {
|
||||
// "typeVersion": [
|
||||
// 0,
|
||||
// 0
|
||||
// ],
|
||||
// "executedQueryString": "SELECT * FROM tbl"
|
||||
// }
|
||||
// Name:
|
||||
// Dimensions: 12 Fields by 2 Rows
|
||||
// +----------------------------------------+----------------------------------------+--------------------------------------+--------------------------------------+---------------------------------+---------------------------------+--------------------------------------+--------------------------------------+----------------------------------------+----------------------------------------+-----------------+-----------------+
|
||||
// | Name: ts | Name: tsnn | Name: tsz | Name: tsznn | Name: d | Name: dnn | Name: t | Name: tnn | Name: tz | Name: tznn | Name: i | Name: inn |
|
||||
// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: |
|
||||
// | Type: []*time.Time | Type: []*time.Time | Type: []*time.Time | Type: []*time.Time | Type: []*time.Time | Type: []*time.Time | Type: []*time.Time | Type: []*time.Time | Type: []*time.Time | Type: []*time.Time | Type: []*string | Type: []*string |
|
||||
// +----------------------------------------+----------------------------------------+--------------------------------------+--------------------------------------+---------------------------------+---------------------------------+--------------------------------------+--------------------------------------+----------------------------------------+----------------------------------------+-----------------+-----------------+
|
||||
// | 2023-11-15 05:06:07.123456 +0000 +0000 | 2023-11-15 05:06:08.123456 +0000 +0000 | 2021-07-22 11:22:33.654321 +0000 UTC | 2021-07-22 11:22:34.654321 +0000 UTC | 2023-12-20 00:00:00 +0000 +0000 | 2023-12-21 00:00:00 +0000 +0000 | 0000-01-01 12:34:56.234567 +0000 UTC | 0000-01-01 12:34:57.234567 +0000 UTC | 0000-01-01 23:12:36.765432 +0100 +0100 | 0000-01-01 23:12:37.765432 +0100 +0100 | 00:00:00.987654 | 00:00:00.887654 |
|
||||
// | null | 2023-11-15 05:06:09.123456 +0000 +0000 | null | 2021-07-22 11:22:35.654321 +0000 UTC | null | 2023-12-22 00:00:00 +0000 +0000 | null | 0000-01-01 12:34:58.234567 +0000 UTC | null | 0000-01-01 23:12:38.765432 +0100 +0100 | null | 00:00:00.787654 |
|
||||
// +----------------------------------------+----------------------------------------+--------------------------------------+--------------------------------------+---------------------------------+---------------------------------+--------------------------------------+--------------------------------------+----------------------------------------+----------------------------------------+-----------------+-----------------+
|
||||
//
|
||||
//
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
{
|
||||
"status": 200,
|
||||
"frames": [
|
||||
{
|
||||
"schema": {
|
||||
"meta": {
|
||||
"typeVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"executedQueryString": "SELECT * FROM tbl"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "ts",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tsnn",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tsz",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tsznn",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "d",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "dnn",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "t",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tnn",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tz",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tznn",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "i",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "inn",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"values": [
|
||||
[
|
||||
1700024767123,
|
||||
null
|
||||
],
|
||||
[
|
||||
1700024768123,
|
||||
1700024769123
|
||||
],
|
||||
[
|
||||
1626952953654,
|
||||
null
|
||||
],
|
||||
[
|
||||
1626952954654,
|
||||
1626952955654
|
||||
],
|
||||
[
|
||||
1703030400000,
|
||||
null
|
||||
],
|
||||
[
|
||||
1703116800000,
|
||||
1703203200000
|
||||
],
|
||||
[
|
||||
-62167173903766,
|
||||
null
|
||||
],
|
||||
[
|
||||
-62167173902766,
|
||||
-62167173901766
|
||||
],
|
||||
[
|
||||
-62167139243235,
|
||||
null
|
||||
],
|
||||
[
|
||||
-62167139242235,
|
||||
-62167139241235
|
||||
],
|
||||
[
|
||||
"00:00:00.987654",
|
||||
null
|
||||
],
|
||||
[
|
||||
"00:00:00.887654",
|
||||
"00:00:00.787654"
|
||||
]
|
||||
],
|
||||
"nanos": [
|
||||
[
|
||||
456000,
|
||||
0
|
||||
],
|
||||
[
|
||||
456000,
|
||||
456000
|
||||
],
|
||||
[
|
||||
321000,
|
||||
0
|
||||
],
|
||||
[
|
||||
321000,
|
||||
321000
|
||||
],
|
||||
null,
|
||||
null,
|
||||
[
|
||||
567000,
|
||||
0
|
||||
],
|
||||
[
|
||||
567000,
|
||||
567000
|
||||
],
|
||||
[
|
||||
432000,
|
||||
0
|
||||
],
|
||||
[
|
||||
432000,
|
||||
432000
|
||||
],
|
||||
null,
|
||||
null
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
-- SELECT * FROM tbl
|
||||
-- test all date/time-based postgres data types
|
||||
CREATE TEMPORARY TABLE tbl (
|
||||
ts timestamp,
|
||||
tsnn timestamp NOT NULL,
|
||||
tsz timestamp with time zone,
|
||||
tsznn timestamp with time zone NOT NULL,
|
||||
d date,
|
||||
dnn date NOT NULL,
|
||||
t time,
|
||||
tnn time NOT NULL,
|
||||
tz time with time zone,
|
||||
tznn time with time zone NOT NULL,
|
||||
i interval,
|
||||
inn interval NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO tbl (ts, tsnn, tsz, tsznn, d, dnn, t, tnn, tz, tznn, i, inn) VALUES (
|
||||
'2023-11-15 05:06:07.123456',
|
||||
'2023-11-15 05:06:08.123456',
|
||||
'2021-07-22 13:22:33.654321 Europe/Berlin',
|
||||
'2021-07-22 13:22:34.654321 Europe/Berlin',
|
||||
'2023-12-20',
|
||||
'2023-12-21',
|
||||
'12:34:56.234567',
|
||||
'12:34:57.234567',
|
||||
'23:12:36.765432+1',
|
||||
'23:12:37.765432+1',
|
||||
'987654 microsecond',
|
||||
'887654 microsecond'
|
||||
), (
|
||||
NULL,
|
||||
'2023-11-15 05:06:09.123456',
|
||||
NULL,
|
||||
'2021-07-22 13:22:35.654321 Europe/Berlin',
|
||||
NULL,
|
||||
'2023-12-22',
|
||||
NULL,
|
||||
'12:34:58.234567',
|
||||
NULL,
|
||||
'23:12:38.765432+1',
|
||||
NULL,
|
||||
'787654 microsecond'
|
||||
);
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
//
|
||||
// Frame[0] {
|
||||
// "typeVersion": [
|
||||
// 0,
|
||||
// 0
|
||||
// ],
|
||||
// "executedQueryString": "SELECT * FROM tbl"
|
||||
// }
|
||||
// Name:
|
||||
// Dimensions: 12 Fields by 2 Rows
|
||||
// +----------------+----------------+----------------+----------------+----------------+----------------+------------------+------------------+------------------+------------------+------------------+------------------+
|
||||
// | Name: i16 | Name: i16nn | Name: i32 | Name: i32nn | Name: i64 | Name: i64nn | Name: n | Name: nnn | Name: f32 | Name: f32nn | Name: f64 | Name: f64nn |
|
||||
// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: |
|
||||
// | Type: []*int16 | Type: []*int16 | Type: []*int32 | Type: []*int32 | Type: []*int64 | Type: []*int64 | Type: []*float64 | Type: []*float64 | Type: []*float64 | Type: []*float64 | Type: []*float64 | Type: []*float64 |
|
||||
// +----------------+----------------+----------------+----------------+----------------+----------------+------------------+------------------+------------------+------------------+------------------+------------------+
|
||||
// | 1 | 2 | 3 | 4 | 5 | 6 | 81.75 | 7065.25 | 30.75 | 14.625 | 21.5625 | 14.25 |
|
||||
// | null | 22 | null | 44 | null | 66 | null | 169.75 | null | 77.125 | null | 215.8125 |
|
||||
// +----------------+----------------+----------------+----------------+----------------+----------------+------------------+------------------+------------------+------------------+------------------+------------------+
|
||||
//
|
||||
//
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
{
|
||||
"status": 200,
|
||||
"frames": [
|
||||
{
|
||||
"schema": {
|
||||
"meta": {
|
||||
"typeVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"executedQueryString": "SELECT * FROM tbl"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "i16",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "int16",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "i16nn",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "int16",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "i32",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "int32",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "i32nn",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "int32",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "i64",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "int64",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "i64nn",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "int64",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "n",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nnn",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "f32",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "f32nn",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "f64",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "f64nn",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"values": [
|
||||
[
|
||||
1,
|
||||
null
|
||||
],
|
||||
[
|
||||
2,
|
||||
22
|
||||
],
|
||||
[
|
||||
3,
|
||||
null
|
||||
],
|
||||
[
|
||||
4,
|
||||
44
|
||||
],
|
||||
[
|
||||
5,
|
||||
null
|
||||
],
|
||||
[
|
||||
6,
|
||||
66
|
||||
],
|
||||
[
|
||||
81.75,
|
||||
null
|
||||
],
|
||||
[
|
||||
7065.25,
|
||||
169.75
|
||||
],
|
||||
[
|
||||
30.75,
|
||||
null
|
||||
],
|
||||
[
|
||||
14.625,
|
||||
77.125
|
||||
],
|
||||
[
|
||||
21.5625,
|
||||
null
|
||||
],
|
||||
[
|
||||
14.25,
|
||||
215.8125
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
-- SELECT * FROM tbl
|
||||
-- test all numeric postgres data types
|
||||
CREATE TEMPORARY TABLE tbl (
|
||||
i16 smallint,
|
||||
i16nn smallint NOT NULL,
|
||||
i32 integer,
|
||||
i32nn integer NOT NULL,
|
||||
i64 bigint,
|
||||
i64nn bigint NOT NULL,
|
||||
n numeric(7, 2),
|
||||
nnn numeric(7,2) NOT NULL,
|
||||
f32 real,
|
||||
f32nn real NOT NULL,
|
||||
f64 double precision,
|
||||
f64nn double precision NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO tbl (i16, i16nn, i32, i32nn, i64, i64nn, n, nnn, f32, f32nn, f64, f64nn) VALUES
|
||||
(1, 2, 3, 4, 5, 6, 81.75, 7065.25, 30.75, 14.625, 21.5625, 14.25),
|
||||
(NULL, 22, NULL, 44, NULL, 66, NULL, 169.75, NULL, 77.125, NULL, 215.8125);
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
//
|
||||
// Frame[0] {
|
||||
// "typeVersion": [
|
||||
// 0,
|
||||
// 0
|
||||
// ],
|
||||
// "executedQueryString": "SELECT * FROM tbl"
|
||||
// }
|
||||
// Name:
|
||||
// Dimensions: 6 Fields by 3 Rows
|
||||
// +-----------------+-----------------+-----------------+-----------------+---------------+---------------+
|
||||
// | Name: m | Name: mnn | Name: bt | Name: btnn | Name: bl | Name: blnn |
|
||||
// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: |
|
||||
// | Type: []*string | Type: []*string | Type: []*string | Type: []*string | Type: []*bool | Type: []*bool |
|
||||
// +-----------------+-----------------+-----------------+-----------------+---------------+---------------+
|
||||
// | $12.34 | $23.45 | ABCD | EFGH | true | true |
|
||||
// | $12.34 | $23.45 | QRST | UVWX | false | false |
|
||||
// | null | $34.56 | null | abcd | null | true |
|
||||
// +-----------------+-----------------+-----------------+-----------------+---------------+---------------+
|
||||
//
|
||||
//
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
{
|
||||
"status": 200,
|
||||
"frames": [
|
||||
{
|
||||
"schema": {
|
||||
"meta": {
|
||||
"typeVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"executedQueryString": "SELECT * FROM tbl"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "m",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mnn",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bt",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "btnn",
|
||||
"type": "string",
|
||||
"typeInfo": {
|
||||
"frame": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bl",
|
||||
"type": "boolean",
|
||||
"typeInfo": {
|
||||
"frame": "bool",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "blnn",
|
||||
"type": "boolean",
|
||||
"typeInfo": {
|
||||
"frame": "bool",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"values": [
|
||||
[
|
||||
"$12.34",
|
||||
"$12.34",
|
||||
null
|
||||
],
|
||||
[
|
||||
"$23.45",
|
||||
"$23.45",
|
||||
"$34.56"
|
||||
],
|
||||
[
|
||||
"ABCD",
|
||||
"QRST",
|
||||
null
|
||||
],
|
||||
[
|
||||
"EFGH",
|
||||
"UVWX",
|
||||
"abcd"
|
||||
],
|
||||
[
|
||||
true,
|
||||
false,
|
||||
null
|
||||
],
|
||||
[
|
||||
true,
|
||||
false,
|
||||
true
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
-- SELECT * FROM tbl
|
||||
-- test the less used postgres data types
|
||||
CREATE TEMPORARY TABLE tbl (
|
||||
m money,
|
||||
mnn money NOT NULL,
|
||||
bt bytea,
|
||||
btnn bytea NOT NULL,
|
||||
bl boolean,
|
||||
blnn boolean NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO tbl (m, mnn, bt, btnn, bl, blnn) VALUES
|
||||
(12.34, 23.45, '\x41424344'::bytea, '\x45464748'::bytea, TRUE, TRUE),
|
||||
(12.34, 23.45, '\x51525354'::bytea, '\x55565758'::bytea, FALSE, FALSE),
|
||||
(NULL, 34.56, NULL, '\x61626364'::bytea, NULL, TRUE);
|
||||
Vendored
+93
@@ -0,0 +1,93 @@
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
//
|
||||
// Frame[0] {
|
||||
// "type": "timeseries-wide",
|
||||
// "typeVersion": [
|
||||
// 0,
|
||||
// 0
|
||||
// ],
|
||||
// "executedQueryString": "SELECT * FROM tbl"
|
||||
// }
|
||||
// Name:
|
||||
// Dimensions: 3 Fields by 5 Rows
|
||||
// +-------------------------------+------------------+------------------+
|
||||
// | Name: Time | Name: a | Name: b |
|
||||
// | Labels: | Labels: | Labels: |
|
||||
// | Type: []time.Time | Type: []*float64 | Type: []*float64 |
|
||||
// +-------------------------------+------------------+------------------+
|
||||
// | 2023-12-24 14:30:03 +0000 UTC | 10 | 110 |
|
||||
// | 2023-12-24 14:31:03 +0000 UTC | 20 | 120 |
|
||||
// | 2023-12-24 14:32:03 +0000 UTC | 30 | 130 |
|
||||
// | 2023-12-24 14:33:03 +0000 UTC | 40 | 140 |
|
||||
// | 2023-12-24 14:34:03 +0000 UTC | 50 | 150 |
|
||||
// +-------------------------------+------------------+------------------+
|
||||
//
|
||||
//
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
{
|
||||
"status": 200,
|
||||
"frames": [
|
||||
{
|
||||
"schema": {
|
||||
"meta": {
|
||||
"type": "timeseries-wide",
|
||||
"typeVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"executedQueryString": "SELECT * FROM tbl"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "Time",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "b",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"values": [
|
||||
[
|
||||
1703428203000,
|
||||
1703428263000,
|
||||
1703428323000,
|
||||
1703428383000,
|
||||
1703428443000
|
||||
],
|
||||
[
|
||||
10,
|
||||
20,
|
||||
30,
|
||||
40,
|
||||
50
|
||||
],
|
||||
[
|
||||
110,
|
||||
120,
|
||||
130,
|
||||
140,
|
||||
150
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
-- SELECT * FROM tbl
|
||||
-- there's special backward-compat code which handles a field named 'metric'
|
||||
CREATE TEMPORARY TABLE tbl (
|
||||
"time" timestamp with time zone,
|
||||
v double precision,
|
||||
metric text
|
||||
);
|
||||
|
||||
INSERT INTO tbl ("time", v, metric) VALUES
|
||||
('2023-12-24 14:30:03 UTC', 10, 'a'),
|
||||
('2023-12-24 14:30:03 UTC', 110, 'b'),
|
||||
('2023-12-24 14:31:03 UTC', 20, 'a'),
|
||||
('2023-12-24 14:31:03 UTC', 120, 'b'),
|
||||
('2023-12-24 14:32:03 UTC', 30, 'a'),
|
||||
('2023-12-24 14:32:03 UTC', 130, 'b'),
|
||||
('2023-12-24 14:33:03 UTC', 40, 'a'),
|
||||
('2023-12-24 14:33:03 UTC', 140, 'b'),
|
||||
('2023-12-24 14:34:03 UTC', 50, 'a'),
|
||||
('2023-12-24 14:34:03 UTC', 150, 'b');
|
||||
Vendored
+245
@@ -0,0 +1,245 @@
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
//
|
||||
// Frame[0] {
|
||||
// "type": "timeseries-wide",
|
||||
// "typeVersion": [
|
||||
// 0,
|
||||
// 0
|
||||
// ],
|
||||
// "executedQueryString": "SELECT * FROM tbl"
|
||||
// }
|
||||
// Name:
|
||||
// Dimensions: 11 Fields by 1 Rows
|
||||
// +-------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
// | Name: Time | Name: v1 | Name: v1nn | Name: v2 | Name: v2nn | Name: x1 | Name: x1nn | Name: x2 | Name: x2nn | Name: x3 | Name: x3nn |
|
||||
// | Labels: | Labels: c1=one, c1nn=two, c2=three, c2nn=four, c3=five , c3nn=six | Labels: c1=one, c1nn=two, c2=three, c2nn=four, c3=five , c3nn=six | Labels: c1=one, c1nn=two, c2=three, c2nn=four, c3=five , c3nn=six | Labels: c1=one, c1nn=two, c2=three, c2nn=four, c3=five , c3nn=six | Labels: c1=one, c1nn=two, c2=three, c2nn=four, c3=five , c3nn=six | Labels: c1=one, c1nn=two, c2=three, c2nn=four, c3=five , c3nn=six | Labels: c1=one, c1nn=two, c2=three, c2nn=four, c3=five , c3nn=six | Labels: c1=one, c1nn=two, c2=three, c2nn=four, c3=five , c3nn=six | Labels: c1=one, c1nn=two, c2=three, c2nn=four, c3=five , c3nn=six | Labels: c1=one, c1nn=two, c2=three, c2nn=four, c3=five , c3nn=six |
|
||||
// | Type: []time.Time | Type: []*float64 | Type: []*float64 | Type: []*float64 | Type: []*float64 | Type: []*float64 | Type: []*float64 | Type: []*float64 | Type: []*float64 | Type: []*float64 | Type: []*float64 |
|
||||
// +-------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
// | 2023-12-21 11:30:03 +0000 UTC | 10.1 | 11.1 | 12.1 | 13.1 | 101 | 102 | 103 | 104 | 105 | 106 |
|
||||
// +-------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
//
|
||||
//
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
{
|
||||
"status": 200,
|
||||
"frames": [
|
||||
{
|
||||
"schema": {
|
||||
"meta": {
|
||||
"type": "timeseries-wide",
|
||||
"typeVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"executedQueryString": "SELECT * FROM tbl"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "Time",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v1",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c1": "one",
|
||||
"c1nn": "two",
|
||||
"c2": "three",
|
||||
"c2nn": "four",
|
||||
"c3": "five ",
|
||||
"c3nn": "six "
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v1nn",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c1": "one",
|
||||
"c1nn": "two",
|
||||
"c2": "three",
|
||||
"c2nn": "four",
|
||||
"c3": "five ",
|
||||
"c3nn": "six "
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v2",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c1": "one",
|
||||
"c1nn": "two",
|
||||
"c2": "three",
|
||||
"c2nn": "four",
|
||||
"c3": "five ",
|
||||
"c3nn": "six "
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v2nn",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c1": "one",
|
||||
"c1nn": "two",
|
||||
"c2": "three",
|
||||
"c2nn": "four",
|
||||
"c3": "five ",
|
||||
"c3nn": "six "
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x1",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c1": "one",
|
||||
"c1nn": "two",
|
||||
"c2": "three",
|
||||
"c2nn": "four",
|
||||
"c3": "five ",
|
||||
"c3nn": "six "
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x1nn",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c1": "one",
|
||||
"c1nn": "two",
|
||||
"c2": "three",
|
||||
"c2nn": "four",
|
||||
"c3": "five ",
|
||||
"c3nn": "six "
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x2",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c1": "one",
|
||||
"c1nn": "two",
|
||||
"c2": "three",
|
||||
"c2nn": "four",
|
||||
"c3": "five ",
|
||||
"c3nn": "six "
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x2nn",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c1": "one",
|
||||
"c1nn": "two",
|
||||
"c2": "three",
|
||||
"c2nn": "four",
|
||||
"c3": "five ",
|
||||
"c3nn": "six "
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x3",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c1": "one",
|
||||
"c1nn": "two",
|
||||
"c2": "three",
|
||||
"c2nn": "four",
|
||||
"c3": "five ",
|
||||
"c3nn": "six "
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x3nn",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c1": "one",
|
||||
"c1nn": "two",
|
||||
"c2": "three",
|
||||
"c2nn": "four",
|
||||
"c3": "five ",
|
||||
"c3nn": "six "
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"values": [
|
||||
[
|
||||
1703158203000
|
||||
],
|
||||
[
|
||||
10.1
|
||||
],
|
||||
[
|
||||
11.1
|
||||
],
|
||||
[
|
||||
12.1
|
||||
],
|
||||
[
|
||||
13.1
|
||||
],
|
||||
[
|
||||
101
|
||||
],
|
||||
[
|
||||
102
|
||||
],
|
||||
[
|
||||
103
|
||||
],
|
||||
[
|
||||
104
|
||||
],
|
||||
[
|
||||
105
|
||||
],
|
||||
[
|
||||
106
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
-- SELECT * FROM tbl
|
||||
-- in timeseries mode, most fields gets converted to float6
|
||||
CREATE TEMPORARY TABLE tbl (
|
||||
"time" timestamp with time zone,
|
||||
v1 double precision,
|
||||
v1nn double precision NOT NULL,
|
||||
v2 real,
|
||||
v2nn real NOT NULL,
|
||||
c1 text,
|
||||
c1nn text NOT NULL,
|
||||
c2 varchar(10),
|
||||
c2nn varchar(10) NOT NULL,
|
||||
c3 char(10),
|
||||
c3nn char(10) NOT NULL,
|
||||
x1 smallint,
|
||||
x1nn smallint NOT NULL,
|
||||
x2 integer,
|
||||
x2nn integer NOT NULL,
|
||||
x3 bigint,
|
||||
x3nn bigint NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO tbl ("time",
|
||||
v1, v1nn, v2, v2nn,
|
||||
c1, c1nn, c2, c2nn, c3, c3nn,
|
||||
x1, x1nn, x2, x2nn, x3, x3nn) VALUES
|
||||
('2023-12-21 11:30:03 UTC',
|
||||
10.1, 11.1, 12.1, 13.1,
|
||||
'one', 'two', 'three', 'four', 'five', 'six',
|
||||
101, 102, 103, 104, 105, 106);
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
//
|
||||
// Frame[0] {
|
||||
// "type": "timeseries-wide",
|
||||
// "typeVersion": [
|
||||
// 0,
|
||||
// 0
|
||||
// ],
|
||||
// "executedQueryString": "SELECT floor(extract(epoch from \"time\")/300)*300 AS \"time\",c,avg(v) AS \"v\" FROM tbl GROUP BY 1,2 ORDER BY 1,2"
|
||||
// }
|
||||
// Name:
|
||||
// Dimensions: 3 Fields by 7 Rows
|
||||
// +-------------------------------+------------------+------------------+
|
||||
// | Name: Time | Name: v | Name: v |
|
||||
// | Labels: | Labels: c=a | Labels: c=b |
|
||||
// | Type: []time.Time | Type: []*float64 | Type: []*float64 |
|
||||
// +-------------------------------+------------------+------------------+
|
||||
// | 2023-12-24 15:15:00 +0100 CET | null | null |
|
||||
// | 2023-12-24 15:20:00 +0100 CET | 15 | 115 |
|
||||
// | 2023-12-24 15:25:00 +0100 CET | null | null |
|
||||
// | 2023-12-24 15:30:00 +0100 CET | null | null |
|
||||
// | 2023-12-24 15:35:00 +0100 CET | 50 | 150 |
|
||||
// | 2023-12-24 15:40:00 +0100 CET | null | null |
|
||||
// | 2023-12-24 15:45:00 +0100 CET | null | null |
|
||||
// +-------------------------------+------------------+------------------+
|
||||
//
|
||||
//
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
{
|
||||
"status": 200,
|
||||
"frames": [
|
||||
{
|
||||
"schema": {
|
||||
"meta": {
|
||||
"type": "timeseries-wide",
|
||||
"typeVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"executedQueryString": "SELECT floor(extract(epoch from \"time\")/300)*300 AS \"time\",c,avg(v) AS \"v\" FROM tbl GROUP BY 1,2 ORDER BY 1,2"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "Time",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c": "a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c": "b"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"values": [
|
||||
[
|
||||
1703427300000,
|
||||
1703427600000,
|
||||
1703427900000,
|
||||
1703428200000,
|
||||
1703428500000,
|
||||
1703428800000,
|
||||
1703429100000
|
||||
],
|
||||
[
|
||||
null,
|
||||
15,
|
||||
null,
|
||||
null,
|
||||
50,
|
||||
null,
|
||||
null
|
||||
],
|
||||
[
|
||||
null,
|
||||
115,
|
||||
null,
|
||||
null,
|
||||
150,
|
||||
null,
|
||||
null
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
-- SELECT $__timeGroup("time",5m,NULL),c,avg(v) AS "v" FROM tbl GROUP BY 1,2 ORDER BY 1,2
|
||||
-- tests fill-mode=null
|
||||
CREATE TEMPORARY TABLE tbl (
|
||||
"time" timestamp with time zone,
|
||||
v double precision,
|
||||
c text
|
||||
);
|
||||
|
||||
INSERT INTO tbl ("time", v, c) VALUES
|
||||
('2023-12-24 14:21:03 UTC', 10, 'a'),
|
||||
('2023-12-24 14:21:03 UTC', 110, 'b'),
|
||||
('2023-12-24 14:23:03 UTC', 20, 'a'),
|
||||
('2023-12-24 14:23:03 UTC', 120, 'b'),
|
||||
('2023-12-24 14:39:03 UTC', 50, 'a'),
|
||||
('2023-12-24 14:39:03 UTC', 150, 'b');
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
//
|
||||
// Frame[0] {
|
||||
// "type": "timeseries-wide",
|
||||
// "typeVersion": [
|
||||
// 0,
|
||||
// 0
|
||||
// ],
|
||||
// "executedQueryString": "SELECT floor(extract(epoch from \"time\")/300)*300 AS \"time\",c,avg(v) AS \"v\" FROM tbl GROUP BY 1,2 ORDER BY 1,2"
|
||||
// }
|
||||
// Name:
|
||||
// Dimensions: 3 Fields by 7 Rows
|
||||
// +-------------------------------+------------------+------------------+
|
||||
// | Name: Time | Name: v | Name: v |
|
||||
// | Labels: | Labels: c=a | Labels: c=b |
|
||||
// | Type: []time.Time | Type: []*float64 | Type: []*float64 |
|
||||
// +-------------------------------+------------------+------------------+
|
||||
// | 2023-12-24 15:15:00 +0100 CET | null | null |
|
||||
// | 2023-12-24 15:20:00 +0100 CET | 15 | 115 |
|
||||
// | 2023-12-24 15:25:00 +0100 CET | 15 | 115 |
|
||||
// | 2023-12-24 15:30:00 +0100 CET | 15 | 115 |
|
||||
// | 2023-12-24 15:35:00 +0100 CET | 50 | 150 |
|
||||
// | 2023-12-24 15:40:00 +0100 CET | 50 | 150 |
|
||||
// | 2023-12-24 15:45:00 +0100 CET | 50 | 150 |
|
||||
// +-------------------------------+------------------+------------------+
|
||||
//
|
||||
//
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
{
|
||||
"status": 200,
|
||||
"frames": [
|
||||
{
|
||||
"schema": {
|
||||
"meta": {
|
||||
"type": "timeseries-wide",
|
||||
"typeVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"executedQueryString": "SELECT floor(extract(epoch from \"time\")/300)*300 AS \"time\",c,avg(v) AS \"v\" FROM tbl GROUP BY 1,2 ORDER BY 1,2"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "Time",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c": "a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c": "b"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"values": [
|
||||
[
|
||||
1703427300000,
|
||||
1703427600000,
|
||||
1703427900000,
|
||||
1703428200000,
|
||||
1703428500000,
|
||||
1703428800000,
|
||||
1703429100000
|
||||
],
|
||||
[
|
||||
null,
|
||||
15,
|
||||
15,
|
||||
15,
|
||||
50,
|
||||
50,
|
||||
50
|
||||
],
|
||||
[
|
||||
null,
|
||||
115,
|
||||
115,
|
||||
115,
|
||||
150,
|
||||
150,
|
||||
150
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
-- SELECT $__timeGroup("time",5m,previous),c,avg(v) AS "v" FROM tbl GROUP BY 1,2 ORDER BY 1,2
|
||||
-- tests fill-mode=previous
|
||||
CREATE TEMPORARY TABLE tbl (
|
||||
"time" timestamp with time zone,
|
||||
v double precision,
|
||||
c text
|
||||
);
|
||||
|
||||
INSERT INTO tbl ("time", v, c) VALUES
|
||||
('2023-12-24 14:21:03 UTC', 10, 'a'),
|
||||
('2023-12-24 14:21:03 UTC', 110, 'b'),
|
||||
('2023-12-24 14:23:03 UTC', 20, 'a'),
|
||||
('2023-12-24 14:23:03 UTC', 120, 'b'),
|
||||
('2023-12-24 14:39:03 UTC', 50, 'a'),
|
||||
('2023-12-24 14:39:03 UTC', 150, 'b');
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
//
|
||||
// Frame[0] {
|
||||
// "type": "timeseries-wide",
|
||||
// "typeVersion": [
|
||||
// 0,
|
||||
// 0
|
||||
// ],
|
||||
// "executedQueryString": "SELECT floor(extract(epoch from \"time\")/300)*300 AS \"time\",c,avg(v) AS \"v\" FROM tbl GROUP BY 1,2 ORDER BY 1,2"
|
||||
// }
|
||||
// Name:
|
||||
// Dimensions: 3 Fields by 7 Rows
|
||||
// +-------------------------------+------------------+------------------+
|
||||
// | Name: Time | Name: v | Name: v |
|
||||
// | Labels: | Labels: c=a | Labels: c=b |
|
||||
// | Type: []time.Time | Type: []*float64 | Type: []*float64 |
|
||||
// +-------------------------------+------------------+------------------+
|
||||
// | 2023-12-24 15:15:00 +0100 CET | 27 | 27 |
|
||||
// | 2023-12-24 15:20:00 +0100 CET | 15 | 115 |
|
||||
// | 2023-12-24 15:25:00 +0100 CET | 27 | 27 |
|
||||
// | 2023-12-24 15:30:00 +0100 CET | 27 | 27 |
|
||||
// | 2023-12-24 15:35:00 +0100 CET | 50 | 150 |
|
||||
// | 2023-12-24 15:40:00 +0100 CET | 27 | 27 |
|
||||
// | 2023-12-24 15:45:00 +0100 CET | 27 | 27 |
|
||||
// +-------------------------------+------------------+------------------+
|
||||
//
|
||||
//
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
{
|
||||
"status": 200,
|
||||
"frames": [
|
||||
{
|
||||
"schema": {
|
||||
"meta": {
|
||||
"type": "timeseries-wide",
|
||||
"typeVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"executedQueryString": "SELECT floor(extract(epoch from \"time\")/300)*300 AS \"time\",c,avg(v) AS \"v\" FROM tbl GROUP BY 1,2 ORDER BY 1,2"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "Time",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c": "a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c": "b"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"values": [
|
||||
[
|
||||
1703427300000,
|
||||
1703427600000,
|
||||
1703427900000,
|
||||
1703428200000,
|
||||
1703428500000,
|
||||
1703428800000,
|
||||
1703429100000
|
||||
],
|
||||
[
|
||||
27,
|
||||
15,
|
||||
27,
|
||||
27,
|
||||
50,
|
||||
27,
|
||||
27
|
||||
],
|
||||
[
|
||||
27,
|
||||
115,
|
||||
27,
|
||||
27,
|
||||
150,
|
||||
27,
|
||||
27
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
-- SELECT $__timeGroup("time",5m,27),c,avg(v) AS "v" FROM tbl GROUP BY 1,2 ORDER BY 1,2
|
||||
-- tests fill-mode=value
|
||||
CREATE TEMPORARY TABLE tbl (
|
||||
"time" timestamp with time zone,
|
||||
v double precision,
|
||||
c text
|
||||
);
|
||||
|
||||
INSERT INTO tbl ("time", v, c) VALUES
|
||||
('2023-12-24 14:21:03 UTC', 10, 'a'),
|
||||
('2023-12-24 14:21:03 UTC', 110, 'b'),
|
||||
('2023-12-24 14:23:03 UTC', 20, 'a'),
|
||||
('2023-12-24 14:23:03 UTC', 120, 'b'),
|
||||
('2023-12-24 14:39:03 UTC', 50, 'a'),
|
||||
('2023-12-24 14:39:03 UTC', 150, 'b');
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
//
|
||||
// Frame[0] {
|
||||
// "type": "timeseries-wide",
|
||||
// "typeVersion": [
|
||||
// 0,
|
||||
// 0
|
||||
// ],
|
||||
// "executedQueryString": "SELECT * FROM tbl"
|
||||
// }
|
||||
// Name:
|
||||
// Dimensions: 3 Fields by 5 Rows
|
||||
// +-------------------------------+------------------+------------------+
|
||||
// | Name: Time | Name: v | Name: v |
|
||||
// | Labels: | Labels: c=a | Labels: c=b |
|
||||
// | Type: []time.Time | Type: []*float64 | Type: []*float64 |
|
||||
// +-------------------------------+------------------+------------------+
|
||||
// | 2023-12-24 14:30:03 +0000 UTC | 10 | 110 |
|
||||
// | 2023-12-24 14:31:03 +0000 UTC | 20 | 120 |
|
||||
// | 2023-12-24 14:32:03 +0000 UTC | 30 | 130 |
|
||||
// | 2023-12-24 14:33:03 +0000 UTC | 40 | 140 |
|
||||
// | 2023-12-24 14:34:03 +0000 UTC | 50 | 150 |
|
||||
// +-------------------------------+------------------+------------------+
|
||||
//
|
||||
//
|
||||
// 🌟 This was machine generated. Do not edit. 🌟
|
||||
{
|
||||
"status": 200,
|
||||
"frames": [
|
||||
{
|
||||
"schema": {
|
||||
"meta": {
|
||||
"type": "timeseries-wide",
|
||||
"typeVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"executedQueryString": "SELECT * FROM tbl"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "Time",
|
||||
"type": "time",
|
||||
"typeInfo": {
|
||||
"frame": "time.Time"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c": "a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "number",
|
||||
"typeInfo": {
|
||||
"frame": "float64",
|
||||
"nullable": true
|
||||
},
|
||||
"labels": {
|
||||
"c": "b"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"values": [
|
||||
[
|
||||
1703428203000,
|
||||
1703428263000,
|
||||
1703428323000,
|
||||
1703428383000,
|
||||
1703428443000
|
||||
],
|
||||
[
|
||||
10,
|
||||
20,
|
||||
30,
|
||||
40,
|
||||
50
|
||||
],
|
||||
[
|
||||
110,
|
||||
120,
|
||||
130,
|
||||
140,
|
||||
150
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
-- SELECT * FROM tbl
|
||||
CREATE TEMPORARY TABLE tbl (
|
||||
"time" timestamp with time zone,
|
||||
v double precision,
|
||||
c text
|
||||
);
|
||||
|
||||
INSERT INTO tbl ("time", v, c) VALUES
|
||||
('2023-12-24 14:30:03 UTC', 10, 'a'),
|
||||
('2023-12-24 14:30:03 UTC', 110, 'b'),
|
||||
('2023-12-24 14:31:03 UTC', 20, 'a'),
|
||||
('2023-12-24 14:31:03 UTC', 120, 'b'),
|
||||
('2023-12-24 14:32:03 UTC', 30, 'a'),
|
||||
('2023-12-24 14:32:03 UTC', 130, 'b'),
|
||||
('2023-12-24 14:33:03 UTC', 40, 'a'),
|
||||
('2023-12-24 14:33:03 UTC', 140, 'b'),
|
||||
('2023-12-24 14:34:03 UTC', 50, 'a'),
|
||||
('2023-12-24 14:34:03 UTC', 150, 'b');
|
||||
@@ -10,9 +10,11 @@ import { logInfo, LogMessages } from './Analytics';
|
||||
import { GrafanaRulesExporter } from './components/export/GrafanaRulesExporter';
|
||||
import { AlertingAction, useAlertingAbility } from './hooks/useAbilities';
|
||||
|
||||
interface Props {}
|
||||
interface Props {
|
||||
enableExport?: boolean;
|
||||
}
|
||||
|
||||
export function MoreActionsRuleButtons({}: Props) {
|
||||
export function MoreActionsRuleButtons({ enableExport }: Props) {
|
||||
const [createRuleSupported, createRuleAllowed] = useAlertingAbility(AlertingAction.CreateAlertRule);
|
||||
const [createCloudRuleSupported, createCloudRuleAllowed] = useAlertingAbility(AlertingAction.CreateExternalAlertRule);
|
||||
const [exportRulesSupported, exportRulesAllowed] = useAlertingAbility(AlertingAction.ExportGrafanaManagedRules);
|
||||
@@ -40,7 +42,13 @@ export function MoreActionsRuleButtons({}: Props) {
|
||||
|
||||
if (canExportRules) {
|
||||
menuItems.push(
|
||||
<MenuItem label="Export all Grafana-managed rules" key="export-all-rules" onClick={toggleShowExportDrawer} />
|
||||
<MenuItem
|
||||
label="Export all Grafana-managed rules"
|
||||
key="export-all-rules"
|
||||
onClick={toggleShowExportDrawer}
|
||||
disabled={!enableExport}
|
||||
description={enableExport ? '' : 'No Grafana-managed rules found'}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import { useFilteredRules, useRulesFilter } from './hooks/useFilteredRules';
|
||||
import { useUnifiedAlertingSelector } from './hooks/useUnifiedAlertingSelector';
|
||||
import { fetchAllPromAndRulerRulesAction } from './state/actions';
|
||||
import { RULE_LIST_POLL_INTERVAL_MS } from './utils/constants';
|
||||
import { getAllRulesSourceNames } from './utils/datasource';
|
||||
import { getAllRulesSourceNames, GRAFANA_RULES_SOURCE_NAME } from './utils/datasource';
|
||||
|
||||
const VIEWS = {
|
||||
groups: RuleListGroupView,
|
||||
@@ -77,6 +77,9 @@ const RuleList = withErrorBoundary(
|
||||
return noRules && state.dispatched;
|
||||
});
|
||||
|
||||
const grafanaRules = useUnifiedAlertingSelector((state) => state.rulerRules[GRAFANA_RULES_SOURCE_NAME]?.result);
|
||||
const hasGrafanaRules = Object.keys(grafanaRules ?? {}).length > 0;
|
||||
|
||||
const limitAlerts = hasActiveFilters ? undefined : LIMIT_ALERTS;
|
||||
// Trigger data refresh only when the RULE_LIST_POLL_INTERVAL_MS elapsed since the previous load FINISHED
|
||||
const [_, fetchRules] = useAsyncFn(async () => {
|
||||
@@ -126,7 +129,7 @@ const RuleList = withErrorBoundary(
|
||||
<RuleStats namespaces={filteredNamespaces} />
|
||||
</div>
|
||||
<Stack direction="row" gap={0.5}>
|
||||
<MoreActionsRuleButtons />
|
||||
<MoreActionsRuleButtons enableExport={hasGrafanaRules} />
|
||||
</Stack>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
|
||||
import { PageLayoutType } from '@grafana/data';
|
||||
import { SceneComponentProps, SceneObjectBase } from '@grafana/scenes';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { getDashboardSceneFor } from '../utils/utils';
|
||||
|
||||
import { DashboardEditView, DashboardEditViewState, useDashboardEditPageNav } from './utils';
|
||||
|
||||
export interface VersionsEditViewState extends DashboardEditViewState {}
|
||||
|
||||
export class VersionsEditView extends SceneObjectBase<VersionsEditViewState> implements DashboardEditView {
|
||||
public static Component = VersionsEditorSettingsListView;
|
||||
|
||||
public getUrlKey(): string {
|
||||
return 'versions';
|
||||
}
|
||||
|
||||
public getDashboard(): DashboardScene {
|
||||
return getDashboardSceneFor(this);
|
||||
}
|
||||
}
|
||||
|
||||
function VersionsEditorSettingsListView({ model }: SceneComponentProps<VersionsEditView>) {
|
||||
const dashboard = model.getDashboard();
|
||||
|
||||
const { navModel, pageNav } = useDashboardEditPageNav(dashboard, model.getUrlKey());
|
||||
|
||||
return (
|
||||
<Page navModel={navModel} pageNav={pageNav} layout={PageLayoutType.Standard}>
|
||||
<div>TODO</div>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import { AnnotationsEditView } from './AnnotationsEditView';
|
||||
import { DashboardLinksEditView } from './DashboardLinksEditView';
|
||||
import { GeneralSettingsEditView } from './GeneralSettingsEditView';
|
||||
import { VariablesEditView } from './VariablesEditView';
|
||||
import { VersionsEditView } from './VersionsEditView';
|
||||
|
||||
export interface DashboardEditViewState extends SceneObjectState {}
|
||||
|
||||
@@ -54,6 +55,11 @@ export function useDashboardEditPageNav(dashboard: DashboardScene, currentEditVi
|
||||
url: locationUtil.getUrlForPartial(location, { editview: 'links', editIndex: null }),
|
||||
active: currentEditView === 'links',
|
||||
},
|
||||
{
|
||||
text: t('dashboard-settings.versions.title', 'Versions'),
|
||||
url: locationUtil.getUrlForPartial(location, { editview: 'versions', editIndex: null }),
|
||||
active: currentEditView === 'versions',
|
||||
},
|
||||
],
|
||||
parentItem: dashboardPageNav,
|
||||
};
|
||||
@@ -69,6 +75,8 @@ export function createDashboardEditViewFor(editview: string): DashboardEditView
|
||||
return new VariablesEditView({});
|
||||
case 'links':
|
||||
return new DashboardLinksEditView({});
|
||||
case 'versions':
|
||||
return new VersionsEditView({});
|
||||
case 'settings':
|
||||
default:
|
||||
return new GeneralSettingsEditView({});
|
||||
|
||||
@@ -251,7 +251,7 @@ export const DashNav = React.memo<Props>((props) => {
|
||||
};
|
||||
|
||||
const renderRightActions = () => {
|
||||
const { dashboard, onAddPanel, isFullscreen, kioskMode } = props;
|
||||
const { dashboard, onAddPanel, isFullscreen, kioskMode, hideTimePicker } = props;
|
||||
const { canSave, canEdit, showSettings, canShare } = dashboard.meta;
|
||||
const { snapshot } = dashboard;
|
||||
const snapshotUrl = snapshot && snapshot.originalUrl;
|
||||
@@ -335,7 +335,10 @@ export const DashNav = React.memo<Props>((props) => {
|
||||
buttons.push(<ShareButton key="button-share" dashboard={dashboard} />);
|
||||
}
|
||||
|
||||
buttons.push(<NavToolbarSeparator key="toolbar-separator" />);
|
||||
// if the timepicker is hidden, we don't need to add this separator
|
||||
if (!hideTimePicker) {
|
||||
buttons.push(<NavToolbarSeparator key="toolbar-separator" />);
|
||||
}
|
||||
|
||||
buttons.push(renderTimeControls());
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { css, CSSObject } from '@emotion/css';
|
||||
import { css } from '@emotion/css';
|
||||
import React from 'react';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
@@ -25,12 +25,11 @@ export function OptionsPaneItemOverrides({ overrides }: Props) {
|
||||
}
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => {
|
||||
const common: CSSObject = {
|
||||
const common = {
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: theme.shape.radius.circle,
|
||||
marginLeft: theme.spacing(1),
|
||||
position: 'relative',
|
||||
top: '-1px',
|
||||
};
|
||||
|
||||
@@ -40,10 +39,12 @@ const getStyles = (theme: GrafanaTheme2) => {
|
||||
}),
|
||||
rule: css({
|
||||
...common,
|
||||
position: 'relative',
|
||||
backgroundColor: theme.colors.primary.main,
|
||||
}),
|
||||
data: css({
|
||||
...common,
|
||||
position: 'relative',
|
||||
backgroundColor: theme.colors.warning.main,
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import userEvent from '@testing-library/user-event';
|
||||
import React, { ComponentProps } from 'react';
|
||||
|
||||
import { LogsSortOrder } from '@grafana/data';
|
||||
import { DataQuery } from '@grafana/schema';
|
||||
|
||||
import LogsNavigation from './LogsNavigation';
|
||||
|
||||
@@ -93,6 +94,42 @@ describe('LogsNavigation', () => {
|
||||
expect(onChangeTimeMock).toHaveBeenCalledWith({ from: 1637319338000, to: 1637322938000 });
|
||||
});
|
||||
|
||||
it('should correctly display the active page', async () => {
|
||||
const queries: DataQuery[] = [];
|
||||
const { rerender } = setup({
|
||||
absoluteRange: { from: 1704737384139, to: 1704737684139 },
|
||||
visibleRange: { from: 1704737384207, to: 1704737683316 },
|
||||
queries,
|
||||
logsSortOrder: LogsSortOrder.Descending,
|
||||
});
|
||||
|
||||
expect(await screen.findByTestId('page1')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('page1').firstChild).toHaveClass('selectedBg');
|
||||
|
||||
expect(screen.queryByTestId('page2')).not.toBeInTheDocument();
|
||||
|
||||
await userEvent.click(screen.getByTestId('olderLogsButton'));
|
||||
|
||||
rerender(
|
||||
<LogsNavigation
|
||||
{...defaultProps}
|
||||
absoluteRange={{ from: 1704737084207, to: 1704737384207 }}
|
||||
visibleRange={{ from: 1704737084627, to: 1704737383765 }}
|
||||
onChangeTime={jest.fn()}
|
||||
logsSortOrder={LogsSortOrder.Descending}
|
||||
queries={queries}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(await screen.findByTestId('page1')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('page1').firstChild).not.toHaveClass('selectedBg');
|
||||
|
||||
expect(await screen.findByTestId('page2')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('page2').firstChild).toHaveClass('selectedBg');
|
||||
|
||||
expect(screen.queryByTestId('page3')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should reset the scroll when pagination is clicked', async () => {
|
||||
const scrollToTopLogsMock = jest.fn();
|
||||
setup({ scrollToTopLogs: scrollToTopLogsMock });
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { isEqual } from 'lodash';
|
||||
import React, { memo, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { AbsoluteTimeRange, GrafanaTheme2, LogsSortOrder } from '@grafana/data';
|
||||
import { reportInteraction } from '@grafana/runtime';
|
||||
@@ -41,7 +41,6 @@ function LogsNavigation({
|
||||
addResultsToCache,
|
||||
}: Props) {
|
||||
const [pages, setPages] = useState<LogsPage[]>([]);
|
||||
const [currentPageIndex, setCurrentPageIndex] = useState(0);
|
||||
|
||||
// These refs are to determine, if we want to clear up logs navigation when totally new query is run
|
||||
const expectedQueriesRef = useRef<DataQuery[]>();
|
||||
@@ -50,6 +49,14 @@ function LogsNavigation({
|
||||
// e.g. if last 5 min selected, always run 5 min range
|
||||
const rangeSpanRef = useRef(0);
|
||||
|
||||
const currentPageIndex = useMemo(
|
||||
() =>
|
||||
pages.findIndex((page) => {
|
||||
return page.queryRange.to === absoluteRange.to;
|
||||
}),
|
||||
[absoluteRange.to, pages]
|
||||
);
|
||||
|
||||
const oldestLogsFirst = logsSortOrder === LogsSortOrder.Ascending;
|
||||
const onFirstPage = oldestLogsFirst ? currentPageIndex === pages.length - 1 : currentPageIndex === 0;
|
||||
const onLastPage = oldestLogsFirst ? currentPageIndex === 0 : currentPageIndex === pages.length - 1;
|
||||
@@ -64,7 +71,6 @@ function LogsNavigation({
|
||||
if (!isEqual(expectedRangeRef.current, absoluteRange) || !isEqual(expectedQueriesRef.current, queries)) {
|
||||
clearCache();
|
||||
setPages([newPage]);
|
||||
setCurrentPageIndex(0);
|
||||
expectedQueriesRef.current = queries;
|
||||
rangeSpanRef.current = absoluteRange.to - absoluteRange.from;
|
||||
} else {
|
||||
@@ -73,14 +79,8 @@ function LogsNavigation({
|
||||
newPages = pages.filter((page) => !isEqual(newPage.queryRange, page.queryRange));
|
||||
// Sort pages based on logsOrder so they visually align with displayed logs
|
||||
newPages = [...newPages, newPage].sort((a, b) => sortPages(a, b, logsSortOrder));
|
||||
// Set new pages
|
||||
|
||||
return newPages;
|
||||
});
|
||||
|
||||
// Set current page index
|
||||
const index = newPages.findIndex((page) => page.queryRange.to === absoluteRange.to);
|
||||
setCurrentPageIndex(index);
|
||||
}
|
||||
addResultsToCache();
|
||||
}, [visibleRange, absoluteRange, logsSortOrder, queries, clearCache, addResultsToCache]);
|
||||
|
||||
@@ -292,6 +292,117 @@ describe('LogRowContextModal', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should highlight the same `foo123` searchwords', async () => {
|
||||
const dfBeforeNs = createDataFrame({
|
||||
fields: [
|
||||
{
|
||||
name: 'time',
|
||||
type: FieldType.time,
|
||||
values: [1, 1],
|
||||
},
|
||||
{
|
||||
name: 'message',
|
||||
type: FieldType.string,
|
||||
values: ['this contains foo123', 'this contains foo123'],
|
||||
},
|
||||
{
|
||||
name: 'tsNs',
|
||||
type: FieldType.string,
|
||||
values: ['1', '2'],
|
||||
},
|
||||
],
|
||||
});
|
||||
const dfNowNs = createDataFrame({
|
||||
fields: [
|
||||
{
|
||||
name: 'time',
|
||||
type: FieldType.time,
|
||||
values: [1],
|
||||
},
|
||||
{
|
||||
name: 'message',
|
||||
type: FieldType.string,
|
||||
values: ['this contains foo123'],
|
||||
},
|
||||
{
|
||||
name: 'tsNs',
|
||||
type: FieldType.string,
|
||||
values: ['2'],
|
||||
},
|
||||
],
|
||||
});
|
||||
const dfAfterNs = createDataFrame({
|
||||
fields: [
|
||||
{
|
||||
name: 'time',
|
||||
type: FieldType.time,
|
||||
values: [1, 1],
|
||||
},
|
||||
{
|
||||
name: 'message',
|
||||
type: FieldType.string,
|
||||
values: ['this contains foo123', 'this contains foo123'],
|
||||
},
|
||||
{
|
||||
name: 'tsNs',
|
||||
type: FieldType.string,
|
||||
values: ['2', '3'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let uniqueRefIdCounter = 1;
|
||||
const logs = dataFrameToLogsModel([dfNowNs]);
|
||||
const row = logs.rows[0];
|
||||
row.searchWords = ['foo123'];
|
||||
const getRowContext = jest.fn().mockImplementation(async (_, options) => {
|
||||
uniqueRefIdCounter += 1;
|
||||
const refId = `refid_${uniqueRefIdCounter}`;
|
||||
if (uniqueRefIdCounter === 2) {
|
||||
return {
|
||||
data: [
|
||||
{
|
||||
refId,
|
||||
...dfBeforeNs,
|
||||
},
|
||||
],
|
||||
};
|
||||
} else if (uniqueRefIdCounter === 3) {
|
||||
return {
|
||||
data: [
|
||||
{
|
||||
refId,
|
||||
...dfAfterNs,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
return { data: [] };
|
||||
});
|
||||
|
||||
render(
|
||||
<LogRowContextModal
|
||||
row={row}
|
||||
open={true}
|
||||
onClose={() => {}}
|
||||
getRowContext={getRowContext}
|
||||
timeZone={timeZone}
|
||||
logsSortOrder={LogsSortOrder.Descending}
|
||||
/>
|
||||
);
|
||||
|
||||
// there need to be 3 lines with that message, all `foo123` should be highlighted
|
||||
await waitFor(() => {
|
||||
expect(screen.getAllByText('foo123').length).toBe(3);
|
||||
for (const el of screen.getAllByText('foo123')) {
|
||||
// highlights are done in `<mark>` tags
|
||||
expect(el.tagName).toBe('MARK');
|
||||
}
|
||||
// test that the rest is not in a MARK
|
||||
expect(screen.getAllByText('this contains')[0].tagName).not.toBe('MARK');
|
||||
});
|
||||
});
|
||||
|
||||
it('should show a split view button', async () => {
|
||||
const getRowContextQuery = jest.fn().mockResolvedValue({ datasource: { uid: 'test-uid' } });
|
||||
|
||||
|
||||
@@ -363,7 +363,10 @@ export const LogRowContextModal: React.FunctionComponent<LogRowContextModalProps
|
||||
// this way this array of rows will never be empty
|
||||
const allRows = [...above.rows, row, ...below.rows];
|
||||
|
||||
const newRows = await loadMore(place, allRows);
|
||||
const newRows = (await loadMore(place, allRows)).map((r) =>
|
||||
// apply the original row's searchWords to all the rows for highlighting
|
||||
!r.searchWords || !r.searchWords?.length ? { ...r, searchWords: row.searchWords } : r
|
||||
);
|
||||
const [older, newer] = partition(newRows, (newRow) => newRow.timeEpochNs > row.timeEpochNs);
|
||||
const newAbove = logsSortOrder === LogsSortOrder.Ascending ? newer : older;
|
||||
const newBelow = logsSortOrder === LogsSortOrder.Ascending ? older : newer;
|
||||
|
||||
@@ -69,7 +69,7 @@ export class TemplateSrv implements BaseTemplateSrv {
|
||||
*
|
||||
* Use getVariables function instead
|
||||
*/
|
||||
get variables(): any[] {
|
||||
get variables(): TypedVariableModel[] {
|
||||
deprecationWarning('template_srv.ts', 'variables', 'getVariables');
|
||||
return this.getVariables();
|
||||
}
|
||||
@@ -84,7 +84,7 @@ export class TemplateSrv implements BaseTemplateSrv {
|
||||
}
|
||||
|
||||
updateIndex() {
|
||||
const existsOrEmpty = (value: any) => value || value === '';
|
||||
const existsOrEmpty = (value: unknown) => value || value === '';
|
||||
|
||||
this.index = this._variables.reduce((acc, currentValue) => {
|
||||
if (currentValue.current && (currentValue.current.isNone || existsOrEmpty(currentValue.current.value))) {
|
||||
@@ -360,7 +360,7 @@ export class TemplateSrv implements BaseTemplateSrv {
|
||||
});
|
||||
}
|
||||
|
||||
isAllValue(value: any) {
|
||||
isAllValue(value: unknown) {
|
||||
return value === ALL_VARIABLE_VALUE || (Array.isArray(value) && value[0] === ALL_VARIABLE_VALUE);
|
||||
}
|
||||
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
import { css } from '@emotion/css';
|
||||
import React from 'react';
|
||||
import { useToggle } from 'react-use';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { Collapse, useStyles2, Stack } from '@grafana/ui';
|
||||
|
||||
export interface Props {
|
||||
title: string;
|
||||
collapsedInfo: string[];
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function QueryOptionGroup({ title, children, collapsedInfo }: Props) {
|
||||
const [isOpen, toggleOpen] = useToggle(false);
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<Collapse
|
||||
className={styles.collapse}
|
||||
collapsible
|
||||
isOpen={isOpen}
|
||||
onToggle={toggleOpen}
|
||||
label={
|
||||
<Stack gap={0}>
|
||||
<h6 className={styles.title}>{title}</h6>
|
||||
{!isOpen && (
|
||||
<div className={styles.description}>
|
||||
{collapsedInfo.map((x, i) => (
|
||||
<span key={i}>{x}</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Stack>
|
||||
}
|
||||
>
|
||||
<div className={styles.body}>{children}</div>
|
||||
</Collapse>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
collapse: css({
|
||||
backgroundColor: 'unset',
|
||||
border: 'unset',
|
||||
marginBottom: 0,
|
||||
|
||||
['> button']: {
|
||||
padding: theme.spacing(0, 1),
|
||||
},
|
||||
}),
|
||||
wrapper: css({
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'baseline',
|
||||
}),
|
||||
title: css({
|
||||
flexGrow: 1,
|
||||
overflow: 'hidden',
|
||||
fontSize: theme.typography.bodySmall.fontSize,
|
||||
fontWeight: theme.typography.fontWeightMedium,
|
||||
margin: 0,
|
||||
}),
|
||||
description: css({
|
||||
color: theme.colors.text.secondary,
|
||||
fontSize: theme.typography.bodySmall.fontSize,
|
||||
fontWeight: theme.typography.bodySmall.fontWeight,
|
||||
paddingLeft: theme.spacing(2),
|
||||
gap: theme.spacing(2),
|
||||
display: 'flex',
|
||||
}),
|
||||
body: css({
|
||||
display: 'flex',
|
||||
gap: theme.spacing(2),
|
||||
flexWrap: 'wrap',
|
||||
}),
|
||||
};
|
||||
};
|
||||
+1
-1
@@ -5,10 +5,10 @@ import { CoreApp, GrafanaTheme2, SelectableValue } from '@grafana/data';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { useStyles2, RadioButtonGroup, MultiSelect, Input } from '@grafana/ui';
|
||||
|
||||
import { QueryOptionGroup } from '../../prometheus/querybuilder/shared/QueryOptionGroup';
|
||||
import { Query } from '../types';
|
||||
|
||||
import { EditorField } from './EditorField';
|
||||
import { QueryOptionGroup } from './QueryOptionGroup';
|
||||
import { Stack } from './Stack';
|
||||
|
||||
export interface Props {
|
||||
|
||||
@@ -2,8 +2,6 @@ import { from, map, Observable, of } from 'rxjs';
|
||||
|
||||
import { CustomVariableSupport, DataQueryRequest, DataQueryResponse, MetricFindValue } from '@grafana/data';
|
||||
|
||||
import { getTimeSrv, TimeSrv } from '../../../features/dashboard/services/TimeSrv';
|
||||
|
||||
import { VariableQueryEditor } from './VariableQueryEditor';
|
||||
import { PyroscopeDataSource } from './datasource';
|
||||
import { ProfileTypeMessage, VariableQuery } from './types';
|
||||
@@ -15,10 +13,7 @@ export interface DataAPI {
|
||||
}
|
||||
|
||||
export class VariableSupport extends CustomVariableSupport<PyroscopeDataSource> {
|
||||
constructor(
|
||||
private readonly dataAPI: DataAPI,
|
||||
private readonly timeSrv: TimeSrv = getTimeSrv()
|
||||
) {
|
||||
constructor(private readonly dataAPI: DataAPI) {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -26,9 +21,7 @@ export class VariableSupport extends CustomVariableSupport<PyroscopeDataSource>
|
||||
|
||||
query(request: DataQueryRequest<VariableQuery>): Observable<DataQueryResponse> {
|
||||
if (request.targets[0].type === 'profileType') {
|
||||
return from(
|
||||
this.dataAPI.getProfileTypes(this.timeSrv.timeRange().from.valueOf(), this.timeSrv.timeRange().to.valueOf())
|
||||
).pipe(
|
||||
return from(this.dataAPI.getProfileTypes(request.range.from.valueOf(), request.range.to.valueOf())).pipe(
|
||||
map((values) => {
|
||||
return { data: values.map<MetricFindValue>((v) => ({ text: v.label, value: v.id })) };
|
||||
})
|
||||
@@ -42,8 +35,8 @@ export class VariableSupport extends CustomVariableSupport<PyroscopeDataSource>
|
||||
return from(
|
||||
this.dataAPI.getLabelNames(
|
||||
request.targets[0].profileTypeId + '{}',
|
||||
this.timeSrv.timeRange().from.valueOf(),
|
||||
this.timeSrv.timeRange().to.valueOf()
|
||||
request.range.from.valueOf(),
|
||||
request.range.to.valueOf()
|
||||
)
|
||||
).pipe(
|
||||
map((values) => {
|
||||
@@ -60,8 +53,8 @@ export class VariableSupport extends CustomVariableSupport<PyroscopeDataSource>
|
||||
this.dataAPI.getLabelValues(
|
||||
request.targets[0].profileTypeId + '{}',
|
||||
request.targets[0].labelName,
|
||||
this.timeSrv.timeRange().from.valueOf(),
|
||||
this.timeSrv.timeRange().to.valueOf()
|
||||
request.range.from.valueOf(),
|
||||
request.range.to.valueOf()
|
||||
)
|
||||
).pipe(
|
||||
map((values) => {
|
||||
|
||||
@@ -409,12 +409,12 @@ function setup(value: string, offset: number, tagsV1?: string[], tagsV2?: Scope[
|
||||
EnumMember: 2,
|
||||
},
|
||||
},
|
||||
} as any;
|
||||
} as unknown as typeof monacoTypes;
|
||||
provider.editor = {
|
||||
getModel() {
|
||||
return model;
|
||||
},
|
||||
} as any;
|
||||
} as unknown as monacoTypes.editor.IStandaloneCodeEditor;
|
||||
|
||||
return { provider, model } as unknown as { provider: CompletionProvider; model: monacoTypes.editor.ITextModel };
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ type OptionsState = {
|
||||
// Exported for tests
|
||||
export function useLoadOptions(datasource: ZipkinDatasource) {
|
||||
const isMounted = useMountedState();
|
||||
const [allOptions, setAllOptions] = useState({} as OptionsState);
|
||||
const [allOptions, setAllOptions] = useState<OptionsState>({});
|
||||
|
||||
const [, fetchSpans] = useAsyncFn(
|
||||
async function findSpans(service: string): Promise<void> {
|
||||
|
||||
@@ -61,7 +61,7 @@ export class ZipkinDatasource extends DataSourceApi<ZipkinQuery, ZipkinJsonData>
|
||||
return of(emptyDataQueryResponse);
|
||||
}
|
||||
|
||||
async metadataRequest(url: string, params?: Record<string, any>): Promise<any> {
|
||||
async metadataRequest(url: string, params?: Record<string, unknown>) {
|
||||
const res = await lastValueFrom(this.request(url, params, { hideFromInspector: true }));
|
||||
return res.data;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ export class ZipkinDatasource extends DataSourceApi<ZipkinQuery, ZipkinJsonData>
|
||||
|
||||
private request<T = any>(
|
||||
apiUrl: string,
|
||||
data?: any,
|
||||
data?: unknown,
|
||||
options?: Partial<BackendSrvRequest>
|
||||
): Observable<FetchResponse<T>> {
|
||||
const params = data ? urlUtil.serializeParams(data) : '';
|
||||
|
||||
@@ -16,7 +16,7 @@ export const alertListPanelMigrationHandler = (
|
||||
tags: panel.options.tags ?? panel.dashboardTags ?? [],
|
||||
stateFilter:
|
||||
panel.options.stateFilter ??
|
||||
panel.stateFilter?.reduce((filterObj: any, curFilter: any) => ({ ...filterObj, [curFilter]: true }), {}) ??
|
||||
panel.stateFilter?.reduce((filterObj: object, curFilter: any) => ({ ...filterObj, [curFilter]: true }), {}) ??
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ const defaultOptions: Options = {
|
||||
tags: ['tag A', 'tag B'],
|
||||
};
|
||||
|
||||
const defaultResult: any = {
|
||||
const defaultResult = {
|
||||
text: 'Result text',
|
||||
userId: 1,
|
||||
login: 'Result login',
|
||||
@@ -40,7 +40,7 @@ const defaultResult: any = {
|
||||
time: Date.UTC(2021, 0, 1, 0, 0, 0, 0),
|
||||
panelId: 13,
|
||||
dashboardId: 14, // deliberately different from panelId
|
||||
id: 14,
|
||||
id: '14',
|
||||
uid: '7MeksYbmk',
|
||||
dashboardUID: '7MeksYbmk',
|
||||
url: '/d/asdkjhajksd/some-dash',
|
||||
@@ -55,7 +55,7 @@ async function setupTestContext({
|
||||
const getMock = jest.spyOn(backendSrv, 'get');
|
||||
getMock.mockResolvedValue(results);
|
||||
|
||||
const dash: any = { uid: 'srx16xR4z', formatDate: (time: number) => new Date(time).toISOString() };
|
||||
const dash = { uid: 'srx16xR4z', formatDate: (time: number) => new Date(time).toISOString() };
|
||||
const dashSrv: any = { getCurrent: () => dash };
|
||||
setDashboardSrv(dashSrv);
|
||||
const pushSpy = jest.spyOn(locationService, 'push');
|
||||
|
||||
@@ -90,7 +90,11 @@ export class AnnoListPanel extends PureComponent<Props, State> {
|
||||
const { options } = this.props;
|
||||
const { queryUser, queryTags } = this.state;
|
||||
|
||||
const params: any = {
|
||||
const params: {
|
||||
tags: typeof options.tags;
|
||||
limit: typeof options.limit;
|
||||
type: string;
|
||||
} & Record<string, unknown> = {
|
||||
tags: options.tags,
|
||||
limit: options.limit,
|
||||
type: 'annotation', // Skip the Annotations that are really alerts. (Use the alerts panel!)
|
||||
@@ -139,15 +143,12 @@ export class AnnoListPanel extends PureComponent<Props, State> {
|
||||
const dashboardSrv = getDashboardSrv();
|
||||
const current = dashboardSrv.getCurrent();
|
||||
|
||||
const params: any = {
|
||||
const params = {
|
||||
from: this._timeOffset(anno.time, options.navigateBefore, true),
|
||||
to: this._timeOffset(anno.timeEnd ?? anno.time, options.navigateAfter, false),
|
||||
viewPanel: options.navigateToPanel ? anno.panelId : undefined,
|
||||
};
|
||||
|
||||
if (options.navigateToPanel) {
|
||||
params.viewPanel = anno.panelId;
|
||||
}
|
||||
|
||||
if (current?.uid === anno.dashboardUID) {
|
||||
locationService.partial(params);
|
||||
return;
|
||||
@@ -157,8 +158,8 @@ export class AnnoListPanel extends PureComponent<Props, State> {
|
||||
if (result && result.length && result[0].uid === anno.dashboardUID) {
|
||||
const dash = result[0];
|
||||
const url = new URL(dash.url, window.location.origin);
|
||||
url.searchParams.set('from', params.from);
|
||||
url.searchParams.set('to', params.to);
|
||||
url.searchParams.set('from', String(params.from));
|
||||
url.searchParams.set('to', String(params.to));
|
||||
locationService.push(locationUtil.stripBaseFromUrl(url.toString()));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -95,9 +95,9 @@ export const plugin = new PanelPlugin<Options>(AnnoListPanel)
|
||||
});
|
||||
})
|
||||
// TODO, we should support this directly in the plugin infrastructure
|
||||
.setPanelChangeHandler((panel: PanelModel<Options>, prevPluginId: string, prevOptions: unknown) => {
|
||||
.setPanelChangeHandler((panel: PanelModel<Options>, prevPluginId, prevOptions) => {
|
||||
if (prevPluginId === 'ryantxu-annolist-panel') {
|
||||
return prevOptions as Options;
|
||||
return prevOptions;
|
||||
}
|
||||
|
||||
return panel.options;
|
||||
|
||||
@@ -19,7 +19,7 @@ describe('dashlist migrations', () => {
|
||||
const basePanelModel = wellFormedPanelModel({});
|
||||
basePanelModel.pluginVersion = '5.1';
|
||||
|
||||
const angularPanel: PanelModel<any> & AngularModel = {
|
||||
const angularPanel: PanelModel & AngularModel = {
|
||||
...basePanelModel,
|
||||
// pluginVersion: '5.1',
|
||||
starred: true,
|
||||
|
||||
@@ -52,7 +52,7 @@ export class EventBusLoggerPanel extends PureComponent<Props, State> {
|
||||
|
||||
eventObserver: PartialObserver<BusEvent> = {
|
||||
next: (event: BusEvent) => {
|
||||
const origin = event.origin as any;
|
||||
const origin: any = event.origin;
|
||||
this.history.add({
|
||||
key: counter++,
|
||||
type: event.type,
|
||||
|
||||
@@ -154,6 +154,6 @@ export async function initLayer(
|
||||
return state;
|
||||
}
|
||||
|
||||
export const getMapLayerState = (l: any) => {
|
||||
return l?.__state as MapLayerState;
|
||||
export const getMapLayerState = (l: any): MapLayerState => {
|
||||
return l?.__state;
|
||||
};
|
||||
|
||||
@@ -62,7 +62,7 @@ export const pointerMoveListener = (evt: MapBrowserEvent<MouseEvent>, panel: Geo
|
||||
panel.map.forEachFeatureAtPixel(
|
||||
pixel,
|
||||
(feature, layer, geo) => {
|
||||
const s: MapLayerState = getMapLayerState(layer);
|
||||
const s = getMapLayerState(layer);
|
||||
//match hover layer to layer in layers
|
||||
//check if the layer show tooltip is enabled
|
||||
//then also pass the list of tooltip fields if exists
|
||||
|
||||
@@ -287,7 +287,9 @@ export class Histogram extends React.Component<HistogramProps, State> {
|
||||
}
|
||||
|
||||
prepState(props: HistogramProps, withConfig = true) {
|
||||
let state: State = null as any;
|
||||
let state: State = {
|
||||
alignedData: [],
|
||||
};
|
||||
|
||||
const { alignedFrame } = props;
|
||||
if (alignedFrame) {
|
||||
|
||||
@@ -184,10 +184,10 @@ function inBounds(value: number, min: number | undefined, max: number | undefine
|
||||
}
|
||||
|
||||
// The issue here is that TouchEvent is undefined while using instanceof in Firefox and Safari
|
||||
// which will throw an exception but if it's (event as TouchEvent).changedTouches it will be undefined
|
||||
// which will throw an exception but if it's event.changedTouches it will be undefined
|
||||
// and the if check will fail so it will go to the else but will not throw an exception
|
||||
function getEventXY(event: Event): { x: number; y: number } {
|
||||
if ((event as TouchEvent).changedTouches && event instanceof TouchEvent) {
|
||||
if ('changedTouches' in event && event instanceof TouchEvent) {
|
||||
return { x: event.changedTouches[0].clientX, y: event.changedTouches[0].clientY };
|
||||
} else if (event instanceof MouseEvent) {
|
||||
return { x: event.clientX, y: event.clientY };
|
||||
|
||||
@@ -275,6 +275,7 @@ function makeNodeDatum(options: Partial<NodeDatum> = {}) {
|
||||
config: {
|
||||
color: {
|
||||
fixedColor: 'green',
|
||||
mode: 'fixed',
|
||||
},
|
||||
},
|
||||
name: 'arc__success',
|
||||
@@ -285,6 +286,7 @@ function makeNodeDatum(options: Partial<NodeDatum> = {}) {
|
||||
config: {
|
||||
color: {
|
||||
fixedColor: 'red',
|
||||
mode: 'fixed',
|
||||
},
|
||||
},
|
||||
name: 'arc__errors',
|
||||
|
||||
@@ -370,7 +370,7 @@ function makeNode(index: number) {
|
||||
}
|
||||
|
||||
function nodesFrame() {
|
||||
const fields: any = {
|
||||
const fields = {
|
||||
[NodeGraphDataFrameFieldNames.id]: {
|
||||
values: [],
|
||||
type: FieldType.string,
|
||||
@@ -394,17 +394,17 @@ function nodesFrame() {
|
||||
[NodeGraphDataFrameFieldNames.arc + 'success']: {
|
||||
values: [],
|
||||
type: FieldType.number,
|
||||
config: { color: { fixedColor: 'green' } },
|
||||
config: { color: { mode: FieldColorModeId.Fixed, fixedColor: 'green' } },
|
||||
},
|
||||
[NodeGraphDataFrameFieldNames.arc + 'errors']: {
|
||||
values: [],
|
||||
type: FieldType.number,
|
||||
config: { color: { fixedColor: 'red' } },
|
||||
config: { color: { mode: FieldColorModeId.Fixed, fixedColor: 'red' } },
|
||||
},
|
||||
[NodeGraphDataFrameFieldNames.color]: {
|
||||
values: [],
|
||||
type: FieldType.number,
|
||||
config: { color: { mode: 'continuous-GrYlRd' } },
|
||||
config: { color: { mode: FieldColorModeId.ContinuousGrYlRd } },
|
||||
},
|
||||
[NodeGraphDataFrameFieldNames.icon]: {
|
||||
values: [],
|
||||
@@ -418,8 +418,8 @@ function nodesFrame() {
|
||||
|
||||
return new MutableDataFrame({
|
||||
name: 'nodes',
|
||||
fields: Object.keys(fields).map((key) => ({
|
||||
...fields[key],
|
||||
fields: Object.entries(fields).map(([key, value]) => ({
|
||||
...value,
|
||||
name: key,
|
||||
})),
|
||||
});
|
||||
@@ -440,7 +440,7 @@ export function makeEdgesDataFrame(
|
||||
}
|
||||
|
||||
function edgesFrame() {
|
||||
const fields: any = {
|
||||
const fields = {
|
||||
[NodeGraphDataFrameFieldNames.id]: {
|
||||
values: [],
|
||||
type: FieldType.string,
|
||||
@@ -465,8 +465,8 @@ function edgesFrame() {
|
||||
|
||||
return new MutableDataFrame({
|
||||
name: 'edges',
|
||||
fields: Object.keys(fields).map((key) => ({
|
||||
...fields[key],
|
||||
fields: Object.entries(fields).map(([key, value]) => ({
|
||||
...value,
|
||||
name: key,
|
||||
})),
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Options } from './panelcfg.gen';
|
||||
|
||||
// This is called when the panel changes from another panel
|
||||
export const statPanelChangedHandler = (
|
||||
panel: PanelModel<Partial<Options>> | any,
|
||||
panel: PanelModel<Partial<Options>>,
|
||||
prevPluginId: string,
|
||||
prevOptions: any
|
||||
) => {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { IScope, IAngularStatic } from 'angular';
|
||||
import $ from 'jquery';
|
||||
import { defaults } from 'lodash';
|
||||
|
||||
import { isTableData, PanelEvents, PanelPlugin } from '@grafana/data';
|
||||
import { AnnotationsSrv } from 'app/angular/services/annotations_srv';
|
||||
import config from 'app/core/config';
|
||||
import { applyFilterFromTable } from 'app/features/variables/adhoc/actions';
|
||||
import { MetricsPanelCtrl } from 'app/plugins/sdk';
|
||||
@@ -56,9 +58,9 @@ export class TablePanelCtrl extends MetricsPanelCtrl {
|
||||
static $inject = ['$scope', '$injector', 'annotationsSrv', '$sanitize'];
|
||||
|
||||
constructor(
|
||||
$scope: any,
|
||||
$injector: any,
|
||||
private annotationsSrv: any,
|
||||
$scope: IScope,
|
||||
$injector: IAngularStatic['injector'],
|
||||
private annotationsSrv: AnnotationsSrv,
|
||||
private $sanitize: any
|
||||
) {
|
||||
super($scope, $injector);
|
||||
@@ -101,12 +103,11 @@ export class TablePanelCtrl extends MetricsPanelCtrl {
|
||||
panel: this.panel,
|
||||
range: this.range,
|
||||
})
|
||||
.then((anno: any) => {
|
||||
.then((anno) => {
|
||||
this.loading = false;
|
||||
this.dataRaw = anno;
|
||||
this.pageIndex = 0;
|
||||
this.render();
|
||||
return { data: this.dataRaw }; // Not used
|
||||
});
|
||||
}
|
||||
|
||||
@@ -170,7 +171,7 @@ export class TablePanelCtrl extends MetricsPanelCtrl {
|
||||
this.render();
|
||||
}
|
||||
|
||||
link(scope: any, elem: JQuery, attrs: any, ctrl: TablePanelCtrl) {
|
||||
link(scope: IScope, elem: JQuery, attrs: any, ctrl: TablePanelCtrl) {
|
||||
let data: any;
|
||||
const panel = ctrl.panel;
|
||||
let pageCount = 0;
|
||||
@@ -191,7 +192,7 @@ export class TablePanelCtrl extends MetricsPanelCtrl {
|
||||
tbodyElem.html(ctrl.renderer.render(ctrl.pageIndex));
|
||||
}
|
||||
|
||||
function switchPage(e: any) {
|
||||
function switchPage(e: JQueryEventObject) {
|
||||
const el = $(e.currentTarget);
|
||||
ctrl.pageIndex = parseInt(el.text(), 10) - 1;
|
||||
renderPanel();
|
||||
@@ -263,7 +264,7 @@ export class TablePanelCtrl extends MetricsPanelCtrl {
|
||||
unbindDestroy();
|
||||
});
|
||||
|
||||
ctrl.events.on(PanelEvents.render, (renderData: any) => {
|
||||
ctrl.events.on(PanelEvents.render, (renderData: unknown) => {
|
||||
data = renderData || data;
|
||||
if (data) {
|
||||
renderPanel();
|
||||
|
||||
@@ -399,7 +399,7 @@ export function graphToTimeseriesOptions(angular: any): {
|
||||
|
||||
// timeRegions migration
|
||||
if (angular.timeRegions?.length) {
|
||||
let regions: any[] = angular.timeRegions.map((old: GraphTimeRegionConfig, idx: number) => ({
|
||||
let regions = angular.timeRegions.map((old: GraphTimeRegionConfig, idx: number) => ({
|
||||
name: `T${idx + 1}`,
|
||||
color: old.colorMode !== 'custom' ? old.colorMode : old.fillColor,
|
||||
line: old.line,
|
||||
@@ -684,7 +684,7 @@ function validNumber(val: unknown): number | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getReducersFromLegend(obj: Record<string, any>): string[] {
|
||||
function getReducersFromLegend(obj: Record<string, unknown>): string[] {
|
||||
const ids: string[] = [];
|
||||
for (const key of Object.keys(obj)) {
|
||||
const r = fieldReducers.getIfExists(key);
|
||||
|
||||
@@ -45,7 +45,7 @@ export const AutoEditor = ({ value, onChange, context }: StandardEditorProps<XYD
|
||||
};
|
||||
const frame = context.data ? context.data[value?.frame ?? 0] : undefined;
|
||||
if (frame) {
|
||||
const xName = dims.x ? getFieldDisplayName(dims.x, dims.frame, context.data) : undefined;
|
||||
const xName = 'x' in dims ? getFieldDisplayName(dims.x, dims.frame, context.data) : undefined;
|
||||
for (let field of frame.fields) {
|
||||
if (isGraphable(field)) {
|
||||
const name = getFieldDisplayName(field, frame, context.data);
|
||||
|
||||
@@ -15,18 +15,21 @@ export interface XYDimensions {
|
||||
frame: DataFrame; // matches order from configs, excluds non-graphable values
|
||||
x: Field;
|
||||
fields: XYFieldMatchers;
|
||||
error?: DimensionError;
|
||||
hasData?: boolean;
|
||||
hasTime?: boolean;
|
||||
}
|
||||
|
||||
export interface XYDimensionsError {
|
||||
error: DimensionError;
|
||||
}
|
||||
|
||||
export function isGraphable(field: Field) {
|
||||
return field.type === FieldType.number;
|
||||
}
|
||||
|
||||
export function getXYDimensions(cfg?: XYDimensionConfig, data?: DataFrame[]): XYDimensions {
|
||||
export function getXYDimensions(cfg?: XYDimensionConfig, data?: DataFrame[]): XYDimensions | XYDimensionsError {
|
||||
if (!data || !data.length) {
|
||||
return { error: DimensionError.NoData } as XYDimensions;
|
||||
return { error: DimensionError.NoData };
|
||||
}
|
||||
if (!cfg) {
|
||||
cfg = {
|
||||
@@ -36,7 +39,7 @@ export function getXYDimensions(cfg?: XYDimensionConfig, data?: DataFrame[]): XY
|
||||
|
||||
let frame = data[cfg.frame ?? 0];
|
||||
if (!frame) {
|
||||
return { error: DimensionError.BadFrameSelection } as XYDimensions;
|
||||
return { error: DimensionError.BadFrameSelection };
|
||||
}
|
||||
|
||||
let xIndex = -1;
|
||||
@@ -99,5 +102,5 @@ function getSimpleFieldNotMatcher(f: Field): FieldMatcher {
|
||||
return () => false;
|
||||
}
|
||||
const m = getSimpleFieldMatcher(f);
|
||||
return (field) => !m(field, undefined as any, undefined as any);
|
||||
return (field) => !m(field, { fields: [], length: 0 }, []);
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ export function ControllerTestContext(this: any) {
|
||||
});
|
||||
};
|
||||
|
||||
this.setIsUtc = (isUtc: any = false) => {
|
||||
this.setIsUtc = (isUtc = false) => {
|
||||
self.isUtc = isUtc;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user