mirror of
https://github.com/grafana/grafana.git
synced 2025-08-06 05:30:12 +08:00
AzureMonitor: Update Logs workspace() template variable query to return resource URIs (#34445)
* Migrate template variables straight into resource field, Display error if unable to migrate * Update workspace() template variable query function to return a resource URI * update backend to support resource uris in workspace field * don't load resource names for variables * throw error when workspace migration returns no results * update testDatasource to work with either resource URI or workspace GUID * fix tests * cleanup types just a little bit, as a treat
This commit is contained in:
@ -11,6 +11,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"regexp"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/grafana/grafana/pkg/api/pluginproxy"
|
||||
@ -65,6 +66,29 @@ func (e *AzureLogAnalyticsDatasource) executeTimeSeriesQuery(ctx context.Context
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func getApiURL(queryJSONModel logJSONQuery) string {
|
||||
// Legacy queries only specify a Workspace GUID, which we need to use the old workspace-centric
|
||||
// API URL for, and newer queries specifying a resource URI should use resource-centric API.
|
||||
// However, legacy workspace queries using a `workspaces()` template variable will be resolved
|
||||
// to a resource URI, so they should use the new resource-centric.
|
||||
azureLogAnalyticsTarget := queryJSONModel.AzureLogAnalytics
|
||||
var resourceOrWorkspace string
|
||||
|
||||
if azureLogAnalyticsTarget.Resource != "" {
|
||||
resourceOrWorkspace = azureLogAnalyticsTarget.Resource
|
||||
} else {
|
||||
resourceOrWorkspace = azureLogAnalyticsTarget.Workspace
|
||||
}
|
||||
|
||||
matchesResourceURI, _ := regexp.MatchString("^/subscriptions/", resourceOrWorkspace)
|
||||
|
||||
if matchesResourceURI {
|
||||
return fmt.Sprintf("v1%s/query", resourceOrWorkspace)
|
||||
} else {
|
||||
return fmt.Sprintf("v1/workspaces/%s/query", resourceOrWorkspace)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *AzureLogAnalyticsDatasource) buildQueries(queries []plugins.DataSubQuery,
|
||||
timeRange plugins.DataTimeRange) ([]*AzureLogAnalyticsQuery, error) {
|
||||
azureLogAnalyticsQueries := []*AzureLogAnalyticsQuery{}
|
||||
@ -89,13 +113,7 @@ func (e *AzureLogAnalyticsDatasource) buildQueries(queries []plugins.DataSubQuer
|
||||
resultFormat = timeSeries
|
||||
}
|
||||
|
||||
// Handle legacy queries without a Resource
|
||||
var apiURL string
|
||||
if azureLogAnalyticsTarget.Resource != "" {
|
||||
apiURL = fmt.Sprintf("v1%s/query", azureLogAnalyticsTarget.Resource)
|
||||
} else {
|
||||
apiURL = fmt.Sprintf("v1/workspaces/%s/query", azureLogAnalyticsTarget.Workspace)
|
||||
}
|
||||
apiURL := getApiURL(queryJSONModel)
|
||||
|
||||
params := url.Values{}
|
||||
rawQuery, err := KqlInterpolate(query, timeRange, azureLogAnalyticsTarget.Query, "TimeGenerated")
|
||||
|
@ -19,6 +19,11 @@ func TestBuildingAzureLogAnalyticsQueries(t *testing.T) {
|
||||
datasource := &AzureLogAnalyticsDatasource{}
|
||||
fromStart := time.Date(2018, 3, 15, 13, 0, 0, 0, time.UTC).In(time.Local)
|
||||
|
||||
timeRange := plugins.DataTimeRange{
|
||||
From: fmt.Sprintf("%v", fromStart.Unix()*1000),
|
||||
To: fmt.Sprintf("%v", fromStart.Add(34*time.Minute).Unix()*1000),
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
queryModel []plugins.DataSubQuery
|
||||
@ -27,11 +32,8 @@ func TestBuildingAzureLogAnalyticsQueries(t *testing.T) {
|
||||
Err require.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "Query with macros should be interpolated",
|
||||
timeRange: plugins.DataTimeRange{
|
||||
From: fmt.Sprintf("%v", fromStart.Unix()*1000),
|
||||
To: fmt.Sprintf("%v", fromStart.Add(34*time.Minute).Unix()*1000),
|
||||
},
|
||||
name: "Query with macros should be interpolated",
|
||||
timeRange: timeRange,
|
||||
queryModel: []plugins.DataSubQuery{
|
||||
{
|
||||
DataSource: &models.DataSource{
|
||||
@ -65,12 +67,11 @@ func TestBuildingAzureLogAnalyticsQueries(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Err: require.NoError,
|
||||
}, {
|
||||
name: "Legacy workspace queries should use workspace query endpoint",
|
||||
timeRange: plugins.DataTimeRange{
|
||||
From: fmt.Sprintf("%v", fromStart.Unix()*1000),
|
||||
To: fmt.Sprintf("%v", fromStart.Add(34*time.Minute).Unix()*1000),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "Legacy queries with a workspace GUID should use workspace-centric url",
|
||||
timeRange: timeRange,
|
||||
queryModel: []plugins.DataSubQuery{
|
||||
{
|
||||
DataSource: &models.DataSource{
|
||||
@ -80,7 +81,7 @@ func TestBuildingAzureLogAnalyticsQueries(t *testing.T) {
|
||||
"queryType": "Azure Log Analytics",
|
||||
"azureLogAnalytics": map[string]interface{}{
|
||||
"workspace": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
|
||||
"query": "query=Perf | where $__timeFilter() | where $__contains(Computer, 'comp1','comp2') | summarize avg(CounterValue) by bin(TimeGenerated, $__interval), Computer",
|
||||
"query": "query=Perf",
|
||||
"resultFormat": timeSeries,
|
||||
},
|
||||
}),
|
||||
@ -94,13 +95,89 @@ func TestBuildingAzureLogAnalyticsQueries(t *testing.T) {
|
||||
URL: "v1/workspaces/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/query",
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"azureLogAnalytics": map[string]interface{}{
|
||||
"query": "query=Perf | where $__timeFilter() | where $__contains(Computer, 'comp1','comp2') | summarize avg(CounterValue) by bin(TimeGenerated, $__interval), Computer",
|
||||
"resultFormat": timeSeries,
|
||||
"workspace": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
|
||||
"query": "query=Perf",
|
||||
"resultFormat": timeSeries,
|
||||
},
|
||||
}),
|
||||
Params: url.Values{"query": {"query=Perf | where ['TimeGenerated'] >= datetime('2018-03-15T13:00:00Z') and ['TimeGenerated'] <= datetime('2018-03-15T13:34:00Z') | where ['Computer'] in ('comp1','comp2') | summarize avg(CounterValue) by bin(TimeGenerated, 34000ms), Computer"}},
|
||||
Target: "query=query%3DPerf+%7C+where+%5B%27TimeGenerated%27%5D+%3E%3D+datetime%28%272018-03-15T13%3A00%3A00Z%27%29+and+%5B%27TimeGenerated%27%5D+%3C%3D+datetime%28%272018-03-15T13%3A34%3A00Z%27%29+%7C+where+%5B%27Computer%27%5D+in+%28%27comp1%27%2C%27comp2%27%29+%7C+summarize+avg%28CounterValue%29+by+bin%28TimeGenerated%2C+34000ms%29%2C+Computer",
|
||||
Params: url.Values{"query": {"query=Perf"}},
|
||||
Target: "query=query%3DPerf",
|
||||
},
|
||||
},
|
||||
Err: require.NoError,
|
||||
},
|
||||
|
||||
{
|
||||
name: "Legacy workspace queries with a resource URI (from a template variable) should use resource-centric url",
|
||||
timeRange: timeRange,
|
||||
queryModel: []plugins.DataSubQuery{
|
||||
{
|
||||
DataSource: &models.DataSource{
|
||||
JsonData: simplejson.NewFromAny(map[string]interface{}{}),
|
||||
},
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"queryType": "Azure Log Analytics",
|
||||
"azureLogAnalytics": map[string]interface{}{
|
||||
"workspace": "/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/cloud-datasources/providers/Microsoft.OperationalInsights/workspaces/AppInsightsTestDataWorkspace",
|
||||
"query": "query=Perf",
|
||||
"resultFormat": timeSeries,
|
||||
},
|
||||
}),
|
||||
RefID: "A",
|
||||
},
|
||||
},
|
||||
azureLogAnalyticsQueries: []*AzureLogAnalyticsQuery{
|
||||
{
|
||||
RefID: "A",
|
||||
ResultFormat: timeSeries,
|
||||
URL: "v1/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/cloud-datasources/providers/Microsoft.OperationalInsights/workspaces/AppInsightsTestDataWorkspace/query",
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"azureLogAnalytics": map[string]interface{}{
|
||||
"workspace": "/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/cloud-datasources/providers/Microsoft.OperationalInsights/workspaces/AppInsightsTestDataWorkspace",
|
||||
"query": "query=Perf",
|
||||
"resultFormat": timeSeries,
|
||||
},
|
||||
}),
|
||||
Params: url.Values{"query": {"query=Perf"}},
|
||||
Target: "query=query%3DPerf",
|
||||
},
|
||||
},
|
||||
Err: require.NoError,
|
||||
},
|
||||
|
||||
{
|
||||
name: "Queries with a Resource should use resource-centric url",
|
||||
timeRange: timeRange,
|
||||
queryModel: []plugins.DataSubQuery{
|
||||
{
|
||||
DataSource: &models.DataSource{
|
||||
JsonData: simplejson.NewFromAny(map[string]interface{}{}),
|
||||
},
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"queryType": "Azure Log Analytics",
|
||||
"azureLogAnalytics": map[string]interface{}{
|
||||
"resource": "/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/cloud-datasources/providers/Microsoft.OperationalInsights/workspaces/AppInsightsTestDataWorkspace",
|
||||
"query": "query=Perf",
|
||||
"resultFormat": timeSeries,
|
||||
},
|
||||
}),
|
||||
RefID: "A",
|
||||
},
|
||||
},
|
||||
azureLogAnalyticsQueries: []*AzureLogAnalyticsQuery{
|
||||
{
|
||||
RefID: "A",
|
||||
ResultFormat: timeSeries,
|
||||
URL: "v1/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/cloud-datasources/providers/Microsoft.OperationalInsights/workspaces/AppInsightsTestDataWorkspace/query",
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"azureLogAnalytics": map[string]interface{}{
|
||||
"resource": "/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/cloud-datasources/providers/Microsoft.OperationalInsights/workspaces/AppInsightsTestDataWorkspace",
|
||||
"query": "query=Perf",
|
||||
"resultFormat": timeSeries,
|
||||
},
|
||||
}),
|
||||
Params: url.Values{"query": {"query=Perf"}},
|
||||
Target: "query=query%3DPerf",
|
||||
},
|
||||
},
|
||||
Err: require.NoError,
|
||||
|
Reference in New Issue
Block a user