Skip to content
This repository has been archived by the owner on Jul 12, 2024. It is now read-only.

Commit

Permalink
Allow zero for interval value. (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
a-feld authored Jul 28, 2021
1 parent bfff122 commit 8f3e613
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 10 deletions.
21 changes: 14 additions & 7 deletions telemetry/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ type Count struct {
// Interval is the length of time for this metric. If Interval is unset
// then the time between Harvester harvests will be used.
Interval time.Duration
// Set to true to force the value of interval to be written to the payload
ForceIntervalValid bool
}

func (m Count) validate() map[string]interface{} {
Expand All @@ -61,12 +63,12 @@ type Metric interface {
validate() map[string]interface{}
}

func writeTimestampInterval(w *internal.JSONFieldsWriter, timestamp time.Time, interval time.Duration) {
func writeTimestampInterval(w *internal.JSONFieldsWriter, timestamp time.Time, interval time.Duration, forceIntervalValid bool) {
if !timestamp.IsZero() {
w.IntField("timestamp", timestamp.UnixNano()/(1000*1000))
}
if interval != 0 {
w.IntField("interval.ms", interval.Nanoseconds()/(1000*1000))
if interval != 0 || forceIntervalValid {
w.IntField("interval.ms", interval.Milliseconds())
}
}

Expand All @@ -76,7 +78,7 @@ func (m Count) writeJSON(buf *bytes.Buffer) {
w.StringField("name", m.Name)
w.StringField("type", "count")
w.FloatField("value", m.Value)
writeTimestampInterval(&w, m.Timestamp, m.Interval)
writeTimestampInterval(&w, m.Timestamp, m.Interval, m.ForceIntervalValid)
if nil != m.Attributes {
w.WriterField("attributes", internal.Attributes(m.Attributes))
} else if nil != m.AttributesJSON {
Expand Down Expand Up @@ -117,6 +119,8 @@ type Summary struct {
// Interval is the length of time for this metric. If Interval is unset
// then the time between Harvester harvests will be used.
Interval time.Duration
// Set to true to force the value of interval to be written to the payload
ForceIntervalValid bool
}

func (m Summary) validate() map[string]interface{} {
Expand Down Expand Up @@ -173,7 +177,7 @@ func (m Summary) writeJSON(buf *bytes.Buffer) {
}
buf.WriteByte('}')

writeTimestampInterval(&w, m.Timestamp, m.Interval)
writeTimestampInterval(&w, m.Timestamp, m.Interval, m.ForceIntervalValid)
if nil != m.Attributes {
w.WriterField("attributes", internal.Attributes(m.Attributes))
} else if nil != m.AttributesJSON {
Expand Down Expand Up @@ -225,7 +229,7 @@ func (m Gauge) writeJSON(buf *bytes.Buffer) {
w.StringField("name", m.Name)
w.StringField("type", "gauge")
w.FloatField("value", m.Value)
writeTimestampInterval(&w, m.Timestamp, 0)
writeTimestampInterval(&w, m.Timestamp, 0, false)
if nil != m.Attributes {
w.WriterField("attributes", internal.Attributes(m.Attributes))
} else if nil != m.AttributesJSON {
Expand All @@ -244,6 +248,8 @@ type metricCommonBlock struct {
// Summary metric. interval must be set to a non-zero value here or on
// all Count and Summary metrics.
interval time.Duration
// Set to true to force the value of interval to be written to the payload
forceIntervalValid bool
// attributes is the reference to the common attributes that apply to
// all metrics in the batch.
attributes *commonAttributes
Expand All @@ -258,7 +264,7 @@ func (mcb *metricCommonBlock) DataTypeKey() string {
func (mcb *metricCommonBlock) WriteDataEntry(buf *bytes.Buffer) *bytes.Buffer {
buf.WriteByte('{')
w := internal.JSONFieldsWriter{Buf: buf}
writeTimestampInterval(&w, mcb.timestamp, mcb.interval)
writeTimestampInterval(&w, mcb.timestamp, mcb.interval, mcb.forceIntervalValid)
if nil != mcb.attributes && nil != mcb.attributes.RawJSON {
w.AddKey(mcb.attributes.DataTypeKey())
mcb.attributes.WriteDataEntry(buf)
Expand Down Expand Up @@ -302,6 +308,7 @@ func WithMetricAttributes(commonAttributes map[string]interface{}) MetricCommonB
func WithMetricInterval(interval time.Duration) MetricCommonBlockOption {
return func(b *metricCommonBlock) error {
b.interval = interval
b.forceIntervalValid = true
return nil
}
}
Expand Down
9 changes: 6 additions & 3 deletions telemetry/metrics_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,13 +375,13 @@ func TestCommonAttributes(t *testing.T) {
}
sometime := time.Date(2014, time.November, 28, 1, 1, 0, 0, time.UTC)
testcases := []testStruct{
{expect: `[{"common":{},"metrics":[]}]`},
{start: sometime, expect: `[{"common":{"timestamp":1417136460000},"metrics":[]}]`},
{expect: `[{"common":{"interval.ms":0},"metrics":[]}]`},
{start: sometime, expect: `[{"common":{"timestamp":1417136460000,"interval.ms":0},"metrics":[]}]`},
{interval: 5 * time.Second, expect: `[{"common":{"interval.ms":5000},"metrics":[]}]`},
{start: sometime, interval: 5 * time.Second,
expect: `[{"common":{"timestamp":1417136460000,"interval.ms":5000},"metrics":[]}]`},
{attributes: map[string]interface{}{"zip": "zap", "invalid": []string{"invalid"}},
expect: `[{"common":{"attributes":{"zip":"zap"}},"metrics":[]}]`},
expect: `[{"common":{"interval.ms":0,"attributes":{"zip":"zap"}},"metrics":[]}]`},
}

emptyGroup := NewMetricGroup(nil)
Expand All @@ -393,6 +393,9 @@ func TestCommonAttributes(t *testing.T) {
)
testGroupJSON(t, []Batch{{commonBlock, emptyGroup}}, test.expect)
}
// Verify an empty common block (without metric interval) can be written without metric interval call
commonBlock, _ := NewMetricCommonBlock()
testGroupJSON(t, []Batch{{commonBlock, emptyGroup}}, `[{"common":{},"metrics":[]}]`)
}

func TestMetricsJSONWithCommonAttributesJSON(t *testing.T) {
Expand Down

0 comments on commit 8f3e613

Please sign in to comment.