diff --git a/plugins/outputs/stackdriver/stackdriver.go b/plugins/outputs/stackdriver/stackdriver.go index f630f458f..a16d78aa5 100644 --- a/plugins/outputs/stackdriver/stackdriver.go +++ b/plugins/outputs/stackdriver/stackdriver.go @@ -15,6 +15,7 @@ import ( "google.golang.org/api/option" metricpb "google.golang.org/genproto/googleapis/api/metric" monitoredrespb "google.golang.org/genproto/googleapis/api/monitoredres" + "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" "github.com/influxdata/telegraf" @@ -54,10 +55,6 @@ const ( // MaxInt is the max int64 value. MaxInt = int(^uint(0) >> 1) - - errStringPointsOutOfOrder = "one or more of the points specified had an older end time than the most recent point" - errStringPointsTooOld = "data points cannot be written more than 24h in the past" - errStringPointsTooFrequent = "one or more points were written more frequently than the maximum sampling period configured for the metric" ) func (s *Stackdriver) Init() error { @@ -322,12 +319,13 @@ func (s *Stackdriver) sendBatch(batch []telegraf.Metric) error { // Create the time series in Stackdriver. err := s.client.CreateTimeSeries(ctx, timeSeriesRequest) if err != nil { - if strings.Contains(err.Error(), errStringPointsOutOfOrder) || - strings.Contains(err.Error(), errStringPointsTooOld) || - strings.Contains(err.Error(), errStringPointsTooFrequent) { - s.Log.Debugf("Unable to write to Stackdriver: %s", err) - return nil + if errStatus, ok := status.FromError(err); ok { + if errStatus.Code().String() == "InvalidArgument" { + s.Log.Warnf("Unable to write to Stackdriver - dropping metrics: %s", err) + return nil + } } + s.Log.Errorf("Unable to write to Stackdriver: %s", err) return err } diff --git a/plugins/outputs/stackdriver/stackdriver_test.go b/plugins/outputs/stackdriver/stackdriver_test.go index c8142cdda..817468d37 100644 --- a/plugins/outputs/stackdriver/stackdriver_test.go +++ b/plugins/outputs/stackdriver/stackdriver_test.go @@ -18,8 +18,10 @@ import ( "google.golang.org/api/option" metricpb "google.golang.org/genproto/googleapis/api/metric" "google.golang.org/grpc" + "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/timestamppb" @@ -55,9 +57,18 @@ func (s *mockMetricServer) CreateTimeSeries(ctx context.Context, req *monitoring if xg := md["x-goog-api-client"]; len(xg) == 0 || !strings.Contains(xg[0], "gl-go/") { return nil, fmt.Errorf("x-goog-api-client = %v, expected gl-go key", xg) } + s.reqs = append(s.reqs, req) if s.err != nil { - return nil, s.err + var statusResp *status.Status + switch s.err.Error() { + case "InvalidArgument": + statusResp = status.New(codes.InvalidArgument, s.err.Error()) + default: + statusResp = status.New(codes.Unknown, s.err.Error()) + } + + return nil, statusResp.Err() } return s.resps[0].(*emptypb.Empty), nil } @@ -396,23 +407,16 @@ func TestWriteIgnoredErrors(t *testing.T) { err error expectedErr bool }{ - { - name: "points too old", - err: errors.New(errStringPointsTooOld), - }, - { - name: "points out of order", - err: errors.New(errStringPointsOutOfOrder), - }, - { - name: "points too frequent", - err: errors.New(errStringPointsTooFrequent), - }, { name: "other errors reported", - err: errors.New("test"), + err: errors.New("Unknown"), expectedErr: true, }, + { + name: "invalid argument", + err: errors.New("InvalidArgument"), + expectedErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -431,13 +435,11 @@ func TestWriteIgnoredErrors(t *testing.T) { client: c, } - err = s.Connect() - require.NoError(t, err) - err = s.Write(testutil.MockMetrics()) + require.NoError(t, s.Connect()) if tt.expectedErr { - require.Error(t, err) + require.Error(t, s.Write(testutil.MockMetrics())) } else { - require.NoError(t, err) + require.NoError(t, s.Write(testutil.MockMetrics())) } }) }