637 lines
20 KiB
Go
637 lines
20 KiB
Go
package tests
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"runtime/debug"
|
|
"slices"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/jmoiron/sqlx"
|
|
mockhouse "github.com/srikanthccv/ClickHouse-go-mock"
|
|
"github.com/stretchr/testify/require"
|
|
"go.signoz.io/signoz/pkg/query-service/app"
|
|
"go.signoz.io/signoz/pkg/query-service/app/dashboards"
|
|
"go.signoz.io/signoz/pkg/query-service/app/integrations"
|
|
"go.signoz.io/signoz/pkg/query-service/app/logparsingpipeline"
|
|
"go.signoz.io/signoz/pkg/query-service/auth"
|
|
"go.signoz.io/signoz/pkg/query-service/dao"
|
|
"go.signoz.io/signoz/pkg/query-service/featureManager"
|
|
"go.signoz.io/signoz/pkg/query-service/model"
|
|
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
|
|
"go.signoz.io/signoz/pkg/query-service/utils"
|
|
)
|
|
|
|
// Higher level tests for UI facing APIs
|
|
|
|
func TestSignozIntegrationLifeCycle(t *testing.T) {
|
|
require := require.New(t)
|
|
testbed := NewIntegrationsTestBed(t, nil)
|
|
|
|
installedResp := testbed.GetInstalledIntegrationsFromQS()
|
|
require.Equal(
|
|
len(installedResp.Integrations), 0,
|
|
"no integrations should be installed at the beginning",
|
|
)
|
|
|
|
availableResp := testbed.GetAvailableIntegrationsFromQS()
|
|
availableIntegrations := availableResp.Integrations
|
|
require.Greater(
|
|
len(availableIntegrations), 0,
|
|
"some integrations should come bundled with SigNoz",
|
|
)
|
|
|
|
// Should be able to install integration
|
|
require.False(availableIntegrations[0].IsInstalled)
|
|
testbed.RequestQSToInstallIntegration(
|
|
availableIntegrations[0].Id, map[string]interface{}{},
|
|
)
|
|
|
|
ii := testbed.GetIntegrationDetailsFromQS(availableIntegrations[0].Id)
|
|
require.Equal(ii.Id, availableIntegrations[0].Id)
|
|
require.NotNil(ii.Installation)
|
|
|
|
installedResp = testbed.GetInstalledIntegrationsFromQS()
|
|
installedIntegrations := installedResp.Integrations
|
|
require.Equal(len(installedIntegrations), 1)
|
|
require.Equal(installedIntegrations[0].Id, availableIntegrations[0].Id)
|
|
|
|
availableResp = testbed.GetAvailableIntegrationsFromQS()
|
|
availableIntegrations = availableResp.Integrations
|
|
require.Greater(len(availableIntegrations), 0)
|
|
|
|
// Integration connection status should get updated after signal data has been received.
|
|
testbed.mockLogQueryResponse([]model.SignozLog{})
|
|
testbed.mockMetricStatusQueryResponse(nil)
|
|
connectionStatus := testbed.GetIntegrationConnectionStatus(ii.Id)
|
|
require.NotNil(connectionStatus)
|
|
require.Nil(connectionStatus.Logs)
|
|
require.Nil(connectionStatus.Metrics)
|
|
|
|
testLog := makeTestSignozLog("test log body", map[string]interface{}{
|
|
"source": "nginx",
|
|
})
|
|
testbed.mockLogQueryResponse([]model.SignozLog{testLog})
|
|
|
|
testMetricName := ii.ConnectionTests.Metrics[0]
|
|
testMetricLastReceivedTs := time.Now().UnixMilli()
|
|
testbed.mockMetricStatusQueryResponse(&model.MetricStatus{
|
|
MetricName: testMetricName,
|
|
LastReceivedTsMillis: testMetricLastReceivedTs,
|
|
})
|
|
|
|
connectionStatus = testbed.GetIntegrationConnectionStatus(ii.Id)
|
|
require.NotNil(connectionStatus)
|
|
require.NotNil(connectionStatus.Logs)
|
|
require.Equal(connectionStatus.Logs.LastReceivedTsMillis, int64(testLog.Timestamp/1000000))
|
|
require.NotNil(connectionStatus.Metrics)
|
|
require.Equal(connectionStatus.Metrics.LastReceivedTsMillis, testMetricLastReceivedTs)
|
|
|
|
// Should be able to uninstall integration
|
|
require.True(availableIntegrations[0].IsInstalled)
|
|
testbed.RequestQSToUninstallIntegration(
|
|
availableIntegrations[0].Id,
|
|
)
|
|
|
|
ii = testbed.GetIntegrationDetailsFromQS(availableIntegrations[0].Id)
|
|
require.Equal(ii.Id, availableIntegrations[0].Id)
|
|
require.Nil(ii.Installation)
|
|
|
|
installedResp = testbed.GetInstalledIntegrationsFromQS()
|
|
installedIntegrations = installedResp.Integrations
|
|
require.Equal(len(installedIntegrations), 0)
|
|
|
|
availableResp = testbed.GetAvailableIntegrationsFromQS()
|
|
availableIntegrations = availableResp.Integrations
|
|
require.Greater(len(availableIntegrations), 0)
|
|
require.False(availableIntegrations[0].IsInstalled)
|
|
}
|
|
|
|
func TestLogPipelinesForInstalledSignozIntegrations(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
testDB := utils.NewQueryServiceDBForTests(t)
|
|
integrationsTB := NewIntegrationsTestBed(t, testDB)
|
|
pipelinesTB := NewLogPipelinesTestBed(t, testDB)
|
|
|
|
availableIntegrationsResp := integrationsTB.GetAvailableIntegrationsFromQS()
|
|
availableIntegrations := availableIntegrationsResp.Integrations
|
|
require.Greater(
|
|
len(availableIntegrations), 0,
|
|
"some integrations should come bundled with SigNoz",
|
|
)
|
|
|
|
getPipelinesResp := pipelinesTB.GetPipelinesFromQS()
|
|
require.Equal(
|
|
0, len(getPipelinesResp.Pipelines),
|
|
"There should be no pipelines at the start",
|
|
)
|
|
|
|
// Find an available integration that contains a log pipeline
|
|
var testAvailableIntegration *integrations.IntegrationsListItem
|
|
for _, ai := range availableIntegrations {
|
|
details := integrationsTB.GetIntegrationDetailsFromQS(ai.Id)
|
|
require.NotNil(details)
|
|
if len(details.Assets.Logs.Pipelines) > 0 {
|
|
testAvailableIntegration = &ai
|
|
break
|
|
}
|
|
}
|
|
|
|
if testAvailableIntegration == nil {
|
|
// None of the built in integrations include a pipeline right now.
|
|
return
|
|
}
|
|
|
|
// Installing an integration should add its pipelines to pipelines list
|
|
require.NotNil(testAvailableIntegration)
|
|
require.False(testAvailableIntegration.IsInstalled)
|
|
integrationsTB.RequestQSToInstallIntegration(
|
|
testAvailableIntegration.Id, map[string]interface{}{},
|
|
)
|
|
|
|
testIntegration := integrationsTB.GetIntegrationDetailsFromQS(testAvailableIntegration.Id)
|
|
require.NotNil(testIntegration.Installation)
|
|
testIntegrationPipelines := testIntegration.Assets.Logs.Pipelines
|
|
require.Greater(
|
|
len(testIntegrationPipelines), 0,
|
|
"test integration expected to have a pipeline",
|
|
)
|
|
|
|
getPipelinesResp = pipelinesTB.GetPipelinesFromQS()
|
|
require.Equal(
|
|
len(testIntegrationPipelines), len(getPipelinesResp.Pipelines),
|
|
"Pipelines for installed integrations should appear in pipelines list",
|
|
)
|
|
lastPipeline := getPipelinesResp.Pipelines[len(getPipelinesResp.Pipelines)-1]
|
|
require.NotNil(integrations.IntegrationIdForPipeline(lastPipeline))
|
|
require.Equal(testIntegration.Id, *integrations.IntegrationIdForPipeline(lastPipeline))
|
|
|
|
pipelinesTB.assertPipelinesSentToOpampClient(getPipelinesResp.Pipelines)
|
|
pipelinesTB.assertNewAgentGetsPipelinesOnConnection(getPipelinesResp.Pipelines)
|
|
|
|
// After saving a user created pipeline, pipelines response should include
|
|
// both user created pipelines and pipelines for installed integrations.
|
|
postablePipelines := logparsingpipeline.PostablePipelines{
|
|
Pipelines: []logparsingpipeline.PostablePipeline{
|
|
{
|
|
OrderId: 1,
|
|
Name: "pipeline1",
|
|
Alias: "pipeline1",
|
|
Enabled: true,
|
|
Filter: &v3.FilterSet{
|
|
Operator: "AND",
|
|
Items: []v3.FilterItem{
|
|
{
|
|
Key: v3.AttributeKey{
|
|
Key: "method",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeTag,
|
|
},
|
|
Operator: "=",
|
|
Value: "GET",
|
|
},
|
|
},
|
|
},
|
|
Config: []logparsingpipeline.PipelineOperator{
|
|
{
|
|
OrderId: 1,
|
|
ID: "add",
|
|
Type: "add",
|
|
Field: "attributes.test",
|
|
Value: "val",
|
|
Enabled: true,
|
|
Name: "test add",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
pipelinesTB.PostPipelinesToQS(postablePipelines)
|
|
|
|
getPipelinesResp = pipelinesTB.GetPipelinesFromQS()
|
|
require.Equal(1+len(testIntegrationPipelines), len(getPipelinesResp.Pipelines))
|
|
pipelinesTB.assertPipelinesSentToOpampClient(getPipelinesResp.Pipelines)
|
|
pipelinesTB.assertNewAgentGetsPipelinesOnConnection(getPipelinesResp.Pipelines)
|
|
|
|
// Reordering integration pipelines should be possible.
|
|
postable := postableFromPipelines(getPipelinesResp.Pipelines)
|
|
slices.Reverse(postable.Pipelines)
|
|
for i := range postable.Pipelines {
|
|
postable.Pipelines[i].OrderId = i + 1
|
|
}
|
|
|
|
pipelinesTB.PostPipelinesToQS(postable)
|
|
|
|
getPipelinesResp = pipelinesTB.GetPipelinesFromQS()
|
|
firstPipeline := getPipelinesResp.Pipelines[0]
|
|
require.NotNil(integrations.IntegrationIdForPipeline(firstPipeline))
|
|
require.Equal(testIntegration.Id, *integrations.IntegrationIdForPipeline(firstPipeline))
|
|
|
|
pipelinesTB.assertPipelinesSentToOpampClient(getPipelinesResp.Pipelines)
|
|
pipelinesTB.assertNewAgentGetsPipelinesOnConnection(getPipelinesResp.Pipelines)
|
|
|
|
// enabling/disabling integration pipelines should be possible.
|
|
require.True(firstPipeline.Enabled)
|
|
|
|
postable.Pipelines[0].Enabled = false
|
|
pipelinesTB.PostPipelinesToQS(postable)
|
|
|
|
getPipelinesResp = pipelinesTB.GetPipelinesFromQS()
|
|
require.Equal(1+len(testIntegrationPipelines), len(getPipelinesResp.Pipelines))
|
|
|
|
firstPipeline = getPipelinesResp.Pipelines[0]
|
|
require.NotNil(integrations.IntegrationIdForPipeline(firstPipeline))
|
|
require.Equal(testIntegration.Id, *integrations.IntegrationIdForPipeline(firstPipeline))
|
|
|
|
require.False(firstPipeline.Enabled)
|
|
|
|
pipelinesTB.assertPipelinesSentToOpampClient(getPipelinesResp.Pipelines)
|
|
pipelinesTB.assertNewAgentGetsPipelinesOnConnection(getPipelinesResp.Pipelines)
|
|
|
|
// should not be able to edit integrations pipeline.
|
|
require.Greater(len(postable.Pipelines[0].Config), 0)
|
|
postable.Pipelines[0].Config = []logparsingpipeline.PipelineOperator{}
|
|
pipelinesTB.PostPipelinesToQS(postable)
|
|
|
|
getPipelinesResp = pipelinesTB.GetPipelinesFromQS()
|
|
require.Equal(1+len(testIntegrationPipelines), len(getPipelinesResp.Pipelines))
|
|
|
|
firstPipeline = getPipelinesResp.Pipelines[0]
|
|
require.NotNil(integrations.IntegrationIdForPipeline(firstPipeline))
|
|
require.Equal(testIntegration.Id, *integrations.IntegrationIdForPipeline(firstPipeline))
|
|
|
|
require.False(firstPipeline.Enabled)
|
|
require.Greater(len(firstPipeline.Config), 0)
|
|
|
|
// should not be able to delete integrations pipeline
|
|
postable.Pipelines = []logparsingpipeline.PostablePipeline{postable.Pipelines[1]}
|
|
pipelinesTB.PostPipelinesToQS(postable)
|
|
|
|
getPipelinesResp = pipelinesTB.GetPipelinesFromQS()
|
|
require.Equal(1+len(testIntegrationPipelines), len(getPipelinesResp.Pipelines))
|
|
|
|
lastPipeline = getPipelinesResp.Pipelines[1]
|
|
require.NotNil(integrations.IntegrationIdForPipeline(lastPipeline))
|
|
require.Equal(testIntegration.Id, *integrations.IntegrationIdForPipeline(lastPipeline))
|
|
|
|
// Uninstalling an integration should remove its pipelines
|
|
// from pipelines list in the UI
|
|
integrationsTB.RequestQSToUninstallIntegration(
|
|
testIntegration.Id,
|
|
)
|
|
getPipelinesResp = pipelinesTB.GetPipelinesFromQS()
|
|
require.Equal(
|
|
1, len(getPipelinesResp.Pipelines),
|
|
"Pipelines for uninstalled integrations should get removed from pipelines list",
|
|
)
|
|
pipelinesTB.assertPipelinesSentToOpampClient(getPipelinesResp.Pipelines)
|
|
pipelinesTB.assertNewAgentGetsPipelinesOnConnection(getPipelinesResp.Pipelines)
|
|
}
|
|
|
|
func TestDashboardsForInstalledIntegrationDashboards(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
testDB := utils.NewQueryServiceDBForTests(t)
|
|
integrationsTB := NewIntegrationsTestBed(t, testDB)
|
|
|
|
availableIntegrationsResp := integrationsTB.GetAvailableIntegrationsFromQS()
|
|
availableIntegrations := availableIntegrationsResp.Integrations
|
|
require.Greater(
|
|
len(availableIntegrations), 0,
|
|
"some integrations should come bundled with SigNoz",
|
|
)
|
|
|
|
dashboards := integrationsTB.GetDashboardsFromQS()
|
|
require.Equal(
|
|
0, len(dashboards),
|
|
"There should be no dashboards at the start",
|
|
)
|
|
|
|
// Find an available integration that contains dashboards
|
|
var testAvailableIntegration *integrations.IntegrationsListItem
|
|
for _, ai := range availableIntegrations {
|
|
details := integrationsTB.GetIntegrationDetailsFromQS(ai.Id)
|
|
require.NotNil(details)
|
|
if len(details.Assets.Dashboards) > 0 {
|
|
testAvailableIntegration = &ai
|
|
break
|
|
}
|
|
}
|
|
require.NotNil(testAvailableIntegration)
|
|
|
|
// Installing an integration should make its dashboards appear in the dashboard list
|
|
require.False(testAvailableIntegration.IsInstalled)
|
|
tsBeforeInstallation := time.Now().Unix()
|
|
integrationsTB.RequestQSToInstallIntegration(
|
|
testAvailableIntegration.Id, map[string]interface{}{},
|
|
)
|
|
|
|
testIntegration := integrationsTB.GetIntegrationDetailsFromQS(testAvailableIntegration.Id)
|
|
require.NotNil(testIntegration.Installation)
|
|
testIntegrationDashboards := testIntegration.Assets.Dashboards
|
|
require.Greater(
|
|
len(testIntegrationDashboards), 0,
|
|
"test integration is expected to have dashboards",
|
|
)
|
|
|
|
dashboards = integrationsTB.GetDashboardsFromQS()
|
|
require.Equal(
|
|
len(testIntegrationDashboards), len(dashboards),
|
|
"dashboards for installed integrations should appear in dashboards list",
|
|
)
|
|
require.GreaterOrEqual(dashboards[0].CreatedAt.Unix(), tsBeforeInstallation)
|
|
require.GreaterOrEqual(dashboards[0].UpdatedAt.Unix(), tsBeforeInstallation)
|
|
|
|
// Should be able to get installed integrations dashboard by id
|
|
dd := integrationsTB.GetDashboardByIdFromQS(dashboards[0].Uuid)
|
|
require.GreaterOrEqual(dd.CreatedAt.Unix(), tsBeforeInstallation)
|
|
require.GreaterOrEqual(dd.UpdatedAt.Unix(), tsBeforeInstallation)
|
|
require.Equal(*dd, dashboards[0])
|
|
|
|
// Integration dashboards should not longer appear in dashboard list after uninstallation
|
|
integrationsTB.RequestQSToUninstallIntegration(
|
|
testIntegration.Id,
|
|
)
|
|
dashboards = integrationsTB.GetDashboardsFromQS()
|
|
require.Equal(
|
|
0, len(dashboards),
|
|
"dashboards for uninstalled integrations should not appear in dashboards list",
|
|
)
|
|
}
|
|
|
|
type IntegrationsTestBed struct {
|
|
t *testing.T
|
|
testUser *model.User
|
|
qsHttpHandler http.Handler
|
|
mockClickhouse mockhouse.ClickConnMockCommon
|
|
}
|
|
|
|
func (tb *IntegrationsTestBed) GetAvailableIntegrationsFromQS() *integrations.IntegrationsListResponse {
|
|
result := tb.RequestQS("/api/v1/integrations", nil)
|
|
|
|
dataJson, err := json.Marshal(result.Data)
|
|
if err != nil {
|
|
tb.t.Fatalf("could not marshal apiResponse.Data: %v", err)
|
|
}
|
|
var integrationsResp integrations.IntegrationsListResponse
|
|
err = json.Unmarshal(dataJson, &integrationsResp)
|
|
if err != nil {
|
|
tb.t.Fatalf("could not unmarshal apiResponse.Data json into PipelinesResponse")
|
|
}
|
|
|
|
return &integrationsResp
|
|
}
|
|
|
|
func (tb *IntegrationsTestBed) GetInstalledIntegrationsFromQS() *integrations.IntegrationsListResponse {
|
|
result := tb.RequestQS("/api/v1/integrations?is_installed=true", nil)
|
|
|
|
dataJson, err := json.Marshal(result.Data)
|
|
if err != nil {
|
|
tb.t.Fatalf("could not marshal apiResponse.Data: %v", err)
|
|
}
|
|
var integrationsResp integrations.IntegrationsListResponse
|
|
err = json.Unmarshal(dataJson, &integrationsResp)
|
|
if err != nil {
|
|
tb.t.Fatalf(" could not unmarshal apiResponse.Data json into PipelinesResponse")
|
|
}
|
|
|
|
return &integrationsResp
|
|
}
|
|
|
|
func (tb *IntegrationsTestBed) GetIntegrationDetailsFromQS(
|
|
integrationId string,
|
|
) *integrations.Integration {
|
|
result := tb.RequestQS(fmt.Sprintf(
|
|
"/api/v1/integrations/%s", integrationId,
|
|
), nil)
|
|
|
|
dataJson, err := json.Marshal(result.Data)
|
|
if err != nil {
|
|
tb.t.Fatalf("could not marshal apiResponse.Data: %v", err)
|
|
}
|
|
var integrationResp integrations.Integration
|
|
err = json.Unmarshal(dataJson, &integrationResp)
|
|
if err != nil {
|
|
tb.t.Fatalf("could not unmarshal apiResponse.Data json")
|
|
}
|
|
|
|
return &integrationResp
|
|
}
|
|
|
|
func (tb *IntegrationsTestBed) GetIntegrationConnectionStatus(
|
|
integrationId string,
|
|
) *integrations.IntegrationConnectionStatus {
|
|
result := tb.RequestQS(fmt.Sprintf(
|
|
"/api/v1/integrations/%s/connection_status", integrationId,
|
|
), nil)
|
|
|
|
dataJson, err := json.Marshal(result.Data)
|
|
if err != nil {
|
|
tb.t.Fatalf("could not marshal apiResponse.Data: %v", err)
|
|
}
|
|
var connectionStatus integrations.IntegrationConnectionStatus
|
|
err = json.Unmarshal(dataJson, &connectionStatus)
|
|
if err != nil {
|
|
tb.t.Fatalf("could not unmarshal apiResponse.Data json")
|
|
}
|
|
|
|
return &connectionStatus
|
|
}
|
|
|
|
func (tb *IntegrationsTestBed) RequestQSToInstallIntegration(
|
|
integrationId string, config map[string]interface{},
|
|
) {
|
|
request := integrations.InstallIntegrationRequest{
|
|
IntegrationId: integrationId,
|
|
Config: config,
|
|
}
|
|
tb.RequestQS("/api/v1/integrations/install", request)
|
|
}
|
|
|
|
func (tb *IntegrationsTestBed) RequestQSToUninstallIntegration(
|
|
integrationId string,
|
|
) {
|
|
request := integrations.UninstallIntegrationRequest{
|
|
IntegrationId: integrationId,
|
|
}
|
|
tb.RequestQS("/api/v1/integrations/uninstall", request)
|
|
}
|
|
|
|
func (tb *IntegrationsTestBed) GetDashboardsFromQS() []dashboards.Dashboard {
|
|
result := tb.RequestQS("/api/v1/dashboards", nil)
|
|
|
|
dataJson, err := json.Marshal(result.Data)
|
|
if err != nil {
|
|
tb.t.Fatalf("could not marshal apiResponse.Data: %v", err)
|
|
}
|
|
|
|
dashboards := []dashboards.Dashboard{}
|
|
err = json.Unmarshal(dataJson, &dashboards)
|
|
if err != nil {
|
|
tb.t.Fatalf(" could not unmarshal apiResponse.Data json into dashboards")
|
|
}
|
|
|
|
return dashboards
|
|
}
|
|
|
|
func (tb *IntegrationsTestBed) GetDashboardByIdFromQS(dashboardUuid string) *dashboards.Dashboard {
|
|
result := tb.RequestQS(fmt.Sprintf("/api/v1/dashboards/%s", dashboardUuid), nil)
|
|
|
|
dataJson, err := json.Marshal(result.Data)
|
|
if err != nil {
|
|
tb.t.Fatalf("could not marshal apiResponse.Data: %v", err)
|
|
}
|
|
|
|
dashboard := dashboards.Dashboard{}
|
|
err = json.Unmarshal(dataJson, &dashboard)
|
|
if err != nil {
|
|
tb.t.Fatalf(" could not unmarshal apiResponse.Data json into dashboards")
|
|
}
|
|
|
|
return &dashboard
|
|
}
|
|
|
|
func (tb *IntegrationsTestBed) RequestQS(
|
|
path string,
|
|
postData interface{},
|
|
) *app.ApiResponse {
|
|
req, err := NewAuthenticatedTestRequest(
|
|
tb.testUser, path, postData,
|
|
)
|
|
if err != nil {
|
|
tb.t.Fatalf("couldn't create authenticated test request: %v", err)
|
|
}
|
|
|
|
respWriter := httptest.NewRecorder()
|
|
tb.qsHttpHandler.ServeHTTP(respWriter, req)
|
|
response := respWriter.Result()
|
|
responseBody, err := io.ReadAll(response.Body)
|
|
if err != nil {
|
|
tb.t.Fatalf("couldn't read response body received from QS: %v", err)
|
|
}
|
|
|
|
if response.StatusCode != 200 {
|
|
tb.t.Fatalf(
|
|
"unexpected response status from query service for path %s. status: %d, body: %v\n%v",
|
|
path, response.StatusCode, string(responseBody), string(debug.Stack()),
|
|
)
|
|
}
|
|
|
|
var result app.ApiResponse
|
|
err = json.Unmarshal(responseBody, &result)
|
|
if err != nil {
|
|
tb.t.Fatalf(
|
|
"Could not unmarshal QS response into an ApiResponse.\nResponse body: %s",
|
|
string(responseBody),
|
|
)
|
|
}
|
|
|
|
return &result
|
|
}
|
|
|
|
func (tb *IntegrationsTestBed) mockLogQueryResponse(logsInResponse []model.SignozLog) {
|
|
addLogsQueryExpectation(tb.mockClickhouse, logsInResponse)
|
|
}
|
|
|
|
func (tb *IntegrationsTestBed) mockMetricStatusQueryResponse(expectation *model.MetricStatus) {
|
|
cols := []mockhouse.ColumnType{}
|
|
cols = append(cols, mockhouse.ColumnType{Type: "String", Name: "metric_name"})
|
|
cols = append(cols, mockhouse.ColumnType{Type: "String", Name: "labels"})
|
|
cols = append(cols, mockhouse.ColumnType{Type: "Int64", Name: "unix_milli"})
|
|
|
|
values := [][]any{}
|
|
if expectation != nil {
|
|
rowValues := []any{}
|
|
|
|
rowValues = append(rowValues, expectation.MetricName)
|
|
|
|
labelsJson, err := json.Marshal(expectation.LastReceivedLabels)
|
|
require.Nil(tb.t, err)
|
|
rowValues = append(rowValues, labelsJson)
|
|
|
|
rowValues = append(rowValues, expectation.LastReceivedTsMillis)
|
|
|
|
values = append(values, rowValues)
|
|
}
|
|
|
|
tb.mockClickhouse.ExpectQuery(
|
|
`SELECT.*metric_name, labels, unix_milli.*from.*signoz_metrics.*where metric_name in.*limit 1.*`,
|
|
).WillReturnRows(mockhouse.NewRows(cols, values))
|
|
}
|
|
|
|
// testDB can be injected for sharing a DB across multiple integration testbeds.
|
|
func NewIntegrationsTestBed(t *testing.T, testDB *sqlx.DB) *IntegrationsTestBed {
|
|
if testDB == nil {
|
|
testDB = utils.NewQueryServiceDBForTests(t)
|
|
}
|
|
|
|
controller, err := integrations.NewController(testDB)
|
|
if err != nil {
|
|
t.Fatalf("could not create integrations controller: %v", err)
|
|
}
|
|
|
|
fm := featureManager.StartManager()
|
|
reader, mockClickhouse := NewMockClickhouseReader(t, testDB, fm)
|
|
mockClickhouse.MatchExpectationsInOrder(false)
|
|
|
|
apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{
|
|
Reader: reader,
|
|
AppDao: dao.DB(),
|
|
IntegrationsController: controller,
|
|
FeatureFlags: fm,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("could not create a new ApiHandler: %v", err)
|
|
}
|
|
|
|
router := app.NewRouter()
|
|
am := app.NewAuthMiddleware(auth.GetUserFromRequest)
|
|
apiHandler.RegisterRoutes(router, am)
|
|
apiHandler.RegisterIntegrationRoutes(router, am)
|
|
|
|
user, apiErr := createTestUser()
|
|
if apiErr != nil {
|
|
t.Fatalf("could not create a test user: %v", apiErr)
|
|
}
|
|
|
|
return &IntegrationsTestBed{
|
|
t: t,
|
|
testUser: user,
|
|
qsHttpHandler: router,
|
|
mockClickhouse: mockClickhouse,
|
|
}
|
|
}
|
|
|
|
func postableFromPipelines(pipelines []logparsingpipeline.Pipeline) logparsingpipeline.PostablePipelines {
|
|
result := logparsingpipeline.PostablePipelines{}
|
|
|
|
for _, p := range pipelines {
|
|
postable := logparsingpipeline.PostablePipeline{
|
|
Id: p.Id,
|
|
OrderId: p.OrderId,
|
|
Name: p.Name,
|
|
Alias: p.Alias,
|
|
Enabled: p.Enabled,
|
|
Config: p.Config,
|
|
}
|
|
|
|
if p.Description != nil {
|
|
postable.Description = *p.Description
|
|
}
|
|
|
|
if p.Filter != nil {
|
|
postable.Filter = p.Filter
|
|
}
|
|
|
|
result.Pipelines = append(result.Pipelines, postable)
|
|
}
|
|
|
|
return result
|
|
}
|