2022-03-02 08:41:07 -06:00
|
|
|
package loganalytics
|
2020-06-05 11:32:10 -05:00
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2023-04-27 14:24:11 -05:00
|
|
|
"fmt"
|
2020-06-05 11:32:10 -05:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2024-10-24 08:32:09 -05:00
|
|
|
"strconv"
|
2023-04-27 14:24:11 -05:00
|
|
|
"strings"
|
2020-06-05 11:32:10 -05:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
2023-04-27 14:24:11 -05:00
|
|
|
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/kinds/dataquery"
|
|
|
|
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/testdata"
|
2024-10-24 08:32:09 -05:00
|
|
|
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/types"
|
2020-12-15 02:32:06 -06:00
|
|
|
"github.com/stretchr/testify/assert"
|
2020-06-05 11:32:10 -05:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestLogTableToFrame(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
testFile string
|
|
|
|
expectedFrame func() *data.Frame
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "single series",
|
|
|
|
testFile: "loganalytics/1-log-analytics-response-metrics-single-series.json",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "response table",
|
|
|
|
testFile: "loganalytics/6-log-analytics-response-table.json",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "all supported field types",
|
|
|
|
testFile: "loganalytics/7-log-analytics-all-types-table.json",
|
|
|
|
},
|
2020-07-15 08:39:41 -05:00
|
|
|
{
|
|
|
|
name: "nan and infinity in real response",
|
|
|
|
testFile: "loganalytics/8-log-analytics-response-nan-inf.json",
|
|
|
|
},
|
2022-06-24 01:56:58 -05:00
|
|
|
{
|
|
|
|
name: "data and error in real response",
|
|
|
|
testFile: "loganalytics/9-log-analytics-response-error.json",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "data and warning in real response",
|
|
|
|
testFile: "loganalytics/10-log-analytics-response-warning.json",
|
|
|
|
},
|
2022-10-05 08:29:34 -05:00
|
|
|
{
|
|
|
|
name: "empty data response",
|
|
|
|
testFile: "loganalytics/11-log-analytics-response-empty.json",
|
|
|
|
},
|
2020-06-05 11:32:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
2023-04-27 14:24:11 -05:00
|
|
|
res := loadTestFileWithNumber(t, tt.testFile)
|
2024-10-24 08:32:09 -05:00
|
|
|
frame, err := ResponseTableToFrame(&res.Tables[0], "A", "query", dataquery.AzureQueryTypeAzureLogAnalytics, dataquery.ResultFormatTable, false)
|
2022-10-05 08:29:34 -05:00
|
|
|
appendErrorNotice(frame, res.Error)
|
2020-06-05 11:32:10 -05:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-04-27 14:24:11 -05:00
|
|
|
testdata.CheckGoldenFrame(t, "../testdata", tt.testFile, frame)
|
2020-06-05 11:32:10 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-27 14:24:11 -05:00
|
|
|
func TestTraceTableToFrame(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
testFile string
|
|
|
|
expectedFrame func() *data.Frame
|
|
|
|
resultFormat dataquery.ResultFormat
|
2024-06-06 11:53:17 -05:00
|
|
|
queryType dataquery.AzureQueryType
|
2023-04-27 14:24:11 -05:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "multi trace",
|
|
|
|
testFile: "traces/1-traces-multiple-table.json",
|
|
|
|
resultFormat: dataquery.ResultFormatTable,
|
2024-06-06 11:53:17 -05:00
|
|
|
queryType: dataquery.AzureQueryTypeAzureTraces,
|
2023-04-27 14:24:11 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "multi trace as trace format",
|
|
|
|
testFile: "traces/1-traces-multiple-table.json",
|
|
|
|
resultFormat: dataquery.ResultFormatTrace,
|
2024-06-06 11:53:17 -05:00
|
|
|
queryType: dataquery.AzureQueryTypeAzureTraces,
|
2023-04-27 14:24:11 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "single trace",
|
|
|
|
testFile: "traces/2-traces-single-table.json",
|
|
|
|
resultFormat: dataquery.ResultFormatTable,
|
2024-06-06 11:53:17 -05:00
|
|
|
queryType: dataquery.AzureQueryTypeAzureTraces,
|
2023-04-27 14:24:11 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "single trace as trace format",
|
|
|
|
testFile: "traces/2-traces-single-table.json",
|
|
|
|
resultFormat: dataquery.ResultFormatTrace,
|
2024-06-06 11:53:17 -05:00
|
|
|
queryType: dataquery.AzureQueryTypeAzureTraces,
|
2023-04-27 14:24:11 -05:00
|
|
|
},
|
2023-08-11 07:13:19 -05:00
|
|
|
{
|
|
|
|
name: "single trace with empty serviceTags and tags",
|
|
|
|
testFile: "traces/3-traces-empty-dynamics.json",
|
|
|
|
resultFormat: dataquery.ResultFormatTrace,
|
2024-06-06 11:53:17 -05:00
|
|
|
queryType: dataquery.AzureQueryTypeAzureTraces,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "single trace as trace format from exemplars query",
|
|
|
|
testFile: "traces/2-traces-single-table.json",
|
|
|
|
resultFormat: dataquery.ResultFormatTrace,
|
|
|
|
queryType: dataquery.AzureQueryTypeTraceql,
|
2023-08-11 07:13:19 -05:00
|
|
|
},
|
2023-04-27 14:24:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
res := loadTestFileWithNumber(t, tt.testFile)
|
2024-10-24 08:32:09 -05:00
|
|
|
frame, err := ResponseTableToFrame(&res.Tables[0], "A", "query", tt.queryType, tt.resultFormat, false)
|
2023-04-27 14:24:11 -05:00
|
|
|
appendErrorNotice(frame, res.Error)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
testdata.CheckGoldenFrame(t, "../testdata", fmt.Sprintf("%s.%s", tt.testFile, strings.ReplaceAll(tt.name, " ", "-")), frame)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-24 08:32:09 -05:00
|
|
|
func TestLargeLogsResponse(t *testing.T) {
|
|
|
|
t.Run("large logs response with limit enabled", func(t *testing.T) {
|
|
|
|
res := AzureLogAnalyticsResponse{
|
|
|
|
Tables: []types.AzureResponseTable{
|
|
|
|
{Name: "PrimaryResult",
|
|
|
|
Columns: []struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
Type string `json:"type"`
|
|
|
|
}{
|
|
|
|
{Name: "value", Type: "int"},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
rows := [][]any{}
|
|
|
|
for i := 0; i <= 30000; i++ {
|
|
|
|
rows = append(rows, []any{json.Number(strconv.Itoa(i))})
|
|
|
|
}
|
|
|
|
res.Tables[0].Rows = rows
|
|
|
|
resultFormat := dataquery.ResultFormatLogs
|
|
|
|
frame, err := ResponseTableToFrame(&res.Tables[0], "A", "query", dataquery.AzureQueryTypeAzureLogAnalytics, resultFormat, false)
|
|
|
|
appendErrorNotice(frame, res.Error)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, frame.Rows(), 30000)
|
|
|
|
require.Len(t, frame.Meta.Notices, 1)
|
|
|
|
require.Equal(t, frame.Meta.Notices[0], data.Notice{
|
|
|
|
Severity: data.NoticeSeverityWarning,
|
|
|
|
Text: "The number of results in the result set has been limited to 30,000.",
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("large logs response with limit disabled", func(t *testing.T) {
|
|
|
|
res := AzureLogAnalyticsResponse{
|
|
|
|
Tables: []types.AzureResponseTable{
|
|
|
|
{Name: "PrimaryResult",
|
|
|
|
Columns: []struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
Type string `json:"type"`
|
|
|
|
}{
|
|
|
|
{Name: "value", Type: "int"},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
rows := [][]any{}
|
|
|
|
for i := 0; i < 40000; i++ {
|
|
|
|
rows = append(rows, []any{json.Number(strconv.Itoa(i))})
|
|
|
|
}
|
|
|
|
res.Tables[0].Rows = rows
|
|
|
|
resultFormat := dataquery.ResultFormatLogs
|
|
|
|
frame, err := ResponseTableToFrame(&res.Tables[0], "A", "query", dataquery.AzureQueryTypeAzureLogAnalytics, resultFormat, true)
|
|
|
|
appendErrorNotice(frame, res.Error)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, frame.Rows(), 40000)
|
|
|
|
require.Nil(t, frame.Meta.Notices)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-04-27 14:24:11 -05:00
|
|
|
func loadTestFileWithNumber(t *testing.T, name string) AzureLogAnalyticsResponse {
|
2020-12-15 02:32:06 -06:00
|
|
|
t.Helper()
|
2022-03-02 08:41:07 -06:00
|
|
|
path := filepath.Join("../testdata", name)
|
2020-12-15 02:32:06 -06:00
|
|
|
// Ignore gosec warning G304 since it's a test
|
|
|
|
// nolint:gosec
|
2020-06-05 11:32:10 -05:00
|
|
|
f, err := os.Open(path)
|
2020-12-15 02:32:06 -06:00
|
|
|
require.NoError(t, err)
|
|
|
|
defer func() {
|
|
|
|
err := f.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}()
|
|
|
|
|
2020-06-05 11:32:10 -05:00
|
|
|
d := json.NewDecoder(f)
|
|
|
|
d.UseNumber()
|
2020-12-15 02:32:06 -06:00
|
|
|
var data AzureLogAnalyticsResponse
|
2020-06-05 11:32:10 -05:00
|
|
|
err = d.Decode(&data)
|
2020-12-15 02:32:06 -06:00
|
|
|
require.NoError(t, err)
|
|
|
|
return data
|
2020-06-05 11:32:10 -05:00
|
|
|
}
|