mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
This commit adds a customizable timeout for screenshots called capture_timeout. The default value is 10 seconds, and the maximum value is 30 seconds. This timeout should be less than the minimum Interval of all Evaluation Groups to avoid back pressure on alert rule evaluation.
147 lines
4.7 KiB
Go
147 lines
4.7 KiB
Go
package image
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/golang/mock/gomock"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/xorcare/pointer"
|
|
|
|
"github.com/grafana/grafana/pkg/components/imguploader"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
|
"github.com/grafana/grafana/pkg/services/screenshot"
|
|
)
|
|
|
|
func TestScreenshotImageService(t *testing.T) {
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
var (
|
|
cache = NewMockCacheService(ctrl)
|
|
images = store.NewFakeImageStore(t)
|
|
limiter = screenshot.NoOpRateLimiter{}
|
|
screenshots = screenshot.NewMockScreenshotService(ctrl)
|
|
uploads = imguploader.NewMockImageUploader(ctrl)
|
|
)
|
|
|
|
s := NewScreenshotImageService(cache, &limiter, log.NewNopLogger(), screenshots, 5*time.Second, images,
|
|
NewUploadingService(uploads, prometheus.NewRegistry()))
|
|
|
|
ctx := context.Background()
|
|
|
|
t.Run("image is taken, uploaded, saved to database and cached", func(t *testing.T) {
|
|
// assert that the cache is checked for an existing image
|
|
cache.EXPECT().Get(gomock.Any(), "M2DGZaRLXtg=").Return(models.Image{}, false)
|
|
|
|
// assert that a screenshot is taken
|
|
screenshots.EXPECT().Take(gomock.Any(), screenshot.ScreenshotOptions{
|
|
DashboardUID: "foo",
|
|
PanelID: 1,
|
|
Timeout: 5 * time.Second,
|
|
}).Return(&screenshot.Screenshot{
|
|
Path: "foo.png",
|
|
}, nil)
|
|
|
|
// assert that the screenshot is made into an image and uploaded
|
|
uploads.EXPECT().Upload(gomock.Any(), "foo.png").
|
|
Return("https://example.com/foo.png", nil)
|
|
|
|
// assert that the image is saved into the database
|
|
expected := models.Image{
|
|
ID: 1,
|
|
Token: "foo",
|
|
Path: "foo.png",
|
|
URL: "https://example.com/foo.png",
|
|
}
|
|
|
|
// assert that the image is saved into the cache
|
|
cache.EXPECT().Set(gomock.Any(), "M2DGZaRLXtg=", expected).Return(nil)
|
|
|
|
image, err := s.NewImage(ctx, &models.AlertRule{
|
|
OrgID: 1,
|
|
UID: "foo",
|
|
DashboardUID: pointer.String("foo"),
|
|
PanelID: pointer.Int64(1)})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, expected, *image)
|
|
})
|
|
|
|
t.Run("image is taken, upload return error, saved to database without URL and cached", func(t *testing.T) {
|
|
// assert that the cache is checked for an existing image
|
|
cache.EXPECT().Get(gomock.Any(), "rTOWVcbRidk=").Return(models.Image{}, false)
|
|
|
|
// assert that a screenshot is taken
|
|
screenshots.EXPECT().Take(gomock.Any(), screenshot.ScreenshotOptions{
|
|
DashboardUID: "bar",
|
|
PanelID: 1,
|
|
Timeout: 5 * time.Second,
|
|
}).Return(&screenshot.Screenshot{
|
|
Path: "bar.png",
|
|
}, nil)
|
|
|
|
// the screenshot is made into an image and uploaded, but the upload returns an error
|
|
uploads.EXPECT().Upload(gomock.Any(), "bar.png").
|
|
Return("", errors.New("failed to upload bar.png"))
|
|
|
|
// and then saved into the database, but without a URL
|
|
expected := models.Image{
|
|
ID: 2,
|
|
Token: "bar",
|
|
Path: "bar.png",
|
|
}
|
|
|
|
// assert that the image is saved into the cache, but without a URL
|
|
cache.EXPECT().Set(gomock.Any(), "rTOWVcbRidk=", expected).Return(nil)
|
|
|
|
image, err := s.NewImage(ctx, &models.AlertRule{
|
|
OrgID: 1,
|
|
UID: "bar",
|
|
DashboardUID: pointer.String("bar"),
|
|
PanelID: pointer.Int64(1)})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, expected, *image)
|
|
})
|
|
|
|
t.Run("image is returned from cache", func(t *testing.T) {
|
|
expected := models.Image{Path: "baz.png", URL: "https://example.com/baz.png"}
|
|
|
|
// assert that the cache is checked for an existing image and it is returned
|
|
cache.EXPECT().Get(gomock.Any(), "8hJuVe20rVE=").Return(expected, true)
|
|
|
|
image, err := s.NewImage(ctx, &models.AlertRule{
|
|
OrgID: 1,
|
|
UID: "baz",
|
|
DashboardUID: pointer.String("baz"),
|
|
PanelID: pointer.Int64(1)})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, expected, *image)
|
|
})
|
|
|
|
t.Run("error is returned when timeout is exceeded", func(t *testing.T) {
|
|
// assert that the cache is checked for an existing image
|
|
cache.EXPECT().Get(gomock.Any(), "jtThkFaZLA4=").Return(models.Image{}, false)
|
|
|
|
// assert that when the timeout is exceeded an error is returned
|
|
screenshots.EXPECT().Take(gomock.Any(), screenshot.ScreenshotOptions{
|
|
DashboardUID: "qux",
|
|
PanelID: 1,
|
|
Timeout: 5 * time.Second,
|
|
}).Return(nil, context.DeadlineExceeded)
|
|
|
|
image, err := s.NewImage(ctx, &models.AlertRule{
|
|
OrgID: 1,
|
|
UID: "qux",
|
|
DashboardUID: pointer.String("qux"),
|
|
PanelID: pointer.Int64(1)})
|
|
assert.EqualError(t, err, "context deadline exceeded")
|
|
assert.Nil(t, image)
|
|
})
|
|
}
|