func TestNewOnHostDatapoint(t *testing.T) { hostname, _ := os.Hostname() dp1 := NewOnHostDatapoint("metrica", nil, datapoint.Counter) assert.Equal(t, "metrica", dp1.Metric) dp := Wrap(datapoint.New("metric", map[string]string{}, datapoint.NewFloatValue(3.0), datapoint.Counter, time.Now())) assert.Equal(t, hostname, dp.Dimensions["host"], "Should get source back") osXXXHostname = func() (string, error) { return "", errors.New("unable to get hostname") } dp = Wrap(datapoint.New("metric", map[string]string{}, datapoint.NewFloatValue(3.0), datapoint.Counter, time.Now())) assert.Equal(t, "unknown", dp.Dimensions["host"], "Should get source back") osXXXHostname = os.Hostname }
// NewDatapoint creates a new datapoint from collectd's write_http endpoint JSON format // defaultDimensions are added to the datapoint created, but will be overridden by any dimension // values in the JSON // Dimensions are pulled out of type_instance, plugin_instance and host in that order of precedence func NewDatapoint(point *JSONWriteFormat, index uint, defaultDimensions map[string]string) *datapoint.Datapoint { dstype, val, dsname := point.Dstypes[index], point.Values[index], point.Dsnames[index] // if you add another dimension that we read from the json update this number const MaxCollectDDims = 6 dimensions := make(map[string]string, len(defaultDimensions)+MaxCollectDDims) for k, v := range defaultDimensions { dimensions[k] = v } metricType := metricTypeFromDsType(dstype) metricName, usedParts := getReasonableMetricName(point, index) addIfNotNullOrEmpty(dimensions, "plugin", true, point.Plugin) _, usedInMetricName := usedParts["type_instance"] parseDimensionsOut(dimensions, usedInMetricName, point.TypeInstance, point.PluginInstance, point.Host) _, usedInMetricName = usedParts["type"] addIfNotNullOrEmpty(dimensions, "type", !usedInMetricName, point.TypeS) _, usedInMetricName = usedParts["dsname"] addIfNotNullOrEmpty(dimensions, "dsname", !usedInMetricName, dsname) timestamp := time.Unix(0, int64(float64(time.Second)**point.Time)) return datapoint.New(metricName, dimensions, datapoint.NewFloatValue(*val), metricType, timestamp) }
// NewDatumValue creates new datapoint value referenced from a value of the datum protobuf func NewDatumValue(val *com_signalfx_metrics_protobuf.Datum) datapoint.Value { if val.DoubleValue != nil { return datapoint.NewFloatValue(val.GetDoubleValue()) } if val.IntValue != nil { return datapoint.NewIntValue(val.GetIntValue()) } return datapoint.NewStringValue(val.GetStrValue()) }
func TestNewProtobufDataPoint(t *testing.T) { protoDatapoint := &com_signalfx_metrics_protobuf.DataPoint{ Source: workarounds.GolangDoesnotAllowPointerToStringLiteral("asource"), Metric: workarounds.GolangDoesnotAllowPointerToStringLiteral("ametric"), Value: &com_signalfx_metrics_protobuf.Datum{IntValue: workarounds.GolangDoesnotAllowPointerToIntLiteral(2)}, Dimensions: []*com_signalfx_metrics_protobuf.Dimension{{ Key: workarounds.GolangDoesnotAllowPointerToStringLiteral("key"), Value: workarounds.GolangDoesnotAllowPointerToStringLiteral("value"), }}, } dp, err := NewProtobufDataPointWithType(protoDatapoint, com_signalfx_metrics_protobuf.MetricType_COUNTER) assert.Equal(t, "asource", dp.Dimensions["sf_source"], "Line should be invalid") assert.NoError(t, err) assert.Equal(t, datapoint.Count, dp.MetricType, "Line should be invalid") v := com_signalfx_metrics_protobuf.MetricType_CUMULATIVE_COUNTER protoDatapoint.MetricType = &v dp, err = NewProtobufDataPointWithType(protoDatapoint, com_signalfx_metrics_protobuf.MetricType_COUNTER) assert.NoError(t, err) assert.Equal(t, datapoint.Counter, dp.MetricType, "Line should be invalid") item := &BodySendFormatV2{ Metric: "ametric", Value: 3.0, } assert.Contains(t, item.String(), "ametric", "Should get metric name back") f, _ := ValueToValue(item.Value) assert.Equal(t, datapoint.NewFloatValue(3.0), f, "Should get value 3 back") item.Value = 3 i, _ := ValueToValue(item.Value) assert.Equal(t, datapoint.NewIntValue(3), i, "Should get value 3 back") item.Value = int64(3) ValueToValue(item.Value) item.Value = "abc" s, _ := ValueToValue(item.Value) assert.Equal(t, datapoint.NewStringValue("abc"), s, "Should get value abc back") item.Value = struct{}{} _, err = ValueToValue(item.Value) assert.Error(t, err) }
// ValueToValue converts the v2 JSON value to a core api Value func ValueToValue(v ValueToSend) (datapoint.Value, error) { f, ok := v.(float64) if ok { return datapoint.NewFloatValue(f), nil } i, ok := v.(int64) if ok { return datapoint.NewIntValue(i), nil } i2, ok := v.(int) if ok { return datapoint.NewIntValue(int64(i2)), nil } s, ok := v.(string) if ok { return datapoint.NewStringValue(s), nil } return nil, fmt.Errorf("unable to convert value: %s", v) }
func (decoder *JSONDecoderV1) Read(ctx context.Context, req *http.Request) error { dec := json.NewDecoder(req.Body) for { var d JSONDatapointV1 if err := dec.Decode(&d); err == io.EOF { break } else if err != nil { return err } else { log.WithField("dp", d).Debug("Got a new point") if d.Metric == "" { log.WithField("dp", d).Debug("Invalid Datapoint") continue } mt := fromMT(decoder.TypeGetter.GetMetricTypeFromMap(d.Metric)) dp := datapoint.New(d.Metric, map[string]string{"sf_source": d.Source}, datapoint.NewFloatValue(d.Value), mt, time.Now()) decoder.Sink.AddDatapoints(ctx, []*datapoint.Datapoint{dp}) } } return nil }
func TestDatumForPoint(t *testing.T) { assert.Equal(t, int64(3), datumForPoint(datapoint.NewIntValue(3)).GetIntValue()) assert.Equal(t, 0.0, datumForPoint(datapoint.NewIntValue(3)).GetDoubleValue()) assert.Equal(t, .1, datumForPoint(datapoint.NewFloatValue(.1)).GetDoubleValue()) assert.Equal(t, "hi", datumForPoint(datapoint.NewStringValue("hi")).GetStrValue()) }