2023-03-30 00:01:18 +08:00
|
|
|
package loganalytics
|
|
|
|
|
|
|
|
|
|
import (
|
2024-05-11 00:11:54 +08:00
|
|
|
"fmt"
|
|
|
|
|
"regexp"
|
|
|
|
|
"strings"
|
|
|
|
|
|
2023-03-30 00:01:18 +08:00
|
|
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
2024-05-11 00:11:54 +08:00
|
|
|
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/kinds/dataquery"
|
2023-03-30 00:01:18 +08:00
|
|
|
)
|
|
|
|
|
|
2023-04-28 03:24:11 +08:00
|
|
|
func AddCustomDataLink(frame data.Frame, dataLink data.DataLink) data.Frame {
|
2023-03-30 00:01:18 +08:00
|
|
|
for i := range frame.Fields {
|
|
|
|
|
if frame.Fields[i].Config == nil {
|
|
|
|
|
frame.Fields[i].Config = &data.FieldConfig{}
|
|
|
|
|
}
|
2023-04-28 03:24:11 +08:00
|
|
|
|
|
|
|
|
frame.Fields[i].Config.Links = append(frame.Fields[i].Config.Links, dataLink)
|
|
|
|
|
}
|
|
|
|
|
return frame
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func AddConfigLinks(frame data.Frame, dl string, title *string) data.Frame {
|
2024-03-21 02:39:00 +08:00
|
|
|
linkTitle := "View query in Azure Portal"
|
2023-04-28 03:24:11 +08:00
|
|
|
if title != nil {
|
|
|
|
|
linkTitle = *title
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
deepLink := data.DataLink{
|
|
|
|
|
Title: linkTitle,
|
|
|
|
|
TargetBlank: true,
|
|
|
|
|
URL: dl,
|
2023-03-30 00:01:18 +08:00
|
|
|
}
|
2023-04-28 03:24:11 +08:00
|
|
|
|
|
|
|
|
frame = AddCustomDataLink(frame, deepLink)
|
|
|
|
|
|
2023-03-30 00:01:18 +08:00
|
|
|
return frame
|
|
|
|
|
}
|
2024-05-11 00:11:54 +08:00
|
|
|
|
|
|
|
|
func ParseResultFormat(queryResultFormat *dataquery.ResultFormat, queryType dataquery.AzureQueryType) dataquery.ResultFormat {
|
|
|
|
|
var resultFormat dataquery.ResultFormat
|
|
|
|
|
if queryResultFormat != nil {
|
|
|
|
|
resultFormat = *queryResultFormat
|
|
|
|
|
}
|
|
|
|
|
if resultFormat == "" {
|
|
|
|
|
if queryType == dataquery.AzureQueryTypeAzureLogAnalytics {
|
|
|
|
|
// Default to logs format for logs queries
|
|
|
|
|
resultFormat = dataquery.ResultFormatLogs
|
|
|
|
|
}
|
|
|
|
|
if queryType == dataquery.AzureQueryTypeAzureTraces {
|
|
|
|
|
// Default to table format for traces queries as many traces may be returned
|
|
|
|
|
resultFormat = dataquery.ResultFormatTable
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return resultFormat
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getApiURL(resourceOrWorkspace string, isAppInsightsQuery bool) string {
|
|
|
|
|
matchesResourceURI, _ := regexp.MatchString("^/subscriptions/", resourceOrWorkspace)
|
|
|
|
|
|
|
|
|
|
if matchesResourceURI {
|
|
|
|
|
if isAppInsightsQuery {
|
|
|
|
|
componentName := resourceOrWorkspace[strings.LastIndex(resourceOrWorkspace, "/")+1:]
|
|
|
|
|
return fmt.Sprintf("v1/apps/%s/query", componentName)
|
|
|
|
|
}
|
|
|
|
|
return fmt.Sprintf("v1%s/query", resourceOrWorkspace)
|
|
|
|
|
} else {
|
|
|
|
|
return fmt.Sprintf("v1/workspaces/%s/query", resourceOrWorkspace)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
func retrieveResources(query dataquery.AzureLogsQuery) ([]string, string) {
|
|
|
|
|
resources := []string{}
|
|
|
|
|
var resourceOrWorkspace string
|
|
|
|
|
if len(query.Resources) > 0 {
|
|
|
|
|
resources = query.Resources
|
|
|
|
|
resourceOrWorkspace = query.Resources[0]
|
|
|
|
|
} else if query.Resource != nil && *query.Resource != "" {
|
|
|
|
|
resources = []string{*query.Resource}
|
|
|
|
|
resourceOrWorkspace = *query.Resource
|
|
|
|
|
} else if query.Workspace != nil {
|
|
|
|
|
resourceOrWorkspace = *query.Workspace
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return resources, resourceOrWorkspace
|
|
|
|
|
}
|