AzureMonitor: Support querying any Resource for Logs queries (#33879)

* wip

* wip:

* ui work for resource picker

* disable rows when others are selected

* resource picker open button

* Azure Monitor: Connect to backend with real data (#34024)

* Connect to backend with real data

* Fixes from code review.

* WIP:Begin thinking about how to make queries with scope determined by the resource picker

* More fixes post code review.

* Fixes after rebasing

* Remove outdated todo

* AzureMonitor: Support any resource for Logs queries (#33762)

* Apply button for resource picker

* scroll table body

* secondary cancel button

* loading state for nested rows

* Display resource components in picker button

* fix tests

* fix icons

* move route function

* Migrate from workspace to resource uri for log analytics (#34337)

* reword backwards compat comment

* remove base url suffix

* fix lint error

* move migrations to seperate file

* cleanup

* update regex

* cleanup

* update plugin routes to use new azure auth type

* use AzureDataSourceInstanceSettings alias

Co-authored-by: Sarah Zinger <sarahzinger@users.noreply.github.com>
This commit is contained in:
Josh Hunt
2021-05-19 17:39:08 +01:00
committed by GitHub
co-authored by Sarah Zinger
parent c61dd82163
commit 5dca9fd4d8
26 changed files with 1311 additions and 315 deletions
@@ -89,9 +89,13 @@ func (e *AzureLogAnalyticsDatasource) buildQueries(queries []plugins.DataSubQuer
resultFormat = timeSeries
}
urlComponents := map[string]string{}
urlComponents["workspace"] = azureLogAnalyticsTarget.Workspace
apiURL := fmt.Sprintf("%s/query", urlComponents["workspace"])
// 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)
}
params := url.Values{}
rawQuery, err := KqlInterpolate(query, timeRange, azureLogAnalyticsTarget.Query, "TimeGenerated")
@@ -32,6 +32,45 @@ func TestBuildingAzureLogAnalyticsQueries(t *testing.T) {
From: fmt.Sprintf("%v", fromStart.Unix()*1000),
To: fmt.Sprintf("%v", fromStart.Add(34*time.Minute).Unix()*1000),
},
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 | where $__timeFilter() | where $__contains(Computer, 'comp1','comp2') | summarize avg(CounterValue) by bin(TimeGenerated, $__interval), Computer",
"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{}{
"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",
},
}),
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",
},
},
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),
},
queryModel: []plugins.DataSubQuery{
{
DataSource: &models.DataSource{
@@ -52,7 +91,7 @@ func TestBuildingAzureLogAnalyticsQueries(t *testing.T) {
{
RefID: "A",
ResultFormat: timeSeries,
URL: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/query",
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",
@@ -92,7 +131,7 @@ func TestPluginRoutes(t *testing.T) {
{
Path: "loganalyticsazure",
Method: "GET",
URL: "https://api.loganalytics.io/v1/workspaces",
URL: "https://api.loganalytics.io/",
Headers: []plugins.AppPluginRouteHeader{
{Name: "x-ms-app", Content: "Grafana"},
},
@@ -100,7 +139,7 @@ func TestPluginRoutes(t *testing.T) {
{
Path: "chinaloganalyticsazure",
Method: "GET",
URL: "https://api.loganalytics.azure.cn/v1/workspaces",
URL: "https://api.loganalytics.azure.cn/",
Headers: []plugins.AppPluginRouteHeader{
{Name: "x-ms-app", Content: "Grafana"},
},
@@ -108,7 +147,7 @@ func TestPluginRoutes(t *testing.T) {
{
Path: "govloganalyticsazure",
Method: "GET",
URL: "https://api.loganalytics.us/v1/workspaces",
URL: "https://api.loganalytics.us/",
Headers: []plugins.AppPluginRouteHeader{
{Name: "x-ms-app", Content: "Grafana"},
},
@@ -135,7 +174,7 @@ func TestPluginRoutes(t *testing.T) {
},
},
expectedProxypass: "loganalyticsazure",
expectedRouteURL: "https://api.loganalytics.io/v1/workspaces",
expectedRouteURL: "https://api.loganalytics.io/",
Err: require.NoError,
},
{
@@ -150,7 +189,7 @@ func TestPluginRoutes(t *testing.T) {
},
},
expectedProxypass: "chinaloganalyticsazure",
expectedRouteURL: "https://api.loganalytics.azure.cn/v1/workspaces",
expectedRouteURL: "https://api.loganalytics.azure.cn/",
Err: require.NoError,
},
{
@@ -165,7 +204,7 @@ func TestPluginRoutes(t *testing.T) {
},
},
expectedProxypass: "govloganalyticsazure",
expectedRouteURL: "https://api.loganalytics.us/v1/workspaces",
expectedRouteURL: "https://api.loganalytics.us/",
Err: require.NoError,
},
}
+4 -1
View File
@@ -138,7 +138,10 @@ type logJSONQuery struct {
AzureLogAnalytics struct {
Query string `json:"query"`
ResultFormat string `json:"resultFormat"`
Workspace string `json:"workspace"`
Resource string `json:"resource"`
// Deprecated: Queries should be migrated to use Resource instead
Workspace string `json:"workspace"`
} `json:"azureLogAnalytics"`
}