diff --git a/.drone.yml b/.drone.yml index 658e2d4adde..2efa39792df 100644 --- a/.drone.yml +++ b/.drone.yml @@ -865,7 +865,7 @@ services: - commands: - /bin/mimir -target=backend -alertmanager.grafana-alertmanager-compatibility-enabled environment: {} - image: us.gcr.io/kubernetes-dev/mimir:santihernandezc-validate_grafana_am_config-1e903e462-WIP + image: grafana/mimir-alpine:r295-a23e559 name: mimir_backend - environment: {} image: redis:6.2.11-alpine @@ -1312,7 +1312,7 @@ services: - commands: - /bin/mimir -target=backend -alertmanager.grafana-alertmanager-compatibility-enabled environment: {} - image: us.gcr.io/kubernetes-dev/mimir:santihernandezc-validate_grafana_am_config-1e903e462-WIP + image: grafana/mimir-alpine:r295-a23e559 name: mimir_backend - environment: {} image: redis:6.2.11-alpine @@ -2299,7 +2299,7 @@ services: - commands: - /bin/mimir -target=backend -alertmanager.grafana-alertmanager-compatibility-enabled environment: {} - image: us.gcr.io/kubernetes-dev/mimir:santihernandezc-validate_grafana_am_config-1e903e462-WIP + image: grafana/mimir-alpine:r295-a23e559 name: mimir_backend - environment: {} image: redis:6.2.11-alpine @@ -4154,7 +4154,7 @@ services: - commands: - /bin/mimir -target=backend -alertmanager.grafana-alertmanager-compatibility-enabled environment: {} - image: us.gcr.io/kubernetes-dev/mimir:santihernandezc-validate_grafana_am_config-1e903e462-WIP + image: grafana/mimir-alpine:r295-a23e559 name: mimir_backend - environment: {} image: redis:6.2.11-alpine @@ -4673,7 +4673,7 @@ steps: - trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM plugins/slack - trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM python:3.8 - trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM postgres:12.3-alpine - - trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM us.gcr.io/kubernetes-dev/mimir:santihernandezc-validate_grafana_am_config-1e903e462-WIP + - trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM grafana/mimir-alpine:r295-a23e559 - trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM mysql:5.7.39 - trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM mysql:8.0.32 - trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM redis:6.2.11-alpine @@ -4708,7 +4708,7 @@ steps: - trivy --exit-code 1 --severity HIGH,CRITICAL plugins/slack - trivy --exit-code 1 --severity HIGH,CRITICAL python:3.8 - trivy --exit-code 1 --severity HIGH,CRITICAL postgres:12.3-alpine - - trivy --exit-code 1 --severity HIGH,CRITICAL us.gcr.io/kubernetes-dev/mimir:santihernandezc-validate_grafana_am_config-1e903e462-WIP + - trivy --exit-code 1 --severity HIGH,CRITICAL grafana/mimir-alpine:r295-a23e559 - trivy --exit-code 1 --severity HIGH,CRITICAL mysql:5.7.39 - trivy --exit-code 1 --severity HIGH,CRITICAL mysql:8.0.32 - trivy --exit-code 1 --severity HIGH,CRITICAL redis:6.2.11-alpine diff --git a/devenv/docker/blocks/mimir_backend/docker-compose.yaml b/devenv/docker/blocks/mimir_backend/docker-compose.yaml index 76a19755d9f..2297d16acc6 100644 --- a/devenv/docker/blocks/mimir_backend/docker-compose.yaml +++ b/devenv/docker/blocks/mimir_backend/docker-compose.yaml @@ -1,5 +1,5 @@ mimir_backend: - image: us.gcr.io/kubernetes-dev/mimir:santihernandezc-validate_grafana_am_config-1e903e462-WIP + image: grafana/mimir-alpine:r295-a23e559 container_name: mimir_backend command: - -target=backend diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index 53578a6dfb7..fc6e4bd12ad 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -151,6 +151,7 @@ Experimental features might be changed or removed without prior notice. | `pluginsAPIMetrics` | Sends metrics of public grafana packages usage by plugins | | `idForwarding` | Generate signed id token for identity that can be forwarded to plugins and external services | | `enableNativeHTTPHistogram` | Enables native HTTP Histograms | +| `disableClassicHTTPHistogram` | Disables classic HTTP Histogram (use with enableNativeHTTPHistogram) | | `kubernetesSnapshots` | Routes snapshot requests from /api to the /apis endpoint | | `kubernetesDashboards` | Use the kubernetes API in the frontend for dashboards | | `datasourceQueryTypes` | Show query type endpoints in datasource API servers (currently hardcoded for testdata, expressions, and prometheus) | diff --git a/go.work.sum b/go.work.sum index ee55d688198..66e4511b188 100644 --- a/go.work.sum +++ b/go.work.sum @@ -423,6 +423,7 @@ github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= github.com/KimMachineGun/automemlimit v0.6.0 h1:p/BXkH+K40Hax+PuWWPQ478hPjsp9h1CPDhLlA3Z37E= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= +github.com/MicahParks/keyfunc v1.9.0 h1:lhKd5xrFHLNOWrDc4Tyb/Q1AJ4LCzQ48GVJyVIID3+o= github.com/MicahParks/keyfunc v1.9.0/go.mod h1:IdnCilugA0O/99dW+/MkvlyrsX8+L8+x95xuVNtM5jw= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= @@ -696,6 +697,7 @@ github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/crewjam/httperr v0.2.0 h1:b2BfXR8U3AlIHwNeFFvZ+BV1LFvKLlzMjzaTnZMybNo= github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3pglZ5oH4= @@ -855,8 +857,6 @@ github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJ github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k= github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= -github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd h1:hSkbZ9XSyjyBirMeqSqUrK+9HboWrweVlzRNqoBi2d4= github.com/gobuffalo/depgen v0.1.0 h1:31atYa/UW9V5q8vMJ+W6wd64OaaTHUrCUXER358zLM4= github.com/gobuffalo/envy v1.7.0 h1:GlXgaiBkmrYMHco6t4j7SacKO4XUjvh5pwXh0f4uxXU= @@ -915,6 +915,7 @@ github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2c github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/googleapis/go-type-adapters v1.0.0 h1:9XdMn+d/G57qq1s8dNc5IesGCXHf6V2HZ2JwRxfA2tA= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8 h1:tlyzajkF3030q6M8SvmJSemC9DTHL/xaMa18b65+JM4= +github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720 h1:zC34cGQu69FG7qzJ3WiKW244WfhDC3xxYMeNOX2gtUQ= github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= @@ -1025,6 +1026,7 @@ github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52Cu github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/jon-whit/go-grpc-prometheus v1.4.0 h1:/wmpGDJcLXuEjXryWhVYEGt9YBRhtLwFEN7T+Flr8sw= github.com/jon-whit/go-grpc-prometheus v1.4.0/go.mod h1:iTPm+Iuhh3IIqR0iGZ91JJEg5ax6YQEe1I0f6vtBuao= github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jsternberg/zap-logfmt v1.2.0 h1:1v+PK4/B48cy8cfQbxL4FmmNZrjnIMr2BsnyEmXqv2o= @@ -1151,12 +1153,15 @@ github.com/nats-io/jwt/v2 v2.5.0/go.mod h1:24BeQtRwxRV8ruvC4CojXlx/WQ/VjuwlYiH+v github.com/nats-io/nats-server/v2 v2.5.0 h1:wsnVaaXH9VRSg+A2MVg5Q727/CqxnmPLGFQ3YZYKTQg= github.com/nats-io/nats.go v1.12.1 h1:+0ndxwUPz3CmQ2vjbXdkC1fo3FdiOQDim4gl3Mge8Qo= github.com/nats-io/nats.go v1.28.0/go.mod h1:XpbWUlOElGwTYbMR7imivs7jJj9GtK7ypv321Wp6pjc= +github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E= github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8= github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64= +github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY= github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= github.com/oapi-codegen/testutil v1.0.0/go.mod h1:ttCaYbHvJtHuiyeBF0tPIX+4uhEPTeizXKx28okijLw= github.com/oklog/oklog v0.3.2 h1:wVfs8F+in6nTBMkA7CbRw+zZMIB7nNM825cM1wuzoTk= @@ -1236,6 +1241,7 @@ github.com/openzipkin/zipkin-go v0.4.1/go.mod h1:qY0VqDSN1pOBN94dBc6w2GJlWLiovAy github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw= github.com/pact-foundation/pact-go v1.0.4 h1:OYkFijGHoZAYbOIb1LWXrwKQbMMRUv1oQ89blD2Mh2Q= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30 h1:BHT1/DKsYDGkUgQ2jmMaozVcdk+sVfz0+1ZJq4zkWgw= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= @@ -1258,6 +1264,7 @@ github.com/pkg/profile v1.2.1 h1:F++O52m40owAmADcojzM+9gyjmMOY/T4oYJkgFDH8RE= github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs= +github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo= github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= @@ -1298,6 +1305,7 @@ github.com/ryanuber/columnize v2.1.2+incompatible h1:C89EOx/XBWwIXl8wm8OPJBd7kPF github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/sagikazarmark/crypt v0.6.0 h1:REOEXCs/NFY/1jOCEouMuT4zEniE5YoXbvpC5X/TLF8= +github.com/sagikazarmark/crypt v0.17.0 h1:ZA/7pXyjkHoK4bW4mIdnCLvL8hd+Nrbiw7Dqk7D4qUk= github.com/sagikazarmark/crypt v0.17.0/go.mod h1:SMtHTvdmsZMuY/bpZoqokSoChIrcJ/epOxZN58PbZDg= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da h1:p3Vo3i64TCLY7gIfzeQaUJ+kppEO5WQG3cL8iE8tGHU= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= @@ -1366,6 +1374,7 @@ github.com/tdewolff/parse/v2 v2.6.8 h1:mhNZXYCx//xG7Yq2e/kVLNZw4YfYmeHbhx+Zc0OvF github.com/tdewolff/parse/v2 v2.6.8/go.mod h1:XHDhaU6IBgsryfdnpzUXBlT6leW/l25yrFBTEb4eIyM= github.com/tidwall/gjson v1.14.2 h1:6BBkirS0rAHjumnjHF6qgy5d2YAJ1TLIaFE2lzfOLqo= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= diff --git a/package.json b/package.json index 9f32bc39ac5..1968f5ffd78 100644 --- a/package.json +++ b/package.json @@ -244,6 +244,7 @@ "@emotion/react": "11.11.4", "@fingerprintjs/fingerprintjs": "^3.4.2", "@floating-ui/react": "0.26.16", + "@formatjs/intl-durationformat": "^0.2.4", "@glideapps/glide-data-grid": "^6.0.0", "@grafana/aws-sdk": "0.3.3", "@grafana/azure-sdk": "0.0.3", diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index 7f5da38828d..5bb2f23c949 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -112,6 +112,7 @@ export interface FeatureToggles { externalServiceAccounts?: boolean; panelMonitoring?: boolean; enableNativeHTTPHistogram?: boolean; + disableClassicHTTPHistogram?: boolean; formatString?: boolean; transformationsVariableSupport?: boolean; kubernetesPlaylists?: boolean; diff --git a/packages/grafana-e2e-selectors/src/selectors/components.ts b/packages/grafana-e2e-selectors/src/selectors/components.ts index 3a763ec3fe5..677fe0d0d84 100644 --- a/packages/grafana-e2e-selectors/src/selectors/components.ts +++ b/packages/grafana-e2e-selectors/src/selectors/components.ts @@ -603,4 +603,7 @@ export const Components = { headerOrderSwitch: 'data-testid header-order-switch', headerPreviewSwitch: 'data-testid header-preview-switch', }, + EntityNotFound: { + container: 'data-testid entity-not-found', + }, }; diff --git a/packages/grafana-prometheus/src/language_provider.test.ts b/packages/grafana-prometheus/src/language_provider.test.ts index dd7dec7ce71..e1496bd06d8 100644 --- a/packages/grafana-prometheus/src/language_provider.test.ts +++ b/packages/grafana-prometheus/src/language_provider.test.ts @@ -505,6 +505,20 @@ describe('Language completion provider', () => { ) ); }); + + it('should dont send match[] parameter if there is no metric', async () => { + const mockQueries: PromQuery[] = [ + { + refId: 'A', + expr: '', + }, + ]; + const fetchLabel = languageProvider.fetchLabels; + const requestSpy = jest.spyOn(languageProvider, 'request'); + await fetchLabel(tr, mockQueries); + expect(requestSpy).toHaveBeenCalled(); + expect(requestSpy.mock.calls[0][0].indexOf('match[]')).toEqual(-1); + }); }); }); diff --git a/packages/grafana-prometheus/src/language_provider.ts b/packages/grafana-prometheus/src/language_provider.ts index a6105c988a3..b7ec09163e9 100644 --- a/packages/grafana-prometheus/src/language_provider.ts +++ b/packages/grafana-prometheus/src/language_provider.ts @@ -219,11 +219,13 @@ export default class PromQlLanguageProvider extends LanguageProvider { const searchParams = new URLSearchParams({ ...timeParams }); queries?.forEach((q) => { const visualQuery = buildVisualQueryFromString(q.expr); - searchParams.append('match[]', visualQuery.query.metric); - if (visualQuery.query.binaryQueries) { - visualQuery.query.binaryQueries.forEach((bq) => { - searchParams.append('match[]', bq.query.metric); - }); + if (visualQuery.query.metric !== '') { + searchParams.append('match[]', visualQuery.query.metric); + if (visualQuery.query.binaryQueries) { + visualQuery.query.binaryQueries.forEach((bq) => { + searchParams.append('match[]', bq.query.metric); + }); + } } }); diff --git a/packages/grafana-prometheus/src/querybuilder/aggregations.ts b/packages/grafana-prometheus/src/querybuilder/aggregations.ts index d4129c3665e..8fff6505173 100644 --- a/packages/grafana-prometheus/src/querybuilder/aggregations.ts +++ b/packages/grafana-prometheus/src/querybuilder/aggregations.ts @@ -28,6 +28,10 @@ export function getAggregationOperations(): QueryBuilderOperationDef[] { params: [{ name: 'Identifier', type: 'string' }], defaultParams: ['count'], }), + ...createAggregationOperationWithParam(PromOperationId.Quantile, { + params: [{ name: 'Value', type: 'number' }], + defaultParams: [1], + }), createAggregationOverTime(PromOperationId.SumOverTime), createAggregationOverTime(PromOperationId.AvgOverTime), createAggregationOverTime(PromOperationId.MinOverTime), diff --git a/packages/grafana-prometheus/src/querybuilder/components/promQail/state/templates.ts b/packages/grafana-prometheus/src/querybuilder/components/promQail/state/templates.ts index 330de01da2f..6e455accdb9 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/promQail/state/templates.ts +++ b/packages/grafana-prometheus/src/querybuilder/components/promQail/state/templates.ts @@ -76,6 +76,10 @@ export const generalTemplates: TemplateData[] = [ template: 'count_values("aaaa",metric_a{})', description: 'Count number of label values for a label named "aaaa"', }, + { + template: 'quantile by(l) (1,metric_a)', + description: 'Quantile of series in the metric "metric_a" grouped by the label "l"', + }, ]; export const counterTemplates: TemplateData[] = [ diff --git a/packages/grafana-prometheus/src/querybuilder/operations.ts b/packages/grafana-prometheus/src/querybuilder/operations.ts index cb83b0a44d6..afd77331239 100644 --- a/packages/grafana-prometheus/src/querybuilder/operations.ts +++ b/packages/grafana-prometheus/src/querybuilder/operations.ts @@ -230,12 +230,6 @@ export function getOperationDefinitions(): QueryBuilderOperationDef[] { id: PromOperationId.Pi, renderer: (model) => `${model.id}()`, }), - createFunction({ - id: PromOperationId.Quantile, - params: [{ name: 'Value', type: 'number' }], - defaultParams: [1], - renderer: functionRendererLeft, - }), createFunction({ id: PromOperationId.Rad }), createRangeFunction(PromOperationId.Resets), createFunction({ diff --git a/pkg/middleware/request_metrics.go b/pkg/middleware/request_metrics.go index b109a52a56f..94c60f57509 100644 --- a/pkg/middleware/request_metrics.go +++ b/pkg/middleware/request_metrics.go @@ -51,12 +51,19 @@ func RequestMetrics(features featuremgmt.FeatureToggles, cfg *setting.Cfg, promR if features.IsEnabledGlobally(featuremgmt.FlagEnableNativeHTTPHistogram) { // the recommended default value from the prom_client // https://github.com/prometheus/client_golang/blob/main/prometheus/histogram.go#L411 - // Giving this variable an value means the client will expose the histograms as an - // native histogram instead of normal a normal histogram. + // Giving this variable a value means the client will expose a native + // histogram. histogramOptions.NativeHistogramBucketFactor = 1.1 // The default value in OTel. It probably good enough for us as well. histogramOptions.NativeHistogramMaxBucketNumber = 160 histogramOptions.NativeHistogramMinResetDuration = time.Hour + + if features.IsEnabledGlobally(featuremgmt.FlagDisableClassicHTTPHistogram) { + // setting Buckets to nil with native options set means the classic + // histogram will no longer be exposed - this can be a good way to + // reduce cardinality in the exposed metrics + histogramOptions.Buckets = nil + } } httpRequestDurationHistogram := prometheus.NewHistogramVec( diff --git a/pkg/services/authz/zanzana/logger.go b/pkg/services/authz/zanzana/logger.go new file mode 100644 index 00000000000..4f74c03284c --- /dev/null +++ b/pkg/services/authz/zanzana/logger.go @@ -0,0 +1,86 @@ +package zanzana + +import ( + "context" + + "go.uber.org/zap" + + "github.com/grafana/grafana/pkg/infra/log" +) + +// zanzanaLogger is a grafana logger wrapper compatible with OpenFGA logger interface +type zanzanaLogger struct { + logger *log.ConcreteLogger +} + +func newZanzanaLogger() *zanzanaLogger { + logger := log.New("openfga-server") + + return &zanzanaLogger{ + logger: logger, + } +} + +// Simple converter for zap logger fields +func zapFieldsToArgs(fields []zap.Field) []any { + args := make([]any, 0) + for _, f := range fields { + args = append(args, f.Key) + if f.Interface != nil { + args = append(args, f.Interface) + } else if f.String != "" { + args = append(args, f.String) + } else { + args = append(args, f.Integer) + } + } + return args +} + +func (l *zanzanaLogger) Debug(msg string, fields ...zap.Field) { + l.logger.Debug(msg, zapFieldsToArgs(fields)...) +} + +func (l *zanzanaLogger) Info(msg string, fields ...zap.Field) { + l.logger.Info(msg, zapFieldsToArgs(fields)...) +} + +func (l *zanzanaLogger) Warn(msg string, fields ...zap.Field) { + l.logger.Warn(msg, zapFieldsToArgs(fields)...) +} + +func (l *zanzanaLogger) Error(msg string, fields ...zap.Field) { + l.logger.Error(msg, zapFieldsToArgs(fields)...) +} + +func (l *zanzanaLogger) Panic(msg string, fields ...zap.Field) { + l.logger.Error(msg, zapFieldsToArgs(fields)...) +} + +func (l *zanzanaLogger) Fatal(msg string, fields ...zap.Field) { + l.logger.Error(msg, zapFieldsToArgs(fields)...) +} + +func (l *zanzanaLogger) DebugWithContext(ctx context.Context, msg string, fields ...zap.Field) { + l.logger.Debug(msg, zapFieldsToArgs(fields)...) +} + +func (l *zanzanaLogger) InfoWithContext(ctx context.Context, msg string, fields ...zap.Field) { + l.logger.Info(msg, zapFieldsToArgs(fields)...) +} + +func (l *zanzanaLogger) WarnWithContext(ctx context.Context, msg string, fields ...zap.Field) { + l.logger.Warn(msg, zapFieldsToArgs(fields)...) +} + +func (l *zanzanaLogger) ErrorWithContext(ctx context.Context, msg string, fields ...zap.Field) { + l.logger.Error(msg, zapFieldsToArgs(fields)...) +} + +func (l *zanzanaLogger) PanicWithContext(ctx context.Context, msg string, fields ...zap.Field) { + l.logger.Error(msg, zapFieldsToArgs(fields)...) +} + +func (l *zanzanaLogger) FatalWithContext(ctx context.Context, msg string, fields ...zap.Field) { + l.logger.Error(msg, zapFieldsToArgs(fields)...) +} diff --git a/pkg/services/authz/zanzana/server.go b/pkg/services/authz/zanzana/server.go index e00b2a22eb5..73c929252b4 100644 --- a/pkg/services/authz/zanzana/server.go +++ b/pkg/services/authz/zanzana/server.go @@ -1,7 +1,6 @@ package zanzana import ( - "github.com/openfga/openfga/pkg/logger" "github.com/openfga/openfga/pkg/server" "github.com/openfga/openfga/pkg/storage" ) @@ -10,8 +9,7 @@ func NewServer(store storage.OpenFGADatastore) (*server.Server, error) { // FIXME(kalleep): add support for more options, configure logging, tracing etc opts := []server.OpenFGAServiceV1Option{ server.WithDatastore(store), - // FIXME(kalleep): Write and log adapter for open fga logging interface - server.WithLogger(logger.NewNoopLogger()), + server.WithLogger(newZanzanaLogger()), } // FIXME(kalleep): Interceptors diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index 51bf6ea8828..8842445b5a6 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -700,11 +700,24 @@ var ( FrontendOnly: true, }, { - Name: "enableNativeHTTPHistogram", - Description: "Enables native HTTP Histograms", - Stage: FeatureStageExperimental, - FrontendOnly: false, - Owner: hostedGrafanaTeam, + Name: "enableNativeHTTPHistogram", + Description: "Enables native HTTP Histograms", + Stage: FeatureStageExperimental, + FrontendOnly: false, + Owner: grafanaBackendServicesSquad, + HideFromAdminPage: true, + AllowSelfServe: false, + RequiresRestart: true, + }, + FeatureFlag{ + Name: "disableClassicHTTPHistogram", + Description: "Disables classic HTTP Histogram (use with enableNativeHTTPHistogram)", + Stage: FeatureStageExperimental, + FrontendOnly: false, + Owner: grafanaBackendServicesSquad, + HideFromAdminPage: true, + AllowSelfServe: false, + RequiresRestart: true, }, { Name: "formatString", diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index c0b5e76d4c1..969586eee2b 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -92,7 +92,8 @@ pluginsAPIMetrics,experimental,@grafana/plugins-platform-backend,false,false,tru idForwarding,experimental,@grafana/identity-access-team,false,false,false externalServiceAccounts,preview,@grafana/identity-access-team,false,false,false panelMonitoring,GA,@grafana/dataviz-squad,false,false,true -enableNativeHTTPHistogram,experimental,@grafana/hosted-grafana-team,false,false,false +enableNativeHTTPHistogram,experimental,@grafana/grafana-backend-services-squad,false,true,false +disableClassicHTTPHistogram,experimental,@grafana/grafana-backend-services-squad,false,true,false formatString,preview,@grafana/dataviz-squad,false,false,true transformationsVariableSupport,GA,@grafana/dataviz-squad,false,false,true kubernetesPlaylists,GA,@grafana/grafana-app-platform-squad,false,true,false diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index d7f10257ddf..45d8a4f2380 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -383,6 +383,10 @@ const ( // Enables native HTTP Histograms FlagEnableNativeHTTPHistogram = "enableNativeHTTPHistogram" + // FlagDisableClassicHTTPHistogram + // Disables classic HTTP Histogram (use with enableNativeHTTPHistogram) + FlagDisableClassicHTTPHistogram = "disableClassicHTTPHistogram" + // FlagFormatString // Enable format string transformer FlagFormatString = "formatString" diff --git a/pkg/services/featuremgmt/toggles_gen.json b/pkg/services/featuremgmt/toggles_gen.json index 02df39301fd..bde6f3022f7 100644 --- a/pkg/services/featuremgmt/toggles_gen.json +++ b/pkg/services/featuremgmt/toggles_gen.json @@ -6,7 +6,7 @@ { "metadata": { "name": "accessActionSets", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-04-12T16:19:25Z" }, "spec": { @@ -18,7 +18,7 @@ { "metadata": { "name": "accessControlOnCall", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-10-19T16:10:09Z" }, "spec": { @@ -31,7 +31,7 @@ { "metadata": { "name": "addFieldFromCalculationStatFunctions", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-03T14:39:58Z" }, "spec": { @@ -44,7 +44,7 @@ { "metadata": { "name": "aiGeneratedDashboardChanges", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-03-05T12:01:31Z" }, "spec": { @@ -57,7 +57,7 @@ { "metadata": { "name": "alertStateHistoryLokiOnly", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-03-30T18:53:21Z" }, "spec": { @@ -69,7 +69,7 @@ { "metadata": { "name": "alertStateHistoryLokiPrimary", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-03-30T18:53:21Z" }, "spec": { @@ -81,7 +81,7 @@ { "metadata": { "name": "alertStateHistoryLokiSecondary", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-03-30T18:53:21Z" }, "spec": { @@ -93,7 +93,7 @@ { "metadata": { "name": "alertingBacktesting", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-12-14T14:44:14Z" }, "spec": { @@ -105,7 +105,7 @@ { "metadata": { "name": "alertingCentralAlertHistory", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-05-29T15:01:38Z" }, "spec": { @@ -118,7 +118,7 @@ { "metadata": { "name": "alertingDisableSendAlertsExternal", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-05-23T12:29:19Z" }, "spec": { @@ -132,7 +132,7 @@ { "metadata": { "name": "alertingInsights", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-09-14T12:58:04Z" }, "spec": { @@ -146,7 +146,7 @@ { "metadata": { "name": "alertingListViewV2", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-05-24T14:40:49Z" }, "spec": { @@ -159,7 +159,7 @@ { "metadata": { "name": "alertingNoDataErrorExecution", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-08-15T14:27:15Z" }, "spec": { @@ -172,7 +172,7 @@ { "metadata": { "name": "alertingNoNormalState", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-01-13T23:29:29Z" }, "spec": { @@ -185,7 +185,7 @@ { "metadata": { "name": "alertingQueryOptimization", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-01-10T20:52:58Z" }, "spec": { @@ -197,7 +197,7 @@ { "metadata": { "name": "alertingSaveStatePeriodic", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-01-23T16:03:30Z" }, "spec": { @@ -209,7 +209,7 @@ { "metadata": { "name": "alertingSimplifiedRouting", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-10T13:14:39Z" }, "spec": { @@ -221,7 +221,7 @@ { "metadata": { "name": "alertmanagerRemoteOnly", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-30T16:27:08Z" }, "spec": { @@ -233,7 +233,7 @@ { "metadata": { "name": "alertmanagerRemotePrimary", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-30T16:27:08Z" }, "spec": { @@ -245,7 +245,7 @@ { "metadata": { "name": "alertmanagerRemoteSecondary", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-30T16:27:08Z" }, "spec": { @@ -257,7 +257,7 @@ { "metadata": { "name": "angularDeprecationUI", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-08-29T14:05:47Z" }, "spec": { @@ -270,7 +270,7 @@ { "metadata": { "name": "annotationPermissionUpdate", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-31T13:30:13Z" }, "spec": { @@ -282,7 +282,7 @@ { "metadata": { "name": "authAPIAccessTokenAuth", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-04-02T15:45:15Z" }, "spec": { @@ -296,8 +296,8 @@ { "metadata": { "name": "authZGRPCServer", - "resourceVersion": "1718093439898", - "creationTimestamp": "2024-06-11T08:10:39Z" + "resourceVersion": "1718727528075", + "creationTimestamp": "2024-06-18T16:18:48Z" }, "spec": { "description": "Enables the gRPC server for authorization", @@ -310,7 +310,7 @@ { "metadata": { "name": "autoMigrateGraphPanel", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-02-08T22:00:48Z" }, "spec": { @@ -323,7 +323,7 @@ { "metadata": { "name": "autoMigrateOldPanels", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-03-23T04:02:36Z" }, "spec": { @@ -336,7 +336,7 @@ { "metadata": { "name": "autoMigratePiechartPanel", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-02-14T16:06:25Z" }, "spec": { @@ -349,7 +349,7 @@ { "metadata": { "name": "autoMigrateStatPanel", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-02-14T16:06:25Z" }, "spec": { @@ -362,7 +362,7 @@ { "metadata": { "name": "autoMigrateTablePanel", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-02-14T16:06:25Z" }, "spec": { @@ -375,7 +375,7 @@ { "metadata": { "name": "autoMigrateWorldmapPanel", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-02-14T16:06:25Z" }, "spec": { @@ -388,7 +388,7 @@ { "metadata": { "name": "autoMigrateXYChartPanel", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-03-22T15:44:37Z" }, "spec": { @@ -401,7 +401,7 @@ { "metadata": { "name": "autofixDSUID", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-05-03T11:32:07Z" }, "spec": { @@ -413,7 +413,7 @@ { "metadata": { "name": "awsAsyncQueryCaching", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-07-21T15:34:07Z" }, "spec": { @@ -425,7 +425,7 @@ { "metadata": { "name": "awsDatasourcesNewFormStyling", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-12T08:59:10Z" }, "spec": { @@ -438,7 +438,7 @@ { "metadata": { "name": "awsDatasourcesTempCredentials", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-07-06T15:06:11Z" }, "spec": { @@ -450,7 +450,7 @@ { "metadata": { "name": "azureMonitorPrometheusExemplars", - "resourceVersion": "1717667267324", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-06-06T16:53:17Z" }, "spec": { @@ -459,24 +459,10 @@ "codeowner": "@grafana/partner-datasources" } }, - { - "metadata": { - "name": "betterPageScrolling", - "resourceVersion": "1717578796182", - "creationTimestamp": "2024-03-06T15:06:47Z", - "deletionTimestamp": "2024-06-18T09:25:56Z" - }, - "spec": { - "description": "Removes CustomScrollbar from the UI, relying on native browser scrollbars", - "stage": "GA", - "codeowner": "@grafana/grafana-frontend-platform", - "frontend": true - } - }, { "metadata": { "name": "cachingOptimizeSerializationMemoryUsage", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-12T16:56:49Z" }, "spec": { @@ -488,7 +474,7 @@ { "metadata": { "name": "canvasPanelNesting", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-05-31T19:03:34Z" }, "spec": { @@ -502,7 +488,7 @@ { "metadata": { "name": "canvasPanelPanZoom", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-01-02T19:52:21Z" }, "spec": { @@ -515,7 +501,7 @@ { "metadata": { "name": "cloudRBACRoles", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-01-10T13:19:01Z" }, "spec": { @@ -529,7 +515,7 @@ { "metadata": { "name": "cloudWatchBatchQueries", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-20T19:09:41Z" }, "spec": { @@ -541,7 +527,7 @@ { "metadata": { "name": "cloudWatchCrossAccountQuerying", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-11-28T11:39:12Z" }, "spec": { @@ -554,7 +540,7 @@ { "metadata": { "name": "cloudWatchNewLabelParsing", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-04-05T15:57:56Z" }, "spec": { @@ -566,7 +552,7 @@ { "metadata": { "name": "configurableSchedulerTick", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-07-26T16:44:12Z" }, "spec": { @@ -580,7 +566,7 @@ { "metadata": { "name": "correlations", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-09-16T13:14:27Z" }, "spec": { @@ -593,7 +579,7 @@ { "metadata": { "name": "dashboardRestore", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-05-16T17:36:26Z" }, "spec": { @@ -606,7 +592,7 @@ { "metadata": { "name": "dashboardScene", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-13T08:51:21Z" }, "spec": { @@ -619,7 +605,7 @@ { "metadata": { "name": "dashboardSceneForViewers", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-02T19:02:25Z" }, "spec": { @@ -632,7 +618,7 @@ { "metadata": { "name": "dashboardSceneSolo", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-02-11T08:08:47Z" }, "spec": { @@ -645,7 +631,7 @@ { "metadata": { "name": "dashgpt", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-08-30T20:22:05Z" }, "spec": { @@ -658,8 +644,8 @@ { "metadata": { "name": "databaseReadReplica", - "resourceVersion": "1718308641844", - "creationTimestamp": "2024-06-13T19:57:21Z" + "resourceVersion": "1718727528075", + "creationTimestamp": "2024-06-18T16:18:48Z" }, "spec": { "description": "Use a read replica for some database queries.", @@ -670,7 +656,7 @@ { "metadata": { "name": "dataplaneFrontendFallback", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-04-07T21:13:19Z" }, "spec": { @@ -684,7 +670,7 @@ { "metadata": { "name": "datasourceProxyDisableRBAC", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-05-21T13:05:16Z" }, "spec": { @@ -697,7 +683,7 @@ { "metadata": { "name": "datasourceQueryMultiStatus", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-05-03T16:02:20Z" }, "spec": { @@ -709,7 +695,7 @@ { "metadata": { "name": "datasourceQueryTypes", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-05-23T16:46:28Z" }, "spec": { @@ -722,7 +708,7 @@ { "metadata": { "name": "disableAngular", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-03-23T15:43:45Z" }, "spec": { @@ -733,10 +719,24 @@ "hideFromAdminPage": true } }, + { + "metadata": { + "name": "disableClassicHTTPHistogram", + "resourceVersion": "1718727528075", + "creationTimestamp": "2024-06-18T16:18:48Z" + }, + "spec": { + "description": "Disables classic HTTP Histogram (use with enableNativeHTTPHistogram)", + "stage": "experimental", + "codeowner": "@grafana/grafana-backend-services-squad", + "requiresRestart": true, + "hideFromAdminPage": true + } + }, { "metadata": { "name": "disableEnvelopeEncryption", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-05-24T08:34:47Z" }, "spec": { @@ -749,7 +749,7 @@ { "metadata": { "name": "disableNumericMetricsSortingInExpressions", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-04-16T14:52:47Z" }, "spec": { @@ -762,7 +762,7 @@ { "metadata": { "name": "disableSSEDataplane", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-04-12T16:24:34Z" }, "spec": { @@ -774,7 +774,7 @@ { "metadata": { "name": "disableSecretsCompatibility", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-07-12T20:27:37Z" }, "spec": { @@ -787,7 +787,7 @@ { "metadata": { "name": "editPanelCSVDragAndDrop", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-01-24T09:43:44Z" }, "spec": { @@ -800,7 +800,7 @@ { "metadata": { "name": "enableDatagridEditing", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-04-24T14:46:31Z" }, "spec": { @@ -810,36 +810,24 @@ "frontend": true } }, - { - "metadata": { - "name": "enableElasticsearchBackendQuerying", - "resourceVersion": "1717578796182", - "creationTimestamp": "2023-04-14T09:24:35Z", - "deletionTimestamp": "2024-06-05T15:03:29Z" - }, - "spec": { - "description": "Enable the processing of queries and responses in the Elasticsearch data source through backend", - "stage": "GA", - "codeowner": "@grafana/observability-logs", - "allowSelfServe": true - } - }, { "metadata": { "name": "enableNativeHTTPHistogram", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-03T18:23:55Z" }, "spec": { "description": "Enables native HTTP Histograms", "stage": "experimental", - "codeowner": "@grafana/hosted-grafana-team" + "codeowner": "@grafana/grafana-backend-services-squad", + "requiresRestart": true, + "hideFromAdminPage": true } }, { "metadata": { "name": "exploreContentOutline", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-13T16:57:13Z" }, "spec": { @@ -853,7 +841,7 @@ { "metadata": { "name": "exploreMetrics", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-04-09T18:15:18Z" }, "spec": { @@ -866,7 +854,7 @@ { "metadata": { "name": "expressionParser", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-02-17T00:59:11Z" }, "spec": { @@ -879,7 +867,7 @@ { "metadata": { "name": "externalCorePlugins", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-09-22T08:50:13Z" }, "spec": { @@ -891,7 +879,7 @@ { "metadata": { "name": "externalServiceAccounts", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-09-28T07:26:37Z" }, "spec": { @@ -904,7 +892,7 @@ { "metadata": { "name": "extraThemes", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-05-10T13:37:04Z" }, "spec": { @@ -917,7 +905,7 @@ { "metadata": { "name": "extractFieldsNameDeduplication", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-02T15:47:42Z" }, "spec": { @@ -930,7 +918,7 @@ { "metadata": { "name": "faroDatasourceSelector", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-05-05T00:35:10Z" }, "spec": { @@ -943,7 +931,7 @@ { "metadata": { "name": "featureHighlights", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-02-03T11:53:23Z" }, "spec": { @@ -956,7 +944,7 @@ { "metadata": { "name": "featureToggleAdminPage", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-07-18T20:43:32Z" }, "spec": { @@ -970,7 +958,7 @@ { "metadata": { "name": "flameGraphItemCollapsing", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-09T14:31:07Z" }, "spec": { @@ -983,7 +971,7 @@ { "metadata": { "name": "formatString", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-13T18:17:12Z" }, "spec": { @@ -996,7 +984,7 @@ { "metadata": { "name": "frontendSandboxMonitorOnly", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-07-05T11:48:25Z" }, "spec": { @@ -1009,7 +997,7 @@ { "metadata": { "name": "grafanaAPIServerEnsureKubectlAccess", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-12-06T20:21:21Z" }, "spec": { @@ -1023,7 +1011,7 @@ { "metadata": { "name": "grafanaAPIServerWithExperimentalAPIs", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-06T18:55:22Z" }, "spec": { @@ -1037,7 +1025,7 @@ { "metadata": { "name": "grafanaManagedRecordingRules", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-04-22T17:53:16Z" }, "spec": { @@ -1051,7 +1039,7 @@ { "metadata": { "name": "groupByVariable", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-02-14T17:18:04Z" }, "spec": { @@ -1065,7 +1053,7 @@ { "metadata": { "name": "groupToNestedTableTransformation", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-02-07T14:28:26Z" }, "spec": { @@ -1078,7 +1066,7 @@ { "metadata": { "name": "grpcServer", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-09-26T20:25:34Z" }, "spec": { @@ -1091,7 +1079,7 @@ { "metadata": { "name": "idForwarding", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-09-25T15:21:28Z" }, "spec": { @@ -1103,7 +1091,7 @@ { "metadata": { "name": "individualCookiePreferences", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-02-21T10:19:07Z" }, "spec": { @@ -1115,7 +1103,7 @@ { "metadata": { "name": "influxdbBackendMigration", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-02-09T18:26:16Z", "deletionTimestamp": "2023-01-17T14:11:26Z" }, @@ -1129,7 +1117,7 @@ { "metadata": { "name": "influxdbRunQueriesInParallel", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-02-01T10:58:24Z" }, "spec": { @@ -1141,7 +1129,7 @@ { "metadata": { "name": "influxqlStreamingParser", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-29T17:29:35Z" }, "spec": { @@ -1153,7 +1141,7 @@ { "metadata": { "name": "jitterAlertRulesWithinGroups", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-01-18T18:48:11Z" }, "spec": { @@ -1167,7 +1155,7 @@ { "metadata": { "name": "kubernetesAggregator", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-02-12T20:59:35Z" }, "spec": { @@ -1180,7 +1168,7 @@ { "metadata": { "name": "kubernetesDashboards", - "resourceVersion": "1717593661635", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-06-05T14:34:23Z" }, "spec": { @@ -1193,7 +1181,7 @@ { "metadata": { "name": "kubernetesFeatureToggles", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-01-18T05:32:44Z" }, "spec": { @@ -1207,7 +1195,7 @@ { "metadata": { "name": "kubernetesPlaylists", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-05T19:00:36Z" }, "spec": { @@ -1220,7 +1208,7 @@ { "metadata": { "name": "kubernetesSnapshots", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-12-05T22:31:49Z" }, "spec": { @@ -1233,7 +1221,7 @@ { "metadata": { "name": "libraryPanelRBAC", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-11T23:30:50Z" }, "spec": { @@ -1246,7 +1234,7 @@ { "metadata": { "name": "live-service-web-worker", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-01-26T17:44:20Z" }, "spec": { @@ -1259,7 +1247,7 @@ { "metadata": { "name": "logRequestsInstrumentedAsUnknown", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-06-10T08:56:55Z" }, "spec": { @@ -1271,7 +1259,7 @@ { "metadata": { "name": "logRowsPopoverMenu", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-16T09:48:10Z" }, "spec": { @@ -1284,7 +1272,7 @@ { "metadata": { "name": "logsContextDatasourceUi", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-01-27T14:12:01Z" }, "spec": { @@ -1298,7 +1286,7 @@ { "metadata": { "name": "logsExploreTableDefaultVisualization", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-05-02T15:28:15Z" }, "spec": { @@ -1311,7 +1299,7 @@ { "metadata": { "name": "logsExploreTableVisualisation", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-07-12T13:52:42Z" }, "spec": { @@ -1324,7 +1312,7 @@ { "metadata": { "name": "logsInfiniteScrolling", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-09T10:54:03Z" }, "spec": { @@ -1337,7 +1325,7 @@ { "metadata": { "name": "lokiExperimentalStreaming", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-06-19T10:03:51Z" }, "spec": { @@ -1349,7 +1337,7 @@ { "metadata": { "name": "lokiLogsDataplane", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-07-13T07:58:00Z" }, "spec": { @@ -1361,7 +1349,7 @@ { "metadata": { "name": "lokiMetricDataplane", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-04-13T13:07:08Z" }, "spec": { @@ -1374,7 +1362,7 @@ { "metadata": { "name": "lokiPredefinedOperations", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-06-02T10:52:36Z" }, "spec": { @@ -1387,7 +1375,7 @@ { "metadata": { "name": "lokiQueryHints", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-12-18T20:43:16Z" }, "spec": { @@ -1400,7 +1388,7 @@ { "metadata": { "name": "lokiQuerySplitting", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-02-09T17:27:02Z" }, "spec": { @@ -1414,7 +1402,7 @@ { "metadata": { "name": "lokiQuerySplittingConfig", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-03-20T15:51:36Z" }, "spec": { @@ -1427,7 +1415,7 @@ { "metadata": { "name": "lokiRunQueriesInParallel", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-09-19T09:34:01Z" }, "spec": { @@ -1439,7 +1427,7 @@ { "metadata": { "name": "lokiStructuredMetadata", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-16T16:06:14Z" }, "spec": { @@ -1451,7 +1439,7 @@ { "metadata": { "name": "managedPluginsInstall", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-18T13:17:03Z" }, "spec": { @@ -1463,7 +1451,7 @@ { "metadata": { "name": "metricsSummary", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-08-28T14:02:12Z" }, "spec": { @@ -1476,7 +1464,7 @@ { "metadata": { "name": "mlExpressions", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-07-13T17:37:50Z" }, "spec": { @@ -1488,7 +1476,7 @@ { "metadata": { "name": "mysqlAnsiQuotes", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-10-12T11:43:35Z" }, "spec": { @@ -1500,7 +1488,7 @@ { "metadata": { "name": "nestedFolders", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-10-26T14:15:14Z" }, "spec": { @@ -1512,7 +1500,7 @@ { "metadata": { "name": "newDashboardSharingComponent", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-05-03T15:02:18Z" }, "spec": { @@ -1525,7 +1513,7 @@ { "metadata": { "name": "newDashboardWithFiltersAndGroupBy", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-04-04T11:25:21Z" }, "spec": { @@ -1539,7 +1527,7 @@ { "metadata": { "name": "newFolderPicker", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-01-15T11:43:19Z" }, "spec": { @@ -1552,7 +1540,7 @@ { "metadata": { "name": "newPDFRendering", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-02-08T12:09:34Z" }, "spec": { @@ -1564,7 +1552,7 @@ { "metadata": { "name": "nodeGraphDotLayout", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-01-31T16:26:12Z" }, "spec": { @@ -1577,7 +1565,7 @@ { "metadata": { "name": "notificationBanner", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-05-13T09:32:34Z" }, "spec": { @@ -1589,7 +1577,7 @@ { "metadata": { "name": "oauthRequireSubClaim", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-03-25T13:22:24Z" }, "spec": { @@ -1603,7 +1591,7 @@ { "metadata": { "name": "onPremToCloudMigrations", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-01-22T16:09:08Z" }, "spec": { @@ -1615,8 +1603,8 @@ { "metadata": { "name": "openSearchBackendFlowEnabled", - "resourceVersion": "1718357852240", - "creationTimestamp": "2024-06-14T09:37:32Z" + "resourceVersion": "1718727528075", + "creationTimestamp": "2024-06-18T16:18:48Z" }, "spec": { "description": "Enables the backend query flow for Open Search datasource plugin", @@ -1627,7 +1615,7 @@ { "metadata": { "name": "panelFilterVariable", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-03T12:15:54Z" }, "spec": { @@ -1641,7 +1629,7 @@ { "metadata": { "name": "panelMonitoring", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-09T05:19:08Z" }, "spec": { @@ -1654,7 +1642,7 @@ { "metadata": { "name": "panelTitleSearch", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-02-15T18:26:03Z" }, "spec": { @@ -1667,7 +1655,7 @@ { "metadata": { "name": "panelTitleSearchInV1", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-13T12:04:24Z" }, "spec": { @@ -1680,7 +1668,7 @@ { "metadata": { "name": "pdfTables", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-06T13:39:22Z" }, "spec": { @@ -1692,7 +1680,7 @@ { "metadata": { "name": "permissionsFilterRemoveSubquery", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-08-02T07:39:25Z" }, "spec": { @@ -1704,8 +1692,8 @@ { "metadata": { "name": "pinNavItems", - "resourceVersion": "1718017263521", - "creationTimestamp": "2024-06-10T11:01:03Z" + "resourceVersion": "1718727528075", + "creationTimestamp": "2024-06-18T16:18:48Z" }, "spec": { "description": "Enables pinning of nav items", @@ -1716,7 +1704,7 @@ { "metadata": { "name": "pluginProxyPreserveTrailingSlash", - "resourceVersion": "1717581171624", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-06-05T11:36:14Z" }, "spec": { @@ -1728,7 +1716,7 @@ { "metadata": { "name": "pluginsAPIMetrics", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-09-21T11:36:32Z" }, "spec": { @@ -1741,7 +1729,7 @@ { "metadata": { "name": "pluginsFrontendSandbox", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-06-05T08:51:36Z" }, "spec": { @@ -1754,7 +1742,7 @@ { "metadata": { "name": "pluginsSkipHostEnvVars", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-15T17:09:14Z" }, "spec": { @@ -1766,7 +1754,7 @@ { "metadata": { "name": "preserveDashboardStateWhenNavigating", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-05-27T12:28:06Z" }, "spec": { @@ -1780,7 +1768,7 @@ { "metadata": { "name": "promQLScope", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-01-29T20:22:17Z" }, "spec": { @@ -1792,7 +1780,7 @@ { "metadata": { "name": "prometheusCodeModeMetricNamesSearch", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-04-04T20:38:23Z" }, "spec": { @@ -1805,7 +1793,7 @@ { "metadata": { "name": "prometheusConfigOverhaulAuth", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-07-26T16:09:53Z" }, "spec": { @@ -1817,7 +1805,7 @@ { "metadata": { "name": "prometheusDataplane", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-03-29T15:26:32Z" }, "spec": { @@ -1830,7 +1818,7 @@ { "metadata": { "name": "prometheusIncrementalQueryInstrumentation", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-07-05T19:39:49Z" }, "spec": { @@ -1843,7 +1831,7 @@ { "metadata": { "name": "prometheusMetricEncyclopedia", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-03-07T18:41:05Z" }, "spec": { @@ -1857,7 +1845,7 @@ { "metadata": { "name": "prometheusPromQAIL", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-19T15:45:32Z" }, "spec": { @@ -1870,7 +1858,7 @@ { "metadata": { "name": "publicDashboards", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-04-07T18:30:19Z" }, "spec": { @@ -1883,7 +1871,7 @@ { "metadata": { "name": "publicDashboardsEmailSharing", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-01-03T19:45:15Z" }, "spec": { @@ -1897,7 +1885,7 @@ { "metadata": { "name": "publicDashboardsScene", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-03-22T14:48:21Z" }, "spec": { @@ -1910,7 +1898,7 @@ { "metadata": { "name": "queryLibrary", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-10-07T18:31:45Z", "deletionTimestamp": "2023-03-20T16:00:14Z" }, @@ -1923,7 +1911,7 @@ { "metadata": { "name": "queryOverLive", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-01-26T17:44:20Z" }, "spec": { @@ -1936,7 +1924,7 @@ { "metadata": { "name": "queryService", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-04-19T09:26:21Z" }, "spec": { @@ -1949,7 +1937,7 @@ { "metadata": { "name": "queryServiceFromUI", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-04-19T09:26:21Z" }, "spec": { @@ -1962,7 +1950,7 @@ { "metadata": { "name": "queryServiceRewrite", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-04-19T09:26:21Z" }, "spec": { @@ -1975,7 +1963,7 @@ { "metadata": { "name": "recordedQueriesMulti", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-06-14T12:34:22Z" }, "spec": { @@ -1987,7 +1975,7 @@ { "metadata": { "name": "recoveryThreshold", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-10T14:51:50Z" }, "spec": { @@ -2000,7 +1988,7 @@ { "metadata": { "name": "refactorVariablesTimeRange", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-06-06T13:12:09Z" }, "spec": { @@ -2013,7 +2001,7 @@ { "metadata": { "name": "regressionTransformation", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-24T14:49:16Z" }, "spec": { @@ -2026,7 +2014,7 @@ { "metadata": { "name": "renderAuthJWT", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-04-03T16:53:38Z" }, "spec": { @@ -2039,7 +2027,7 @@ { "metadata": { "name": "reportingRetries", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-08-31T07:47:47Z" }, "spec": { @@ -2052,7 +2040,7 @@ { "metadata": { "name": "scenes", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-07-07T06:53:02Z" }, "spec": { @@ -2065,7 +2053,7 @@ { "metadata": { "name": "scopeFilters", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-03-05T15:41:19Z" }, "spec": { @@ -2079,7 +2067,7 @@ { "metadata": { "name": "showDashboardValidationWarnings", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-10-14T13:51:05Z" }, "spec": { @@ -2091,7 +2079,7 @@ { "metadata": { "name": "sqlDatasourceDatabaseSelection", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-06-06T16:28:52Z" }, "spec": { @@ -2105,7 +2093,7 @@ { "metadata": { "name": "sqlExpressions", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-02-27T21:16:00Z" }, "spec": { @@ -2117,7 +2105,7 @@ { "metadata": { "name": "sseGroupByDatasource", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-09-07T20:02:07Z" }, "spec": { @@ -2129,7 +2117,7 @@ { "metadata": { "name": "ssoSettingsApi", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-11-08T09:50:01Z" }, "spec": { @@ -2142,8 +2130,8 @@ { "metadata": { "name": "ssoSettingsLDAP", - "resourceVersion": "1718624569822", - "creationTimestamp": "2024-06-17T11:42:49Z" + "resourceVersion": "1718727528075", + "creationTimestamp": "2024-06-18T16:18:48Z" }, "spec": { "description": "Use the new SSO Settings API to configure LDAP", @@ -2156,7 +2144,7 @@ { "metadata": { "name": "ssoSettingsSAML", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-03-14T11:04:45Z" }, "spec": { @@ -2169,7 +2157,7 @@ { "metadata": { "name": "storage", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-03-17T17:19:23Z" }, "spec": { @@ -2181,7 +2169,7 @@ { "metadata": { "name": "tableSharedCrosshair", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-12-13T09:33:14Z" }, "spec": { @@ -2194,7 +2182,7 @@ { "metadata": { "name": "teamHttpHeaders", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-10-17T10:23:54Z" }, "spec": { @@ -2206,7 +2194,7 @@ { "metadata": { "name": "tlsMemcached", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2024-05-09T19:12:08Z" }, "spec": { @@ -2219,7 +2207,7 @@ { "metadata": { "name": "topnav", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2022-06-20T14:25:43Z" }, "spec": { @@ -2231,7 +2219,7 @@ { "metadata": { "name": "traceQLStreaming", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-07-26T13:33:16Z" }, "spec": { @@ -2244,7 +2232,7 @@ { "metadata": { "name": "transformationsRedesign", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-07-12T16:35:49Z" }, "spec": { @@ -2258,11 +2246,8 @@ { "metadata": { "name": "transformationsVariableSupport", - "resourceVersion": "1718190346540", - "creationTimestamp": "2023-10-04T14:28:46Z", - "annotations": { - "grafana.app/updatedTimestamp": "2024-06-12 11:05:46.540869 +0000 UTC" - } + "resourceVersion": "1718727528075", + "creationTimestamp": "2023-10-04T14:28:46Z" }, "spec": { "description": "Allows using variables in transformations", @@ -2274,7 +2259,7 @@ { "metadata": { "name": "unifiedRequestLog", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-03-31T13:38:09Z" }, "spec": { @@ -2286,7 +2271,7 @@ { "metadata": { "name": "unifiedStorage", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-12-06T20:21:21Z" }, "spec": { @@ -2299,7 +2284,7 @@ { "metadata": { "name": "vizAndWidgetSplit", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-06-27T10:22:13Z" }, "spec": { @@ -2312,7 +2297,7 @@ { "metadata": { "name": "wargamesTesting", - "resourceVersion": "1717578796182", + "resourceVersion": "1718727528075", "creationTimestamp": "2023-09-13T18:32:01Z" }, "spec": { diff --git a/pkg/services/ngalert/remote/alertmanager.go b/pkg/services/ngalert/remote/alertmanager.go index 4feca91ed4b..2014220eda9 100644 --- a/pkg/services/ngalert/remote/alertmanager.go +++ b/pkg/services/ngalert/remote/alertmanager.go @@ -15,7 +15,6 @@ import ( amalert "github.com/prometheus/alertmanager/api/v2/client/alert" amalertgroup "github.com/prometheus/alertmanager/api/v2/client/alertgroup" amgeneral "github.com/prometheus/alertmanager/api/v2/client/general" - amreceiver "github.com/prometheus/alertmanager/api/v2/client/receiver" amsilence "github.com/prometheus/alertmanager/api/v2/client/silence" "github.com/prometheus/client_golang/prometheus" @@ -487,21 +486,7 @@ func (am *Alertmanager) GetStatus(ctx context.Context) (apimodels.GettableStatus } func (am *Alertmanager) GetReceivers(ctx context.Context) ([]apimodels.Receiver, error) { - params := amreceiver.NewGetReceiversParamsWithContext(ctx) - res, err := am.amClient.Receiver.GetReceivers(params) - if err != nil { - return []apimodels.Receiver{}, err - } - - rcvs := make([]apimodels.Receiver, len(res.Payload)) - for i, rcv := range res.Payload { - rcvs[i] = apimodels.Receiver{ - Name: *rcv.Name, - Integrations: []apimodels.Integration{}, - } - } - - return rcvs, nil + return am.mimirClient.GetReceivers(ctx) } func (am *Alertmanager) TestReceivers(ctx context.Context, c apimodels.TestReceiversConfigBodyParams) (*notifier.TestReceiversResult, error) { diff --git a/pkg/services/ngalert/remote/alertmanager_test.go b/pkg/services/ngalert/remote/alertmanager_test.go index 5016ab49e38..9617a0f820d 100644 --- a/pkg/services/ngalert/remote/alertmanager_test.go +++ b/pkg/services/ngalert/remote/alertmanager_test.go @@ -717,7 +717,13 @@ func TestIntegrationRemoteAlertmanagerReceivers(t *testing.T) { // We should start with the default config. rcvs, err := am.GetReceivers(context.Background()) require.NoError(t, err) - require.Equal(t, "empty-receiver", rcvs[0].Name) + require.Equal(t, []apimodels.Receiver{ + { + Active: true, + Name: "empty-receiver", + Integrations: []apimodels.Integration{}, + }, + }, rcvs) } func genAlert(active bool, labels map[string]string) amv2.PostableAlert { diff --git a/pkg/services/ngalert/remote/client/alertmanager_configuration.go b/pkg/services/ngalert/remote/client/alertmanager_configuration.go index f3a66451163..ebb61ce9196 100644 --- a/pkg/services/ngalert/remote/client/alertmanager_configuration.go +++ b/pkg/services/ngalert/remote/client/alertmanager_configuration.go @@ -11,7 +11,8 @@ import ( ) const ( - grafanaAlertmanagerConfigPath = "/api/v1/grafana/config" + grafanaAlertmanagerConfigPath = "/api/v1/grafana/config" + grafanaAlertmanagerReceiversPath = "/api/v1/grafana/receivers" ) type UserGrafanaConfig struct { @@ -63,3 +64,16 @@ func (mc *Mimir) CreateGrafanaAlertmanagerConfig(ctx context.Context, cfg *apimo func (mc *Mimir) DeleteGrafanaAlertmanagerConfig(ctx context.Context) error { return mc.doOK(ctx, grafanaAlertmanagerConfigPath, http.MethodDelete, nil) } + +func (mc *Mimir) GetReceivers(ctx context.Context) ([]apimodels.Receiver, error) { + response := []apimodels.Receiver{} + + // nolint:bodyclose + // closed within `do` + _, err := mc.do(ctx, grafanaAlertmanagerReceiversPath, http.MethodGet, nil, &response) + if err != nil { + return nil, err + } + + return response, nil +} diff --git a/pkg/services/ngalert/remote/client/mimir.go b/pkg/services/ngalert/remote/client/mimir.go index cf0a0941652..1fda8206c4d 100644 --- a/pkg/services/ngalert/remote/client/mimir.go +++ b/pkg/services/ngalert/remote/client/mimir.go @@ -29,6 +29,9 @@ type MimirClient interface { DeleteGrafanaAlertmanagerConfig(ctx context.Context) error ShouldPromoteConfig() bool + + // Mimir implements an extended version of the receivers API under a different path. + GetReceivers(ctx context.Context) ([]apimodels.Receiver, error) } type Mimir struct { diff --git a/pkg/services/notifications/webhook.go b/pkg/services/notifications/webhook.go index 6ff7df5efe8..7fbaf59eaad 100644 --- a/pkg/services/notifications/webhook.go +++ b/pkg/services/notifications/webhook.go @@ -4,10 +4,12 @@ import ( "bytes" "context" "crypto/tls" + "errors" "fmt" "io" "net" "net/http" + "net/url" "time" "github.com/grafana/grafana/pkg/util" @@ -62,6 +64,11 @@ func (ns *NotificationService) sendWebRequestSync(ctx context.Context, webhook * if err != nil { return err } + url, err := url.Parse(webhook.Url) + if err != nil { + // Should not be possible - NewRequestWithContext should also err if the URL is bad. + return err + } if webhook.ContentType == "" { webhook.ContentType = "application/json" @@ -80,7 +87,7 @@ func (ns *NotificationService) sendWebRequestSync(ctx context.Context, webhook * resp, err := netClient.Do(request) if err != nil { - return err + return redactURL(err) } defer func() { if err := resp.Body.Close(); err != nil { @@ -96,16 +103,25 @@ func (ns *NotificationService) sendWebRequestSync(ctx context.Context, webhook * if webhook.Validation != nil { err := webhook.Validation(body, resp.StatusCode) if err != nil { - ns.log.Debug("Webhook failed validation", "url", webhook.Url, "statuscode", resp.Status, "body", string(body)) + ns.log.Debug("Webhook failed validation", "url", url.Redacted(), "statuscode", resp.Status, "body", string(body), "error", err) return fmt.Errorf("webhook failed validation: %w", err) } } if resp.StatusCode/100 == 2 { - ns.log.Debug("Webhook succeeded", "url", webhook.Url, "statuscode", resp.Status) + ns.log.Debug("Webhook succeeded", "url", url.Redacted(), "statuscode", resp.Status) return nil } - ns.log.Debug("Webhook failed", "url", webhook.Url, "statuscode", resp.Status, "body", string(body)) + ns.log.Debug("Webhook failed", "url", url.Redacted(), "statuscode", resp.Status, "body", string(body)) return fmt.Errorf("webhook response status %v", resp.Status) } + +func redactURL(err error) error { + var e *url.Error + if !errors.As(err, &e) { + return err + } + e.URL = "" + return e +} diff --git a/pkg/tsdb/influxdb/flux/macros.go b/pkg/tsdb/influxdb/flux/macros.go index 4dce9d76822..fbec2b4d1fe 100644 --- a/pkg/tsdb/influxdb/flux/macros.go +++ b/pkg/tsdb/influxdb/flux/macros.go @@ -25,27 +25,40 @@ func interpolateInterval(flux string, interval time.Duration) string { var fluxVariableFilterExp = regexp.MustCompile(`(?m)([a-zA-Z]+)\.([a-zA-Z]+)`) func interpolateFluxSpecificVariables(query queryModel) string { + rawQuery := query.RawQuery flux := query.RawQuery - matches := fluxVariableFilterExp.FindAllStringSubmatch(flux, -1) + matches := fluxVariableFilterExp.FindAllStringSubmatchIndex(rawQuery, -1) if matches != nil { timeRange := query.TimeRange from := timeRange.From.UTC().Format(time.RFC3339Nano) to := timeRange.To.UTC().Format(time.RFC3339Nano) for _, match := range matches { - switch match[2] { + // For query "range(start: v.timeRangeStart, stop: v.timeRangeStop)" + // rawQuery[match[0]:match[1]] will be v.timeRangeStart + // rawQuery[match[2]:match[3]] will be v + // rawQuery[match[4]:match[5]] will be timeRangeStart + fullMatch := rawQuery[match[0]:match[1]] + key := rawQuery[match[4]:match[5]] + + switch key { case "timeRangeStart": - flux = strings.ReplaceAll(flux, match[0], from) + flux = strings.ReplaceAll(flux, fullMatch, from) case "timeRangeStop": - flux = strings.ReplaceAll(flux, match[0], to) + flux = strings.ReplaceAll(flux, fullMatch, to) case "windowPeriod": - flux = strings.ReplaceAll(flux, match[0], query.Interval.String()) + flux = strings.ReplaceAll(flux, fullMatch, query.Interval.String()) case "bucket": - flux = strings.ReplaceAll(flux, match[0], "\""+query.Options.Bucket+"\"") + // Check if 'bucket' is part of a join query + beforeMatch := rawQuery[:match[0]] + if strings.Contains(beforeMatch, "join.") { + continue + } + flux = strings.ReplaceAll(flux, fullMatch, "\""+query.Options.Bucket+"\"") case "defaultBucket": - flux = strings.ReplaceAll(flux, match[0], "\""+query.Options.DefaultBucket+"\"") + flux = strings.ReplaceAll(flux, fullMatch, "\""+query.Options.DefaultBucket+"\"") case "organization": - flux = strings.ReplaceAll(flux, match[0], "\""+query.Options.Organization+"\"") + flux = strings.ReplaceAll(flux, fullMatch, "\""+query.Options.Organization+"\"") } } } diff --git a/pkg/tsdb/influxdb/flux/macros_test.go b/pkg/tsdb/influxdb/flux/macros_test.go index 9bf0fa3570a..283835ab24e 100644 --- a/pkg/tsdb/influxdb/flux/macros_test.go +++ b/pkg/tsdb/influxdb/flux/macros_test.go @@ -31,6 +31,11 @@ func TestInterpolate(t *testing.T) { before: `v.timeRangeStart, something.timeRangeStop, XYZ.bucket, uuUUu.defaultBucket, aBcDefG.organization, window.windowPeriod, a91{}.bucket, $__interval, $__interval_ms`, after: `2021-09-22T10:12:51.310985041Z, 2021-09-22T11:12:51.310985042Z, "grafana2", "grafana3", "grafana1", 1m1.258s, a91{}.bucket, 1m, 61258`, }, + { + name: "don't interpolate bucket variable in join query", + before: `range(start: v.timeRangeStart, stop: v.timeRangeStop) join.left(left: left |> group(), right: right,on:((l,r) => l.bucket == r.id), as: ((l, r) => ({l with name: r.name})))`, + after: `range(start: 2021-09-22T10:12:51.310985041Z, stop: 2021-09-22T11:12:51.310985042Z) join.left(left: left |> group(), right: right,on:((l,r) => l.bucket == r.id), as: ((l, r) => ({l with name: r.name})))`, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/public/app/core/components/PageNotFound/EntityNotFound.tsx b/public/app/core/components/PageNotFound/EntityNotFound.tsx index 24edfa76f5c..c749d30aa19 100644 --- a/public/app/core/components/PageNotFound/EntityNotFound.tsx +++ b/public/app/core/components/PageNotFound/EntityNotFound.tsx @@ -2,6 +2,7 @@ import { css } from '@emotion/css'; import React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; +import { selectors } from '@grafana/e2e-selectors'; import { EmptyState, TextLink, useStyles2 } from '@grafana/ui'; export interface Props { @@ -15,7 +16,7 @@ export function EntityNotFound({ entity = 'Page' }: Props) { const styles = useStyles2(getStyles); return ( -
+
We're looking but can't seem to find this {entity.toLowerCase()}. Try returning{' '} home or seeking help on the{' '} diff --git a/public/app/core/internationalization/dates.ts b/public/app/core/internationalization/dates.ts new file mode 100644 index 00000000000..429db533901 --- /dev/null +++ b/public/app/core/internationalization/dates.ts @@ -0,0 +1,20 @@ +import '@formatjs/intl-durationformat/polyfill'; + +import { getI18next } from './index'; + +export function formatDate(value: number | Date | string, format: Intl.DateTimeFormatOptions = {}): string { + if (typeof value === 'string') { + return formatDate(new Date(value), format); + } + + const i18n = getI18next(); + const dateFormatter = new Intl.DateTimeFormat(i18n.language, format); + return dateFormatter.format(value); +} + +export function formatDuration(duration: Intl.DurationInput, options: Intl.DurationFormatOptions = {}) { + const i18n = getI18next(); + + const dateFormatter = new Intl.DurationFormat(i18n.language, options); + return dateFormatter.format(duration); +} diff --git a/public/app/core/internationalization/index.tsx b/public/app/core/internationalization/index.tsx index 812fc4f83b7..f111be88b98 100644 --- a/public/app/core/internationalization/index.tsx +++ b/public/app/core/internationalization/index.tsx @@ -7,6 +7,7 @@ import { DEFAULT_LANGUAGE, NAMESPACES, VALID_LANGUAGES } from './constants'; import { loadTranslations } from './loadTranslations'; let tFunc: TFunction | undefined; +let i18nInstance: typeof i18n; export async function initializeI18n(language: string): Promise<{ language: string | undefined }> { // This is a placeholder so we can put a 'comment' in the message json files. @@ -28,7 +29,7 @@ export async function initializeI18n(language: string): Promise<{ language: stri ns: NAMESPACES, }; - let i18nInstance = i18n; + i18nInstance = i18n; if (language === 'detect') { i18nInstance = i18nInstance.use(LanguageDetector); const detection: DetectorOptions = { order: ['navigator'], caches: [] }; @@ -79,10 +80,20 @@ export const t = (id: string, defaultMessage: string, values?: Record { - if (typeof value === 'string') { - return i18nDate(new Date(value), format); +export function getI18next() { + if (!tFunc) { + if (process.env.NODE_ENV !== 'test') { + console.warn( + 'An attempt to internationalize was made before it was initialized. This was probably caused by calling a locale-aware function in the root module scope, instead of in render' + ); + } + + if (process.env.NODE_ENV === 'development') { + throw new Error('getI18next was called before i18n was initialized'); + } + + return i18n; } - const dateFormatter = new Intl.DateTimeFormat(i18n.language, format); - return dateFormatter.format(value); -}; + + return i18nInstance || i18n; +} diff --git a/public/app/core/internationalization/types.d.ts b/public/app/core/internationalization/types.d.ts new file mode 100644 index 00000000000..7a4ac64930c --- /dev/null +++ b/public/app/core/internationalization/types.d.ts @@ -0,0 +1,13 @@ +import { + DurationFormatConstructor, + DurationFormatOptions as _DurationFormatOptions, + DurationInput as _DurationInput, +} from '@formatjs/intl-durationformat/src/types'; + +declare global { + namespace Intl { + const DurationFormat: DurationFormatConstructor; + type DurationFormatOptions = _DurationFormatOptions; + type DurationInput = _DurationInput; + } +} diff --git a/public/app/core/services/echo/backends/PerformanceBackend.ts b/public/app/core/services/echo/backends/PerformanceBackend.ts index 29ff37882bc..7fd3a18d572 100644 --- a/public/app/core/services/echo/backends/PerformanceBackend.ts +++ b/public/app/core/services/echo/backends/PerformanceBackend.ts @@ -32,9 +32,17 @@ export class PerformanceBackend implements EchoBackend { + // Just swallow this error - it's non-critical + }); this.buffer = []; }; diff --git a/public/app/features/admin/UserSessions.tsx b/public/app/features/admin/UserSessions.tsx index 465072ba34d..91f8694998b 100644 --- a/public/app/features/admin/UserSessions.tsx +++ b/public/app/features/admin/UserSessions.tsx @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import { ConfirmButton, ConfirmModal, Button, Stack } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; -import { i18nDate } from 'app/core/internationalization'; +import { formatDate } from 'app/core/internationalization/dates'; import { AccessControlAction, UserSession } from 'app/types'; interface Props { @@ -68,7 +68,7 @@ class BaseUserSessions extends PureComponent { sessions.map((session, index) => ( {session.isActive ? 'Now' : session.seenAt} - {i18nDate(session.createdAt, { dateStyle: 'long' })} + {formatDate(session.createdAt, { dateStyle: 'long' })} {session.clientIp} {`${session.browser} on ${session.os} ${session.osVersion}`} diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx index bb4488f705f..91e50fba9e1 100644 --- a/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx @@ -200,6 +200,20 @@ describe('DashboardScene', () => { expect(resoredLayout.state.children.map((c) => c.state.key)).toEqual(originalPanelOrder); }); + it('Should exit edit mode and discard panel changes if leaving the dashboard while in panel edit', () => { + const panel = findVizPanelByKey(scene, 'panel-1'); + const editPanel = buildPanelEditScene(panel!); + scene.setState({ + editPanel, + }); + + expect(scene.state.editPanel!['_discardChanges']).toBe(false); + + scene.exitEditMode({ skipConfirm: true }); + + expect(scene.state.editPanel!['_discardChanges']).toBe(true); + }); + it.each` prop | value ${'title'} | ${'new title'} diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.tsx index 83b0edbc9c3..2b04bec57de 100644 --- a/public/app/features/dashboard-scene/scene/DashboardScene.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardScene.tsx @@ -317,6 +317,13 @@ export class DashboardScene extends SceneObjectBase { this.setState({ isEditing: false }); } + // if we are in edit panel, we need to onDiscard() + // so the useEffect cleanup comes later and + // doesn't try to commit the changes + if (this.state.editPanel) { + this.state.editPanel.onDiscard(); + } + // Disable grid dragging this.propagateEditModeChange(); } @@ -385,6 +392,10 @@ export class DashboardScene extends SceneObjectBase { public getPageNav(location: H.Location, navIndex: NavIndex) { const { meta, viewPanelScene, editPanel } = this.state; + if (meta.dashboardNotFound) { + return { text: 'Not found' }; + } + let pageNav: NavModelItem = { text: this.state.title, url: getDashboardUrl({ diff --git a/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.test.tsx b/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.test.tsx new file mode 100644 index 00000000000..47d5cd076b3 --- /dev/null +++ b/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.test.tsx @@ -0,0 +1,65 @@ +import { render, screen } from '@testing-library/react'; +import React from 'react'; +import { Provider } from 'react-redux'; +import { Router } from 'react-router'; +import { getGrafanaContextMock } from 'test/mocks/getGrafanaContextMock'; + +import { selectors } from '@grafana/e2e-selectors'; +import { locationService } from '@grafana/runtime'; +import { GrafanaContext } from 'app/core/context/GrafanaContext'; +import { configureStore } from 'app/store/configureStore'; + +import { transformSaveModelToScene } from '../serialization/transformSaveModelToScene'; + +describe('DashboardSceneRenderer', () => { + it('should render Not Found notice when dashboard is not found', async () => { + const scene = transformSaveModelToScene({ + meta: { + isSnapshot: true, + dashboardNotFound: true, + canStar: false, + canDelete: false, + canSave: false, + canEdit: false, + canShare: false, + }, + dashboard: { + title: 'Not found', + uid: 'uid', + schemaVersion: 0, + // Disabling build in annotations to avoid mocking Grafana data source + annotations: { + list: [ + { + builtIn: 1, + datasource: { + type: 'grafana', + uid: '-- Grafana --', + }, + enable: false, + hide: true, + iconColor: 'rgba(0, 211, 255, 1)', + name: 'Annotations & Alerts', + type: 'dashboard', + }, + ], + }, + }, + }); + + const store = configureStore({}); + const context = getGrafanaContextMock(); + + render( + + + + + + + + ); + + expect(await screen.findByTestId(selectors.components.EntityNotFound.container)).toBeInTheDocument(); + }); +}); diff --git a/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx b/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx index 553710923cf..7687efa6107 100644 --- a/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx @@ -7,6 +7,7 @@ import { selectors } from '@grafana/e2e-selectors'; import { SceneComponentProps } from '@grafana/scenes'; import { CustomScrollbar, useStyles2 } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; +import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound'; import { getNavModel } from 'app/core/selectors/navModel'; import DashboardEmpty from 'app/features/dashboard/dashgrid/DashboardEmpty'; import { useSelector } from 'app/types'; @@ -35,14 +36,26 @@ export function DashboardSceneRenderer({ model }: SceneComponentProps; + const emptyState = ( + + ); const withPanels = ( -
+
); + const notFound = meta.dashboardNotFound && ; + + let body = [withPanels]; + + if (notFound) { + body = [notFound]; + } else if (isEmpty) { + body = [emptyState, withPanels]; + } + return ( {editPanel && } @@ -55,7 +68,7 @@ export function DashboardSceneRenderer({ model }: SceneComponentProps - {scopes && } + {scopes && !meta.dashboardNotFound && } {controls && hasControls && (
-
- <>{isEmpty && emptyState} - {withPanels} -
+
{body}
)} diff --git a/public/app/features/dashboard-scene/scene/NavToolbarActions.test.tsx b/public/app/features/dashboard-scene/scene/NavToolbarActions.test.tsx index 797a80fe51d..ce2bfb8fa66 100644 --- a/public/app/features/dashboard-scene/scene/NavToolbarActions.test.tsx +++ b/public/app/features/dashboard-scene/scene/NavToolbarActions.test.tsx @@ -8,6 +8,7 @@ import { selectors } from '@grafana/e2e-selectors'; import { config, locationService } from '@grafana/runtime'; import { SceneGridLayout, SceneQueryRunner, SceneTimeRange, UrlSyncContextProvider, VizPanel } from '@grafana/scenes'; import { playlistSrv } from 'app/features/playlist/PlaylistSrv'; +import { DashboardMeta } from 'app/types'; import { buildPanelEditScene } from '../panel-edit/PanelEditor'; @@ -163,9 +164,27 @@ describe('NavToolbarActions', () => { expect(newShareButton).toBeInTheDocument(); }); }); + + describe('Snapshot', () => { + it('should show link button when is a snapshot', () => { + setup({ + isSnapshot: true, + }); + + expect(screen.queryByTestId('button-snapshot')).toBeInTheDocument(); + }); + it('should not show link button when is not found dashboard', () => { + setup({ + isSnapshot: true, + dashboardNotFound: true, + }); + + expect(screen.queryByTestId('button-snapshot')).not.toBeInTheDocument(); + }); + }); }); -function setup() { +function setup(meta?: DashboardMeta) { const dashboard = new DashboardScene({ $timeRange: new SceneTimeRange({ from: 'now-6h', to: 'now' }), meta: { @@ -177,6 +196,7 @@ function setup() { canStar: true, canAdmin: true, canDelete: true, + ...meta, }, title: 'hello', uid: 'dash-1', diff --git a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx index 18a6a336ccf..47a714cc1dc 100644 --- a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx +++ b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx @@ -139,7 +139,7 @@ export function ToolbarActions({ dashboard }: Props) { toolbarActions.push({ group: 'icon-actions', - condition: meta.isSnapshot && !isEditing, + condition: meta.isSnapshot && !meta.dashboardNotFound && !isEditing, render: () => ( { - return this._dashboardLoadFailed('Not found', true); + const dash = this._dashboardLoadFailed('Not found', true); + dash.dashboard.uid = uid; + return dash; }); } else { throw new Error('Dashboard uid or slug required'); diff --git a/public/app/features/profile/UserSessions.tsx b/public/app/features/profile/UserSessions.tsx index ec9dbb034e7..9d93c5a9e08 100644 --- a/public/app/features/profile/UserSessions.tsx +++ b/public/app/features/profile/UserSessions.tsx @@ -4,7 +4,8 @@ import React, { PureComponent } from 'react'; import { selectors } from '@grafana/e2e-selectors'; import { Button, Icon, LoadingPlaceholder } from '@grafana/ui'; -import { i18nDate, Trans } from 'app/core/internationalization'; +import { Trans } from 'app/core/internationalization'; +import { formatDate } from 'app/core/internationalization/dates'; import { UserSession } from 'app/types'; interface Props { @@ -50,7 +51,7 @@ class UserSessions extends PureComponent { {sessions.map((session: UserSession, index) => ( {session.isActive ? Now : {session.seenAt}} - {i18nDate(session.createdAt, { dateStyle: 'long' })} + {formatDate(session.createdAt, { dateStyle: 'long' })} {session.clientIp} {session.browser} on {session.os} {session.osVersion} diff --git a/public/app/features/transformers/calculateHeatmap/heatmap.ts b/public/app/features/transformers/calculateHeatmap/heatmap.ts index 1de1d638361..538b2c9a97a 100644 --- a/public/app/features/transformers/calculateHeatmap/heatmap.ts +++ b/public/app/features/transformers/calculateHeatmap/heatmap.ts @@ -15,6 +15,7 @@ import { durationToMilliseconds, parseDuration, TransformationApplicabilityLevels, + TimeRange, } from '@grafana/data'; import { isLikelyAscendingVector } from '@grafana/data/src/transformations/transformers/joinDataFrames'; import { config } from '@grafana/runtime'; @@ -292,7 +293,14 @@ export function prepBucketFrames(frames: DataFrame[]): DataFrame[] { })); } -export function calculateHeatmapFromData(frames: DataFrame[], options: HeatmapCalculationOptions): DataFrame { +interface HeatmapCalculationOptionsWithTimeRange extends HeatmapCalculationOptions { + timeRange?: TimeRange; +} + +export function calculateHeatmapFromData( + frames: DataFrame[], + options: HeatmapCalculationOptionsWithTimeRange +): DataFrame { // Find fields in the heatmap const { xField, yField, xs, ys } = findHeatmapFields(frames); @@ -329,6 +337,9 @@ export function calculateHeatmapFromData(frames: DataFrame[], options: HeatmapCa ySize: yBucketsCfg.value ? +yBucketsCfg.value : undefined, yLog: scaleDistribution?.type === ScaleDistribution.Log ? (scaleDistribution?.log as 2 | 10 | undefined) : undefined, + + xMin: options.timeRange?.from.valueOf(), + xMax: options.timeRange?.to.valueOf(), }); const frame = { @@ -460,20 +471,23 @@ function heatmap(xs: number[], ys: number[], opts?: HeatmapOpts) { let ySorted = opts?.ySorted ?? false; // find x and y limits to pre-compute buckets struct - let minX = xSorted ? xs[0] : Infinity; + let minX = opts?.xMin ?? (xSorted ? xs[0] : Infinity); let minY = ySorted ? ys[0] : Infinity; - let maxX = xSorted ? xs[len - 1] : -Infinity; + let maxX = opts?.xMax ?? (xSorted ? xs[len - 1] : -Infinity); let maxY = ySorted ? ys[len - 1] : -Infinity; let yExp = opts?.yLog; + let withPredefX = opts?.xMin != null && opts?.xMax != null; + let withPredefY = opts?.yMin != null && opts?.yMax != null; + for (let i = 0; i < len; i++) { - if (!xSorted) { + if (!xSorted && !withPredefX) { minX = Math.min(minX, xs[i]); maxX = Math.max(maxX, xs[i]); } - if (!ySorted) { + if (!ySorted && !withPredefY) { if (!yExp || ys[i] > 0) { minY = Math.min(minY, ys[i]); maxY = Math.max(maxY, ys[i]); @@ -500,7 +514,6 @@ function heatmap(xs: number[], ys: number[], opts?: HeatmapOpts) { } if (xMode === HeatmapCalculationMode.Count) { - // TODO: optionally use view range min/max instead of data range for bucket sizing let approx = (maxX - minX) / Math.max(xBinIncr - 1, 1); // nice-ify let xIncrs = opts?.xTime ? niceTimeIncrs : niceLinearIncrs; @@ -509,7 +522,6 @@ function heatmap(xs: number[], ys: number[], opts?: HeatmapOpts) { } if (yMode === HeatmapCalculationMode.Count) { - // TODO: optionally use view range min/max instead of data range for bucket sizing let approx = (maxY - minY) / Math.max(yBinIncr - 1, 1); // nice-ify let yIncrs = opts?.yTime ? niceTimeIncrs : niceLinearIncrs; diff --git a/public/app/plugins/datasource/influxdb/fsql/sqlUtil.test.ts b/public/app/plugins/datasource/influxdb/fsql/sqlUtil.test.ts index 4864004b8ec..7ca87d9f8ae 100644 --- a/public/app/plugins/datasource/influxdb/fsql/sqlUtil.test.ts +++ b/public/app/plugins/datasource/influxdb/fsql/sqlUtil.test.ts @@ -78,4 +78,29 @@ describe('toRawSql', () => { const result = toRawSql(testQuery); expect(result).toEqual(expected); }); + + it('should not wrap * with quote', () => { + const expected = 'SELECT * FROM "TestValue" WHERE "time" >= $__timeFrom AND "time" <= $__timeTo LIMIT 50'; + const testQuery: SQLQuery = { + refId: 'A', + sql: { + limit: 50, + columns: [ + { + parameters: [ + { + name: '*', + type: QueryEditorExpressionType.FunctionParameter, + }, + ], + type: QueryEditorExpressionType.Function, + }, + ], + }, + dataset: 'iox', + table: 'TestValue', + }; + const result = toRawSql(testQuery); + expect(result).toEqual(expected); + }); }); diff --git a/public/app/plugins/datasource/influxdb/fsql/sqlUtil.ts b/public/app/plugins/datasource/influxdb/fsql/sqlUtil.ts index 41317454a95..8d357fce734 100644 --- a/public/app/plugins/datasource/influxdb/fsql/sqlUtil.ts +++ b/public/app/plugins/datasource/influxdb/fsql/sqlUtil.ts @@ -26,7 +26,10 @@ export function toRawSql({ sql, table }: SQLQuery): string { } // wrapping the column name with quotes - const sc = sql.columns.map((c) => ({ ...c, parameters: c.parameters?.map((p) => ({ ...p, name: `"${p.name}"` })) })); + const sc = sql.columns.map((c) => ({ + ...c, + parameters: c.parameters?.map((p) => ({ ...p, name: formatTableName(p.name) })), + })); rawQuery += createSelectClause(sc); if (table) { @@ -66,6 +69,16 @@ export function toRawSql({ sql, table }: SQLQuery): string { return rawQuery; } +// When the column name is *, do not wrap the column name in double-quotes. +// See: https://github.com/grafana/grafana/issues/88008 +function formatTableName(parameter: string | undefined): string { + if (parameter === '*') { + return parameter; + } + + return `"${parameter}"`; +} + const isLimit = (limit: number | undefined): boolean => limit !== undefined && limit >= 0; // Puts double quotes (") around the identifier if it is necessary. diff --git a/public/app/plugins/datasource/influxdb/variables.ts b/public/app/plugins/datasource/influxdb/variables.ts index a51430f62bd..f3ee7eb75b5 100644 --- a/public/app/plugins/datasource/influxdb/variables.ts +++ b/public/app/plugins/datasource/influxdb/variables.ts @@ -40,7 +40,7 @@ export class InfluxVariableSupport extends CustomVariableSupport ({ data: results }))); diff --git a/public/app/plugins/panel/heatmap/HeatmapPanel.tsx b/public/app/plugins/panel/heatmap/HeatmapPanel.tsx index f3cde37e399..b7ce5ab2be9 100644 --- a/public/app/plugins/panel/heatmap/HeatmapPanel.tsx +++ b/public/app/plugins/panel/heatmap/HeatmapPanel.tsx @@ -59,11 +59,19 @@ export const HeatmapPanel = ({ const info = useMemo(() => { try { - return prepareHeatmapData(data.series, data.annotations, options, palette, theme, replaceVariables); + return prepareHeatmapData({ + frames: data.series, + annotations: data.annotations, + options, + palette, + theme, + replaceVariables, + timeRange, + }); } catch (ex) { return { warning: `${ex}` }; } - }, [data.series, data.annotations, options, palette, theme, replaceVariables]); + }, [data.series, data.annotations, options, palette, theme, replaceVariables, timeRange]); const facets = useMemo(() => { let exemplarsXFacet: number[] | undefined = []; // "Time" field diff --git a/public/app/plugins/panel/heatmap/fields.ts b/public/app/plugins/panel/heatmap/fields.ts index aeb79a3538f..534d963e92e 100644 --- a/public/app/plugins/panel/heatmap/fields.ts +++ b/public/app/plugins/panel/heatmap/fields.ts @@ -10,6 +10,7 @@ import { GrafanaTheme2, InterpolateFunction, outerJoinDataFrames, + TimeRange, ValueFormatter, } from '@grafana/data'; import { parseSampleValue, sortSeriesByLabel } from '@grafana/prometheus'; @@ -65,14 +66,25 @@ export interface HeatmapData { warning?: string; } -export function prepareHeatmapData( - frames: DataFrame[], - annotations: DataFrame[] | undefined, - options: Options, - palette: string[], - theme: GrafanaTheme2, - replaceVariables: InterpolateFunction = (v) => v -): HeatmapData { +interface PrepareHeatmapDataOptions { + frames: DataFrame[]; + annotations?: DataFrame[]; + options: Options; + palette: string[]; + theme: GrafanaTheme2; + replaceVariables?: InterpolateFunction; + timeRange?: TimeRange; +} + +export function prepareHeatmapData({ + frames, + annotations, + options, + palette, + theme, + replaceVariables = (v) => v, + timeRange, +}: PrepareHeatmapDataOptions): HeatmapData { if (!frames?.length) { return {}; } @@ -104,7 +116,7 @@ export function prepareHeatmapData( } return getDenseHeatmapData( - calculateHeatmapFromData(frames, optionsCopy.calculation ?? {}), + calculateHeatmapFromData(frames, { ...options.calculation, timeRange }), exemplars, optionsCopy, palette, @@ -113,7 +125,7 @@ export function prepareHeatmapData( } return getDenseHeatmapData( - calculateHeatmapFromData(frames, options.calculation ?? {}), + calculateHeatmapFromData(frames, { ...options.calculation, timeRange }), exemplars, options, palette, diff --git a/public/app/plugins/panel/heatmap/module.tsx b/public/app/plugins/panel/heatmap/module.tsx index 8c35609950a..660e71e7261 100644 --- a/public/app/plugins/panel/heatmap/module.tsx +++ b/public/app/plugins/panel/heatmap/module.tsx @@ -53,7 +53,12 @@ export const plugin = new PanelPlugin(HeatmapPanel) // NOTE: this feels like overkill/expensive just to assert if we have an ordinal y // can probably simplify without doing full dataprep const palette = quantizeScheme(opts.color, config.theme2); - const v = prepareHeatmapData(context.data, undefined, opts, palette, config.theme2); + const v = prepareHeatmapData({ + frames: context.data, + options: opts, + palette, + theme: config.theme2, + }); isOrdinalY = readHeatmapRowsCustomMeta(v.heatmap).yOrdinalDisplay != null; } catch {} } diff --git a/public/app/plugins/panel/heatmap/suggestions.ts b/public/app/plugins/panel/heatmap/suggestions.ts index e9778229e7e..f49de761e85 100644 --- a/public/app/plugins/panel/heatmap/suggestions.ts +++ b/public/app/plugins/panel/heatmap/suggestions.ts @@ -20,7 +20,12 @@ export class HeatmapSuggestionsSupplier { } const palette = quantizeScheme(defaultOptions.color, config.theme2); - const info = prepareHeatmapData(builder.data.series, undefined, defaultOptions, palette, config.theme2); + const info = prepareHeatmapData({ + frames: builder.data.series, + options: defaultOptions, + palette, + theme: config.theme2, + }); if (!info || info.warning) { return; } diff --git a/scripts/drone/utils/images.star b/scripts/drone/utils/images.star index 3a0114cb442..5f85f735b08 100644 --- a/scripts/drone/utils/images.star +++ b/scripts/drone/utils/images.star @@ -21,7 +21,7 @@ images = { "plugins_slack": "plugins/slack", "python": "python:3.8", "postgres_alpine": "postgres:12.3-alpine", - "mimir": "us.gcr.io/kubernetes-dev/mimir:santihernandezc-validate_grafana_am_config-1e903e462-WIP", + "mimir": "grafana/mimir-alpine:r295-a23e559", "mysql5": "mysql:5.7.39", "mysql8": "mysql:8.0.32", "redis_alpine": "redis:6.2.11-alpine", diff --git a/yarn.lock b/yarn.lock index 4529834161a..079e080a949 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2503,6 +2503,16 @@ __metadata: languageName: node linkType: hard +"@formatjs/ecma402-abstract@npm:2.0.0": + version: 2.0.0 + resolution: "@formatjs/ecma402-abstract@npm:2.0.0" + dependencies: + "@formatjs/intl-localematcher": "npm:0.5.4" + tslib: "npm:^2.4.0" + checksum: 10/41543ba509ea3c7d6530d57b888115f7ca242f13462a951fae4d1d1f28bae10c999f4dea28a71d2f08366d4889a3f5276cae3a16c6f6417b841a84fd314c2234 + languageName: node + linkType: hard + "@formatjs/fast-memoize@npm:1.2.6": version: 1.2.6 resolution: "@formatjs/fast-memoize@npm:1.2.6" @@ -2533,6 +2543,17 @@ __metadata: languageName: node linkType: hard +"@formatjs/intl-durationformat@npm:^0.2.4": + version: 0.2.4 + resolution: "@formatjs/intl-durationformat@npm:0.2.4" + dependencies: + "@formatjs/ecma402-abstract": "npm:2.0.0" + "@formatjs/intl-localematcher": "npm:0.5.4" + tslib: "npm:^2.4.0" + checksum: 10/5f500409a20d18967e17ffbc222f9b4c4bf7ef08cce20023c33f06d1989c2bc4cf700d1dd1d048748d0a36c882109d5375896a4964d6700f73ec18914c6de4ba + languageName: node + linkType: hard + "@formatjs/intl-localematcher@npm:0.2.31": version: 0.2.31 resolution: "@formatjs/intl-localematcher@npm:0.2.31" @@ -2542,6 +2563,15 @@ __metadata: languageName: node linkType: hard +"@formatjs/intl-localematcher@npm:0.5.4": + version: 0.5.4 + resolution: "@formatjs/intl-localematcher@npm:0.5.4" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/780cb29b42e1ea87f2eb5db268577fcdc53da52d9f096871f3a1bb78603b4ba81d208ea0b0b9bc21548797c941ce435321f62d2522795b83b740f90b0ceb5778 + languageName: node + linkType: hard + "@gar/promisify@npm:^1.0.1": version: 1.1.3 resolution: "@gar/promisify@npm:1.1.3" @@ -17036,6 +17066,7 @@ __metadata: "@emotion/react": "npm:11.11.4" "@fingerprintjs/fingerprintjs": "npm:^3.4.2" "@floating-ui/react": "npm:0.26.16" + "@formatjs/intl-durationformat": "npm:^0.2.4" "@glideapps/glide-data-grid": "npm:^6.0.0" "@grafana/aws-sdk": "npm:0.3.3" "@grafana/azure-sdk": "npm:0.0.3"