Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7f584d143f | |||
| e38240369b | |||
| 26ac64cf1a | |||
| ba6a783997 | |||
| d8777012cb | |||
| dfa07d8e10 | |||
| f704b8aa79 | |||
| dc63eb3314 | |||
| c1a46fdcb5 | |||
| 7143324229 | |||
| 1e3c6fed55 | |||
| d02201f564 | |||
| 48625d67e5 | |||
| 2a9377ac02 | |||
| 8bad33de4c | |||
| 040854c8af | |||
| 987c1fc6b6 | |||
| 170ac31c5a | |||
| 0d1e0bc21c | |||
| afd84f0335 | |||
| d680537ea1 | |||
| 78d507d285 | |||
| 9d1d0e72c2 | |||
| fd955f90ac | |||
| ccb032f376 | |||
| cf452c167b |
@@ -543,6 +543,7 @@ i18next.config.ts @grafana/grafana-frontend-platform
|
|||||||
/packages/grafana-data/tsconfig.json @grafana/grafana-frontend-platform
|
/packages/grafana-data/tsconfig.json @grafana/grafana-frontend-platform
|
||||||
/packages/grafana-data/test/ @grafana/grafana-frontend-platform
|
/packages/grafana-data/test/ @grafana/grafana-frontend-platform
|
||||||
/packages/grafana-data/typings/ @grafana/grafana-frontend-platform
|
/packages/grafana-data/typings/ @grafana/grafana-frontend-platform
|
||||||
|
/packages/grafana-data/scripts/ @grafana/grafana-frontend-platform
|
||||||
|
|
||||||
/packages/grafana-data/src/**/*logs* @grafana/observability-logs
|
/packages/grafana-data/src/**/*logs* @grafana/observability-logs
|
||||||
/packages/grafana-data/src/context/plugins/ @grafana/plugins-platform-frontend
|
/packages/grafana-data/src/context/plugins/ @grafana/plugins-platform-frontend
|
||||||
|
|||||||
@@ -121,6 +121,8 @@ linters:
|
|||||||
- '**/pkg/tsdb/zipkin/**/*'
|
- '**/pkg/tsdb/zipkin/**/*'
|
||||||
- '**/pkg/tsdb/jaeger/*'
|
- '**/pkg/tsdb/jaeger/*'
|
||||||
- '**/pkg/tsdb/jaeger/**/*'
|
- '**/pkg/tsdb/jaeger/**/*'
|
||||||
|
- '**/pkg/tsdb/elasticsearch/*'
|
||||||
|
- '**/pkg/tsdb/elasticsearch/**/*'
|
||||||
deny:
|
deny:
|
||||||
- pkg: github.com/grafana/grafana/pkg/api
|
- pkg: github.com/grafana/grafana/pkg/api
|
||||||
desc: Core plugins are not allowed to depend on Grafana core packages
|
desc: Core plugins are not allowed to depend on Grafana core packages
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ type check struct {
|
|||||||
PluginStore pluginstore.Store
|
PluginStore pluginstore.Store
|
||||||
PluginContextProvider PluginContextProvider
|
PluginContextProvider PluginContextProvider
|
||||||
PluginClient plugins.Client
|
PluginClient plugins.Client
|
||||||
PluginRepo repo.Service
|
PluginRepo checks.PluginInfoGetter
|
||||||
GrafanaVersion string
|
GrafanaVersion string
|
||||||
pluginCanBeInstalledCache map[string]bool
|
pluginCanBeInstalledCache map[string]bool
|
||||||
pluginExistsCacheMu sync.RWMutex
|
pluginExistsCacheMu sync.RWMutex
|
||||||
@@ -39,7 +39,7 @@ func New(
|
|||||||
pluginStore pluginstore.Store,
|
pluginStore pluginstore.Store,
|
||||||
pluginContextProvider PluginContextProvider,
|
pluginContextProvider PluginContextProvider,
|
||||||
pluginClient plugins.Client,
|
pluginClient plugins.Client,
|
||||||
pluginRepo repo.Service,
|
pluginRepo checks.PluginInfoGetter,
|
||||||
grafanaVersion string,
|
grafanaVersion string,
|
||||||
) checks.Check {
|
) checks.Check {
|
||||||
return &check{
|
return &check{
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
|
|
||||||
type missingPluginStep struct {
|
type missingPluginStep struct {
|
||||||
PluginStore pluginstore.Store
|
PluginStore pluginstore.Store
|
||||||
PluginRepo repo.Service
|
PluginRepo checks.PluginInfoGetter
|
||||||
GrafanaVersion string
|
GrafanaVersion string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/grafana/grafana-app-sdk/logging"
|
"github.com/grafana/grafana-app-sdk/logging"
|
||||||
advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
|
advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
|
||||||
|
"github.com/grafana/grafana/pkg/plugins/repo"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Check returns metadata about the check being executed and the list of Steps
|
// Check returns metadata about the check being executed and the list of Steps
|
||||||
@@ -37,3 +38,10 @@ type Step interface {
|
|||||||
// Run executes the step for an item and returns a report
|
// Run executes the step for an item and returns a report
|
||||||
Run(ctx context.Context, log logging.Logger, obj *advisorv0alpha1.CheckSpec, item any) ([]advisorv0alpha1.CheckReportFailure, error)
|
Run(ctx context.Context, log logging.Logger, obj *advisorv0alpha1.CheckSpec, item any) ([]advisorv0alpha1.CheckReportFailure, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PluginInfoGetter is a minimal interface for retrieving plugin information from a repository.
|
||||||
|
// It contains only the GetPluginsInfo method used by plugincheck and datasourcecheck.
|
||||||
|
type PluginInfoGetter interface {
|
||||||
|
// GetPluginsInfo will return a list of plugins from grafana.com/api/plugins.
|
||||||
|
GetPluginsInfo(ctx context.Context, options repo.GetPluginsInfoOptions, compatOpts repo.CompatOpts) ([]repo.PluginInfo, error)
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const (
|
|||||||
|
|
||||||
func New(
|
func New(
|
||||||
pluginStore pluginstore.Store,
|
pluginStore pluginstore.Store,
|
||||||
pluginRepo repo.Service,
|
pluginRepo checks.PluginInfoGetter,
|
||||||
updateChecker pluginchecker.PluginUpdateChecker,
|
updateChecker pluginchecker.PluginUpdateChecker,
|
||||||
pluginErrorResolver plugins.ErrorResolver,
|
pluginErrorResolver plugins.ErrorResolver,
|
||||||
grafanaVersion string,
|
grafanaVersion string,
|
||||||
@@ -33,7 +33,7 @@ func New(
|
|||||||
|
|
||||||
type check struct {
|
type check struct {
|
||||||
PluginStore pluginstore.Store
|
PluginStore pluginstore.Store
|
||||||
PluginRepo repo.Service
|
PluginRepo checks.PluginInfoGetter
|
||||||
updateChecker pluginchecker.PluginUpdateChecker
|
updateChecker pluginchecker.PluginUpdateChecker
|
||||||
pluginErrorResolver plugins.ErrorResolver
|
pluginErrorResolver plugins.ErrorResolver
|
||||||
GrafanaVersion string
|
GrafanaVersion string
|
||||||
|
|||||||
@@ -800,6 +800,8 @@ VariableOption: {
|
|||||||
text: string | [...string]
|
text: string | [...string]
|
||||||
// Value of the option
|
// Value of the option
|
||||||
value: string | [...string]
|
value: string | [...string]
|
||||||
|
// Additional properties for multi-props variables
|
||||||
|
properties?: {[string]: string}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query variable specification
|
// Query variable specification
|
||||||
|
|||||||
@@ -804,6 +804,8 @@ VariableOption: {
|
|||||||
text: string | [...string]
|
text: string | [...string]
|
||||||
// Value of the option
|
// Value of the option
|
||||||
value: string | [...string]
|
value: string | [...string]
|
||||||
|
// Additional properties for multi-props variables
|
||||||
|
properties?: {[string]: string}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query variable specification
|
// Query variable specification
|
||||||
|
|||||||
@@ -241,6 +241,8 @@ lineage: schemas: [{
|
|||||||
text: string | [...string]
|
text: string | [...string]
|
||||||
// Value of the option
|
// Value of the option
|
||||||
value: string | [...string]
|
value: string | [...string]
|
||||||
|
// Additional properties for multi-props variables
|
||||||
|
properties?: {[string]: string}
|
||||||
} @cuetsy(kind="interface")
|
} @cuetsy(kind="interface")
|
||||||
|
|
||||||
// Options to config when to refresh a variable
|
// Options to config when to refresh a variable
|
||||||
|
|||||||
@@ -241,6 +241,8 @@ lineage: schemas: [{
|
|||||||
text: string | [...string]
|
text: string | [...string]
|
||||||
// Value of the option
|
// Value of the option
|
||||||
value: string | [...string]
|
value: string | [...string]
|
||||||
|
// Additional properties for multi-props variables
|
||||||
|
properties?: {[string]: string}
|
||||||
} @cuetsy(kind="interface")
|
} @cuetsy(kind="interface")
|
||||||
|
|
||||||
// Options to config when to refresh a variable
|
// Options to config when to refresh a variable
|
||||||
|
|||||||
@@ -804,6 +804,8 @@ VariableOption: {
|
|||||||
text: string | [...string]
|
text: string | [...string]
|
||||||
// Value of the option
|
// Value of the option
|
||||||
value: string | [...string]
|
value: string | [...string]
|
||||||
|
// Additional properties for multi-props variables
|
||||||
|
properties?: {[string]: string}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query variable specification
|
// Query variable specification
|
||||||
|
|||||||
@@ -1426,6 +1426,8 @@ type DashboardVariableOption struct {
|
|||||||
Text DashboardStringOrArrayOfString `json:"text"`
|
Text DashboardStringOrArrayOfString `json:"text"`
|
||||||
// Value of the option
|
// Value of the option
|
||||||
Value DashboardStringOrArrayOfString `json:"value"`
|
Value DashboardStringOrArrayOfString `json:"value"`
|
||||||
|
// Additional properties for multi-props variables
|
||||||
|
Properties map[string]string `json:"properties,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDashboardVariableOption creates a new DashboardVariableOption object.
|
// NewDashboardVariableOption creates a new DashboardVariableOption object.
|
||||||
|
|||||||
@@ -5133,6 +5133,22 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardVariableOption(ref common.Refer
|
|||||||
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardStringOrArrayOfString"),
|
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardStringOrArrayOfString"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"properties": {
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "Additional properties for multi-props variables",
|
||||||
|
Type: []string{"object"},
|
||||||
|
AdditionalProperties: &spec.SchemaOrBool{
|
||||||
|
Allows: true,
|
||||||
|
Schema: &spec.Schema{
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Default: "",
|
||||||
|
Type: []string{"string"},
|
||||||
|
Format: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Required: []string{"text", "value"},
|
Required: []string{"text", "value"},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -808,6 +808,8 @@ VariableOption: {
|
|||||||
text: string | [...string]
|
text: string | [...string]
|
||||||
// Value of the option
|
// Value of the option
|
||||||
value: string | [...string]
|
value: string | [...string]
|
||||||
|
// Additional properties for multi-props variables
|
||||||
|
properties?: {[string]: string}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query variable specification
|
// Query variable specification
|
||||||
|
|||||||
@@ -1429,6 +1429,8 @@ type DashboardVariableOption struct {
|
|||||||
Text DashboardStringOrArrayOfString `json:"text"`
|
Text DashboardStringOrArrayOfString `json:"text"`
|
||||||
// Value of the option
|
// Value of the option
|
||||||
Value DashboardStringOrArrayOfString `json:"value"`
|
Value DashboardStringOrArrayOfString `json:"value"`
|
||||||
|
// Additional properties for multi-props variables
|
||||||
|
Properties map[string]string `json:"properties,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDashboardVariableOption creates a new DashboardVariableOption object.
|
// NewDashboardVariableOption creates a new DashboardVariableOption object.
|
||||||
|
|||||||
@@ -5196,6 +5196,22 @@ func schema_pkg_apis_dashboard_v2beta1_DashboardVariableOption(ref common.Refere
|
|||||||
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardStringOrArrayOfString"),
|
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardStringOrArrayOfString"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"properties": {
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "Additional properties for multi-props variables",
|
||||||
|
Type: []string{"object"},
|
||||||
|
AdditionalProperties: &spec.SchemaOrBool{
|
||||||
|
Allows: true,
|
||||||
|
Schema: &spec.Schema{
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Default: "",
|
||||||
|
Type: []string{"string"},
|
||||||
|
Format: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Required: []string{"text", "value"},
|
Required: []string{"text", "value"},
|
||||||
},
|
},
|
||||||
|
|||||||
+2
-2
File diff suppressed because one or more lines are too long
@@ -103,10 +103,11 @@ To configure basic settings for the data source, complete the following steps:
|
|||||||
|
|
||||||
1. Set the data source's basic configuration options:
|
1. Set the data source's basic configuration options:
|
||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
| ----------- | ------------------------------------------------------------------------ |
|
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **Name** | Sets the name you use to refer to the data source in panels and queries. |
|
| **Name** | Sets the name you use to refer to the data source in panels and queries. |
|
||||||
| **Default** | Sets whether the data source is pre-selected for new panels. |
|
| **Default** | Sets whether the data source is pre-selected for new panels. |
|
||||||
|
| **Universe Domain** | The universe domain to connect to. For more information, refer to [Documentation on universe domains](https://docs.cloud.google.com/python/docs/reference/monitoring/latest/google.cloud.monitoring_v3.services.service_monitoring_service.ServiceMonitoringServiceAsyncClient#google_cloud_monitoring_v3_services_service_monitoring_service_ServiceMonitoringServiceAsyncClient_universe_domain). Defaults to `googleapis.com`. |
|
||||||
|
|
||||||
### Provision the data source
|
### Provision the data source
|
||||||
|
|
||||||
@@ -129,6 +130,7 @@ datasources:
|
|||||||
clientEmail: stackdriver@myproject.iam.gserviceaccount.com
|
clientEmail: stackdriver@myproject.iam.gserviceaccount.com
|
||||||
authenticationType: jwt
|
authenticationType: jwt
|
||||||
defaultProject: my-project-name
|
defaultProject: my-project-name
|
||||||
|
universeDomain: googleapis.com
|
||||||
secureJsonData:
|
secureJsonData:
|
||||||
privateKey: |
|
privateKey: |
|
||||||
-----BEGIN PRIVATE KEY-----
|
-----BEGIN PRIVATE KEY-----
|
||||||
@@ -152,6 +154,7 @@ datasources:
|
|||||||
clientEmail: stackdriver@myproject.iam.gserviceaccount.com
|
clientEmail: stackdriver@myproject.iam.gserviceaccount.com
|
||||||
authenticationType: jwt
|
authenticationType: jwt
|
||||||
defaultProject: my-project-name
|
defaultProject: my-project-name
|
||||||
|
universeDomain: googleapis.com
|
||||||
privateKeyPath: /etc/secrets/gce.pem
|
privateKeyPath: /etc/secrets/gce.pem
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -166,6 +169,7 @@ datasources:
|
|||||||
access: proxy
|
access: proxy
|
||||||
jsonData:
|
jsonData:
|
||||||
authenticationType: gce
|
authenticationType: gce
|
||||||
|
universeDomain: googleapis.com
|
||||||
```
|
```
|
||||||
|
|
||||||
## Import pre-configured dashboards
|
## Import pre-configured dashboards
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ With a Grafana Enterprise license, you also get access to premium data sources,
|
|||||||
- [CockroachDB](/grafana/plugins/grafana-cockroachdb-datasource)
|
- [CockroachDB](/grafana/plugins/grafana-cockroachdb-datasource)
|
||||||
- [Databricks](/grafana/plugins/grafana-databricks-datasource)
|
- [Databricks](/grafana/plugins/grafana-databricks-datasource)
|
||||||
- [DataDog](/grafana/plugins/grafana-datadog-datasource)
|
- [DataDog](/grafana/plugins/grafana-datadog-datasource)
|
||||||
|
- [IBM Db2](/grafana/plugins/grafana-ibmdb2-datasource)
|
||||||
- [Drone](/grafana/plugins/grafana-drone-datasource)
|
- [Drone](/grafana/plugins/grafana-drone-datasource)
|
||||||
- [DynamoDB](/grafana/plugins/grafana-dynamodb-datasource/)
|
- [DynamoDB](/grafana/plugins/grafana-dynamodb-datasource/)
|
||||||
- [Dynatrace](/grafana/plugins/grafana-dynatrace-datasource)
|
- [Dynatrace](/grafana/plugins/grafana-dynatrace-datasource)
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ Most [generally available](https://grafana.com/docs/release-life-cycle/#general-
|
|||||||
| `reportingRetries` | Enables rendering retries for the reporting feature |
|
| `reportingRetries` | Enables rendering retries for the reporting feature |
|
||||||
| `externalServiceAccounts` | Automatic service account and token setup for plugins |
|
| `externalServiceAccounts` | Automatic service account and token setup for plugins |
|
||||||
| `cloudWatchBatchQueries` | Runs CloudWatch metrics queries as separate batches |
|
| `cloudWatchBatchQueries` | Runs CloudWatch metrics queries as separate batches |
|
||||||
|
| `dashboardNewLayouts` | Enables new dashboard layouts |
|
||||||
| `pdfTables` | Enables generating table data as PDF in reporting |
|
| `pdfTables` | Enables generating table data as PDF in reporting |
|
||||||
| `canvasPanelPanZoom` | Allow pan and zoom in canvas panel |
|
| `canvasPanelPanZoom` | Allow pan and zoom in canvas panel |
|
||||||
| `alertingSaveStateCompressed` | Enables the compressed protobuf-based alert state storage. Default is enabled. |
|
| `alertingSaveStateCompressed` | Enables the compressed protobuf-based alert state storage. Default is enabled. |
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ refs:
|
|||||||
|
|
||||||
# Datagrid
|
# Datagrid
|
||||||
|
|
||||||
{{< docs/experimental product="The datagrid visualization" featureFlag="`enableDatagridEditing`" >}}
|
{{< admonition type="caution" >}}
|
||||||
|
Starting with Grafana 12.4, Datagrid is deprecated. It will be removed in version 13.0.
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
Datagrids offer you the ability to create, edit, and fine-tune data within Grafana. As such, this panel can act as a data source for other panels
|
Datagrids offer you the ability to create, edit, and fine-tune data within Grafana. As such, this panel can act as a data source for other panels
|
||||||
inside a dashboard.
|
inside a dashboard.
|
||||||
|
|||||||
@@ -3743,46 +3743,21 @@
|
|||||||
"count": 1
|
"count": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"public/app/plugins/datasource/elasticsearch/components/QueryEditor/BucketAggregationsEditor/SettingsEditor/DateHistogramSettingsEditor.tsx": {
|
|
||||||
"@typescript-eslint/consistent-type-assertions": {
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"public/app/plugins/datasource/elasticsearch/components/QueryEditor/BucketAggregationsEditor/SettingsEditor/TermsSettingsEditor.tsx": {
|
|
||||||
"@typescript-eslint/consistent-type-assertions": {
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"public/app/plugins/datasource/elasticsearch/components/QueryEditor/BucketAggregationsEditor/aggregations.ts": {
|
"public/app/plugins/datasource/elasticsearch/components/QueryEditor/BucketAggregationsEditor/aggregations.ts": {
|
||||||
"@typescript-eslint/consistent-type-assertions": {
|
"@typescript-eslint/consistent-type-assertions": {
|
||||||
"count": 1
|
"count": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"public/app/plugins/datasource/elasticsearch/components/QueryEditor/BucketAggregationsEditor/state/reducer.ts": {
|
|
||||||
"@typescript-eslint/consistent-type-assertions": {
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"public/app/plugins/datasource/elasticsearch/components/QueryEditor/MetricAggregationsEditor/MetricEditor.tsx": {
|
"public/app/plugins/datasource/elasticsearch/components/QueryEditor/MetricAggregationsEditor/MetricEditor.tsx": {
|
||||||
"@typescript-eslint/consistent-type-assertions": {
|
"@typescript-eslint/consistent-type-assertions": {
|
||||||
"count": 1
|
"count": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"public/app/plugins/datasource/elasticsearch/components/QueryEditor/MetricAggregationsEditor/SettingsEditor/SettingField.tsx": {
|
|
||||||
"@typescript-eslint/consistent-type-assertions": {
|
|
||||||
"count": 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"public/app/plugins/datasource/elasticsearch/components/QueryEditor/MetricAggregationsEditor/aggregations.ts": {
|
"public/app/plugins/datasource/elasticsearch/components/QueryEditor/MetricAggregationsEditor/aggregations.ts": {
|
||||||
"@typescript-eslint/consistent-type-assertions": {
|
"@typescript-eslint/consistent-type-assertions": {
|
||||||
"count": 1
|
"count": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"public/app/plugins/datasource/elasticsearch/components/QueryEditor/MetricAggregationsEditor/state/reducer.ts": {
|
|
||||||
"@typescript-eslint/consistent-type-assertions": {
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"public/app/plugins/datasource/elasticsearch/configuration/DataLinks.tsx": {
|
"public/app/plugins/datasource/elasticsearch/configuration/DataLinks.tsx": {
|
||||||
"no-restricted-syntax": {
|
"no-restricted-syntax": {
|
||||||
"count": 1
|
"count": 1
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ require (
|
|||||||
github.com/beevik/etree v1.4.1 // @grafana/grafana-backend-group
|
github.com/beevik/etree v1.4.1 // @grafana/grafana-backend-group
|
||||||
github.com/benbjohnson/clock v1.3.5 // @grafana/alerting-backend
|
github.com/benbjohnson/clock v1.3.5 // @grafana/alerting-backend
|
||||||
github.com/blang/semver/v4 v4.0.0 // indirect; @grafana/grafana-developer-enablement-squad
|
github.com/blang/semver/v4 v4.0.0 // indirect; @grafana/grafana-developer-enablement-squad
|
||||||
github.com/blevesearch/bleve/v2 v2.5.0 // @grafana/grafana-search-and-storage
|
github.com/blevesearch/bleve/v2 v2.5.7 // @grafana/grafana-search-and-storage
|
||||||
github.com/blevesearch/bleve_index_api v1.2.7 // @grafana/grafana-search-and-storage
|
github.com/blevesearch/bleve_index_api v1.3.0 // @grafana/grafana-search-and-storage
|
||||||
github.com/blugelabs/bluge v0.2.2 // @grafana/grafana-backend-group
|
github.com/blugelabs/bluge v0.2.2 // @grafana/grafana-backend-group
|
||||||
github.com/blugelabs/bluge_segment_api v0.2.0 // @grafana/grafana-backend-group
|
github.com/blugelabs/bluge_segment_api v0.2.0 // @grafana/grafana-backend-group
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // @grafana/grafana-backend-group
|
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // @grafana/grafana-backend-group
|
||||||
@@ -365,22 +365,22 @@ require (
|
|||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.22.0 // indirect
|
github.com/bits-and-blooms/bitset v1.22.0 // indirect
|
||||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||||
github.com/blevesearch/geo v0.1.20 // indirect
|
github.com/blevesearch/geo v0.2.4 // indirect
|
||||||
github.com/blevesearch/go-faiss v1.0.25 // indirect
|
github.com/blevesearch/go-faiss v1.0.26 // indirect
|
||||||
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
||||||
github.com/blevesearch/gtreap v0.1.1 // indirect
|
github.com/blevesearch/gtreap v0.1.1 // indirect
|
||||||
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
||||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.9 // indirect
|
github.com/blevesearch/scorch_segment_api/v2 v2.3.13 // indirect
|
||||||
github.com/blevesearch/segment v0.9.1 // indirect
|
github.com/blevesearch/segment v0.9.1 // indirect
|
||||||
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
||||||
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
||||||
github.com/blevesearch/vellum v1.1.0 // indirect
|
github.com/blevesearch/vellum v1.1.0 // indirect
|
||||||
github.com/blevesearch/zapx/v11 v11.4.1 // indirect
|
github.com/blevesearch/zapx/v11 v11.4.2 // indirect
|
||||||
github.com/blevesearch/zapx/v12 v12.4.1 // indirect
|
github.com/blevesearch/zapx/v12 v12.4.2 // indirect
|
||||||
github.com/blevesearch/zapx/v13 v13.4.1 // indirect
|
github.com/blevesearch/zapx/v13 v13.4.2 // indirect
|
||||||
github.com/blevesearch/zapx/v14 v14.4.1 // indirect
|
github.com/blevesearch/zapx/v14 v14.4.2 // indirect
|
||||||
github.com/blevesearch/zapx/v15 v15.4.1 // indirect
|
github.com/blevesearch/zapx/v15 v15.4.2 // indirect
|
||||||
github.com/blevesearch/zapx/v16 v16.2.2 // indirect
|
github.com/blevesearch/zapx/v16 v16.2.8 // indirect
|
||||||
github.com/bluele/gcache v0.0.2 // indirect
|
github.com/bluele/gcache v0.0.2 // indirect
|
||||||
github.com/blugelabs/ice v1.0.0 // indirect
|
github.com/blugelabs/ice v1.0.0 // indirect
|
||||||
github.com/blugelabs/ice/v2 v2.0.1 // indirect
|
github.com/blugelabs/ice/v2 v2.0.1 // indirect
|
||||||
@@ -443,7 +443,6 @@ require (
|
|||||||
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
|
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
|
|
||||||
github.com/gomodule/redigo v1.8.9 // indirect
|
github.com/gomodule/redigo v1.8.9 // indirect
|
||||||
github.com/google/btree v1.1.3 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/google/cel-go v0.26.1 // indirect
|
github.com/google/cel-go v0.26.1 // indirect
|
||||||
|
|||||||
@@ -931,14 +931,14 @@ github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdn
|
|||||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||||
github.com/blevesearch/bleve/v2 v2.5.0 h1:HzYqBy/5/M9Ul9ESEmXzN/3Jl7YpmWBdHM/+zzv/3k4=
|
github.com/blevesearch/bleve/v2 v2.5.7 h1:2d9YrL5zrX5EBBW++GOaEKjE+NPWeZGaX77IM26m1Z8=
|
||||||
github.com/blevesearch/bleve/v2 v2.5.0/go.mod h1:PcJzTPnEynO15dCf9isxOga7YFRa/cMSsbnRwnszXUk=
|
github.com/blevesearch/bleve/v2 v2.5.7/go.mod h1:yj0NlS7ocGC4VOSAedqDDMktdh2935v2CSWOCDMHdSA=
|
||||||
github.com/blevesearch/bleve_index_api v1.2.7 h1:c8r9vmbaYQroAMSGag7zq5gEVPiuXrUQDqfnj7uYZSY=
|
github.com/blevesearch/bleve_index_api v1.3.0 h1:DsMpWVjFNlBw9/6pyWf59XoqcAkhHj3H0UWiQsavb6E=
|
||||||
github.com/blevesearch/bleve_index_api v1.2.7/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
|
github.com/blevesearch/bleve_index_api v1.3.0/go.mod h1:xvd48t5XMeeioWQ5/jZvgLrV98flT2rdvEJ3l/ki4Ko=
|
||||||
github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM=
|
github.com/blevesearch/geo v0.2.4 h1:ECIGQhw+QALCZaDcogRTNSJYQXRtC8/m8IKiA706cqk=
|
||||||
github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w=
|
github.com/blevesearch/geo v0.2.4/go.mod h1:K56Q33AzXt2YExVHGObtmRSFYZKYGv0JEN5mdacJJR8=
|
||||||
github.com/blevesearch/go-faiss v1.0.25 h1:lel1rkOUGbT1CJ0YgzKwC7k+XH0XVBHnCVWahdCXk4U=
|
github.com/blevesearch/go-faiss v1.0.26 h1:4dRLolFgjPyjkaXwff4NfbZFdE/dfywbzDqporeQvXI=
|
||||||
github.com/blevesearch/go-faiss v1.0.25/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
|
github.com/blevesearch/go-faiss v1.0.26/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
|
||||||
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
|
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
|
||||||
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
||||||
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
|
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
|
||||||
@@ -947,8 +947,8 @@ github.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+
|
|||||||
github.com/blevesearch/mmap-go v1.0.3/go.mod h1:pYvKl/grLQrBxuaRYgoTssa4rVujYYeenDp++2E+yvs=
|
github.com/blevesearch/mmap-go v1.0.3/go.mod h1:pYvKl/grLQrBxuaRYgoTssa4rVujYYeenDp++2E+yvs=
|
||||||
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
|
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
|
||||||
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
||||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.9 h1:X6nJXnNHl7nasXW+U6y2Ns2Aw8F9STszkYkyBfQ+p0o=
|
github.com/blevesearch/scorch_segment_api/v2 v2.3.13 h1:ZPjv/4VwWvHJZKeMSgScCapOy8+DdmsmRyLmSB88UoY=
|
||||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.9/go.mod h1:IrzspZlVjhf4X29oJiEhBxEteTqOY9RlYlk1lCmYHr4=
|
github.com/blevesearch/scorch_segment_api/v2 v2.3.13/go.mod h1:ENk2LClTehOuMS8XzN3UxBEErYmtwkE7MAArFTXs9Vc=
|
||||||
github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ=
|
github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ=
|
||||||
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
|
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
|
||||||
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
|
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
|
||||||
@@ -960,18 +960,18 @@ github.com/blevesearch/vellum v1.0.5/go.mod h1:atE0EH3fvk43zzS7t1YNdNC7DbmcC3uz+
|
|||||||
github.com/blevesearch/vellum v1.0.7/go.mod h1:doBZpmRhwTsASB4QdUZANlJvqVAUdUyX0ZK7QJCTeBE=
|
github.com/blevesearch/vellum v1.0.7/go.mod h1:doBZpmRhwTsASB4QdUZANlJvqVAUdUyX0ZK7QJCTeBE=
|
||||||
github.com/blevesearch/vellum v1.1.0 h1:CinkGyIsgVlYf8Y2LUQHvdelgXr6PYuvoDIajq6yR9w=
|
github.com/blevesearch/vellum v1.1.0 h1:CinkGyIsgVlYf8Y2LUQHvdelgXr6PYuvoDIajq6yR9w=
|
||||||
github.com/blevesearch/vellum v1.1.0/go.mod h1:QgwWryE8ThtNPxtgWJof5ndPfx0/YMBh+W2weHKPw8Y=
|
github.com/blevesearch/vellum v1.1.0/go.mod h1:QgwWryE8ThtNPxtgWJof5ndPfx0/YMBh+W2weHKPw8Y=
|
||||||
github.com/blevesearch/zapx/v11 v11.4.1 h1:qFCPlFbsEdwbbckJkysptSQOsHn4s6ZOHL5GMAIAVHA=
|
github.com/blevesearch/zapx/v11 v11.4.2 h1:l46SV+b0gFN+Rw3wUI1YdMWdSAVhskYuvxlcgpQFljs=
|
||||||
github.com/blevesearch/zapx/v11 v11.4.1/go.mod h1:qNOGxIqdPC1MXauJCD9HBG487PxviTUUbmChFOAosGs=
|
github.com/blevesearch/zapx/v11 v11.4.2/go.mod h1:4gdeyy9oGa/lLa6D34R9daXNUvfMPZqUYjPwiLmekwc=
|
||||||
github.com/blevesearch/zapx/v12 v12.4.1 h1:K77bhypII60a4v8mwvav7r4IxWA8qxhNjgF9xGdb9eQ=
|
github.com/blevesearch/zapx/v12 v12.4.2 h1:fzRbhllQmEMUuAQ7zBuMvKRlcPA5ESTgWlDEoB9uQNE=
|
||||||
github.com/blevesearch/zapx/v12 v12.4.1/go.mod h1:QRPrlPOzAxBNMI0MkgdD+xsTqx65zbuPr3Ko4Re49II=
|
github.com/blevesearch/zapx/v12 v12.4.2/go.mod h1:TdFmr7afSz1hFh/SIBCCZvcLfzYvievIH6aEISCte58=
|
||||||
github.com/blevesearch/zapx/v13 v13.4.1 h1:EnkEMZFUK0lsW/jOJJF2xOcp+W8TjEsyeN5BeAZEYYE=
|
github.com/blevesearch/zapx/v13 v13.4.2 h1:46PIZCO/ZuKZYgxI8Y7lOJqX3Irkc3N8W82QTK3MVks=
|
||||||
github.com/blevesearch/zapx/v13 v13.4.1/go.mod h1:e6duBMlCvgbH9rkzNMnUa9hRI9F7ri2BRcHfphcmGn8=
|
github.com/blevesearch/zapx/v13 v13.4.2/go.mod h1:knK8z2NdQHlb5ot/uj8wuvOq5PhDGjNYQQy0QDnopZk=
|
||||||
github.com/blevesearch/zapx/v14 v14.4.1 h1:G47kGCshknBZzZAtjcnIAMn3oNx8XBLxp8DMq18ogyE=
|
github.com/blevesearch/zapx/v14 v14.4.2 h1:2SGHakVKd+TrtEqpfeq8X+So5PShQ5nW6GNxT7fWYz0=
|
||||||
github.com/blevesearch/zapx/v14 v14.4.1/go.mod h1:O7sDxiaL2r2PnCXbhh1Bvm7b4sP+jp4unE9DDPWGoms=
|
github.com/blevesearch/zapx/v14 v14.4.2/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8=
|
||||||
github.com/blevesearch/zapx/v15 v15.4.1 h1:B5IoTMUCEzFdc9FSQbhVOxAY+BO17c05866fNruiI7g=
|
github.com/blevesearch/zapx/v15 v15.4.2 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFxEsp31k=
|
||||||
github.com/blevesearch/zapx/v15 v15.4.1/go.mod h1:b/MreHjYeQoLjyY2+UaM0hGZZUajEbE0xhnr1A2/Q6Y=
|
github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
|
||||||
github.com/blevesearch/zapx/v16 v16.2.2 h1:MifKJVRTEhMTgSlle2bDRTb39BGc9jXFRLPZc6r0Rzk=
|
github.com/blevesearch/zapx/v16 v16.2.8 h1:SlnzF0YGtSlrsOE3oE7EgEX6BIepGpeqxs1IjMbHLQI=
|
||||||
github.com/blevesearch/zapx/v16 v16.2.2/go.mod h1:B9Pk4G1CqtErgQV9DyCSA9Lb7WZe4olYfGw7fVDZ4sk=
|
github.com/blevesearch/zapx/v16 v16.2.8/go.mod h1:murSoCJPCk25MqURrcJaBQ1RekuqSCSfMjXH4rHyA14=
|
||||||
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
||||||
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
|
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
|
||||||
github.com/blugelabs/bluge v0.2.2 h1:gat8CqE6P6tOgeX30XGLOVNTC26cpM2RWVcreXWtYcM=
|
github.com/blugelabs/bluge v0.2.2 h1:gat8CqE6P6tOgeX30XGLOVNTC26cpM2RWVcreXWtYcM=
|
||||||
@@ -1442,8 +1442,6 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2V
|
|||||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo=
|
|
||||||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
|
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
|
||||||
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
|
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
|
||||||
|
|||||||
+27
-2
@@ -520,14 +520,40 @@ github.com/benbjohnson/immutable v0.4.0 h1:CTqXbEerYso8YzVPxmWxh2gnoRQbbB9X1quUC
|
|||||||
github.com/benbjohnson/immutable v0.4.0/go.mod h1:iAr8OjJGLnLmVUr9MZ/rz4PWUy6Ouc2JLYuMArmvAJM=
|
github.com/benbjohnson/immutable v0.4.0/go.mod h1:iAr8OjJGLnLmVUr9MZ/rz4PWUy6Ouc2JLYuMArmvAJM=
|
||||||
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
||||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
|
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
|
||||||
|
github.com/blevesearch/bleve/v2 v2.5.7 h1:2d9YrL5zrX5EBBW++GOaEKjE+NPWeZGaX77IM26m1Z8=
|
||||||
|
github.com/blevesearch/bleve/v2 v2.5.7/go.mod h1:yj0NlS7ocGC4VOSAedqDDMktdh2935v2CSWOCDMHdSA=
|
||||||
|
github.com/blevesearch/bleve_index_api v1.2.8/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
|
||||||
|
github.com/blevesearch/bleve_index_api v1.2.11 h1:bXQ54kVuwP8hdrXUSOnvTQfgK0KI1+f9A0ITJT8tX1s=
|
||||||
|
github.com/blevesearch/bleve_index_api v1.2.11/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
|
||||||
|
github.com/blevesearch/bleve_index_api v1.3.0 h1:DsMpWVjFNlBw9/6pyWf59XoqcAkhHj3H0UWiQsavb6E=
|
||||||
|
github.com/blevesearch/bleve_index_api v1.3.0/go.mod h1:xvd48t5XMeeioWQ5/jZvgLrV98flT2rdvEJ3l/ki4Ko=
|
||||||
|
github.com/blevesearch/geo v0.2.4 h1:ECIGQhw+QALCZaDcogRTNSJYQXRtC8/m8IKiA706cqk=
|
||||||
|
github.com/blevesearch/geo v0.2.4/go.mod h1:K56Q33AzXt2YExVHGObtmRSFYZKYGv0JEN5mdacJJR8=
|
||||||
|
github.com/blevesearch/go-faiss v1.0.26/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
|
||||||
github.com/blevesearch/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:kDy+zgJFJJoJYBvdfBSiZYBbdsUL0XcjHYWezpQBGPA=
|
github.com/blevesearch/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:kDy+zgJFJJoJYBvdfBSiZYBbdsUL0XcjHYWezpQBGPA=
|
||||||
github.com/blevesearch/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:9eJDeqxJ3E7WnLebQUlPD7ZjSce7AnDb9vjGmMCbD0A=
|
github.com/blevesearch/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:9eJDeqxJ3E7WnLebQUlPD7ZjSce7AnDb9vjGmMCbD0A=
|
||||||
github.com/blevesearch/goleveldb v1.0.1 h1:iAtV2Cu5s0GD1lwUiekkFHe2gTMCCNVj2foPclDLIFI=
|
github.com/blevesearch/goleveldb v1.0.1 h1:iAtV2Cu5s0GD1lwUiekkFHe2gTMCCNVj2foPclDLIFI=
|
||||||
github.com/blevesearch/goleveldb v1.0.1/go.mod h1:WrU8ltZbIp0wAoig/MHbrPCXSOLpe79nz5lv5nqfYrQ=
|
github.com/blevesearch/goleveldb v1.0.1/go.mod h1:WrU8ltZbIp0wAoig/MHbrPCXSOLpe79nz5lv5nqfYrQ=
|
||||||
|
github.com/blevesearch/scorch_segment_api/v2 v2.3.10/go.mod h1:Z3e6ChN3qyN35yaQpl00MfI5s8AxUJbpTR/DL8QOQ+8=
|
||||||
|
github.com/blevesearch/scorch_segment_api/v2 v2.3.13 h1:ZPjv/4VwWvHJZKeMSgScCapOy8+DdmsmRyLmSB88UoY=
|
||||||
|
github.com/blevesearch/scorch_segment_api/v2 v2.3.13/go.mod h1:ENk2LClTehOuMS8XzN3UxBEErYmtwkE7MAArFTXs9Vc=
|
||||||
github.com/blevesearch/snowball v0.6.1 h1:cDYjn/NCH+wwt2UdehaLpr2e4BwLIjN4V/TdLsL+B5A=
|
github.com/blevesearch/snowball v0.6.1 h1:cDYjn/NCH+wwt2UdehaLpr2e4BwLIjN4V/TdLsL+B5A=
|
||||||
github.com/blevesearch/snowball v0.6.1/go.mod h1:ZF0IBg5vgpeoUhnMza2v0A/z8m1cWPlwhke08LpNusg=
|
github.com/blevesearch/snowball v0.6.1/go.mod h1:ZF0IBg5vgpeoUhnMza2v0A/z8m1cWPlwhke08LpNusg=
|
||||||
github.com/blevesearch/stempel v0.2.0 h1:CYzVPaScODMvgE9o+kf6D4RJ/VRomyi9uHF+PtB+Afc=
|
github.com/blevesearch/stempel v0.2.0 h1:CYzVPaScODMvgE9o+kf6D4RJ/VRomyi9uHF+PtB+Afc=
|
||||||
github.com/blevesearch/stempel v0.2.0/go.mod h1:wjeTHqQv+nQdbPuJ/YcvOjTInA2EIc6Ks1FoSUzSLvc=
|
github.com/blevesearch/stempel v0.2.0/go.mod h1:wjeTHqQv+nQdbPuJ/YcvOjTInA2EIc6Ks1FoSUzSLvc=
|
||||||
|
github.com/blevesearch/vellum v1.0.10/go.mod h1:ul1oT0FhSMDIExNjIxHqJoGpVrBpKCdgDQNxfqgJt7k=
|
||||||
|
github.com/blevesearch/zapx/v11 v11.4.2 h1:l46SV+b0gFN+Rw3wUI1YdMWdSAVhskYuvxlcgpQFljs=
|
||||||
|
github.com/blevesearch/zapx/v11 v11.4.2/go.mod h1:4gdeyy9oGa/lLa6D34R9daXNUvfMPZqUYjPwiLmekwc=
|
||||||
|
github.com/blevesearch/zapx/v12 v12.4.2 h1:fzRbhllQmEMUuAQ7zBuMvKRlcPA5ESTgWlDEoB9uQNE=
|
||||||
|
github.com/blevesearch/zapx/v12 v12.4.2/go.mod h1:TdFmr7afSz1hFh/SIBCCZvcLfzYvievIH6aEISCte58=
|
||||||
|
github.com/blevesearch/zapx/v13 v13.4.2 h1:46PIZCO/ZuKZYgxI8Y7lOJqX3Irkc3N8W82QTK3MVks=
|
||||||
|
github.com/blevesearch/zapx/v13 v13.4.2/go.mod h1:knK8z2NdQHlb5ot/uj8wuvOq5PhDGjNYQQy0QDnopZk=
|
||||||
|
github.com/blevesearch/zapx/v14 v14.4.2 h1:2SGHakVKd+TrtEqpfeq8X+So5PShQ5nW6GNxT7fWYz0=
|
||||||
|
github.com/blevesearch/zapx/v14 v14.4.2/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8=
|
||||||
|
github.com/blevesearch/zapx/v15 v15.4.2 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFxEsp31k=
|
||||||
|
github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
|
||||||
|
github.com/blevesearch/zapx/v16 v16.2.8 h1:SlnzF0YGtSlrsOE3oE7EgEX6BIepGpeqxs1IjMbHLQI=
|
||||||
|
github.com/blevesearch/zapx/v16 v16.2.8/go.mod h1:murSoCJPCk25MqURrcJaBQ1RekuqSCSfMjXH4rHyA14=
|
||||||
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
|
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
|
||||||
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
|
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
|
github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
|
||||||
@@ -998,8 +1024,6 @@ github.com/grafana/prometheus-alertmanager v0.25.1-0.20250331083058-4563aec7a975
|
|||||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20250331083058-4563aec7a975/go.mod h1:FGdGvhI40Dq+CTQaSzK9evuve774cgOUdGfVO04OXkw=
|
github.com/grafana/prometheus-alertmanager v0.25.1-0.20250331083058-4563aec7a975/go.mod h1:FGdGvhI40Dq+CTQaSzK9evuve774cgOUdGfVO04OXkw=
|
||||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20250604130045-92c8f6389b36 h1:AjZ58JRw1ZieFH/SdsddF5BXtsDKt5kSrKNPWrzYz3Y=
|
github.com/grafana/prometheus-alertmanager v0.25.1-0.20250604130045-92c8f6389b36 h1:AjZ58JRw1ZieFH/SdsddF5BXtsDKt5kSrKNPWrzYz3Y=
|
||||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20250604130045-92c8f6389b36/go.mod h1:O/QP1BCm0HHIzbKvgMzqb5sSyH88rzkFk84F4TfJjBU=
|
github.com/grafana/prometheus-alertmanager v0.25.1-0.20250604130045-92c8f6389b36/go.mod h1:O/QP1BCm0HHIzbKvgMzqb5sSyH88rzkFk84F4TfJjBU=
|
||||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20260112162805-d29cc9cf7f0f h1:9tRhudagkQO2s61SLFLSziIdCm7XlkfypVKDxpcHokg=
|
|
||||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20260112162805-d29cc9cf7f0f/go.mod h1:AsVdCBeDFN9QbgpJg+8voDAcgsW0RmNvBd70ecMMdC0=
|
|
||||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU=
|
github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU=
|
||||||
github.com/grafana/pyroscope/api v1.2.1-0.20250415190842-3ff7247547ae/go.mod h1:6CJ1uXmLZ13ufpO9xE4pST+DyaBt0uszzrV0YnoaVLQ=
|
github.com/grafana/pyroscope/api v1.2.1-0.20250415190842-3ff7247547ae/go.mod h1:6CJ1uXmLZ13ufpO9xE4pST+DyaBt0uszzrV0YnoaVLQ=
|
||||||
github.com/grafana/sqlds/v4 v4.2.4/go.mod h1:BQRjUG8rOqrBI4NAaeoWrIMuoNgfi8bdhCJ+5cgEfLU=
|
github.com/grafana/sqlds/v4 v4.2.4/go.mod h1:BQRjUG8rOqrBI4NAaeoWrIMuoNgfi8bdhCJ+5cgEfLU=
|
||||||
@@ -1092,6 +1116,7 @@ github.com/jon-whit/go-grpc-prometheus v1.4.0/go.mod h1:iTPm+Iuhh3IIqR0iGZ91JJEg
|
|||||||
github.com/joncrlsn/dque v0.0.0-20211108142734-c2ef48c5192a h1:sfe532Ipn7GX0V6mHdynBk393rDmqgI0QmjLK7ct7TU=
|
github.com/joncrlsn/dque v0.0.0-20211108142734-c2ef48c5192a h1:sfe532Ipn7GX0V6mHdynBk393rDmqgI0QmjLK7ct7TU=
|
||||||
github.com/joncrlsn/dque v0.0.0-20211108142734-c2ef48c5192a/go.mod h1:dNKs71rs2VJGBAmttu7fouEsRQlRjxy0p1Sx+T5wbpY=
|
github.com/joncrlsn/dque v0.0.0-20211108142734-c2ef48c5192a/go.mod h1:dNKs71rs2VJGBAmttu7fouEsRQlRjxy0p1Sx+T5wbpY=
|
||||||
github.com/josephspurrier/goversioninfo v1.4.0/go.mod h1:JWzv5rKQr+MmW+LvM412ToT/IkYDZjaclF2pKDss8IY=
|
github.com/josephspurrier/goversioninfo v1.4.0/go.mod h1:JWzv5rKQr+MmW+LvM412ToT/IkYDZjaclF2pKDss8IY=
|
||||||
|
github.com/json-iterator/go v0.0.0-20171115153421-f7279a603ede/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
|
github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
|
||||||
github.com/jsternberg/zap-logfmt v1.3.0 h1:z1n1AOHVVydOOVuyphbOKyR4NICDQFiJMn1IK5hVQ5Y=
|
github.com/jsternberg/zap-logfmt v1.3.0 h1:z1n1AOHVVydOOVuyphbOKyR4NICDQFiJMn1IK5hVQ5Y=
|
||||||
github.com/jsternberg/zap-logfmt v1.3.0/go.mod h1:N3DENp9WNmCZxvkBD/eReWwz1149BK6jEN9cQ4fNwZE=
|
github.com/jsternberg/zap-logfmt v1.3.0/go.mod h1:N3DENp9WNmCZxvkBD/eReWwz1149BK6jEN9cQ4fNwZE=
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ module.exports = {
|
|||||||
// Decoupled plugins run their own tests so ignoring them here.
|
// Decoupled plugins run their own tests so ignoring them here.
|
||||||
'<rootDir>/public/app/plugins/datasource/azuremonitor',
|
'<rootDir>/public/app/plugins/datasource/azuremonitor',
|
||||||
'<rootDir>/public/app/plugins/datasource/cloud-monitoring',
|
'<rootDir>/public/app/plugins/datasource/cloud-monitoring',
|
||||||
|
'<rootDir>/public/app/plugins/datasource/elasticsearch',
|
||||||
'<rootDir>/public/app/plugins/datasource/grafana-postgresql-datasource',
|
'<rootDir>/public/app/plugins/datasource/grafana-postgresql-datasource',
|
||||||
'<rootDir>/public/app/plugins/datasource/grafana-pyroscope-datasource',
|
'<rootDir>/public/app/plugins/datasource/grafana-pyroscope-datasource',
|
||||||
'<rootDir>/public/app/plugins/datasource/grafana-testdata-datasource',
|
'<rootDir>/public/app/plugins/datasource/grafana-testdata-datasource',
|
||||||
|
|||||||
@@ -237,6 +237,8 @@ lineage: schemas: [{
|
|||||||
text: string | [...string]
|
text: string | [...string]
|
||||||
// Value of the option
|
// Value of the option
|
||||||
value: string | [...string]
|
value: string | [...string]
|
||||||
|
// Additional properties for multi-props variables
|
||||||
|
properties?: {[string]: string}
|
||||||
} @cuetsy(kind="interface")
|
} @cuetsy(kind="interface")
|
||||||
|
|
||||||
// Options to config when to refresh a variable
|
// Options to config when to refresh a variable
|
||||||
|
|||||||
+2
-2
@@ -293,8 +293,8 @@
|
|||||||
"@grafana/plugin-ui": "^0.11.1",
|
"@grafana/plugin-ui": "^0.11.1",
|
||||||
"@grafana/prometheus": "workspace:*",
|
"@grafana/prometheus": "workspace:*",
|
||||||
"@grafana/runtime": "workspace:*",
|
"@grafana/runtime": "workspace:*",
|
||||||
"@grafana/scenes": "v6.52.1",
|
"@grafana/scenes": "6.52.2",
|
||||||
"@grafana/scenes-react": "v6.52.1",
|
"@grafana/scenes-react": "6.52.2",
|
||||||
"@grafana/schema": "workspace:*",
|
"@grafana/schema": "workspace:*",
|
||||||
"@grafana/sql": "workspace:*",
|
"@grafana/sql": "workspace:*",
|
||||||
"@grafana/ui": "workspace:*",
|
"@grafana/ui": "workspace:*",
|
||||||
|
|||||||
@@ -35,6 +35,14 @@
|
|||||||
},
|
},
|
||||||
"./test": {
|
"./test": {
|
||||||
"@grafana-app/source": "./test/index.ts"
|
"@grafana-app/source": "./test/index.ts"
|
||||||
|
},
|
||||||
|
"./themes/schema.generated.json": {
|
||||||
|
"@grafana-app/source": "./src/themes/schema.generated.json",
|
||||||
|
"default": "./dist/esm/themes/schema.generated.json"
|
||||||
|
},
|
||||||
|
"./themes/definitions/*.json": {
|
||||||
|
"@grafana-app/source": "./src/themes/themeDefinitions/*.json",
|
||||||
|
"default": "./dist/esm/themes/themeDefinitions/*.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
@@ -52,7 +60,7 @@
|
|||||||
"typecheck": "tsc --emitDeclarationOnly false --noEmit",
|
"typecheck": "tsc --emitDeclarationOnly false --noEmit",
|
||||||
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-npm-package.js",
|
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-npm-package.js",
|
||||||
"postpack": "mv package.json.bak package.json",
|
"postpack": "mv package.json.bak package.json",
|
||||||
"themes-schema": "tsx ./src/themes/scripts/generateSchema.ts"
|
"themes-schema": "tsx ./scripts/generateSchema.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@braintree/sanitize-url": "7.0.1",
|
"@braintree/sanitize-url": "7.0.1",
|
||||||
@@ -102,6 +110,7 @@
|
|||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"rimraf": "6.0.1",
|
"rimraf": "6.0.1",
|
||||||
"rollup": "^4.22.4",
|
"rollup": "^4.22.4",
|
||||||
|
"rollup-plugin-copy": "3.5.0",
|
||||||
"rollup-plugin-esbuild": "6.2.1",
|
"rollup-plugin-esbuild": "6.2.1",
|
||||||
"rollup-plugin-node-externals": "^8.0.0",
|
"rollup-plugin-node-externals": "^8.0.0",
|
||||||
"tsx": "^4.21.0",
|
"tsx": "^4.21.0",
|
||||||
|
|||||||
@@ -1,21 +1,40 @@
|
|||||||
import json from '@rollup/plugin-json';
|
import json from '@rollup/plugin-json';
|
||||||
import { createRequire } from 'node:module';
|
import { createRequire } from 'node:module';
|
||||||
|
import copy from 'rollup-plugin-copy';
|
||||||
|
|
||||||
import { entryPoint, plugins, esmOutput, cjsOutput } from '../rollup.config.parts';
|
import { entryPoint, plugins, esmOutput, cjsOutput } from '../rollup.config.parts';
|
||||||
|
|
||||||
const rq = createRequire(import.meta.url);
|
const rq = createRequire(import.meta.url);
|
||||||
const pkg = rq('./package.json');
|
const pkg = rq('./package.json');
|
||||||
|
|
||||||
|
const grafanaDataPlugins = [
|
||||||
|
...plugins,
|
||||||
|
copy({
|
||||||
|
targets: [
|
||||||
|
{
|
||||||
|
src: 'src/themes/schema.generated.json',
|
||||||
|
dest: 'dist/esm/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'src/themes/themeDefinitions/*.json',
|
||||||
|
dest: 'dist/esm/',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
flatten: false,
|
||||||
|
}),
|
||||||
|
json(),
|
||||||
|
];
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
input: entryPoint,
|
input: entryPoint,
|
||||||
plugins: [...plugins, json()],
|
plugins: grafanaDataPlugins,
|
||||||
output: [cjsOutput(pkg, 'grafana-data'), esmOutput(pkg, 'grafana-data')],
|
output: [cjsOutput(pkg, 'grafana-data'), esmOutput(pkg, 'grafana-data')],
|
||||||
treeshake: false,
|
treeshake: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: 'src/unstable.ts',
|
input: 'src/unstable.ts',
|
||||||
plugins: [...plugins, json()],
|
plugins: grafanaDataPlugins,
|
||||||
output: [cjsOutput(pkg, 'grafana-data'), esmOutput(pkg, 'grafana-data')],
|
output: [cjsOutput(pkg, 'grafana-data'), esmOutput(pkg, 'grafana-data')],
|
||||||
treeshake: false,
|
treeshake: false,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import fs from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
|
import { NewThemeOptionsSchema } from '../src/themes/createTheme';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
const jsonOut = path.join(__dirname, '..', 'src', 'themes', 'schema.generated.json');
|
||||||
|
|
||||||
|
fs.writeFileSync(
|
||||||
|
jsonOut,
|
||||||
|
JSON.stringify(
|
||||||
|
NewThemeOptionsSchema.toJSONSchema({
|
||||||
|
target: 'draft-07',
|
||||||
|
}),
|
||||||
|
undefined,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('Successfully generated theme schema');
|
||||||
@@ -844,7 +844,6 @@ export {
|
|||||||
DataLinkConfigOrigin,
|
DataLinkConfigOrigin,
|
||||||
SupportedTransformationType,
|
SupportedTransformationType,
|
||||||
type InternalDataLink,
|
type InternalDataLink,
|
||||||
type LinkTarget,
|
|
||||||
type LinkModel,
|
type LinkModel,
|
||||||
type LinkModelSupplier,
|
type LinkModelSupplier,
|
||||||
VariableOrigin,
|
VariableOrigin,
|
||||||
@@ -852,6 +851,7 @@ export {
|
|||||||
VariableSuggestionsScope,
|
VariableSuggestionsScope,
|
||||||
OneClickMode,
|
OneClickMode,
|
||||||
} from './types/dataLink';
|
} from './types/dataLink';
|
||||||
|
export { type LinkTarget } from './types/linkTarget';
|
||||||
export {
|
export {
|
||||||
type Action,
|
type Action,
|
||||||
type ActionModel,
|
type ActionModel,
|
||||||
|
|||||||
@@ -93,7 +93,6 @@ export { DataTransformerID } from '../transformations/transformers/ids';
|
|||||||
|
|
||||||
export { mergeTransformer } from '../transformations/transformers/merge';
|
export { mergeTransformer } from '../transformations/transformers/merge';
|
||||||
export { getThemeById } from '../themes/registry';
|
export { getThemeById } from '../themes/registry';
|
||||||
export * as experimentalThemeDefinitions from '../themes/themeDefinitions';
|
|
||||||
export { GrafanaEdition } from '../types/config';
|
export { GrafanaEdition } from '../types/config';
|
||||||
export { SIPrefix } from '../valueFormats/symbolFormatters';
|
export { SIPrefix } from '../valueFormats/symbolFormatters';
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,18 @@
|
|||||||
import { Registry, RegistryItem } from '../utils/Registry';
|
import { Registry, RegistryItem } from '../utils/Registry';
|
||||||
|
|
||||||
import { createTheme, NewThemeOptionsSchema } from './createTheme';
|
import { createTheme, NewThemeOptionsSchema } from './createTheme';
|
||||||
import * as extraThemes from './themeDefinitions';
|
import aubergine from './themeDefinitions/aubergine.json';
|
||||||
|
import debug from './themeDefinitions/debug.json';
|
||||||
|
import desertbloom from './themeDefinitions/desertbloom.json';
|
||||||
|
import gildedgrove from './themeDefinitions/gildedgrove.json';
|
||||||
|
import gloom from './themeDefinitions/gloom.json';
|
||||||
|
import mars from './themeDefinitions/mars.json';
|
||||||
|
import matrix from './themeDefinitions/matrix.json';
|
||||||
|
import sapphiredusk from './themeDefinitions/sapphiredusk.json';
|
||||||
|
import synthwave from './themeDefinitions/synthwave.json';
|
||||||
|
import tron from './themeDefinitions/tron.json';
|
||||||
|
import victorian from './themeDefinitions/victorian.json';
|
||||||
|
import zen from './themeDefinitions/zen.json';
|
||||||
import { GrafanaTheme2 } from './types';
|
import { GrafanaTheme2 } from './types';
|
||||||
|
|
||||||
export interface ThemeRegistryItem extends RegistryItem {
|
export interface ThemeRegistryItem extends RegistryItem {
|
||||||
@@ -9,6 +20,21 @@ export interface ThemeRegistryItem extends RegistryItem {
|
|||||||
build: () => GrafanaTheme2;
|
build: () => GrafanaTheme2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const extraThemes: { [key: string]: unknown } = {
|
||||||
|
aubergine,
|
||||||
|
debug,
|
||||||
|
desertbloom,
|
||||||
|
gildedgrove,
|
||||||
|
gloom,
|
||||||
|
mars,
|
||||||
|
matrix,
|
||||||
|
sapphiredusk,
|
||||||
|
synthwave,
|
||||||
|
tron,
|
||||||
|
victorian,
|
||||||
|
zen,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
* Only for internal use, never use this from a plugin
|
* Only for internal use, never use this from a plugin
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
|
|
||||||
import { NewThemeOptionsSchema } from '../createTheme';
|
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
|
||||||
const __dirname = path.dirname(__filename);
|
|
||||||
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(__dirname, '../schema.generated.json'),
|
|
||||||
JSON.stringify(
|
|
||||||
NewThemeOptionsSchema.toJSONSchema({
|
|
||||||
target: 'draft-07',
|
|
||||||
}),
|
|
||||||
undefined,
|
|
||||||
2
|
|
||||||
)
|
|
||||||
);
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
export { default as aubergine } from './aubergine.json';
|
|
||||||
export { default as debug } from './debug.json';
|
|
||||||
export { default as desertbloom } from './desertbloom.json';
|
|
||||||
export { default as gildedgrove } from './gildedgrove.json';
|
|
||||||
export { default as mars } from './mars.json';
|
|
||||||
export { default as matrix } from './matrix.json';
|
|
||||||
export { default as sapphiredusk } from './sapphiredusk.json';
|
|
||||||
export { default as synthwave } from './synthwave.json';
|
|
||||||
export { default as tron } from './tron.json';
|
|
||||||
export { default as victorian } from './victorian.json';
|
|
||||||
export { default as zen } from './zen.json';
|
|
||||||
export { default as gloom } from './gloom.json';
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ScopedVars } from './ScopedVars';
|
import { ScopedVars } from './ScopedVars';
|
||||||
import { ExploreCorrelationHelperData, ExplorePanelsState } from './explore';
|
import { ExploreCorrelationHelperData, ExplorePanelsState } from './explore';
|
||||||
|
import { LinkTarget } from './linkTarget';
|
||||||
import { InterpolateFunction } from './panel';
|
import { InterpolateFunction } from './panel';
|
||||||
import { DataQuery } from './query';
|
import { DataQuery } from './query';
|
||||||
import { TimeRange } from './time';
|
import { TimeRange } from './time';
|
||||||
@@ -88,8 +89,6 @@ export interface InternalDataLink<T extends DataQuery = any> {
|
|||||||
range?: TimeRange;
|
range?: TimeRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type LinkTarget = '_blank' | '_self' | undefined;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processed Link Model. The values are ready to use
|
* Processed Link Model. The values are ready to use
|
||||||
*/
|
*/
|
||||||
|
|||||||
+9
-1
@@ -356,7 +356,7 @@ export interface FeatureToggles {
|
|||||||
*/
|
*/
|
||||||
dashboardScene?: boolean;
|
dashboardScene?: boolean;
|
||||||
/**
|
/**
|
||||||
* Enables experimental new dashboard layouts
|
* Enables new dashboard layouts
|
||||||
*/
|
*/
|
||||||
dashboardNewLayouts?: boolean;
|
dashboardNewLayouts?: boolean;
|
||||||
/**
|
/**
|
||||||
@@ -531,6 +531,10 @@ export interface FeatureToggles {
|
|||||||
*/
|
*/
|
||||||
alertingListViewV2?: boolean;
|
alertingListViewV2?: boolean;
|
||||||
/**
|
/**
|
||||||
|
* Enables the new Alerting navigation structure with improved menu grouping
|
||||||
|
*/
|
||||||
|
alertingNavigationV2?: boolean;
|
||||||
|
/**
|
||||||
* Enables saved searches for alert rules list
|
* Enables saved searches for alert rules list
|
||||||
*/
|
*/
|
||||||
alertingSavedSearches?: boolean;
|
alertingSavedSearches?: boolean;
|
||||||
@@ -1251,4 +1255,8 @@ export interface FeatureToggles {
|
|||||||
* Enables profiles exemplars support in profiles drilldown
|
* Enables profiles exemplars support in profiles drilldown
|
||||||
*/
|
*/
|
||||||
profilesExemplars?: boolean;
|
profilesExemplars?: boolean;
|
||||||
|
/**
|
||||||
|
* Use synchronized dispatch timer to minimize duplicate notifications across alertmanager HA pods
|
||||||
|
*/
|
||||||
|
alertingSyncDispatchTimer?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* Target for links - controls whether link opens in new tab or same tab
|
||||||
|
*/
|
||||||
|
export type LinkTarget = '_blank' | '_self' | undefined;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ComponentType } from 'react';
|
import { ComponentType } from 'react';
|
||||||
|
|
||||||
import { LinkTarget } from './dataLink';
|
|
||||||
import { IconName } from './icon';
|
import { IconName } from './icon';
|
||||||
|
import { LinkTarget } from './linkTarget';
|
||||||
|
|
||||||
export interface NavLinkDTO {
|
export interface NavLinkDTO {
|
||||||
id?: string;
|
id?: string;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { DataFrame } from './dataFrame';
|
|||||||
import { DataQueryError, DataQueryRequest, DataQueryTimings } from './datasource';
|
import { DataQueryError, DataQueryRequest, DataQueryTimings } from './datasource';
|
||||||
import { FieldConfigSource } from './fieldOverrides';
|
import { FieldConfigSource } from './fieldOverrides';
|
||||||
import { IconName } from './icon';
|
import { IconName } from './icon';
|
||||||
|
import { LinkTarget } from './linkTarget';
|
||||||
import { OptionEditorConfig } from './options';
|
import { OptionEditorConfig } from './options';
|
||||||
import { PluginMeta } from './plugin';
|
import { PluginMeta } from './plugin';
|
||||||
import { AbsoluteTimeRange, TimeRange, TimeZone } from './time';
|
import { AbsoluteTimeRange, TimeRange, TimeZone } from './time';
|
||||||
@@ -191,6 +192,7 @@ export interface PanelMenuItem {
|
|||||||
onClick?: (event: React.MouseEvent) => void;
|
onClick?: (event: React.MouseEvent) => void;
|
||||||
shortcut?: string;
|
shortcut?: string;
|
||||||
href?: string;
|
href?: string;
|
||||||
|
target?: LinkTarget;
|
||||||
subMenu?: PanelMenuItem[];
|
subMenu?: PanelMenuItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ export interface VariableOption {
|
|||||||
text: string | string[];
|
text: string | string[];
|
||||||
value: string | string[];
|
value: string | string[];
|
||||||
isNone?: boolean;
|
isNone?: boolean;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
properties?: Record<string, any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IntervalVariableModel extends VariableWithOptions {
|
export interface IntervalVariableModel extends VariableWithOptions {
|
||||||
@@ -118,6 +120,7 @@ export interface QueryVariableModel extends VariableWithMultiSupport {
|
|||||||
definition: string;
|
definition: string;
|
||||||
sort: VariableSort;
|
sort: VariableSort;
|
||||||
queryValue?: string;
|
queryValue?: string;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
query: any;
|
query: any;
|
||||||
regex: string;
|
regex: string;
|
||||||
regexApplyTo?: VariableRegexApplyTo;
|
regexApplyTo?: VariableRegexApplyTo;
|
||||||
@@ -193,6 +196,7 @@ export interface BaseVariableModel {
|
|||||||
skipUrlSync: boolean;
|
skipUrlSync: boolean;
|
||||||
index: number;
|
index: number;
|
||||||
state: LoadingState;
|
state: LoadingState;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
error: any | null;
|
error: any | null;
|
||||||
description: string | null;
|
description: string | null;
|
||||||
usedInRepeat?: boolean;
|
usedInRepeat?: boolean;
|
||||||
|
|||||||
@@ -9,4 +9,4 @@
|
|||||||
* and be subject to the standard policies
|
* and be subject to the standard policies
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export { default as themeJsonSchema } from './themes/schema.generated.json';
|
export {};
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
"emitDeclarationOnly": true,
|
"emitDeclarationOnly": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"rootDirs": ["."],
|
"rootDirs": ["."],
|
||||||
"moduleResolution": "bundler"
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true
|
||||||
},
|
},
|
||||||
"exclude": ["dist/**/*"],
|
"exclude": ["dist/**/*"],
|
||||||
"include": [
|
"include": [
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
import * as common from '@grafana/schema';
|
import * as common from '@grafana/schema';
|
||||||
|
|
||||||
export const pluginVersion = "12.4.0-pre";
|
export const pluginVersion = "%VERSION%";
|
||||||
|
|
||||||
export type BucketAggregation = (DateHistogram | Histogram | Terms | Filters | GeoHashGrid | Nested);
|
export type BucketAggregation = (DateHistogram | Histogram | Terms | Filters | GeoHashGrid | Nested);
|
||||||
|
|
||||||
|
|||||||
@@ -231,6 +231,10 @@ export const defaultVariableModel: Partial<VariableModel> = {
|
|||||||
* Option to be selected in a variable.
|
* Option to be selected in a variable.
|
||||||
*/
|
*/
|
||||||
export interface VariableOption {
|
export interface VariableOption {
|
||||||
|
/**
|
||||||
|
* Additional properties for multi-props variables
|
||||||
|
*/
|
||||||
|
properties?: Record<string, string>;
|
||||||
/**
|
/**
|
||||||
* Whether the option is selected or not
|
* Whether the option is selected or not
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -715,7 +715,9 @@ VariableOption: {
|
|||||||
// Text to be displayed for the option
|
// Text to be displayed for the option
|
||||||
text: string | [...string]
|
text: string | [...string]
|
||||||
// Value of the option
|
// Value of the option
|
||||||
value: string | [...string]
|
value: string | [...string]
|
||||||
|
// Additional properties for multi-props variables
|
||||||
|
properties?: {[string]: string}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query variable specification
|
// Query variable specification
|
||||||
|
|||||||
+2
@@ -903,6 +903,8 @@ type VariableOption struct {
|
|||||||
Text StringOrArrayOfString `json:"text"`
|
Text StringOrArrayOfString `json:"text"`
|
||||||
// Value of the option
|
// Value of the option
|
||||||
Value StringOrArrayOfString `json:"value"`
|
Value StringOrArrayOfString `json:"value"`
|
||||||
|
// Additional properties for multi-props variables
|
||||||
|
Properties map[string]string `json:"properties,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVariableOption creates a new VariableOption object.
|
// NewVariableOption creates a new VariableOption object.
|
||||||
|
|||||||
@@ -574,8 +574,8 @@ var (
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "dashboardNewLayouts",
|
Name: "dashboardNewLayouts",
|
||||||
Description: "Enables experimental new dashboard layouts",
|
Description: "Enables new dashboard layouts",
|
||||||
Stage: FeatureStageExperimental,
|
Stage: FeatureStagePublicPreview,
|
||||||
FrontendOnly: false, // The restore backend feature changes behavior based on this flag
|
FrontendOnly: false, // The restore backend feature changes behavior based on this flag
|
||||||
Owner: grafanaDashboardsSquad,
|
Owner: grafanaDashboardsSquad,
|
||||||
},
|
},
|
||||||
@@ -879,6 +879,13 @@ var (
|
|||||||
Owner: grafanaAlertingSquad,
|
Owner: grafanaAlertingSquad,
|
||||||
FrontendOnly: true,
|
FrontendOnly: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "alertingNavigationV2",
|
||||||
|
Description: "Enables the new Alerting navigation structure with improved menu grouping",
|
||||||
|
Stage: FeatureStageExperimental,
|
||||||
|
Owner: grafanaAlertingSquad,
|
||||||
|
FrontendOnly: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "alertingSavedSearches",
|
Name: "alertingSavedSearches",
|
||||||
Description: "Enables saved searches for alert rules list",
|
Description: "Enables saved searches for alert rules list",
|
||||||
@@ -981,7 +988,8 @@ var (
|
|||||||
Stage: FeatureStageDeprecated,
|
Stage: FeatureStageDeprecated,
|
||||||
Owner: grafanaPartnerPluginsSquad,
|
Owner: grafanaPartnerPluginsSquad,
|
||||||
Expression: "true", // Enabled by default for now
|
Expression: "true", // Enabled by default for now
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
Name: "alertingFilterV2",
|
Name: "alertingFilterV2",
|
||||||
Description: "Enable the new alerting search experience",
|
Description: "Enable the new alerting search experience",
|
||||||
Stage: FeatureStageExperimental,
|
Stage: FeatureStageExperimental,
|
||||||
@@ -2069,6 +2077,14 @@ var (
|
|||||||
Owner: grafanaObservabilityTracesAndProfilingSquad,
|
Owner: grafanaObservabilityTracesAndProfilingSquad,
|
||||||
FrontendOnly: false,
|
FrontendOnly: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "alertingSyncDispatchTimer",
|
||||||
|
Description: "Use synchronized dispatch timer to minimize duplicate notifications across alertmanager HA pods",
|
||||||
|
Stage: FeatureStageExperimental,
|
||||||
|
Owner: grafanaAlertingSquad,
|
||||||
|
RequiresRestart: true,
|
||||||
|
HideFromDocs: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Generated
+3
-1
@@ -79,7 +79,7 @@ annotationPermissionUpdate,GA,@grafana/identity-access-team,false,false,false
|
|||||||
dashboardSceneForViewers,GA,@grafana/dashboards-squad,false,false,true
|
dashboardSceneForViewers,GA,@grafana/dashboards-squad,false,false,true
|
||||||
dashboardSceneSolo,GA,@grafana/dashboards-squad,false,false,true
|
dashboardSceneSolo,GA,@grafana/dashboards-squad,false,false,true
|
||||||
dashboardScene,GA,@grafana/dashboards-squad,false,false,true
|
dashboardScene,GA,@grafana/dashboards-squad,false,false,true
|
||||||
dashboardNewLayouts,experimental,@grafana/dashboards-squad,false,false,false
|
dashboardNewLayouts,preview,@grafana/dashboards-squad,false,false,false
|
||||||
dashboardUndoRedo,experimental,@grafana/dashboards-squad,false,false,true
|
dashboardUndoRedo,experimental,@grafana/dashboards-squad,false,false,true
|
||||||
unlimitedLayoutsNesting,experimental,@grafana/dashboards-squad,false,false,true
|
unlimitedLayoutsNesting,experimental,@grafana/dashboards-squad,false,false,true
|
||||||
drilldownRecommendations,experimental,@grafana/dashboards-squad,false,false,true
|
drilldownRecommendations,experimental,@grafana/dashboards-squad,false,false,true
|
||||||
@@ -121,6 +121,7 @@ dashboardLibrary,experimental,@grafana/sharing-squad,false,false,false
|
|||||||
suggestedDashboards,experimental,@grafana/sharing-squad,false,false,false
|
suggestedDashboards,experimental,@grafana/sharing-squad,false,false,false
|
||||||
dashboardTemplates,preview,@grafana/sharing-squad,false,false,false
|
dashboardTemplates,preview,@grafana/sharing-squad,false,false,false
|
||||||
alertingListViewV2,privatePreview,@grafana/alerting-squad,false,false,true
|
alertingListViewV2,privatePreview,@grafana/alerting-squad,false,false,true
|
||||||
|
alertingNavigationV2,experimental,@grafana/alerting-squad,false,false,false
|
||||||
alertingSavedSearches,experimental,@grafana/alerting-squad,false,false,true
|
alertingSavedSearches,experimental,@grafana/alerting-squad,false,false,true
|
||||||
alertingDisableSendAlertsExternal,experimental,@grafana/alerting-squad,false,false,false
|
alertingDisableSendAlertsExternal,experimental,@grafana/alerting-squad,false,false,false
|
||||||
preserveDashboardStateWhenNavigating,experimental,@grafana/dashboards-squad,false,false,false
|
preserveDashboardStateWhenNavigating,experimental,@grafana/dashboards-squad,false,false,false
|
||||||
@@ -280,3 +281,4 @@ multiPropsVariables,experimental,@grafana/dashboards-squad,false,false,true
|
|||||||
smoothingTransformation,experimental,@grafana/datapro,false,false,true
|
smoothingTransformation,experimental,@grafana/datapro,false,false,true
|
||||||
secretsManagementAppPlatformAwsKeeper,experimental,@grafana/grafana-operator-experience-squad,false,false,false
|
secretsManagementAppPlatformAwsKeeper,experimental,@grafana/grafana-operator-experience-squad,false,false,false
|
||||||
profilesExemplars,experimental,@grafana/observability-traces-and-profiling,false,false,false
|
profilesExemplars,experimental,@grafana/observability-traces-and-profiling,false,false,false
|
||||||
|
alertingSyncDispatchTimer,experimental,@grafana/alerting-squad,false,true,false
|
||||||
|
|||||||
|
Generated
+9
-1
@@ -260,7 +260,7 @@ const (
|
|||||||
FlagAnnotationPermissionUpdate = "annotationPermissionUpdate"
|
FlagAnnotationPermissionUpdate = "annotationPermissionUpdate"
|
||||||
|
|
||||||
// FlagDashboardNewLayouts
|
// FlagDashboardNewLayouts
|
||||||
// Enables experimental new dashboard layouts
|
// Enables new dashboard layouts
|
||||||
FlagDashboardNewLayouts = "dashboardNewLayouts"
|
FlagDashboardNewLayouts = "dashboardNewLayouts"
|
||||||
|
|
||||||
// FlagPdfTables
|
// FlagPdfTables
|
||||||
@@ -371,6 +371,10 @@ const (
|
|||||||
// Enables a flow to get started with a new dashboard from a template
|
// Enables a flow to get started with a new dashboard from a template
|
||||||
FlagDashboardTemplates = "dashboardTemplates"
|
FlagDashboardTemplates = "dashboardTemplates"
|
||||||
|
|
||||||
|
// FlagAlertingNavigationV2
|
||||||
|
// Enables the new Alerting navigation structure with improved menu grouping
|
||||||
|
FlagAlertingNavigationV2 = "alertingNavigationV2"
|
||||||
|
|
||||||
// FlagAlertingDisableSendAlertsExternal
|
// FlagAlertingDisableSendAlertsExternal
|
||||||
// Disables the ability to send alerts to an external Alertmanager datasource.
|
// Disables the ability to send alerts to an external Alertmanager datasource.
|
||||||
FlagAlertingDisableSendAlertsExternal = "alertingDisableSendAlertsExternal"
|
FlagAlertingDisableSendAlertsExternal = "alertingDisableSendAlertsExternal"
|
||||||
@@ -789,4 +793,8 @@ const (
|
|||||||
// FlagProfilesExemplars
|
// FlagProfilesExemplars
|
||||||
// Enables profiles exemplars support in profiles drilldown
|
// Enables profiles exemplars support in profiles drilldown
|
||||||
FlagProfilesExemplars = "profilesExemplars"
|
FlagProfilesExemplars = "profilesExemplars"
|
||||||
|
|
||||||
|
// FlagAlertingSyncDispatchTimer
|
||||||
|
// Use synchronized dispatch timer to minimize duplicate notifications across alertmanager HA pods
|
||||||
|
FlagAlertingSyncDispatchTimer = "alertingSyncDispatchTimer"
|
||||||
)
|
)
|
||||||
|
|||||||
+35
-5
@@ -348,6 +348,18 @@
|
|||||||
"expression": "true"
|
"expression": "true"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"name": "alertingNavigationV2",
|
||||||
|
"resourceVersion": "1768320918269",
|
||||||
|
"creationTimestamp": "2026-01-13T16:15:18Z"
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"description": "Enables the new Alerting navigation structure with improved menu grouping",
|
||||||
|
"stage": "experimental",
|
||||||
|
"codeowner": "@grafana/alerting-squad"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"name": "alertingNotificationHistory",
|
"name": "alertingNotificationHistory",
|
||||||
@@ -511,6 +523,20 @@
|
|||||||
"frontend": true
|
"frontend": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"name": "alertingSyncDispatchTimer",
|
||||||
|
"resourceVersion": "1766161788928",
|
||||||
|
"creationTimestamp": "2025-12-19T16:29:48Z"
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"description": "Use synchronized dispatch timer to minimize duplicate notifications across alertmanager HA pods",
|
||||||
|
"stage": "experimental",
|
||||||
|
"codeowner": "@grafana/alerting-squad",
|
||||||
|
"requiresRestart": true,
|
||||||
|
"hideFromDocs": true
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"name": "alertingTriage",
|
"name": "alertingTriage",
|
||||||
@@ -662,7 +688,8 @@
|
|||||||
"metadata": {
|
"metadata": {
|
||||||
"name": "auditLoggingAppPlatform",
|
"name": "auditLoggingAppPlatform",
|
||||||
"resourceVersion": "1767013056996",
|
"resourceVersion": "1767013056996",
|
||||||
"creationTimestamp": "2025-12-29T12:57:36Z"
|
"creationTimestamp": "2025-12-29T12:57:36Z",
|
||||||
|
"deletionTimestamp": "2026-01-06T09:18:36Z"
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
"description": "Enable audit logging with Kubernetes under app platform",
|
"description": "Enable audit logging with Kubernetes under app platform",
|
||||||
@@ -1015,12 +1042,15 @@
|
|||||||
{
|
{
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"name": "dashboardNewLayouts",
|
"name": "dashboardNewLayouts",
|
||||||
"resourceVersion": "1764664939750",
|
"resourceVersion": "1768382835527",
|
||||||
"creationTimestamp": "2024-10-23T08:55:45Z"
|
"creationTimestamp": "2024-10-23T08:55:45Z",
|
||||||
|
"annotations": {
|
||||||
|
"grafana.app/updatedTimestamp": "2026-01-14 09:27:15.527103 +0000 UTC"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
"description": "Enables experimental new dashboard layouts",
|
"description": "Enables new dashboard layouts",
|
||||||
"stage": "experimental",
|
"stage": "preview",
|
||||||
"codeowner": "@grafana/dashboards-squad"
|
"codeowner": "@grafana/dashboards-squad"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -54,8 +54,7 @@ func (s *ServiceImpl) getAdminNode(c *contextmodel.ReqContext) (*navtree.NavLink
|
|||||||
}
|
}
|
||||||
//nolint:staticcheck // not yet migrated to OpenFeature
|
//nolint:staticcheck // not yet migrated to OpenFeature
|
||||||
if c.HasRole(identity.RoleAdmin) &&
|
if c.HasRole(identity.RoleAdmin) &&
|
||||||
(s.cfg.StackID == "" || // show OnPrem even when provisioning is disabled
|
s.features.IsEnabledGlobally(featuremgmt.FlagProvisioning) {
|
||||||
s.features.IsEnabledGlobally(featuremgmt.FlagProvisioning)) {
|
|
||||||
generalNodeLinks = append(generalNodeLinks, &navtree.NavLink{
|
generalNodeLinks = append(generalNodeLinks, &navtree.NavLink{
|
||||||
Text: "Provisioning",
|
Text: "Provisioning",
|
||||||
Id: "provisioning",
|
Id: "provisioning",
|
||||||
|
|||||||
@@ -213,6 +213,9 @@ func (ng *AlertNG) init() error {
|
|||||||
SkipVerify: ng.Cfg.Smtp.SkipVerify,
|
SkipVerify: ng.Cfg.Smtp.SkipVerify,
|
||||||
StaticHeaders: ng.Cfg.Smtp.StaticHeaders,
|
StaticHeaders: ng.Cfg.Smtp.StaticHeaders,
|
||||||
}
|
}
|
||||||
|
runtimeConfig := remoteClient.RuntimeConfig{
|
||||||
|
DispatchTimer: notifier.GetDispatchTimer(ng.FeatureToggles).String(),
|
||||||
|
}
|
||||||
|
|
||||||
cfg := remote.AlertmanagerConfig{
|
cfg := remote.AlertmanagerConfig{
|
||||||
BasicAuthPassword: ng.Cfg.UnifiedAlerting.RemoteAlertmanager.Password,
|
BasicAuthPassword: ng.Cfg.UnifiedAlerting.RemoteAlertmanager.Password,
|
||||||
@@ -222,6 +225,7 @@ func (ng *AlertNG) init() error {
|
|||||||
ExternalURL: ng.Cfg.AppURL,
|
ExternalURL: ng.Cfg.AppURL,
|
||||||
SmtpConfig: smtpCfg,
|
SmtpConfig: smtpCfg,
|
||||||
Timeout: ng.Cfg.UnifiedAlerting.RemoteAlertmanager.Timeout,
|
Timeout: ng.Cfg.UnifiedAlerting.RemoteAlertmanager.Timeout,
|
||||||
|
RuntimeConfig: runtimeConfig,
|
||||||
}
|
}
|
||||||
autogenFn := func(ctx context.Context, logger log.Logger, orgID int64, cfg *definitions.PostableApiAlertingConfig, invalidReceiverAction notifier.InvalidReceiversAction) error {
|
autogenFn := func(ctx context.Context, logger log.Logger, orgID int64, cfg *definitions.PostableApiAlertingConfig, invalidReceiverAction notifier.InvalidReceiversAction) error {
|
||||||
return notifier.AddAutogenConfig(ctx, logger, ng.store, orgID, cfg, invalidReceiverAction, ng.FeatureToggles)
|
return notifier.AddAutogenConfig(ctx, logger, ng.store, orgID, cfg, invalidReceiverAction, ng.FeatureToggles)
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ const (
|
|||||||
|
|
||||||
// How long we keep silences in the kvstore after they've expired.
|
// How long we keep silences in the kvstore after they've expired.
|
||||||
silenceRetention = 5 * 24 * time.Hour
|
silenceRetention = 5 * 24 * time.Hour
|
||||||
|
|
||||||
|
// How long we keep flushes in the kvstore after they've expired.
|
||||||
|
flushRetention = 5 * 24 * time.Hour
|
||||||
)
|
)
|
||||||
|
|
||||||
type AlertingStore interface {
|
type AlertingStore interface {
|
||||||
@@ -44,8 +47,10 @@ type AlertingStore interface {
|
|||||||
type stateStore interface {
|
type stateStore interface {
|
||||||
SaveSilences(ctx context.Context, st alertingNotify.State) (int64, error)
|
SaveSilences(ctx context.Context, st alertingNotify.State) (int64, error)
|
||||||
SaveNotificationLog(ctx context.Context, st alertingNotify.State) (int64, error)
|
SaveNotificationLog(ctx context.Context, st alertingNotify.State) (int64, error)
|
||||||
|
SaveFlushLog(ctx context.Context, st alertingNotify.State) (int64, error)
|
||||||
GetSilences(ctx context.Context) (string, error)
|
GetSilences(ctx context.Context) (string, error)
|
||||||
GetNotificationLog(ctx context.Context) (string, error)
|
GetNotificationLog(ctx context.Context) (string, error)
|
||||||
|
GetFlushLog(ctx context.Context) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type alertmanager struct {
|
type alertmanager struct {
|
||||||
@@ -101,6 +106,10 @@ func NewAlertmanager(ctx context.Context, orgID int64, cfg *setting.Cfg, store A
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
flushLog, err := stateStore.GetFlushLog(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
silencesOptions := maintenanceOptions{
|
silencesOptions := maintenanceOptions{
|
||||||
initialState: silences,
|
initialState: silences,
|
||||||
@@ -123,12 +132,29 @@ func NewAlertmanager(ctx context.Context, orgID int64, cfg *setting.Cfg, store A
|
|||||||
}
|
}
|
||||||
l := log.New("ngalert.notifier")
|
l := log.New("ngalert.notifier")
|
||||||
|
|
||||||
|
dispatchTimer := GetDispatchTimer(featureToggles)
|
||||||
|
|
||||||
|
var flushLogOptions *maintenanceOptions
|
||||||
|
if dispatchTimer == alertingNotify.DispatchTimerSync {
|
||||||
|
flushLogOptions = &maintenanceOptions{
|
||||||
|
initialState: flushLog,
|
||||||
|
retention: flushRetention,
|
||||||
|
maintenanceFrequency: maintenanceInterval,
|
||||||
|
maintenanceFunc: func(state alertingNotify.State) (int64, error) {
|
||||||
|
// Detached context here is to make sure that when the service is shut down the persist operation is executed.
|
||||||
|
return stateStore.SaveFlushLog(context.Background(), state)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
opts := alertingNotify.GrafanaAlertmanagerOpts{
|
opts := alertingNotify.GrafanaAlertmanagerOpts{
|
||||||
ExternalURL: cfg.AppURL,
|
ExternalURL: cfg.AppURL,
|
||||||
AlertStoreCallback: nil,
|
AlertStoreCallback: nil,
|
||||||
PeerTimeout: cfg.UnifiedAlerting.HAPeerTimeout,
|
PeerTimeout: cfg.UnifiedAlerting.HAPeerTimeout,
|
||||||
Silences: silencesOptions,
|
Silences: silencesOptions,
|
||||||
Nflog: nflogOptions,
|
Nflog: nflogOptions,
|
||||||
|
FlushLog: flushLogOptions,
|
||||||
|
DispatchTimer: dispatchTimer,
|
||||||
Limits: alertingNotify.Limits{
|
Limits: alertingNotify.Limits{
|
||||||
MaxSilences: cfg.UnifiedAlerting.AlertmanagerMaxSilencesCount,
|
MaxSilences: cfg.UnifiedAlerting.AlertmanagerMaxSilencesCount,
|
||||||
MaxSilenceSizeBytes: cfg.UnifiedAlerting.AlertmanagerMaxSilenceSizeBytes,
|
MaxSilenceSizeBytes: cfg.UnifiedAlerting.AlertmanagerMaxSilenceSizeBytes,
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package notifier
|
||||||
|
|
||||||
|
import (
|
||||||
|
alertingNotify "github.com/grafana/alerting/notify"
|
||||||
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetDispatchTimer returns the appropriate dispatch timer based on feature toggles.
|
||||||
|
func GetDispatchTimer(features featuremgmt.FeatureToggles) (dt alertingNotify.DispatchTimer) {
|
||||||
|
//nolint:staticcheck // not yet migrated to OpenFeature
|
||||||
|
enabled := features.IsEnabledGlobally(featuremgmt.FlagAlertingSyncDispatchTimer)
|
||||||
|
if enabled {
|
||||||
|
dt = alertingNotify.DispatchTimerSync
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package notifier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
alertingNotify "github.com/grafana/alerting/notify"
|
||||||
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetDispatchTimer(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
featureFlagValue bool
|
||||||
|
expected alertingNotify.DispatchTimer
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "feature flag enabled returns sync timer",
|
||||||
|
featureFlagValue: true,
|
||||||
|
expected: alertingNotify.DispatchTimerSync,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "feature flag disabled returns default timer",
|
||||||
|
featureFlagValue: false,
|
||||||
|
expected: alertingNotify.DispatchTimerDefault,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
features := featuremgmt.WithFeatures(featuremgmt.FlagAlertingSyncDispatchTimer, tt.featureFlagValue)
|
||||||
|
result := GetDispatchTimer(features)
|
||||||
|
require.Equal(t, tt.expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ const (
|
|||||||
KVNamespace = "alertmanager"
|
KVNamespace = "alertmanager"
|
||||||
NotificationLogFilename = "notifications"
|
NotificationLogFilename = "notifications"
|
||||||
SilencesFilename = "silences"
|
SilencesFilename = "silences"
|
||||||
|
FlushLogFilename = "flushes"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FileStore is in charge of persisting the alertmanager files to the database.
|
// FileStore is in charge of persisting the alertmanager files to the database.
|
||||||
@@ -42,6 +43,10 @@ func (fileStore *FileStore) GetNotificationLog(ctx context.Context) (string, err
|
|||||||
return fileStore.contentFor(ctx, NotificationLogFilename)
|
return fileStore.contentFor(ctx, NotificationLogFilename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fileStore *FileStore) GetFlushLog(ctx context.Context) (string, error) {
|
||||||
|
return fileStore.contentFor(ctx, FlushLogFilename)
|
||||||
|
}
|
||||||
|
|
||||||
// contentFor returns the content for the given Alertmanager kvstore key.
|
// contentFor returns the content for the given Alertmanager kvstore key.
|
||||||
func (fileStore *FileStore) contentFor(ctx context.Context, filename string) (string, error) {
|
func (fileStore *FileStore) contentFor(ctx context.Context, filename string) (string, error) {
|
||||||
// Then, let's attempt to read it from the database.
|
// Then, let's attempt to read it from the database.
|
||||||
@@ -74,6 +79,11 @@ func (fileStore *FileStore) SaveNotificationLog(ctx context.Context, st alerting
|
|||||||
return fileStore.persist(ctx, NotificationLogFilename, st)
|
return fileStore.persist(ctx, NotificationLogFilename, st)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SaveFlushLog saves the flush log to the database and returns the size of the unencoded state.
|
||||||
|
func (fileStore *FileStore) SaveFlushLog(ctx context.Context, st alertingNotify.State) (int64, error) {
|
||||||
|
return fileStore.persist(ctx, FlushLogFilename, st)
|
||||||
|
}
|
||||||
|
|
||||||
// persist takes care of persisting the binary representation of internal state to the database as a base64 encoded string.
|
// persist takes care of persisting the binary representation of internal state to the database as a base64 encoded string.
|
||||||
func (fileStore *FileStore) persist(ctx context.Context, filename string, st alertingNotify.State) (int64, error) {
|
func (fileStore *FileStore) persist(ctx context.Context, filename string, st alertingNotify.State) (int64, error) {
|
||||||
var size int64
|
var size int64
|
||||||
|
|||||||
@@ -106,3 +106,48 @@ func TestFileStore_NotificationLog(t *testing.T) {
|
|||||||
t.Errorf("Unexpected Diff: %v", cmp.Diff(newState, decoded))
|
t.Errorf("Unexpected Diff: %v", cmp.Diff(newState, decoded))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFileStore_FlushLog(t *testing.T) {
|
||||||
|
store := fakes.NewFakeKVStore(t)
|
||||||
|
ctx := context.Background()
|
||||||
|
var orgId int64 = 1
|
||||||
|
|
||||||
|
// Initialize kvstore with empty flush log state.
|
||||||
|
initialState := flushLogState{} // FlushLog uses the same structure as nflog
|
||||||
|
decodedState, err := initialState.MarshalBinary()
|
||||||
|
require.NoError(t, err)
|
||||||
|
encodedState := base64.StdEncoding.EncodeToString(decodedState)
|
||||||
|
err = store.Set(ctx, orgId, KVNamespace, FlushLogFilename, encodedState)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
fs := NewFileStore(orgId, store)
|
||||||
|
|
||||||
|
// Load initial (empty).
|
||||||
|
flushLog, err := fs.GetFlushLog(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
decoded, err := decodeFlushLogState(strings.NewReader(flushLog))
|
||||||
|
require.NoError(t, err)
|
||||||
|
if !cmp.Equal(initialState, decoded) {
|
||||||
|
t.Errorf("Unexpected Diff: %v", cmp.Diff(initialState, decoded))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save new flush log state.
|
||||||
|
now := time.Now()
|
||||||
|
oneHour := now.Add(time.Hour)
|
||||||
|
|
||||||
|
v1 := createFlushLog(1, now, oneHour)
|
||||||
|
v2 := createFlushLog(2, now, oneHour)
|
||||||
|
newState := flushLogState{1: v1, 2: v2}
|
||||||
|
size, err := fs.SaveFlushLog(ctx, newState)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Greater(t, size, int64(0))
|
||||||
|
|
||||||
|
// Load new.
|
||||||
|
flushLog, err = fs.GetFlushLog(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
decoded, err = decodeFlushLogState(strings.NewReader(flushLog))
|
||||||
|
require.NoError(t, err)
|
||||||
|
if !cmp.Equal(newState, decoded) {
|
||||||
|
t.Errorf("Unexpected Diff: %v", cmp.Diff(newState, decoded))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ type Alertmanager interface {
|
|||||||
type ExternalState struct {
|
type ExternalState struct {
|
||||||
Silences []byte
|
Silences []byte
|
||||||
Nflog []byte
|
Nflog []byte
|
||||||
|
FlushLog []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// StateMerger describes a type that is able to merge external state (nflog, silences) with its own.
|
// StateMerger describes a type that is able to merge external state (nflog, silences) with its own.
|
||||||
@@ -378,7 +379,7 @@ func (moa *MultiOrgAlertmanager) SyncAlertmanagersForOrgs(ctx context.Context, o
|
|||||||
func (moa *MultiOrgAlertmanager) cleanupOrphanLocalOrgState(ctx context.Context,
|
func (moa *MultiOrgAlertmanager) cleanupOrphanLocalOrgState(ctx context.Context,
|
||||||
activeOrganizations map[int64]struct{},
|
activeOrganizations map[int64]struct{},
|
||||||
) {
|
) {
|
||||||
storedFiles := []string{NotificationLogFilename, SilencesFilename}
|
storedFiles := []string{NotificationLogFilename, SilencesFilename, FlushLogFilename}
|
||||||
for _, fileName := range storedFiles {
|
for _, fileName := range storedFiles {
|
||||||
keys, err := moa.kvStore.Keys(ctx, kvstore.AllOrganizations, KVNamespace, fileName)
|
keys, err := moa.kvStore.Keys(ctx, kvstore.AllOrganizations, KVNamespace, fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -5,5 +5,8 @@ func (am *alertmanager) MergeState(state ExternalState) error {
|
|||||||
if err := am.Base.MergeNflog(state.Nflog); err != nil {
|
if err := am.Base.MergeNflog(state.Nflog); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return am.Base.MergeSilences(state.Silences)
|
if err := am.Base.MergeSilences(state.Silences); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return am.Base.MergeFlushLog(state.FlushLog)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/matttproud/golang_protobuf_extensions/pbutil"
|
"github.com/matttproud/golang_protobuf_extensions/pbutil"
|
||||||
|
"github.com/prometheus/alertmanager/flushlog/flushlogpb"
|
||||||
"github.com/prometheus/alertmanager/nflog/nflogpb"
|
"github.com/prometheus/alertmanager/nflog/nflogpb"
|
||||||
"github.com/prometheus/alertmanager/silence/silencepb"
|
"github.com/prometheus/alertmanager/silence/silencepb"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
@@ -228,15 +229,13 @@ func (f *FakeOrgStore) FetchOrgIds(_ context.Context) ([]int64, error) {
|
|||||||
return f.orgs, nil
|
return f.orgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type NoValidation struct {
|
type NoValidation struct{}
|
||||||
}
|
|
||||||
|
|
||||||
func (n NoValidation) Validate(_ models.NotificationSettings) error {
|
func (n NoValidation) Validate(_ models.NotificationSettings) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type RejectingValidation struct {
|
type RejectingValidation struct{}
|
||||||
}
|
|
||||||
|
|
||||||
func (n RejectingValidation) Validate(s models.NotificationSettings) error {
|
func (n RejectingValidation) Validate(s models.NotificationSettings) error {
|
||||||
return ErrorReceiverDoesNotExist{ErrorReferenceInvalid: ErrorReferenceInvalid{Reference: s.Receiver}}
|
return ErrorReceiverDoesNotExist{ErrorReferenceInvalid: ErrorReferenceInvalid{Reference: s.Receiver}}
|
||||||
@@ -365,6 +364,51 @@ func createNotificationLog(groupKey string, receiverName string, sentAt, expires
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/grafana/prometheus-alertmanager/blob/main/flushlog/flushlog.go#L136-L136
|
||||||
|
type flushLogState map[uint64]*flushlogpb.MeshFlushLog
|
||||||
|
|
||||||
|
func (s flushLogState) MarshalBinary() ([]byte, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
for _, e := range s {
|
||||||
|
if _, err := pbutil.WriteDelimited(&buf, e); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createFlushLog(groupFingerprint uint64, ts, expiresAt time.Time) *flushlogpb.MeshFlushLog {
|
||||||
|
return &flushlogpb.MeshFlushLog{
|
||||||
|
FlushLog: &flushlogpb.FlushLog{
|
||||||
|
GroupFingerprint: groupFingerprint,
|
||||||
|
Timestamp: ts,
|
||||||
|
},
|
||||||
|
ExpiresAt: expiresAt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeFlushLogState copied from decodeState in prometheus-alertmanager/flushlog/flushlog.go
|
||||||
|
func decodeFlushLogState(r io.Reader) (flushLogState, error) {
|
||||||
|
st := flushLogState{}
|
||||||
|
for {
|
||||||
|
var e flushlogpb.MeshFlushLog
|
||||||
|
_, err := pbutil.ReadDelimited(r, &e)
|
||||||
|
if err == nil {
|
||||||
|
if e.FlushLog == nil || e.FlushLog.GroupFingerprint == 0 || e.FlushLog.Timestamp.IsZero() {
|
||||||
|
return nil, errInvalidState
|
||||||
|
}
|
||||||
|
st[e.FlushLog.GroupFingerprint] = &e
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return st, nil
|
||||||
|
}
|
||||||
|
|
||||||
type call struct {
|
type call struct {
|
||||||
Method string
|
Method string
|
||||||
Args []interface{}
|
Args []interface{}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import (
|
|||||||
type stateStore interface {
|
type stateStore interface {
|
||||||
GetSilences(ctx context.Context) (string, error)
|
GetSilences(ctx context.Context) (string, error)
|
||||||
GetNotificationLog(ctx context.Context) (string, error)
|
GetNotificationLog(ctx context.Context) (string, error)
|
||||||
|
GetFlushLog(ctx context.Context) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AutogenFn is a function that adds auto-generated routes to a configuration.
|
// AutogenFn is a function that adds auto-generated routes to a configuration.
|
||||||
@@ -86,6 +87,8 @@ type Alertmanager struct {
|
|||||||
|
|
||||||
promoteConfig bool
|
promoteConfig bool
|
||||||
externalURL string
|
externalURL string
|
||||||
|
|
||||||
|
runtimeConfig remoteClient.RuntimeConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type AlertmanagerConfig struct {
|
type AlertmanagerConfig struct {
|
||||||
@@ -111,6 +114,9 @@ type AlertmanagerConfig struct {
|
|||||||
|
|
||||||
// Timeout for the HTTP client.
|
// Timeout for the HTTP client.
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
|
|
||||||
|
// RuntimeConfig specifies runtime behavior settings for the remote Alertmanager.
|
||||||
|
RuntimeConfig remoteClient.RuntimeConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *AlertmanagerConfig) Validate() error {
|
func (cfg *AlertmanagerConfig) Validate() error {
|
||||||
@@ -203,6 +209,7 @@ func NewAlertmanager(ctx context.Context, cfg AlertmanagerConfig, store stateSto
|
|||||||
externalURL: cfg.ExternalURL,
|
externalURL: cfg.ExternalURL,
|
||||||
promoteConfig: cfg.PromoteConfig,
|
promoteConfig: cfg.PromoteConfig,
|
||||||
smtp: cfg.SmtpConfig,
|
smtp: cfg.SmtpConfig,
|
||||||
|
runtimeConfig: cfg.RuntimeConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the default configuration once and remember its hash so we can compare it later.
|
// Parse the default configuration once and remember its hash so we can compare it later.
|
||||||
@@ -331,10 +338,11 @@ func (am *Alertmanager) buildConfiguration(ctx context.Context, raw []byte, crea
|
|||||||
AlertmanagerConfig: mergeResult.Config,
|
AlertmanagerConfig: mergeResult.Config,
|
||||||
Templates: templates,
|
Templates: templates,
|
||||||
},
|
},
|
||||||
CreatedAt: createdAtEpoch,
|
CreatedAt: createdAtEpoch,
|
||||||
Promoted: am.promoteConfig,
|
Promoted: am.promoteConfig,
|
||||||
ExternalURL: am.externalURL,
|
ExternalURL: am.externalURL,
|
||||||
SmtpConfig: am.smtp,
|
SmtpConfig: am.smtp,
|
||||||
|
RuntimeConfig: am.runtimeConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
cfgHash, err := calculateUserGrafanaConfigHash(payload)
|
cfgHash, err := calculateUserGrafanaConfigHash(payload)
|
||||||
@@ -388,6 +396,8 @@ func (am *Alertmanager) GetRemoteState(ctx context.Context) (notifier.ExternalSt
|
|||||||
rs.Silences = p.Data
|
rs.Silences = p.Data
|
||||||
case "nfl":
|
case "nfl":
|
||||||
rs.Nflog = p.Data
|
rs.Nflog = p.Data
|
||||||
|
case "fls":
|
||||||
|
rs.FlushLog = p.Data
|
||||||
default:
|
default:
|
||||||
return rs, fmt.Errorf("unknown part key %q", p.Key)
|
return rs, fmt.Errorf("unknown part key %q", p.Key)
|
||||||
}
|
}
|
||||||
@@ -677,6 +687,12 @@ func (am *Alertmanager) getFullState(ctx context.Context) (string, error) {
|
|||||||
}
|
}
|
||||||
parts = append(parts, alertingClusterPB.Part{Key: notifier.NotificationLogFilename, Data: []byte(notificationLog)})
|
parts = append(parts, alertingClusterPB.Part{Key: notifier.NotificationLogFilename, Data: []byte(notificationLog)})
|
||||||
|
|
||||||
|
flushLog, err := am.state.GetFlushLog(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error getting flush log: %w", err)
|
||||||
|
}
|
||||||
|
parts = append(parts, alertingClusterPB.Part{Key: notifier.FlushLogFilename, Data: []byte(flushLog)})
|
||||||
|
|
||||||
fs := alertingClusterPB.FullState{
|
fs := alertingClusterPB.FullState{
|
||||||
Parts: parts,
|
Parts: parts,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ func (u *GrafanaAlertmanagerConfig) MarshalJSON() ([]byte, error) {
|
|||||||
return definition.MarshalJSONWithSecrets((*cfg)(u))
|
return definition.MarshalJSONWithSecrets((*cfg)(u))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RuntimeConfig struct {
|
||||||
|
DispatchTimer string `json:"dispatch_timer"`
|
||||||
|
}
|
||||||
|
|
||||||
type UserGrafanaConfig struct {
|
type UserGrafanaConfig struct {
|
||||||
GrafanaAlertmanagerConfig GrafanaAlertmanagerConfig `json:"configuration"`
|
GrafanaAlertmanagerConfig GrafanaAlertmanagerConfig `json:"configuration"`
|
||||||
Hash string `json:"configuration_hash"`
|
Hash string `json:"configuration_hash"`
|
||||||
@@ -37,6 +41,7 @@ type UserGrafanaConfig struct {
|
|||||||
Promoted bool `json:"promoted"`
|
Promoted bool `json:"promoted"`
|
||||||
ExternalURL string `json:"external_url"`
|
ExternalURL string `json:"external_url"`
|
||||||
SmtpConfig SmtpConfig `json:"smtp_config"`
|
SmtpConfig SmtpConfig `json:"smtp_config"`
|
||||||
|
RuntimeConfig RuntimeConfig `json:"runtime_config"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *Mimir) GetGrafanaAlertmanagerConfig(ctx context.Context) (*UserGrafanaConfig, error) {
|
func (mc *Mimir) GetGrafanaAlertmanagerConfig(ctx context.Context) (*UserGrafanaConfig, error) {
|
||||||
|
|||||||
@@ -600,6 +600,7 @@ type Cfg struct {
|
|||||||
IndexRebuildInterval time.Duration
|
IndexRebuildInterval time.Duration
|
||||||
IndexCacheTTL time.Duration
|
IndexCacheTTL time.Duration
|
||||||
IndexMinUpdateInterval time.Duration // Don't update index if it was updated less than this interval ago.
|
IndexMinUpdateInterval time.Duration // Don't update index if it was updated less than this interval ago.
|
||||||
|
IndexScoringModel string // Note: Temporary config to switch the index scoring model and will be removed soon.
|
||||||
MaxFileIndexAge time.Duration // Max age of file-based indexes. Index older than this will be rebuilt asynchronously.
|
MaxFileIndexAge time.Duration // Max age of file-based indexes. Index older than this will be rebuilt asynchronously.
|
||||||
MinFileIndexBuildVersion string // Minimum version of Grafana that built the file-based index. If index was built with older Grafana, it will be rebuilt asynchronously.
|
MinFileIndexBuildVersion string // Minimum version of Grafana that built the file-based index. If index was built with older Grafana, it will be rebuilt asynchronously.
|
||||||
EnableSharding bool
|
EnableSharding bool
|
||||||
|
|||||||
@@ -123,6 +123,10 @@ func (cfg *Cfg) setUnifiedStorageConfig() {
|
|||||||
cfg.IndexRebuildInterval = section.Key("index_rebuild_interval").MustDuration(24 * time.Hour)
|
cfg.IndexRebuildInterval = section.Key("index_rebuild_interval").MustDuration(24 * time.Hour)
|
||||||
cfg.IndexCacheTTL = section.Key("index_cache_ttl").MustDuration(10 * time.Minute)
|
cfg.IndexCacheTTL = section.Key("index_cache_ttl").MustDuration(10 * time.Minute)
|
||||||
cfg.IndexMinUpdateInterval = section.Key("index_min_update_interval").MustDuration(0)
|
cfg.IndexMinUpdateInterval = section.Key("index_min_update_interval").MustDuration(0)
|
||||||
|
cfg.IndexScoringModel = section.Key("index_scoring_model").MustString("")
|
||||||
|
if cfg.IndexScoringModel != "" {
|
||||||
|
cfg.Logger.Info("Index scoring model set", "model", cfg.IndexScoringModel)
|
||||||
|
}
|
||||||
cfg.SprinklesApiServer = section.Key("sprinkles_api_server").String()
|
cfg.SprinklesApiServer = section.Key("sprinkles_api_server").String()
|
||||||
cfg.SprinklesApiServerPageLimit = section.Key("sprinkles_api_server_page_limit").MustInt(10000)
|
cfg.SprinklesApiServerPageLimit = section.Key("sprinkles_api_server_page_limit").MustInt(10000)
|
||||||
cfg.CACertPath = section.Key("ca_cert_path").String()
|
cfg.CACertPath = section.Key("ca_cert_path").String()
|
||||||
|
|||||||
@@ -9,11 +9,13 @@ import "resource.proto";
|
|||||||
// Unlike the ResourceStore, this service can be exposed to clients directly
|
// Unlike the ResourceStore, this service can be exposed to clients directly
|
||||||
// It should be implemented with efficient indexes and does not need read-after-write semantics
|
// It should be implemented with efficient indexes and does not need read-after-write semantics
|
||||||
service ResourceIndex {
|
service ResourceIndex {
|
||||||
|
// Query for documents
|
||||||
rpc Search(ResourceSearchRequest) returns (ResourceSearchResponse);
|
rpc Search(ResourceSearchRequest) returns (ResourceSearchResponse);
|
||||||
|
|
||||||
// Get the resource stats
|
// Get the resource stats
|
||||||
rpc GetStats(ResourceStatsRequest) returns (ResourceStatsResponse);
|
rpc GetStats(ResourceStatsRequest) returns (ResourceStatsResponse);
|
||||||
|
|
||||||
|
// Rebuild the search index
|
||||||
rpc RebuildIndexes(RebuildIndexesRequest) returns (RebuildIndexesResponse);
|
rpc RebuildIndexes(RebuildIndexesRequest) returns (RebuildIndexesResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +51,20 @@ message ResourceStatsResponse {
|
|||||||
repeated Stats stats = 2;
|
repeated Stats stats = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This controls what query and analyzers are applied to the specified field
|
||||||
|
// See: https://blevesearch.com/docs/Analyzers/
|
||||||
|
enum QueryFieldType {
|
||||||
|
// Picks a reasonable analyzer given the input. Currently this always uses TEXT
|
||||||
|
// In the future, it may change to depend on the indexed field type
|
||||||
|
DEFAULT = 0;
|
||||||
|
// Use free text analyzer. The query is broken into a normalized set of tokens
|
||||||
|
TEXT = 1;
|
||||||
|
// The query must exactly match the indexed token
|
||||||
|
KEYWORD = 2;
|
||||||
|
// Like a text query, but the position and offsets influence the score
|
||||||
|
PHRASE = 3;
|
||||||
|
}
|
||||||
|
|
||||||
// Search within a single resource
|
// Search within a single resource
|
||||||
message ResourceSearchRequest {
|
message ResourceSearchRequest {
|
||||||
message Sort {
|
message Sort {
|
||||||
@@ -64,6 +80,18 @@ message ResourceSearchRequest {
|
|||||||
// date queries
|
// date queries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Defines the field in the index to query
|
||||||
|
// Boost is optional, and allows weighting the field higher in the results
|
||||||
|
message QueryField {
|
||||||
|
// The field name in the index to query
|
||||||
|
string name = 1;
|
||||||
|
|
||||||
|
QueryFieldType type = 2;
|
||||||
|
|
||||||
|
// Boost value for this field
|
||||||
|
float boost = 3;
|
||||||
|
}
|
||||||
|
|
||||||
// The key must include namespace + group + resource
|
// The key must include namespace + group + resource
|
||||||
ListOptions options = 1;
|
ListOptions options = 1;
|
||||||
|
|
||||||
@@ -99,6 +127,9 @@ message ResourceSearchRequest {
|
|||||||
int64 page = 11;
|
int64 page = 11;
|
||||||
|
|
||||||
int64 permission = 12;
|
int64 permission = 12;
|
||||||
|
|
||||||
|
// Optionally specify which fields are included in the query
|
||||||
|
repeated QueryField query_fields = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ResourceSearchResponse {
|
message ResourceSearchResponse {
|
||||||
|
|||||||
@@ -290,7 +290,6 @@ const SEARCH_FIELD_NAMESPACE = "namespace"
|
|||||||
const SEARCH_FIELD_NAME = "name"
|
const SEARCH_FIELD_NAME = "name"
|
||||||
const SEARCH_FIELD_RV = "rv"
|
const SEARCH_FIELD_RV = "rv"
|
||||||
const SEARCH_FIELD_TITLE = "title"
|
const SEARCH_FIELD_TITLE = "title"
|
||||||
const SEARCH_FIELD_TITLE_NGRAM = "title_ngram"
|
|
||||||
const SEARCH_FIELD_TITLE_PHRASE = "title_phrase" // filtering/sorting on title by full phrase
|
const SEARCH_FIELD_TITLE_PHRASE = "title_phrase" // filtering/sorting on title by full phrase
|
||||||
const SEARCH_FIELD_DESCRIPTION = "description"
|
const SEARCH_FIELD_DESCRIPTION = "description"
|
||||||
const SEARCH_FIELD_TAGS = "tags"
|
const SEARCH_FIELD_TAGS = "tags"
|
||||||
|
|||||||
@@ -21,6 +21,65 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// This controls what query and analyzers are applied to the specified field
|
||||||
|
// See: https://blevesearch.com/docs/Analyzers/
|
||||||
|
type QueryFieldType int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Picks a reasonable analyzer given the input. Currently this always uses TEXT
|
||||||
|
// In the future, it may change to depend on the indexed field type
|
||||||
|
QueryFieldType_DEFAULT QueryFieldType = 0
|
||||||
|
// Use free text analyzer. The query is broken into a normalized set of tokens
|
||||||
|
QueryFieldType_TEXT QueryFieldType = 1
|
||||||
|
// The query must exactly match the indexed token
|
||||||
|
QueryFieldType_KEYWORD QueryFieldType = 2
|
||||||
|
// Like a text query, but the position and offsets influence the score
|
||||||
|
QueryFieldType_PHRASE QueryFieldType = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// Enum value maps for QueryFieldType.
|
||||||
|
var (
|
||||||
|
QueryFieldType_name = map[int32]string{
|
||||||
|
0: "DEFAULT",
|
||||||
|
1: "TEXT",
|
||||||
|
2: "KEYWORD",
|
||||||
|
3: "PHRASE",
|
||||||
|
}
|
||||||
|
QueryFieldType_value = map[string]int32{
|
||||||
|
"DEFAULT": 0,
|
||||||
|
"TEXT": 1,
|
||||||
|
"KEYWORD": 2,
|
||||||
|
"PHRASE": 3,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (x QueryFieldType) Enum() *QueryFieldType {
|
||||||
|
p := new(QueryFieldType)
|
||||||
|
*p = x
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x QueryFieldType) String() string {
|
||||||
|
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (QueryFieldType) Descriptor() protoreflect.EnumDescriptor {
|
||||||
|
return file_search_proto_enumTypes[0].Descriptor()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (QueryFieldType) Type() protoreflect.EnumType {
|
||||||
|
return &file_search_proto_enumTypes[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x QueryFieldType) Number() protoreflect.EnumNumber {
|
||||||
|
return protoreflect.EnumNumber(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use QueryFieldType.Descriptor instead.
|
||||||
|
func (QueryFieldType) EnumDescriptor() ([]byte, []int) {
|
||||||
|
return file_search_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
// Get statistics across multiple resources
|
// Get statistics across multiple resources
|
||||||
// For these queries, we do not need authorization to see the actual values
|
// For these queries, we do not need authorization to see the actual values
|
||||||
type ResourceStatsRequest struct {
|
type ResourceStatsRequest struct {
|
||||||
@@ -165,10 +224,12 @@ type ResourceSearchRequest struct {
|
|||||||
// the return fields (empty will return everything)
|
// the return fields (empty will return everything)
|
||||||
Fields []string `protobuf:"bytes,8,rep,name=fields,proto3" json:"fields,omitempty"`
|
Fields []string `protobuf:"bytes,8,rep,name=fields,proto3" json:"fields,omitempty"`
|
||||||
// explain each result (added to the each row)
|
// explain each result (added to the each row)
|
||||||
Explain bool `protobuf:"varint,9,opt,name=explain,proto3" json:"explain,omitempty"`
|
Explain bool `protobuf:"varint,9,opt,name=explain,proto3" json:"explain,omitempty"`
|
||||||
IsDeleted bool `protobuf:"varint,10,opt,name=is_deleted,json=isDeleted,proto3" json:"is_deleted,omitempty"`
|
IsDeleted bool `protobuf:"varint,10,opt,name=is_deleted,json=isDeleted,proto3" json:"is_deleted,omitempty"`
|
||||||
Page int64 `protobuf:"varint,11,opt,name=page,proto3" json:"page,omitempty"`
|
Page int64 `protobuf:"varint,11,opt,name=page,proto3" json:"page,omitempty"`
|
||||||
Permission int64 `protobuf:"varint,12,opt,name=permission,proto3" json:"permission,omitempty"`
|
Permission int64 `protobuf:"varint,12,opt,name=permission,proto3" json:"permission,omitempty"`
|
||||||
|
// Optionally specify which fields are included in the query
|
||||||
|
QueryFields []*ResourceSearchRequest_QueryField `protobuf:"bytes,13,rep,name=query_fields,json=queryFields,proto3" json:"query_fields,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@@ -287,6 +348,13 @@ func (x *ResourceSearchRequest) GetPermission() int64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *ResourceSearchRequest) GetQueryFields() []*ResourceSearchRequest_QueryField {
|
||||||
|
if x != nil {
|
||||||
|
return x.QueryFields
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type ResourceSearchResponse struct {
|
type ResourceSearchResponse struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
// Error details
|
// Error details
|
||||||
@@ -670,6 +738,70 @@ func (x *ResourceSearchRequest_Facet) GetLimit() int64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Defines the field in the index to query
|
||||||
|
// Boost is optional, and allows weighting the field higher in the results
|
||||||
|
type ResourceSearchRequest_QueryField struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
// The field name in the index to query
|
||||||
|
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
|
Type QueryFieldType `protobuf:"varint,2,opt,name=type,proto3,enum=resource.QueryFieldType" json:"type,omitempty"`
|
||||||
|
// Boost value for this field
|
||||||
|
Boost float32 `protobuf:"fixed32,3,opt,name=boost,proto3" json:"boost,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ResourceSearchRequest_QueryField) Reset() {
|
||||||
|
*x = ResourceSearchRequest_QueryField{}
|
||||||
|
mi := &file_search_proto_msgTypes[9]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ResourceSearchRequest_QueryField) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ResourceSearchRequest_QueryField) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ResourceSearchRequest_QueryField) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_search_proto_msgTypes[9]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ResourceSearchRequest_QueryField.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ResourceSearchRequest_QueryField) Descriptor() ([]byte, []int) {
|
||||||
|
return file_search_proto_rawDescGZIP(), []int{2, 2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ResourceSearchRequest_QueryField) GetName() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ResourceSearchRequest_QueryField) GetType() QueryFieldType {
|
||||||
|
if x != nil {
|
||||||
|
return x.Type
|
||||||
|
}
|
||||||
|
return QueryFieldType_DEFAULT
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ResourceSearchRequest_QueryField) GetBoost() float32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Boost
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
type ResourceSearchResponse_Facet struct {
|
type ResourceSearchResponse_Facet struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Field string `protobuf:"bytes,1,opt,name=field,proto3" json:"field,omitempty"`
|
Field string `protobuf:"bytes,1,opt,name=field,proto3" json:"field,omitempty"`
|
||||||
@@ -685,7 +817,7 @@ type ResourceSearchResponse_Facet struct {
|
|||||||
|
|
||||||
func (x *ResourceSearchResponse_Facet) Reset() {
|
func (x *ResourceSearchResponse_Facet) Reset() {
|
||||||
*x = ResourceSearchResponse_Facet{}
|
*x = ResourceSearchResponse_Facet{}
|
||||||
mi := &file_search_proto_msgTypes[10]
|
mi := &file_search_proto_msgTypes[11]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -697,7 +829,7 @@ func (x *ResourceSearchResponse_Facet) String() string {
|
|||||||
func (*ResourceSearchResponse_Facet) ProtoMessage() {}
|
func (*ResourceSearchResponse_Facet) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *ResourceSearchResponse_Facet) ProtoReflect() protoreflect.Message {
|
func (x *ResourceSearchResponse_Facet) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_search_proto_msgTypes[10]
|
mi := &file_search_proto_msgTypes[11]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -751,7 +883,7 @@ type ResourceSearchResponse_TermFacet struct {
|
|||||||
|
|
||||||
func (x *ResourceSearchResponse_TermFacet) Reset() {
|
func (x *ResourceSearchResponse_TermFacet) Reset() {
|
||||||
*x = ResourceSearchResponse_TermFacet{}
|
*x = ResourceSearchResponse_TermFacet{}
|
||||||
mi := &file_search_proto_msgTypes[11]
|
mi := &file_search_proto_msgTypes[12]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -763,7 +895,7 @@ func (x *ResourceSearchResponse_TermFacet) String() string {
|
|||||||
func (*ResourceSearchResponse_TermFacet) ProtoMessage() {}
|
func (*ResourceSearchResponse_TermFacet) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *ResourceSearchResponse_TermFacet) ProtoReflect() protoreflect.Message {
|
func (x *ResourceSearchResponse_TermFacet) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_search_proto_msgTypes[11]
|
mi := &file_search_proto_msgTypes[12]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -818,7 +950,7 @@ var file_search_proto_rawDesc = string([]byte{
|
|||||||
0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63,
|
0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63,
|
||||||
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e,
|
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e,
|
||||||
0x74, 0x22, 0x8e, 0x05, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65,
|
0x74, 0x22, 0xc3, 0x06, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65,
|
||||||
0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x07, 0x6f,
|
0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x07, 0x6f,
|
||||||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72,
|
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72,
|
||||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69,
|
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69,
|
||||||
@@ -846,93 +978,109 @@ var file_search_proto_rawDesc = string([]byte{
|
|||||||
0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x0b,
|
0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x0b,
|
||||||
0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65,
|
0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65,
|
||||||
0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a,
|
0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a,
|
||||||
0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x30, 0x0a, 0x04, 0x53, 0x6f,
|
0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x0c, 0x71, 0x75,
|
||||||
0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
0x65, 0x72, 0x79, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b,
|
||||||
0x09, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63,
|
0x32, 0x2a, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f,
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 0x1a, 0x33, 0x0a, 0x05,
|
|
||||||
0x46, 0x61, 0x63, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01,
|
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c,
|
|
||||||
0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69,
|
|
||||||
0x74, 0x1a, 0x5f, 0x0a, 0x0a, 0x46, 0x61, 0x63, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
|
|
||||||
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
|
|
||||||
0x79, 0x12, 0x3b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
|
||||||
0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f,
|
|
||||||
0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||||
0x74, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
|
0x74, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0b, 0x71, 0x75,
|
||||||
0x38, 0x01, 0x22, 0xea, 0x04, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53,
|
0x65, 0x72, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x30, 0x0a, 0x04, 0x53, 0x6f, 0x72,
|
||||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a,
|
0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72,
|
0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18,
|
||||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73,
|
0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 0x1a, 0x33, 0x0a, 0x05, 0x46,
|
||||||
0x75, 0x6c, 0x74, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x27, 0x0a, 0x03, 0x6b, 0x65,
|
0x61, 0x63, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20,
|
||||||
0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
|
0x01, 0x28, 0x09, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69,
|
||||||
0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x03,
|
0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74,
|
||||||
0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x03,
|
0x1a, 0x64, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x12,
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e,
|
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
|
||||||
0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x07, 0x72,
|
0x6d, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e,
|
||||||
0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
|
0x32, 0x18, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x51, 0x75, 0x65, 0x72,
|
||||||
0x68, 0x69, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x6f, 0x74, 0x61,
|
0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
|
||||||
0x6c, 0x48, 0x69, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x63,
|
0x12, 0x14, 0x0a, 0x05, 0x62, 0x6f, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52,
|
||||||
0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x71, 0x75, 0x65, 0x72, 0x79,
|
0x05, 0x62, 0x6f, 0x6f, 0x73, 0x74, 0x1a, 0x5f, 0x0a, 0x0a, 0x46, 0x61, 0x63, 0x65, 0x74, 0x45,
|
||||||
0x43, 0x6f, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x63, 0x6f, 0x72,
|
0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x53, 0x63, 0x6f, 0x72,
|
0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
|
||||||
0x65, 0x12, 0x41, 0x0a, 0x05, 0x66, 0x61, 0x63, 0x65, 0x74, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b,
|
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||||
0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f,
|
0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52,
|
||||||
|
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61,
|
||||||
|
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xea, 0x04, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f,
|
||||||
0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||||
0x73, 0x65, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x66,
|
0x73, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x61, 0x63, 0x65, 0x74, 0x1a, 0x8f, 0x01, 0x0a, 0x05, 0x46, 0x61, 0x63, 0x65, 0x74, 0x12, 0x14,
|
0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x45, 0x72, 0x72,
|
||||||
0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x66,
|
0x6f, 0x72, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12,
|
||||||
0x69, 0x65, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20,
|
0x27, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72,
|
||||||
0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x69,
|
|
||||||
0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x69, 0x73,
|
|
||||||
0x73, 0x69, 0x6e, 0x67, 0x12, 0x40, 0x0a, 0x05, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x18, 0x04, 0x20,
|
|
||||||
0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52,
|
|
||||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73,
|
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x65, 0x72, 0x6d, 0x46, 0x61, 0x63, 0x65, 0x74, 0x52,
|
|
||||||
0x05, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x1a, 0x35, 0x0a, 0x09, 0x54, 0x65, 0x72, 0x6d, 0x46, 0x61,
|
|
||||||
0x63, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x52, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0x60, 0x0a,
|
|
||||||
0x0a, 0x46, 0x61, 0x63, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
|
||||||
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3c, 0x0a,
|
|
||||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72,
|
|
||||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||||
0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46,
|
0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75,
|
||||||
0x61, 0x63, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22,
|
0x6c, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x72, 0x65, 0x73, 0x6f,
|
||||||
0x60, 0x0a, 0x15, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65,
|
0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x61, 0x62,
|
||||||
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65,
|
0x6c, 0x65, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74,
|
||||||
0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d,
|
0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x68, 0x69, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
|
||||||
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x29, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02,
|
0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x48, 0x69, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x71, 0x75,
|
||||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e,
|
0x65, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09,
|
||||||
0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x04, 0x6b, 0x65, 0x79,
|
0x71, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78,
|
||||||
0x73, 0x22, 0x83, 0x01, 0x0a, 0x16, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64,
|
0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x6d, 0x61,
|
||||||
0x65, 0x78, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0c,
|
0x78, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x41, 0x0a, 0x05, 0x66, 0x61, 0x63, 0x65, 0x74, 0x18,
|
||||||
0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
|
0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||||
0x28, 0x03, 0x52, 0x0c, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74,
|
0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52,
|
||||||
0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x74, 0x45, 0x6e, 0x74,
|
||||||
0x09, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x2b, 0x0a, 0x05, 0x65, 0x72,
|
0x72, 0x79, 0x52, 0x05, 0x66, 0x61, 0x63, 0x65, 0x74, 0x1a, 0x8f, 0x01, 0x0a, 0x05, 0x46, 0x61,
|
||||||
0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f,
|
0x63, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x75, 0x72, 0x63, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74,
|
0x28, 0x09, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74,
|
||||||
0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x32, 0xfe, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f,
|
0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12,
|
||||||
0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x4b, 0x0a, 0x06, 0x53, 0x65, 0x61,
|
0x18, 0x0a, 0x07, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
|
||||||
0x72, 0x63, 0x68, 0x12, 0x1f, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52,
|
0x52, 0x07, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x40, 0x0a, 0x05, 0x74, 0x65, 0x72,
|
||||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71,
|
0x6d, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e,
|
0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72,
|
||||||
0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
|
0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x65, 0x72, 0x6d, 0x46,
|
||||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61,
|
0x61, 0x63, 0x65, 0x74, 0x52, 0x05, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x1a, 0x35, 0x0a, 0x09, 0x54,
|
||||||
0x74, 0x73, 0x12, 0x1e, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65,
|
0x65, 0x72, 0x6d, 0x46, 0x61, 0x63, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x72, 0x6d,
|
||||||
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x12, 0x14, 0x0a, 0x05,
|
||||||
0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65,
|
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75,
|
||||||
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
0x6e, 0x74, 0x1a, 0x60, 0x0a, 0x0a, 0x46, 0x61, 0x63, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79,
|
||||||
0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0e, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e,
|
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
|
||||||
0x64, 0x65, 0x78, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
0x65, 0x79, 0x12, 0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
0x2e, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x52,
|
0x0b, 0x32, 0x26, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73,
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
|
0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||||
0x65, 0x2e, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73,
|
0x6e, 0x73, 0x65, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68,
|
0x3a, 0x02, 0x38, 0x01, 0x22, 0x60, 0x0a, 0x15, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49,
|
||||||
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x67,
|
0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a,
|
||||||
0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61,
|
0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x67, 0x65, 0x2f, 0x75, 0x6e, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75,
|
0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x29, 0x0a, 0x04, 0x6b,
|
||||||
0x72, 0x63, 0x65, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f,
|
||||||
|
0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x65, 0x79,
|
||||||
|
0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x16, 0x52, 0x65, 0x62, 0x75, 0x69,
|
||||||
|
0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||||
|
0x65, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x75, 0x6e,
|
||||||
|
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64,
|
||||||
|
0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
|
||||||
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12,
|
||||||
|
0x2b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15,
|
||||||
|
0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52,
|
||||||
|
0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2a, 0x40, 0x0a, 0x0e,
|
||||||
|
0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b,
|
||||||
|
0x0a, 0x07, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x54,
|
||||||
|
0x45, 0x58, 0x54, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x45, 0x59, 0x57, 0x4f, 0x52, 0x44,
|
||||||
|
0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x48, 0x52, 0x41, 0x53, 0x45, 0x10, 0x03, 0x32, 0xfe,
|
||||||
|
0x01, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78,
|
||||||
|
0x12, 0x4b, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x1f, 0x2e, 0x72, 0x65, 0x73,
|
||||||
|
0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65,
|
||||||
|
0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x65,
|
||||||
|
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53,
|
||||||
|
0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a,
|
||||||
|
0x08, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x72, 0x65, 0x73, 0x6f,
|
||||||
|
0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61,
|
||||||
|
0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x72, 0x65, 0x73, 0x6f,
|
||||||
|
0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61,
|
||||||
|
0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0e, 0x52, 0x65,
|
||||||
|
0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x72,
|
||||||
|
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49,
|
||||||
|
0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e,
|
||||||
|
0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64,
|
||||||
|
0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42,
|
||||||
|
0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72,
|
||||||
|
0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x6b,
|
||||||
|
0x67, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x75, 0x6e, 0x69, 0x66, 0x69, 0x65,
|
||||||
|
0x64, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72,
|
||||||
|
0x6f, 0x74, 0x6f, 0x33,
|
||||||
})
|
})
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -947,53 +1095,58 @@ func file_search_proto_rawDescGZIP() []byte {
|
|||||||
return file_search_proto_rawDescData
|
return file_search_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_search_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
|
var file_search_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||||
|
var file_search_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
|
||||||
var file_search_proto_goTypes = []any{
|
var file_search_proto_goTypes = []any{
|
||||||
(*ResourceStatsRequest)(nil), // 0: resource.ResourceStatsRequest
|
(QueryFieldType)(0), // 0: resource.QueryFieldType
|
||||||
(*ResourceStatsResponse)(nil), // 1: resource.ResourceStatsResponse
|
(*ResourceStatsRequest)(nil), // 1: resource.ResourceStatsRequest
|
||||||
(*ResourceSearchRequest)(nil), // 2: resource.ResourceSearchRequest
|
(*ResourceStatsResponse)(nil), // 2: resource.ResourceStatsResponse
|
||||||
(*ResourceSearchResponse)(nil), // 3: resource.ResourceSearchResponse
|
(*ResourceSearchRequest)(nil), // 3: resource.ResourceSearchRequest
|
||||||
(*RebuildIndexesRequest)(nil), // 4: resource.RebuildIndexesRequest
|
(*ResourceSearchResponse)(nil), // 4: resource.ResourceSearchResponse
|
||||||
(*RebuildIndexesResponse)(nil), // 5: resource.RebuildIndexesResponse
|
(*RebuildIndexesRequest)(nil), // 5: resource.RebuildIndexesRequest
|
||||||
(*ResourceStatsResponse_Stats)(nil), // 6: resource.ResourceStatsResponse.Stats
|
(*RebuildIndexesResponse)(nil), // 6: resource.RebuildIndexesResponse
|
||||||
(*ResourceSearchRequest_Sort)(nil), // 7: resource.ResourceSearchRequest.Sort
|
(*ResourceStatsResponse_Stats)(nil), // 7: resource.ResourceStatsResponse.Stats
|
||||||
(*ResourceSearchRequest_Facet)(nil), // 8: resource.ResourceSearchRequest.Facet
|
(*ResourceSearchRequest_Sort)(nil), // 8: resource.ResourceSearchRequest.Sort
|
||||||
nil, // 9: resource.ResourceSearchRequest.FacetEntry
|
(*ResourceSearchRequest_Facet)(nil), // 9: resource.ResourceSearchRequest.Facet
|
||||||
(*ResourceSearchResponse_Facet)(nil), // 10: resource.ResourceSearchResponse.Facet
|
(*ResourceSearchRequest_QueryField)(nil), // 10: resource.ResourceSearchRequest.QueryField
|
||||||
(*ResourceSearchResponse_TermFacet)(nil), // 11: resource.ResourceSearchResponse.TermFacet
|
nil, // 11: resource.ResourceSearchRequest.FacetEntry
|
||||||
nil, // 12: resource.ResourceSearchResponse.FacetEntry
|
(*ResourceSearchResponse_Facet)(nil), // 12: resource.ResourceSearchResponse.Facet
|
||||||
(*ErrorResult)(nil), // 13: resource.ErrorResult
|
(*ResourceSearchResponse_TermFacet)(nil), // 13: resource.ResourceSearchResponse.TermFacet
|
||||||
(*ListOptions)(nil), // 14: resource.ListOptions
|
nil, // 14: resource.ResourceSearchResponse.FacetEntry
|
||||||
(*ResourceKey)(nil), // 15: resource.ResourceKey
|
(*ErrorResult)(nil), // 15: resource.ErrorResult
|
||||||
(*ResourceTable)(nil), // 16: resource.ResourceTable
|
(*ListOptions)(nil), // 16: resource.ListOptions
|
||||||
|
(*ResourceKey)(nil), // 17: resource.ResourceKey
|
||||||
|
(*ResourceTable)(nil), // 18: resource.ResourceTable
|
||||||
}
|
}
|
||||||
var file_search_proto_depIdxs = []int32{
|
var file_search_proto_depIdxs = []int32{
|
||||||
13, // 0: resource.ResourceStatsResponse.error:type_name -> resource.ErrorResult
|
15, // 0: resource.ResourceStatsResponse.error:type_name -> resource.ErrorResult
|
||||||
6, // 1: resource.ResourceStatsResponse.stats:type_name -> resource.ResourceStatsResponse.Stats
|
7, // 1: resource.ResourceStatsResponse.stats:type_name -> resource.ResourceStatsResponse.Stats
|
||||||
14, // 2: resource.ResourceSearchRequest.options:type_name -> resource.ListOptions
|
16, // 2: resource.ResourceSearchRequest.options:type_name -> resource.ListOptions
|
||||||
15, // 3: resource.ResourceSearchRequest.federated:type_name -> resource.ResourceKey
|
17, // 3: resource.ResourceSearchRequest.federated:type_name -> resource.ResourceKey
|
||||||
7, // 4: resource.ResourceSearchRequest.sortBy:type_name -> resource.ResourceSearchRequest.Sort
|
8, // 4: resource.ResourceSearchRequest.sortBy:type_name -> resource.ResourceSearchRequest.Sort
|
||||||
9, // 5: resource.ResourceSearchRequest.facet:type_name -> resource.ResourceSearchRequest.FacetEntry
|
11, // 5: resource.ResourceSearchRequest.facet:type_name -> resource.ResourceSearchRequest.FacetEntry
|
||||||
13, // 6: resource.ResourceSearchResponse.error:type_name -> resource.ErrorResult
|
10, // 6: resource.ResourceSearchRequest.query_fields:type_name -> resource.ResourceSearchRequest.QueryField
|
||||||
15, // 7: resource.ResourceSearchResponse.key:type_name -> resource.ResourceKey
|
15, // 7: resource.ResourceSearchResponse.error:type_name -> resource.ErrorResult
|
||||||
16, // 8: resource.ResourceSearchResponse.results:type_name -> resource.ResourceTable
|
17, // 8: resource.ResourceSearchResponse.key:type_name -> resource.ResourceKey
|
||||||
12, // 9: resource.ResourceSearchResponse.facet:type_name -> resource.ResourceSearchResponse.FacetEntry
|
18, // 9: resource.ResourceSearchResponse.results:type_name -> resource.ResourceTable
|
||||||
15, // 10: resource.RebuildIndexesRequest.keys:type_name -> resource.ResourceKey
|
14, // 10: resource.ResourceSearchResponse.facet:type_name -> resource.ResourceSearchResponse.FacetEntry
|
||||||
13, // 11: resource.RebuildIndexesResponse.error:type_name -> resource.ErrorResult
|
17, // 11: resource.RebuildIndexesRequest.keys:type_name -> resource.ResourceKey
|
||||||
8, // 12: resource.ResourceSearchRequest.FacetEntry.value:type_name -> resource.ResourceSearchRequest.Facet
|
15, // 12: resource.RebuildIndexesResponse.error:type_name -> resource.ErrorResult
|
||||||
11, // 13: resource.ResourceSearchResponse.Facet.terms:type_name -> resource.ResourceSearchResponse.TermFacet
|
0, // 13: resource.ResourceSearchRequest.QueryField.type:type_name -> resource.QueryFieldType
|
||||||
10, // 14: resource.ResourceSearchResponse.FacetEntry.value:type_name -> resource.ResourceSearchResponse.Facet
|
9, // 14: resource.ResourceSearchRequest.FacetEntry.value:type_name -> resource.ResourceSearchRequest.Facet
|
||||||
2, // 15: resource.ResourceIndex.Search:input_type -> resource.ResourceSearchRequest
|
13, // 15: resource.ResourceSearchResponse.Facet.terms:type_name -> resource.ResourceSearchResponse.TermFacet
|
||||||
0, // 16: resource.ResourceIndex.GetStats:input_type -> resource.ResourceStatsRequest
|
12, // 16: resource.ResourceSearchResponse.FacetEntry.value:type_name -> resource.ResourceSearchResponse.Facet
|
||||||
4, // 17: resource.ResourceIndex.RebuildIndexes:input_type -> resource.RebuildIndexesRequest
|
3, // 17: resource.ResourceIndex.Search:input_type -> resource.ResourceSearchRequest
|
||||||
3, // 18: resource.ResourceIndex.Search:output_type -> resource.ResourceSearchResponse
|
1, // 18: resource.ResourceIndex.GetStats:input_type -> resource.ResourceStatsRequest
|
||||||
1, // 19: resource.ResourceIndex.GetStats:output_type -> resource.ResourceStatsResponse
|
5, // 19: resource.ResourceIndex.RebuildIndexes:input_type -> resource.RebuildIndexesRequest
|
||||||
5, // 20: resource.ResourceIndex.RebuildIndexes:output_type -> resource.RebuildIndexesResponse
|
4, // 20: resource.ResourceIndex.Search:output_type -> resource.ResourceSearchResponse
|
||||||
18, // [18:21] is the sub-list for method output_type
|
2, // 21: resource.ResourceIndex.GetStats:output_type -> resource.ResourceStatsResponse
|
||||||
15, // [15:18] is the sub-list for method input_type
|
6, // 22: resource.ResourceIndex.RebuildIndexes:output_type -> resource.RebuildIndexesResponse
|
||||||
15, // [15:15] is the sub-list for extension type_name
|
20, // [20:23] is the sub-list for method output_type
|
||||||
15, // [15:15] is the sub-list for extension extendee
|
17, // [17:20] is the sub-list for method input_type
|
||||||
0, // [0:15] is the sub-list for field type_name
|
17, // [17:17] is the sub-list for extension type_name
|
||||||
|
17, // [17:17] is the sub-list for extension extendee
|
||||||
|
0, // [0:17] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_search_proto_init() }
|
func init() { file_search_proto_init() }
|
||||||
@@ -1007,13 +1160,14 @@ func file_search_proto_init() {
|
|||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_search_proto_rawDesc), len(file_search_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_search_proto_rawDesc), len(file_search_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 1,
|
||||||
NumMessages: 13,
|
NumMessages: 14,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
GoTypes: file_search_proto_goTypes,
|
GoTypes: file_search_proto_goTypes,
|
||||||
DependencyIndexes: file_search_proto_depIdxs,
|
DependencyIndexes: file_search_proto_depIdxs,
|
||||||
|
EnumInfos: file_search_proto_enumTypes,
|
||||||
MessageInfos: file_search_proto_msgTypes,
|
MessageInfos: file_search_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_search_proto = out.File
|
File_search_proto = out.File
|
||||||
|
|||||||
@@ -31,9 +31,11 @@ const (
|
|||||||
// Unlike the ResourceStore, this service can be exposed to clients directly
|
// Unlike the ResourceStore, this service can be exposed to clients directly
|
||||||
// It should be implemented with efficient indexes and does not need read-after-write semantics
|
// It should be implemented with efficient indexes and does not need read-after-write semantics
|
||||||
type ResourceIndexClient interface {
|
type ResourceIndexClient interface {
|
||||||
|
// Query for documents
|
||||||
Search(ctx context.Context, in *ResourceSearchRequest, opts ...grpc.CallOption) (*ResourceSearchResponse, error)
|
Search(ctx context.Context, in *ResourceSearchRequest, opts ...grpc.CallOption) (*ResourceSearchResponse, error)
|
||||||
// Get the resource stats
|
// Get the resource stats
|
||||||
GetStats(ctx context.Context, in *ResourceStatsRequest, opts ...grpc.CallOption) (*ResourceStatsResponse, error)
|
GetStats(ctx context.Context, in *ResourceStatsRequest, opts ...grpc.CallOption) (*ResourceStatsResponse, error)
|
||||||
|
// Rebuild the search index
|
||||||
RebuildIndexes(ctx context.Context, in *RebuildIndexesRequest, opts ...grpc.CallOption) (*RebuildIndexesResponse, error)
|
RebuildIndexes(ctx context.Context, in *RebuildIndexesRequest, opts ...grpc.CallOption) (*RebuildIndexesResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,9 +84,11 @@ func (c *resourceIndexClient) RebuildIndexes(ctx context.Context, in *RebuildInd
|
|||||||
// Unlike the ResourceStore, this service can be exposed to clients directly
|
// Unlike the ResourceStore, this service can be exposed to clients directly
|
||||||
// It should be implemented with efficient indexes and does not need read-after-write semantics
|
// It should be implemented with efficient indexes and does not need read-after-write semantics
|
||||||
type ResourceIndexServer interface {
|
type ResourceIndexServer interface {
|
||||||
|
// Query for documents
|
||||||
Search(context.Context, *ResourceSearchRequest) (*ResourceSearchResponse, error)
|
Search(context.Context, *ResourceSearchRequest) (*ResourceSearchResponse, error)
|
||||||
// Get the resource stats
|
// Get the resource stats
|
||||||
GetStats(context.Context, *ResourceStatsRequest) (*ResourceStatsResponse, error)
|
GetStats(context.Context, *ResourceStatsRequest) (*ResourceStatsResponse, error)
|
||||||
|
// Rebuild the search index
|
||||||
RebuildIndexes(context.Context, *RebuildIndexesRequest) (*RebuildIndexesResponse, error)
|
RebuildIndexes(context.Context, *RebuildIndexesRequest) (*RebuildIndexesResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,6 +81,11 @@ type BleveOptions struct {
|
|||||||
// Indexes that are not owned by current instance are eligible for cleanup.
|
// Indexes that are not owned by current instance are eligible for cleanup.
|
||||||
// If nil, all indexes are owned by the current instance.
|
// If nil, all indexes are owned by the current instance.
|
||||||
OwnsIndex func(key resource.NamespacedResource) (bool, error)
|
OwnsIndex func(key resource.NamespacedResource) (bool, error)
|
||||||
|
|
||||||
|
// ScoringModel defines the scoring model used for the bleve indexes
|
||||||
|
// Default: index.TFIDFScoring
|
||||||
|
// Supported values: index.TFIDFScoring and index.BM25Scoring
|
||||||
|
ScoringModel string
|
||||||
}
|
}
|
||||||
|
|
||||||
type bleveBackend struct {
|
type bleveBackend struct {
|
||||||
@@ -368,7 +373,7 @@ func (b *bleveBackend) BuildIndex(
|
|||||||
attribute.String("reason", indexBuildReason),
|
attribute.String("reason", indexBuildReason),
|
||||||
)
|
)
|
||||||
|
|
||||||
mapper, err := GetBleveMappings(fields)
|
mapper, err := GetBleveMappings(b.opts.ScoringModel, fields)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -1177,6 +1182,7 @@ func (b *bleveIndex) getIndex(
|
|||||||
return b.index, nil
|
return b.index, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nolint:gocyclo
|
||||||
func (b *bleveIndex) toBleveSearchRequest(ctx context.Context, req *resourcepb.ResourceSearchRequest, access authlib.AccessClient) (*bleve.SearchRequest, *resourcepb.ErrorResult) {
|
func (b *bleveIndex) toBleveSearchRequest(ctx context.Context, req *resourcepb.ResourceSearchRequest, access authlib.AccessClient) (*bleve.SearchRequest, *resourcepb.ErrorResult) {
|
||||||
ctx, span := tracer.Start(ctx, "search.bleveIndex.toBleveSearchRequest")
|
ctx, span := tracer.Start(ctx, "search.bleveIndex.toBleveSearchRequest")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
@@ -1235,42 +1241,62 @@ func (b *bleveIndex) toBleveSearchRequest(ctx context.Context, req *resourcepb.R
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(req.Query) > 1 && strings.Contains(req.Query, "*") {
|
if len(req.Query) > 1 {
|
||||||
// wildcard query is expensive - should be used with caution
|
if strings.Contains(req.Query, "*") {
|
||||||
wildcard := bleve.NewWildcardQuery(req.Query)
|
// wildcard query is expensive - should be used with caution
|
||||||
queries = append(queries, wildcard)
|
wildcard := bleve.NewWildcardQuery(req.Query)
|
||||||
}
|
queries = append(queries, wildcard)
|
||||||
|
} else {
|
||||||
|
// When using a
|
||||||
|
searchrequest.Fields = append(searchrequest.Fields, resource.SEARCH_FIELD_SCORE)
|
||||||
|
disjoin := bleve.NewDisjunctionQuery()
|
||||||
|
queries = append(queries, disjoin)
|
||||||
|
|
||||||
if req.Query != "" && !strings.Contains(req.Query, "*") {
|
queryFields := req.QueryFields
|
||||||
// Add a text query
|
if len(queryFields) == 0 {
|
||||||
searchrequest.Fields = append(searchrequest.Fields, resource.SEARCH_FIELD_SCORE)
|
queryFields = []*resourcepb.ResourceSearchRequest_QueryField{
|
||||||
|
{
|
||||||
|
Name: resource.SEARCH_FIELD_TITLE,
|
||||||
|
Type: resourcepb.QueryFieldType_KEYWORD,
|
||||||
|
Boost: 10, // exact match -- includes ngrams! If they lived on their own field, we could score them differently
|
||||||
|
}, {
|
||||||
|
Name: resource.SEARCH_FIELD_TITLE,
|
||||||
|
Type: resourcepb.QueryFieldType_TEXT,
|
||||||
|
Boost: 2, // standard analyzer (with ngrams!)
|
||||||
|
}, {
|
||||||
|
Name: resource.SEARCH_FIELD_TITLE_PHRASE,
|
||||||
|
Type: resourcepb.QueryFieldType_TEXT,
|
||||||
|
Boost: 5, // standard analyzer
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// There are multiple ways to match the query string to documents. The following queries are ordered by priority:
|
for _, field := range queryFields {
|
||||||
|
switch field.Type {
|
||||||
|
case resourcepb.QueryFieldType_TEXT, resourcepb.QueryFieldType_DEFAULT:
|
||||||
|
q := bleve.NewMatchQuery(removeSmallTerms(req.Query)) // removeSmallTerms should be part of the analyzer
|
||||||
|
q.SetBoost(float64(field.Boost))
|
||||||
|
q.SetField(field.Name)
|
||||||
|
q.Analyzer = standard.Name // analyze the text
|
||||||
|
q.Operator = query.MatchQueryOperatorAnd // all terms must match
|
||||||
|
disjoin.AddQuery(q)
|
||||||
|
|
||||||
// Query 1: Match the exact query string
|
case resourcepb.QueryFieldType_KEYWORD:
|
||||||
queryExact := bleve.NewMatchQuery(req.Query)
|
q := bleve.NewMatchQuery(req.Query)
|
||||||
queryExact.SetBoost(10.0)
|
q.SetBoost(float64(field.Boost))
|
||||||
queryExact.SetField(resource.SEARCH_FIELD_TITLE)
|
q.SetField(field.Name)
|
||||||
queryExact.Analyzer = keyword.Name // don't analyze the query input - treat it as a single token
|
q.Analyzer = keyword.Name // don't analyze the query input - treat it as a single token
|
||||||
queryExact.Operator = query.MatchQueryOperatorAnd // This doesn't make a difference for keyword analyzer, we add it just to be explicit.
|
disjoin.AddQuery(q)
|
||||||
searchQuery := bleve.NewDisjunctionQuery(queryExact)
|
|
||||||
|
|
||||||
// Query 2: Phrase query with standard analyzer
|
case resourcepb.QueryFieldType_PHRASE:
|
||||||
queryPhrase := bleve.NewMatchPhraseQuery(req.Query)
|
q := bleve.NewMatchPhraseQuery(req.Query)
|
||||||
queryPhrase.SetBoost(5.0)
|
q.SetBoost(float64(field.Boost))
|
||||||
queryPhrase.SetField(resource.SEARCH_FIELD_TITLE)
|
q.SetField(field.Name)
|
||||||
queryPhrase.Analyzer = standard.Name
|
q.Analyzer = standard.Name
|
||||||
searchQuery.AddQuery(queryPhrase)
|
disjoin.AddQuery(q)
|
||||||
|
}
|
||||||
// Query 3: Match query with standard analyzer
|
}
|
||||||
queryAnalyzed := bleve.NewMatchQuery(removeSmallTerms(req.Query))
|
}
|
||||||
queryAnalyzed.SetField(resource.SEARCH_FIELD_TITLE)
|
|
||||||
queryAnalyzed.SetBoost(2.0)
|
|
||||||
queryAnalyzed.Analyzer = standard.Name
|
|
||||||
queryAnalyzed.Operator = query.MatchQueryOperatorAnd // Make sure all terms from the query are matched
|
|
||||||
searchQuery.AddQuery(queryAnalyzed)
|
|
||||||
|
|
||||||
queries = append(queries, searchQuery)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch len(queries) {
|
switch len(queries) {
|
||||||
@@ -1872,7 +1898,7 @@ func (q *permissionScopedQuery) Searcher(ctx context.Context, i index.IndexReade
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
filteringSearcher := bleveSearch.NewFilteringSearcher(ctx, searcher, func(d *search.DocumentMatch) bool {
|
filteringSearcher := bleveSearch.NewFilteringSearcher(ctx, searcher, func(_ *search.SearchContext, d *search.DocumentMatch) bool {
|
||||||
// The doc ID has the format: <namespace>/<group>/<resourceType>/<name>
|
// The doc ID has the format: <namespace>/<group>/<resourceType>/<name>
|
||||||
// IndexInternalID will be the same as the doc ID when using an in-memory index, but when using a file-based
|
// IndexInternalID will be the same as the doc ID when using an in-memory index, but when using a file-based
|
||||||
// index it becomes a binary encoded number that has some other internal meaning. Using ExternalID() will get the
|
// index it becomes a binary encoded number that has some other internal meaning. Using ExternalID() will get the
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
index "github.com/blevesearch/bleve_index_api"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
||||||
@@ -19,6 +20,7 @@ func TestBleveSearchBackend(t *testing.T) {
|
|||||||
backend, err := NewBleveBackend(BleveOptions{
|
backend, err := NewBleveBackend(BleveOptions{
|
||||||
Root: tempDir,
|
Root: tempDir,
|
||||||
FileThreshold: 5,
|
FileThreshold: 5,
|
||||||
|
ScoringModel: index.BM25Scoring,
|
||||||
}, nil)
|
}, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, backend)
|
require.NotNil(t, backend)
|
||||||
@@ -52,3 +54,32 @@ func TestSearchBackendBenchmark(t *testing.T) {
|
|||||||
|
|
||||||
unitest.BenchmarkSearchBackend(t, backend, opts)
|
unitest.BenchmarkSearchBackend(t, backend, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkScoringModels(b *testing.B) {
|
||||||
|
models := []string{index.TFIDFScoring, index.BM25Scoring}
|
||||||
|
|
||||||
|
for _, model := range models {
|
||||||
|
b.Run(model, func(b *testing.B) {
|
||||||
|
tempDir := b.TempDir()
|
||||||
|
|
||||||
|
backend, err := NewBleveBackend(BleveOptions{
|
||||||
|
Root: tempDir,
|
||||||
|
ScoringModel: model,
|
||||||
|
}, nil)
|
||||||
|
require.NoError(b, err)
|
||||||
|
require.NotNil(b, backend)
|
||||||
|
|
||||||
|
b.Cleanup(backend.Stop)
|
||||||
|
|
||||||
|
opts := &unitest.BenchmarkOptions{
|
||||||
|
NumResources: 1000,
|
||||||
|
Concurrency: 4,
|
||||||
|
NumNamespaces: 10,
|
||||||
|
NumGroups: 10,
|
||||||
|
NumResourceTypes: 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
unitest.BenchmarkSearchBackend(b, backend, opts)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,13 +5,15 @@ import (
|
|||||||
"github.com/blevesearch/bleve/v2/analysis/analyzer/keyword"
|
"github.com/blevesearch/bleve/v2/analysis/analyzer/keyword"
|
||||||
"github.com/blevesearch/bleve/v2/analysis/analyzer/standard"
|
"github.com/blevesearch/bleve/v2/analysis/analyzer/standard"
|
||||||
"github.com/blevesearch/bleve/v2/mapping"
|
"github.com/blevesearch/bleve/v2/mapping"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
||||||
"github.com/grafana/grafana/pkg/storage/unified/resourcepb"
|
"github.com/grafana/grafana/pkg/storage/unified/resourcepb"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetBleveMappings(fields resource.SearchableDocumentFields) (mapping.IndexMapping, error) {
|
func GetBleveMappings(scoringModel string, fields resource.SearchableDocumentFields) (mapping.IndexMapping, error) {
|
||||||
mapper := bleve.NewIndexMapping()
|
mapper := bleve.NewIndexMapping()
|
||||||
|
if scoringModel != "" {
|
||||||
|
mapper.ScoringModel = scoringModel
|
||||||
|
}
|
||||||
|
|
||||||
err := RegisterCustomAnalyzers(mapper)
|
err := RegisterCustomAnalyzers(mapper)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestDocumentMapping(t *testing.T) {
|
func TestDocumentMapping(t *testing.T) {
|
||||||
mappings, err := search.GetBleveMappings(nil)
|
mappings, err := search.GetBleveMappings("", nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
data := resource.IndexableDocument{
|
data := resource.IndexableDocument{
|
||||||
Title: "title",
|
Title: "title",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/blevesearch/bleve/v2"
|
"github.com/blevesearch/bleve/v2"
|
||||||
|
index "github.com/blevesearch/bleve_index_api"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||||
@@ -258,6 +259,7 @@ func newTestDashboardsIndex(t testing.TB, threshold int64, size int64, writer re
|
|||||||
backend, err := search.NewBleveBackend(search.BleveOptions{
|
backend, err := search.NewBleveBackend(search.BleveOptions{
|
||||||
Root: t.TempDir(),
|
Root: t.TempDir(),
|
||||||
FileThreshold: threshold, // use in-memory for tests
|
FileThreshold: threshold, // use in-memory for tests
|
||||||
|
ScoringModel: index.BM25Scoring,
|
||||||
}, nil)
|
}, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/blevesearch/bleve/v2"
|
"github.com/blevesearch/bleve/v2"
|
||||||
|
index "github.com/blevesearch/bleve_index_api"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/testutil"
|
"github.com/prometheus/client_golang/prometheus/testutil"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -50,6 +51,7 @@ func TestBleveBackend(t *testing.T) {
|
|||||||
backend, err := NewBleveBackend(BleveOptions{
|
backend, err := NewBleveBackend(BleveOptions{
|
||||||
Root: tmpdir,
|
Root: tmpdir,
|
||||||
FileThreshold: 5, // with more than 5 items we create a file on disk
|
FileThreshold: 5, // with more than 5 items we create a file on disk
|
||||||
|
ScoringModel: index.BM25Scoring,
|
||||||
}, nil)
|
}, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
t.Cleanup(backend.Stop)
|
t.Cleanup(backend.Stop)
|
||||||
@@ -773,6 +775,7 @@ func setupBleveBackend(t *testing.T, options ...setupOption) (*bleveBackend, pro
|
|||||||
IndexCacheTTL: defaultIndexCacheTTL,
|
IndexCacheTTL: defaultIndexCacheTTL,
|
||||||
Logger: log.NewNopLogger(),
|
Logger: log.NewNopLogger(),
|
||||||
BuildVersion: buildVersion,
|
BuildVersion: buildVersion,
|
||||||
|
ScoringModel: index.BM25Scoring,
|
||||||
}
|
}
|
||||||
for _, opt := range options {
|
for _, opt := range options {
|
||||||
opt(&opts)
|
opt(&opts)
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ func NewSearchOptions(
|
|||||||
BuildVersion: cfg.BuildVersion,
|
BuildVersion: cfg.BuildVersion,
|
||||||
OwnsIndex: ownsIndexFn,
|
OwnsIndex: ownsIndexFn,
|
||||||
IndexMinUpdateInterval: cfg.IndexMinUpdateInterval,
|
IndexMinUpdateInterval: cfg.IndexMinUpdateInterval,
|
||||||
|
ScoringModel: cfg.IndexScoringModel,
|
||||||
}, indexMetrics)
|
}, indexMetrics)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
index "github.com/blevesearch/bleve_index_api"
|
||||||
"github.com/go-jose/go-jose/v4/jwt"
|
"github.com/go-jose/go-jose/v4/jwt"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -129,21 +130,28 @@ func TestIntegrationSearchAndStorage(t *testing.T) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// Create a new bleve backend
|
scoringModels := []string{index.TFIDFScoring, index.BM25Scoring}
|
||||||
search, err := search.NewBleveBackend(search.BleveOptions{
|
|
||||||
FileThreshold: 0,
|
|
||||||
Root: t.TempDir(),
|
|
||||||
}, nil)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, search)
|
|
||||||
t.Cleanup(search.Stop)
|
|
||||||
|
|
||||||
// Create a new resource backend
|
for _, model := range scoringModels {
|
||||||
storage, _ := newTestBackend(t, false, 0)
|
t.Run(model, func(t *testing.T) {
|
||||||
require.NotNil(t, storage)
|
// Create a new bleve backend
|
||||||
|
search, err := search.NewBleveBackend(search.BleveOptions{
|
||||||
|
FileThreshold: 0,
|
||||||
|
Root: t.TempDir(),
|
||||||
|
ScoringModel: model,
|
||||||
|
}, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, search)
|
||||||
|
t.Cleanup(search.Stop)
|
||||||
|
|
||||||
// Run the shared storage and search tests
|
// Create a new resource backend
|
||||||
unitest.RunTestSearchAndStorage(t, ctx, storage, search)
|
storage, _ := newTestBackend(t, false, 0)
|
||||||
|
require.NotNil(t, storage)
|
||||||
|
|
||||||
|
// Run the shared storage and search tests
|
||||||
|
unitest.RunTestSearchAndStorage(t, ctx, storage, search)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClientServer(t *testing.T) {
|
func TestClientServer(t *testing.T) {
|
||||||
|
|||||||
@@ -24,6 +24,24 @@ func TestMain(m *testing.M) {
|
|||||||
testsuite.Run(m)
|
testsuite.Run(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mockElasticsearchHandler returns a handler that mocks Elasticsearch endpoints.
|
||||||
|
// It responds to GET / with cluster info (required for datasource initialization)
|
||||||
|
// and returns 401 Unauthorized for all other requests.
|
||||||
|
func mockElasticsearchHandler(onRequest func(r *http.Request)) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch {
|
||||||
|
case r.Method == http.MethodGet && r.URL.Path == "/":
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
_, _ = w.Write([]byte(`{"version":{"build_flavor":"default","number":"8.0.0"}}`))
|
||||||
|
default:
|
||||||
|
if onRequest != nil {
|
||||||
|
onRequest(r)
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestIntegrationElasticsearch(t *testing.T) {
|
func TestIntegrationElasticsearch(t *testing.T) {
|
||||||
testutil.SkipIntegrationTestInShortMode(t)
|
testutil.SkipIntegrationTestInShortMode(t)
|
||||||
|
|
||||||
@@ -35,9 +53,8 @@ func TestIntegrationElasticsearch(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
var outgoingRequest *http.Request
|
var outgoingRequest *http.Request
|
||||||
outgoingServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
outgoingServer := httptest.NewServer(mockElasticsearchHandler(func(r *http.Request) {
|
||||||
outgoingRequest = r
|
outgoingRequest = r
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
|
||||||
}))
|
}))
|
||||||
t.Cleanup(outgoingServer.Close)
|
t.Cleanup(outgoingServer.Close)
|
||||||
|
|
||||||
|
|||||||
@@ -209,7 +209,7 @@
|
|||||||
"path": "public/plugins/grafana-azure-monitor-datasource/img/azure_monitor_cpu.png"
|
"path": "public/plugins/grafana-azure-monitor-datasource/img/azure_monitor_cpu.png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": "12.3.0-pre",
|
"version": "12.4.0-pre",
|
||||||
"updated": "",
|
"updated": "",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"azure",
|
"azure",
|
||||||
@@ -589,7 +589,7 @@
|
|||||||
"hasUpdate": false,
|
"hasUpdate": false,
|
||||||
"defaultNavUrl": "/plugins/datagrid/",
|
"defaultNavUrl": "/plugins/datagrid/",
|
||||||
"category": "",
|
"category": "",
|
||||||
"state": "beta",
|
"state": "deprecated",
|
||||||
"signature": "internal",
|
"signature": "internal",
|
||||||
"signatureType": "",
|
"signatureType": "",
|
||||||
"signatureOrg": "",
|
"signatureOrg": "",
|
||||||
@@ -639,7 +639,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"grafanaDependency": "",
|
"grafanaDependency": "\u003e=11.6.0",
|
||||||
"grafanaVersion": "*",
|
"grafanaVersion": "*",
|
||||||
"plugins": [],
|
"plugins": [],
|
||||||
"extensions": {
|
"extensions": {
|
||||||
@@ -880,7 +880,7 @@
|
|||||||
},
|
},
|
||||||
"build": {},
|
"build": {},
|
||||||
"screenshots": null,
|
"screenshots": null,
|
||||||
"version": "12.3.0-pre",
|
"version": "12.4.0-pre",
|
||||||
"updated": "",
|
"updated": "",
|
||||||
"keywords": null
|
"keywords": null
|
||||||
},
|
},
|
||||||
@@ -934,7 +934,7 @@
|
|||||||
},
|
},
|
||||||
"build": {},
|
"build": {},
|
||||||
"screenshots": null,
|
"screenshots": null,
|
||||||
"version": "12.3.0-pre",
|
"version": "12.4.0-pre",
|
||||||
"updated": "",
|
"updated": "",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"grafana",
|
"grafana",
|
||||||
@@ -1000,7 +1000,7 @@
|
|||||||
},
|
},
|
||||||
"build": {},
|
"build": {},
|
||||||
"screenshots": null,
|
"screenshots": null,
|
||||||
"version": "12.3.0-pre",
|
"version": "12.4.0-pre",
|
||||||
"updated": "",
|
"updated": "",
|
||||||
"keywords": null
|
"keywords": null
|
||||||
},
|
},
|
||||||
@@ -1217,7 +1217,7 @@
|
|||||||
},
|
},
|
||||||
"build": {},
|
"build": {},
|
||||||
"screenshots": null,
|
"screenshots": null,
|
||||||
"version": "12.3.0-pre",
|
"version": "12.4.0-pre",
|
||||||
"updated": "",
|
"updated": "",
|
||||||
"keywords": null
|
"keywords": null
|
||||||
},
|
},
|
||||||
@@ -1325,7 +1325,7 @@
|
|||||||
},
|
},
|
||||||
"build": {},
|
"build": {},
|
||||||
"screenshots": null,
|
"screenshots": null,
|
||||||
"version": "12.3.0-pre",
|
"version": "12.4.0-pre",
|
||||||
"updated": "",
|
"updated": "",
|
||||||
"keywords": null
|
"keywords": null
|
||||||
},
|
},
|
||||||
@@ -1375,7 +1375,7 @@
|
|||||||
},
|
},
|
||||||
"build": {},
|
"build": {},
|
||||||
"screenshots": null,
|
"screenshots": null,
|
||||||
"version": "12.3.0-pre",
|
"version": "12.4.0-pre",
|
||||||
"updated": "",
|
"updated": "",
|
||||||
"keywords": null
|
"keywords": null
|
||||||
},
|
},
|
||||||
@@ -1425,7 +1425,7 @@
|
|||||||
},
|
},
|
||||||
"build": {},
|
"build": {},
|
||||||
"screenshots": null,
|
"screenshots": null,
|
||||||
"version": "12.3.0-pre",
|
"version": "12.4.0-pre",
|
||||||
"updated": "",
|
"updated": "",
|
||||||
"keywords": null
|
"keywords": null
|
||||||
},
|
},
|
||||||
@@ -1575,7 +1575,7 @@
|
|||||||
},
|
},
|
||||||
"build": {},
|
"build": {},
|
||||||
"screenshots": null,
|
"screenshots": null,
|
||||||
"version": "",
|
"version": "12.4.0-pre",
|
||||||
"updated": "",
|
"updated": "",
|
||||||
"keywords": null
|
"keywords": null
|
||||||
},
|
},
|
||||||
@@ -1629,7 +1629,7 @@
|
|||||||
},
|
},
|
||||||
"build": {},
|
"build": {},
|
||||||
"screenshots": null,
|
"screenshots": null,
|
||||||
"version": "12.3.0-pre",
|
"version": "12.4.0-pre",
|
||||||
"updated": "",
|
"updated": "",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"grafana",
|
"grafana",
|
||||||
@@ -1734,7 +1734,7 @@
|
|||||||
},
|
},
|
||||||
"build": {},
|
"build": {},
|
||||||
"screenshots": null,
|
"screenshots": null,
|
||||||
"version": "12.3.0-pre",
|
"version": "12.4.0-pre",
|
||||||
"updated": "",
|
"updated": "",
|
||||||
"keywords": null
|
"keywords": null
|
||||||
},
|
},
|
||||||
@@ -2042,7 +2042,7 @@
|
|||||||
},
|
},
|
||||||
"build": {},
|
"build": {},
|
||||||
"screenshots": null,
|
"screenshots": null,
|
||||||
"version": "12.3.0-pre",
|
"version": "12.4.0-pre",
|
||||||
"updated": "",
|
"updated": "",
|
||||||
"keywords": null
|
"keywords": null
|
||||||
},
|
},
|
||||||
@@ -2092,7 +2092,7 @@
|
|||||||
},
|
},
|
||||||
"build": {},
|
"build": {},
|
||||||
"screenshots": null,
|
"screenshots": null,
|
||||||
"version": "12.3.0-pre",
|
"version": "12.4.0-pre",
|
||||||
"updated": "",
|
"updated": "",
|
||||||
"keywords": null
|
"keywords": null
|
||||||
},
|
},
|
||||||
@@ -2445,7 +2445,7 @@
|
|||||||
},
|
},
|
||||||
"build": {},
|
"build": {},
|
||||||
"screenshots": null,
|
"screenshots": null,
|
||||||
"version": "12.3.0-pre",
|
"version": "12.4.0-pre",
|
||||||
"updated": "",
|
"updated": "",
|
||||||
"keywords": null
|
"keywords": null
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ func TestIntegrationSearchDevDashboards(t *testing.T) {
|
|||||||
require.Equal(t, 16, fileCount, "file count from %s", devenv)
|
require.Equal(t, 16, fileCount, "file count from %s", devenv)
|
||||||
|
|
||||||
// Helper to call search
|
// Helper to call search
|
||||||
callSearch := func(user apis.User, params string) dashboardV0.SearchResults {
|
callSearch := func(user apis.User, params map[string]string) dashboardV0.SearchResults {
|
||||||
require.NotNil(t, user)
|
require.NotNil(t, user)
|
||||||
ns := user.Identity.GetNamespace()
|
ns := user.Identity.GetNamespace()
|
||||||
cfg := dynamic.ConfigFor(user.NewRestConfig())
|
cfg := dynamic.ConfigFor(user.NewRestConfig())
|
||||||
@@ -107,17 +107,12 @@ func TestIntegrationSearchDevDashboards(t *testing.T) {
|
|||||||
|
|
||||||
var statusCode int
|
var statusCode int
|
||||||
req := restClient.Get().AbsPath("apis", "dashboard.grafana.app", "v0alpha1", "namespaces", ns, "search").
|
req := restClient.Get().AbsPath("apis", "dashboard.grafana.app", "v0alpha1", "namespaces", ns, "search").
|
||||||
|
//Param("explain", "true") // helpful to understand which field made things match
|
||||||
Param("limit", "1000").
|
Param("limit", "1000").
|
||||||
Param("type", "dashboard") // Only search dashboards
|
Param("type", "dashboard") // Only search dashboards
|
||||||
|
|
||||||
for kv := range strings.SplitSeq(params, "&") {
|
for k, v := range params {
|
||||||
if kv == "" {
|
req = req.Param(k, v)
|
||||||
continue
|
|
||||||
}
|
|
||||||
parts := strings.SplitN(kv, "=", 2)
|
|
||||||
if len(parts) == 2 {
|
|
||||||
req = req.Param(parts[0], parts[1])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
res := req.Do(ctx).StatusCode(&statusCode)
|
res := req.Do(ctx).StatusCode(&statusCode)
|
||||||
require.NoError(t, res.Error())
|
require.NoError(t, res.Error())
|
||||||
@@ -140,22 +135,47 @@ func TestIntegrationSearchDevDashboards(t *testing.T) {
|
|||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
user apis.User
|
user apis.User
|
||||||
params string
|
params map[string]string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "all",
|
name: "all",
|
||||||
user: helper.Org1.Admin,
|
user: helper.Org1.Admin,
|
||||||
params: "", // only dashboards
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "simple-query",
|
name: "query-single-word",
|
||||||
user: helper.Org1.Admin,
|
user: helper.Org1.Admin,
|
||||||
params: "query=stacking",
|
params: map[string]string{
|
||||||
|
"query": "stacking",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with-text-panel",
|
name: "query-multiple-words",
|
||||||
user: helper.Org1.Admin,
|
user: helper.Org1.Admin,
|
||||||
params: "field=panel_types&panelType=text",
|
params: map[string]string{
|
||||||
|
"query": "graph softMin", // must match ALL terms
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with-text-panel",
|
||||||
|
user: helper.Org1.Admin,
|
||||||
|
params: map[string]string{
|
||||||
|
"field": "panel_types", // return panel types
|
||||||
|
"panelType": "text",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "title-ngram-prefix",
|
||||||
|
user: helper.Org1.Admin,
|
||||||
|
params: map[string]string{
|
||||||
|
"query": "zer", // should match "Zero Decimals Y Ticks"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "title-ngram-middle-word",
|
||||||
|
user: helper.Org1.Admin,
|
||||||
|
params: map[string]string{
|
||||||
|
"query": "decim", // should match "Zero Decimals Y Ticks"
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for i, tc := range testCases {
|
for i, tc := range testCases {
|
||||||
|
|||||||
+3
-3
@@ -10,7 +10,7 @@
|
|||||||
"panel-tests",
|
"panel-tests",
|
||||||
"graph-ng"
|
"graph-ng"
|
||||||
],
|
],
|
||||||
"score": 0.658
|
"score": 0.284
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"resource": "dashboards",
|
"resource": "dashboards",
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
"panel-tests",
|
"panel-tests",
|
||||||
"graph-ng"
|
"graph-ng"
|
||||||
],
|
],
|
||||||
"score": 0.625
|
"score": 0.269
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"maxScore": 0.658
|
"maxScore": 0.284
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"totalHits": 1,
|
||||||
|
"hits": [
|
||||||
|
{
|
||||||
|
"resource": "dashboards",
|
||||||
|
"name": "timeseries-soft-limits",
|
||||||
|
"title": "Panel Tests - Graph NG - softMin/softMax",
|
||||||
|
"tags": [
|
||||||
|
"gdev",
|
||||||
|
"panel-tests",
|
||||||
|
"graph-ng"
|
||||||
|
],
|
||||||
|
"score": 0.024
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxScore": 0.024
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"totalHits": 1,
|
||||||
|
"hits": [
|
||||||
|
{
|
||||||
|
"resource": "dashboards",
|
||||||
|
"name": "timeseries-y-ticks-zero-decimals",
|
||||||
|
"title": "Zero Decimals Y Ticks",
|
||||||
|
"tags": [
|
||||||
|
"gdev",
|
||||||
|
"panel-tests",
|
||||||
|
"graph-ng"
|
||||||
|
],
|
||||||
|
"score": 0.35
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxScore": 0.35
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"totalHits": 1,
|
||||||
|
"hits": [
|
||||||
|
{
|
||||||
|
"resource": "dashboards",
|
||||||
|
"name": "timeseries-y-ticks-zero-decimals",
|
||||||
|
"title": "Zero Decimals Y Ticks",
|
||||||
|
"tags": [
|
||||||
|
"gdev",
|
||||||
|
"panel-tests",
|
||||||
|
"graph-ng"
|
||||||
|
],
|
||||||
|
"score": 0.35
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxScore": 0.35
|
||||||
|
}
|
||||||
@@ -3912,6 +3912,13 @@
|
|||||||
"value"
|
"value"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"properties": {
|
||||||
|
"description": "Additional properties for multi-props variables",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
"selected": {
|
"selected": {
|
||||||
"description": "Whether the option is selected or not",
|
"description": "Whether the option is selected or not",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
|||||||
@@ -3939,6 +3939,13 @@
|
|||||||
"value"
|
"value"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"properties": {
|
||||||
|
"description": "Additional properties for multi-props variables",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
"selected": {
|
"selected": {
|
||||||
"description": "Whether the option is selected or not",
|
"description": "Whether the option is selected or not",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ func (s *Service) CheckHealth(ctx context.Context, req *backend.CheckHealthReque
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
url := fmt.Sprintf("%v/v3/projects/%v/metricDescriptors", dsInfo.services[cloudMonitor].url, defaultProject)
|
url := fmt.Sprintf("%s/v3/projects/%s/metricDescriptors", dsInfo.services[cloudMonitor].url, defaultProject)
|
||||||
request, err := http.NewRequest(http.MethodGet, url, nil)
|
request, err := http.NewRequest(http.MethodGet, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -139,6 +139,7 @@ type datasourceInfo struct {
|
|||||||
defaultProject string
|
defaultProject string
|
||||||
clientEmail string
|
clientEmail string
|
||||||
tokenUri string
|
tokenUri string
|
||||||
|
universeDomain string
|
||||||
services map[string]datasourceService
|
services map[string]datasourceService
|
||||||
privateKey string
|
privateKey string
|
||||||
usingImpersonation bool
|
usingImpersonation bool
|
||||||
@@ -150,6 +151,7 @@ type datasourceJSONData struct {
|
|||||||
DefaultProject string `json:"defaultProject"`
|
DefaultProject string `json:"defaultProject"`
|
||||||
ClientEmail string `json:"clientEmail"`
|
ClientEmail string `json:"clientEmail"`
|
||||||
TokenURI string `json:"tokenUri"`
|
TokenURI string `json:"tokenUri"`
|
||||||
|
UniverseDomain string `json:"universeDomain"`
|
||||||
UsingImpersonation bool `json:"usingImpersonation"`
|
UsingImpersonation bool `json:"usingImpersonation"`
|
||||||
ServiceAccountToImpersonate string `json:"serviceAccountToImpersonate"`
|
ServiceAccountToImpersonate string `json:"serviceAccountToImpersonate"`
|
||||||
}
|
}
|
||||||
@@ -179,6 +181,7 @@ func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.Inst
|
|||||||
defaultProject: jsonData.DefaultProject,
|
defaultProject: jsonData.DefaultProject,
|
||||||
clientEmail: jsonData.ClientEmail,
|
clientEmail: jsonData.ClientEmail,
|
||||||
tokenUri: jsonData.TokenURI,
|
tokenUri: jsonData.TokenURI,
|
||||||
|
universeDomain: jsonData.UniverseDomain,
|
||||||
usingImpersonation: jsonData.UsingImpersonation,
|
usingImpersonation: jsonData.UsingImpersonation,
|
||||||
serviceAccountToImpersonate: jsonData.ServiceAccountToImpersonate,
|
serviceAccountToImpersonate: jsonData.ServiceAccountToImpersonate,
|
||||||
services: map[string]datasourceService{},
|
services: map[string]datasourceService{},
|
||||||
@@ -194,13 +197,13 @@ func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.Inst
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, info := range routes {
|
for name := range routes {
|
||||||
client, err := newHTTPClient(dsInfo, opts, &httpClientProvider, name)
|
client, err := newHTTPClient(dsInfo, opts, &httpClientProvider, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dsInfo.services[name] = datasourceService{
|
dsInfo.services[name] = datasourceService{
|
||||||
url: info.url,
|
url: buildURL(name, dsInfo.universeDomain),
|
||||||
client: client,
|
client: client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ type routeInfo struct {
|
|||||||
var routes = map[string]routeInfo{
|
var routes = map[string]routeInfo{
|
||||||
cloudMonitor: {
|
cloudMonitor: {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: "https://monitoring.googleapis.com",
|
url: "https://monitoring.",
|
||||||
scopes: []string{cloudMonitorScope},
|
scopes: []string{cloudMonitorScope},
|
||||||
},
|
},
|
||||||
resourceManager: {
|
resourceManager: {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: "https://cloudresourcemanager.googleapis.com",
|
url: "https://cloudresourcemanager.",
|
||||||
scopes: []string{resourceManagerScope},
|
scopes: []string{resourceManagerScope},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -68,6 +68,13 @@ func getMiddleware(model *datasourceInfo, routePath string) (httpclient.Middlewa
|
|||||||
return tokenprovider.AuthMiddleware(provider), nil
|
return tokenprovider.AuthMiddleware(provider), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildURL(route string, universeDomain string) string {
|
||||||
|
if universeDomain == "" {
|
||||||
|
universeDomain = "googleapis.com"
|
||||||
|
}
|
||||||
|
return routes[route].url + universeDomain
|
||||||
|
}
|
||||||
|
|
||||||
func newHTTPClient(model *datasourceInfo, opts httpclient.Options, clientProvider *httpclient.Provider, route string) (*http.Client, error) {
|
func newHTTPClient(model *datasourceInfo, opts httpclient.Options, clientProvider *httpclient.Provider, route string) (*http.Client, error) {
|
||||||
m, err := getMiddleware(model, route)
|
m, err := getMiddleware(model, route)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ func Test_setRequestVariables(t *testing.T) {
|
|||||||
im: &fakeInstance{
|
im: &fakeInstance{
|
||||||
services: map[string]datasourceService{
|
services: map[string]datasourceService{
|
||||||
cloudMonitor: {
|
cloudMonitor: {
|
||||||
url: routes[cloudMonitor].url,
|
url: buildURL(cloudMonitor, "googleapis.com"),
|
||||||
client: &http.Client{},
|
client: &http.Client{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package elasticsearch
|
|||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
|
||||||
es "github.com/grafana/grafana/pkg/tsdb/elasticsearch/client"
|
es "github.com/grafana/grafana/pkg/tsdb/elasticsearch/client"
|
||||||
|
"github.com/grafana/grafana/pkg/tsdb/elasticsearch/simplejson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// addDateHistogramAgg adds a date histogram aggregation to the aggregation builder
|
// addDateHistogramAgg adds a date histogram aggregation to the aggregation builder
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend/tracing"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/tracing"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Used in logging to mark a stage
|
// Used in logging to mark a stage
|
||||||
@@ -35,6 +34,7 @@ type DatasourceInfo struct {
|
|||||||
Interval string
|
Interval string
|
||||||
MaxConcurrentShardRequests int64
|
MaxConcurrentShardRequests int64
|
||||||
IncludeFrozen bool
|
IncludeFrozen bool
|
||||||
|
ClusterInfo ClusterInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConfiguredFields struct {
|
type ConfiguredFields struct {
|
||||||
@@ -159,7 +159,7 @@ func (c *baseClientImpl) ExecuteMultisearch(r *MultiSearchRequest) (*MultiSearch
|
|||||||
resSpan.End()
|
resSpan.End()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
improvedParsingEnabled := isFeatureEnabled(c.ctx, featuremgmt.FlagElasticsearchImprovedParsing)
|
improvedParsingEnabled := isFeatureEnabled(c.ctx, "elasticsearchImprovedParsing")
|
||||||
msr, err := c.parser.parseMultiSearchResponse(res.Body, improvedParsingEnabled)
|
msr, err := c.parser.parseMultiSearchResponse(res.Body, improvedParsingEnabled)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -197,7 +197,11 @@ func (c *baseClientImpl) createMultiSearchRequests(searchRequests []*SearchReque
|
|||||||
|
|
||||||
func (c *baseClientImpl) getMultiSearchQueryParameters() string {
|
func (c *baseClientImpl) getMultiSearchQueryParameters() string {
|
||||||
var qs []string
|
var qs []string
|
||||||
qs = append(qs, fmt.Sprintf("max_concurrent_shard_requests=%d", c.ds.MaxConcurrentShardRequests))
|
// if the build flavor is not serverless, we can use the max concurrent shard requests
|
||||||
|
// this is because serverless clusters do not support max concurrent shard requests
|
||||||
|
if !c.ds.ClusterInfo.IsServerless() && c.ds.MaxConcurrentShardRequests > 0 {
|
||||||
|
qs = append(qs, fmt.Sprintf("max_concurrent_shard_requests=%d", c.ds.MaxConcurrentShardRequests))
|
||||||
|
}
|
||||||
|
|
||||||
if c.ds.IncludeFrozen {
|
if c.ds.IncludeFrozen {
|
||||||
qs = append(qs, "ignore_throttled=false")
|
qs = append(qs, "ignore_throttled=false")
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/tsdb/elasticsearch/simplejson"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestClient_ExecuteMultisearch(t *testing.T) {
|
func TestClient_ExecuteMultisearch(t *testing.T) {
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package es
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VersionInfo struct {
|
||||||
|
BuildFlavor string `json:"build_flavor"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClusterInfo represents Elasticsearch cluster information returned from the root endpoint.
|
||||||
|
// It is used to determine cluster capabilities and configuration like whether the cluster is serverless.
|
||||||
|
type ClusterInfo struct {
|
||||||
|
Version VersionInfo `json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
BuildFlavorServerless = "serverless"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetClusterInfo fetches cluster information from the Elasticsearch root endpoint.
|
||||||
|
// It returns the cluster build flavor which is used to determine if the cluster is serverless.
|
||||||
|
func GetClusterInfo(httpCli *http.Client, url string) (clusterInfo ClusterInfo, err error) {
|
||||||
|
resp, err := httpCli.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return ClusterInfo{}, fmt.Errorf("error getting ES cluster info: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return ClusterInfo{}, fmt.Errorf("unexpected status code %d getting ES cluster info", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if closeErr := resp.Body.Close(); closeErr != nil && err == nil {
|
||||||
|
err = fmt.Errorf("error closing response body: %w", closeErr)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&clusterInfo)
|
||||||
|
if err != nil {
|
||||||
|
return ClusterInfo{}, fmt.Errorf("error decoding ES cluster info: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return clusterInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ci ClusterInfo) IsServerless() bool {
|
||||||
|
return ci.Version.BuildFlavor == BuildFlavorServerless
|
||||||
|
}
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
package es
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetClusterInfo(t *testing.T) {
|
||||||
|
t.Run("Should successfully get cluster info", func(t *testing.T) {
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
rw.Header().Set("Content-Type", "application/json")
|
||||||
|
_, err := rw.Write([]byte(`{
|
||||||
|
"name": "test-cluster",
|
||||||
|
"cluster_name": "elasticsearch",
|
||||||
|
"cluster_uuid": "abc123",
|
||||||
|
"version": {
|
||||||
|
"number": "8.0.0",
|
||||||
|
"build_flavor": "default",
|
||||||
|
"build_type": "tar",
|
||||||
|
"build_hash": "abc123",
|
||||||
|
"build_date": "2023-01-01T00:00:00.000Z",
|
||||||
|
"build_snapshot": false,
|
||||||
|
"lucene_version": "9.0.0"
|
||||||
|
}
|
||||||
|
}`))
|
||||||
|
require.NoError(t, err)
|
||||||
|
}))
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
ts.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
clusterInfo, err := GetClusterInfo(ts.Client(), ts.URL)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, clusterInfo)
|
||||||
|
assert.Equal(t, "default", clusterInfo.Version.BuildFlavor)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should successfully get serverless cluster info", func(t *testing.T) {
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
rw.Header().Set("Content-Type", "application/json")
|
||||||
|
_, err := rw.Write([]byte(`{
|
||||||
|
"name": "serverless-cluster",
|
||||||
|
"cluster_name": "elasticsearch",
|
||||||
|
"cluster_uuid": "def456",
|
||||||
|
"version": {
|
||||||
|
"number": "8.11.0",
|
||||||
|
"build_flavor": "serverless",
|
||||||
|
"build_type": "docker",
|
||||||
|
"build_hash": "def456",
|
||||||
|
"build_date": "2023-11-01T00:00:00.000Z",
|
||||||
|
"build_snapshot": false,
|
||||||
|
"lucene_version": "9.8.0"
|
||||||
|
}
|
||||||
|
}`))
|
||||||
|
require.NoError(t, err)
|
||||||
|
}))
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
ts.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
clusterInfo, err := GetClusterInfo(ts.Client(), ts.URL)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, clusterInfo)
|
||||||
|
assert.Equal(t, "serverless", clusterInfo.Version.BuildFlavor)
|
||||||
|
assert.True(t, clusterInfo.IsServerless())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should return error when HTTP request fails", func(t *testing.T) {
|
||||||
|
clusterInfo, err := GetClusterInfo(http.DefaultClient, "http://invalid-url-that-does-not-exist.local:9999")
|
||||||
|
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, ClusterInfo{}, clusterInfo)
|
||||||
|
assert.Contains(t, err.Error(), "error getting ES cluster info")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should return error when response body is invalid JSON", func(t *testing.T) {
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
rw.Header().Set("Content-Type", "application/json")
|
||||||
|
_, err := rw.Write([]byte(`{"invalid json`))
|
||||||
|
require.NoError(t, err)
|
||||||
|
}))
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
ts.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
clusterInfo, err := GetClusterInfo(ts.Client(), ts.URL)
|
||||||
|
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, ClusterInfo{}, clusterInfo)
|
||||||
|
assert.Contains(t, err.Error(), "error decoding ES cluster info")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should handle empty version object", func(t *testing.T) {
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
rw.Header().Set("Content-Type", "application/json")
|
||||||
|
_, err := rw.Write([]byte(`{
|
||||||
|
"name": "test-cluster",
|
||||||
|
"version": {}
|
||||||
|
}`))
|
||||||
|
require.NoError(t, err)
|
||||||
|
}))
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
ts.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
clusterInfo, err := GetClusterInfo(ts.Client(), ts.URL)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, ClusterInfo{}, clusterInfo)
|
||||||
|
assert.Equal(t, "", clusterInfo.Version.BuildFlavor)
|
||||||
|
assert.False(t, clusterInfo.IsServerless())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should handle HTTP error status codes", func(t *testing.T) {
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
rw.WriteHeader(http.StatusUnauthorized)
|
||||||
|
_, err := rw.Write([]byte(`{"error": "Unauthorized"}`))
|
||||||
|
require.NoError(t, err)
|
||||||
|
}))
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
ts.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
clusterInfo, err := GetClusterInfo(ts.Client(), ts.URL)
|
||||||
|
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, ClusterInfo{}, clusterInfo)
|
||||||
|
assert.Contains(t, err.Error(), "unexpected status code 401 getting ES cluster info")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClusterInfo_IsServerless(t *testing.T) {
|
||||||
|
t.Run("Should return true when build_flavor is serverless", func(t *testing.T) {
|
||||||
|
clusterInfo := ClusterInfo{
|
||||||
|
Version: VersionInfo{
|
||||||
|
BuildFlavor: BuildFlavorServerless,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, clusterInfo.IsServerless())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should return false when build_flavor is default", func(t *testing.T) {
|
||||||
|
clusterInfo := ClusterInfo{
|
||||||
|
Version: VersionInfo{
|
||||||
|
BuildFlavor: "default",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.False(t, clusterInfo.IsServerless())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should return false when build_flavor is empty", func(t *testing.T) {
|
||||||
|
clusterInfo := ClusterInfo{
|
||||||
|
Version: VersionInfo{
|
||||||
|
BuildFlavor: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.False(t, clusterInfo.IsServerless())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should return false when build_flavor is unknown value", func(t *testing.T) {
|
||||||
|
clusterInfo := ClusterInfo{
|
||||||
|
Version: VersionInfo{
|
||||||
|
BuildFlavor: "unknown",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.False(t, clusterInfo.IsServerless())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return false when cluster info is empty", func(t *testing.T) {
|
||||||
|
clusterInfo := ClusterInfo{}
|
||||||
|
assert.False(t, clusterInfo.IsServerless())
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/tsdb/elasticsearch/simplejson"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSearchRequest(t *testing.T) {
|
func TestSearchRequest(t *testing.T) {
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
|
||||||
es "github.com/grafana/grafana/pkg/tsdb/elasticsearch/client"
|
es "github.com/grafana/grafana/pkg/tsdb/elasticsearch/client"
|
||||||
|
"github.com/grafana/grafana/pkg/tsdb/elasticsearch/simplejson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// processQuery processes a single query and adds it to the multi-search request builder
|
// processQuery processes a single query and adds it to the multi-search request builder
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package elasticsearch
|
|||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/tsdb/elasticsearch/simplejson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// setFloatPath converts a string value at the specified path to float64
|
// setFloatPath converts a string value at the specified path to float64
|
||||||
|
|||||||
@@ -88,6 +88,14 @@ func newInstanceSettings(httpClientProvider *httpclient.Provider) datasource.Ins
|
|||||||
httpCliOpts.SigV4.Service = "es"
|
httpCliOpts.SigV4.Service = "es"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apiKeyAuth, ok := jsonData["apiKeyAuth"].(bool)
|
||||||
|
if ok && apiKeyAuth {
|
||||||
|
apiKey := settings.DecryptedSecureJSONData["apiKey"]
|
||||||
|
if apiKey != "" {
|
||||||
|
httpCliOpts.Header.Add("Authorization", "ApiKey "+apiKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
httpCli, err := httpClientProvider.New(httpCliOpts)
|
httpCli, err := httpClientProvider.New(httpCliOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -151,6 +159,11 @@ func newInstanceSettings(httpClientProvider *httpclient.Provider) datasource.Ins
|
|||||||
includeFrozen = false
|
includeFrozen = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clusterInfo, err := es.GetClusterInfo(httpCli, settings.URL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
configuredFields := es.ConfiguredFields{
|
configuredFields := es.ConfiguredFields{
|
||||||
TimeField: timeField,
|
TimeField: timeField,
|
||||||
LogLevelField: logLevelField,
|
LogLevelField: logLevelField,
|
||||||
@@ -166,6 +179,7 @@ func newInstanceSettings(httpClientProvider *httpclient.Provider) datasource.Ins
|
|||||||
ConfiguredFields: configuredFields,
|
ConfiguredFields: configuredFields,
|
||||||
Interval: interval,
|
Interval: interval,
|
||||||
IncludeFrozen: includeFrozen,
|
IncludeFrozen: includeFrozen,
|
||||||
|
ClusterInfo: clusterInfo,
|
||||||
}
|
}
|
||||||
return model, nil
|
return model, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user