Skip to content

1buran/custom-tags

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Custom Go struct tags

codecov Go Reference goreportcard

This is lib for dump Go structs to different exotic formats (currently supported only influxdb line protocol).

Getting Started

Caution

This is alpha stage, so library api may change!

Convert Go structs to influxdb line protocol format.

The structs should describe their reflection to influx line protocol format with struct tags:

  • tag name represents the name of measurement, tag or field of line protocol row,
  • tag value represents the type of data: measurement, tag, field or timestamp.

The only one measurement and timestamp should be, for these types of data the name of tag may be omitted cos it will not be used.

Example:

import (
  "time"
  "fmt"
  "github.com/1buran/custom-tags/influx"
)

type Node struct {
  Operation     string        `influx:",measurement"` // name is omitted cos will not used
  DataCenter    string        `influx:"dc,tag"`
  CloudProvider string        `influx:"cloud,tag"`
  Errors        int           `influx:"errors,field"`
  ExecutionTime time.Duration `influx:"time,field"`
  Timestamp     time.Time     `influx:",timestamp"` // name is omitted cos will not used
}

func (n Node) String() string { return influx.ConvertToInfluxLineProtocol(n) }

var backupDuration time.Duration = ... // calculate or get the time of backup creation
v := Node{
  Operation: "backup", DataCenter: "east-1", CloudProvider: "AWS",
  ExecutionTime: backupDuration, Timestamp: time.Now(),
}

// expected result:
v.String() == "backup,dc=east-1,cloud=AWS errors=0,time=45m30.233456987s 1735137974129911864"

// you may easy write metrics to file:
fmt.Fprintf(&fileMetrics, v)

Did you notice? The value of time duration time=45m12.233456987s is not what we are wanted, this is just a plain string which is useless to show it as value on the graphs, unfortunately influxdb does not support time.Duration so you have to convert this to meaningful value: seconds, minutes, hours etc what is more suitable for you.

You may just store nanoseconds as golang time duration with maximum of precision, but this is not handy in further representation on graphs.

That is why custom-tags has own handy type Duration which store duration with preferred time fractions and maximum 2 digits of float fraction.

So let's rewrite struct:

type Node struct {
  ...
  ExecutionTime influx.Duration `influx:"time,field"`
  ...
}

var backupDuration time.Duration = ... // calculate or get the time of backup creation
v := Node{
  Operation: "backup", DataCenter: "east-1", CloudProvider: "AWS",
  ExecutionTime: influx.Duration{Value: backupDuration.String(), To: time.Minute}, Timestamp: time.Now(),
}

// expected result:
v.String() == "backup,dc=east-1,cloud=AWS errors=0,time=45.50 1735137974129911864"

now it looks much pretty and became much easy to show on the graphs.

https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/

Custom methods for getting measurement and timestamp of data

Typically you always have the field of struct which can be used as measurement, in terms of influxdb, this is the name of measurement.

But if you have no such field or do not want store extra data in your struct, you may define InfluxMeasurement() string method:

type UploadMetrics struct {
	Ts    time.Time       `influx:",timestamp"`
	Time  time.Duration   `influx:"time,field"`
	Speed float64         `influx:"speed,field"`
}

func (u UploadMetrics) InfluxMeasurement() string { return "upload" }

The same thing is correct for another one special required influx line protocol row field - timestamp. You may define it as InfluxTimestamp() time.Time method:

type UploadMetrics struct {
	Time  time.Duration `influx:"time,field"`
	Speed float64       `influx:"speed,field"`
}

func (u UploadMetrics) InfluxMeasurement() string { return "upload" }
func (u UploadMetrics) InfluxTimestamp() time.Time { return time.Now() }

and then use it in code:

func main() {
  stats := UploadMetrics{}
  ...
  t := time.Now()
  Upload(file)
  stats.Time = time.Since(t)
  stats.Speed = file.size / stats.Time.Seconds()
  fmt.Fprint(&metricsFile, stats)
}

or more shorter variant:

func main() {
  ...
  t := time.Now()
  Upload(file)
  fmt.Fprint(&metricsFile, UploadMetrics{Time: time.Since(t), Speed: file.size / stats.Time.Seconds()})
}

it works fine cos the metrics dumps to disk at the moment of their creation, in real world the mentioned immplementation InfluxTimestamp() time.Time { return time.Now() } is not really what do you want, but having the ability of dynamic construction of measurement timestamp may be very useful in some situations.

About

Convert Go structs to Influxdb line protocol

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages