diff --git a/pkg/api/annotation.go b/pkg/api/annotation.go index 3678168515..fa7c6ac560 100644 --- a/pkg/api/annotation.go +++ b/pkg/api/annotation.go @@ -5,6 +5,7 @@ import ( "encoding/json" "net/http" "strconv" + "time" "github.com/pyroscope-io/pyroscope/pkg/model" "github.com/pyroscope-io/pyroscope/pkg/server/httputils" @@ -42,9 +43,14 @@ func (h *AnnotationsHandler) CreateAnnotation(w http.ResponseWriter, r *http.Req return } + var timestamp time.Time + if params.Timestamp != 0 { + timestamp = attime.Parse(strconv.FormatInt(params.Timestamp, 10)) + } + annotation, err := h.svc.CreateAnnotation(r.Context(), model.CreateAnnotation{ AppName: params.AppName, - Timestamp: attime.Parse(strconv.FormatInt(params.Timestamp, 10)), + Timestamp: timestamp, Content: params.Content, }) if err != nil { diff --git a/pkg/api/annotation_test.go b/pkg/api/annotation_test.go index f7a9fc94ec..8e4d765acb 100644 --- a/pkg/api/annotation_test.go +++ b/pkg/api/annotation_test.go @@ -8,17 +8,18 @@ import ( "time" . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" "github.com/pyroscope-io/pyroscope/pkg/api/router" "github.com/pyroscope-io/pyroscope/pkg/model" "github.com/sirupsen/logrus" ) type mockService struct { - createAnnotationResponse func() (*model.Annotation, error) + createAnnotationResponse func(params model.CreateAnnotation) (*model.Annotation, error) } func (m *mockService) CreateAnnotation(ctx context.Context, params model.CreateAnnotation) (*model.Annotation, error) { - return m.createAnnotationResponse() + return m.createAnnotationResponse(params) } var _ = Describe("AnnotationHandler", func() { @@ -35,7 +36,7 @@ var _ = Describe("AnnotationHandler", func() { When("all parameters are set", func() { BeforeEach(func() { svc = &mockService{ - createAnnotationResponse: func() (*model.Annotation, error) { + createAnnotationResponse: func(params model.CreateAnnotation) (*model.Annotation, error) { return &model.Annotation{ AppName: "myApp", Content: "mycontent", @@ -60,10 +61,39 @@ var _ = Describe("AnnotationHandler", func() { }) }) + When("timestamp is absent", func() { + It("it defaults to zero-value", func() { + svc = &mockService{ + createAnnotationResponse: func(params model.CreateAnnotation) (m *model.Annotation, err error) { + // The service should receive a zero timestamp + Expect(params.Timestamp.IsZero()).To(BeTrue()) + + return &model.Annotation{ + AppName: "myApp", + Content: "mycontent", + Timestamp: time.Unix(1662729099, 0), + }, nil + }, + } + + server = httptest.NewServer(newTestRouter(defaultUserCtx, router.Services{ + Logger: logrus.StandardLogger(), + AnnotationsService: svc, + })) + + url := server.URL + "/annotations" + + expectResponse(newRequest(http.MethodPost, url, + "annotation/create_request_no_timestamp.json"), + "annotation/create_response.json", + http.StatusCreated) + }) + }) + When("fields are invalid", func() { BeforeEach(func() { svc = &mockService{ - createAnnotationResponse: func() (*model.Annotation, error) { + createAnnotationResponse: func(params model.CreateAnnotation) (*model.Annotation, error) { return nil, model.ValidationError{errors.New("myerror")} }, } diff --git a/pkg/api/testdata/annotation/create_request_no_timestamp.json b/pkg/api/testdata/annotation/create_request_no_timestamp.json new file mode 100644 index 0000000000..7506814067 --- /dev/null +++ b/pkg/api/testdata/annotation/create_request_no_timestamp.json @@ -0,0 +1,4 @@ +{ + "appName": "myApp", + "content": "mycontent" +}