func (metrics *Metrics) Inc(name string) {
	if !metrics.Ready {
		return
	}
	now := time.Now().Unix()
	metrics.mux.Lock()
	if c, ok := metrics.Counters[name]; ok {
		if (now - c.Interval) >= defaultInterval {
			c.Count = 0
			c.Interval = now
		} else {
			c.Count++
		}
		metrics.Counters[name] = c
	} else {
		c := Counter{
			Count:    1,
			Interval: now,
		}
		metrics.Counters[name] = c
	}
	value := metrics.Counters[name].Count
	metrics.mux.Unlock()
	metrics.ConnectAndSend(name, value)
}
Inc to increase the counter for a metric
package metrics
import (
	"bytes"
	"fmt"
	"log"
	"net"
	"sync"
	"time"
	"github.com/spf13/viper"
)
const (
	metricsName string = "metrics"
	metricsConfigFile string = "config/" + metricsName + ".json"
)
type Configuration struct {
	Host     string `json:"host"`
	Port     int    `json:"port"`
	Protocol string `json:"protocol"`
}
func LoadConfiguration() (Configuration, error) {
	var _metricsCfg Configuration
	log.Printf("Loading %s", metricsConfigFile)
	viper.SetConfigFile(metricsConfigFile)
	if err := viper.ReadInConfig(); err != nil {
		return _metricsCfg, err
	}
	cfgRaw := viper.Sub(metricsName)
	if err := cfgRaw.Unmarshal(&_metricsCfg); err != nil {
		return _metricsCfg, err
	}
	return _metricsCfg, nil
}
func (metrics *Metrics) metricFormat(name string, value int) string {
	return fmt.Sprintf(
		"%s %d %d\n",
		metrics.Tag+"."+name,
		value,
		time.Now().Unix(),
	)
}
type Counter struct {
	Count    int
	Interval int64
}
type Metrics struct {
	Ready    bool
	mux      sync.Mutex
	Host     string
	Port     int
	Protocol string
	Tag      string
	Timeout  time.Duration
	conn     net.Conn
	Counters map[string]Counter
}
const defaultTimeout = 5
const defaultInterval = 60
const defaultRetries = 5
func (metrics *Metrics) Connect() error {
	if metrics.conn != nil {
		_ = metrics.conn.Close()
	}
	connString := fmt.Sprintf("%s:%d", metrics.Host, metrics.Port)
	if metrics.Timeout == 0 {
		metrics.Timeout = defaultTimeout * time.Second
	}
	var err error
	var conn net.Conn
	var udpAddr *net.UDPAddr
	if metrics.Protocol == "udp" {
		udpAddr, err = net.ResolveUDPAddr("udp", connString)
		if err != nil {
			return err
		}
		conn, err = net.DialUDP(metrics.Protocol, nil, udpAddr)
	} else {
		conn, err = net.DialTimeout(metrics.Protocol, connString, metrics.Timeout)
	}
	if err != nil {
		return err
	}
	metrics.conn = conn
	return nil
}
func (metrics *Metrics) Disconnect() error {
	err := metrics.conn.Close()
	metrics.conn = nil
	return err
}
func (metrics *Metrics) ConnectAndSend(name string, value int) {
	if err := metrics.Connect(); err != nil {
		log.Printf("error connecting %v", err)
	}
	err := metrics.Send(name, value)
	i := 0
	for err != nil {
		log.Printf("Something happened %v", err)
		_ = metrics.Connect()
		err = metrics.Send(name, value)
		if i < defaultRetries {
			i++
		} else {
			log.Printf("Too many retries, exiting")
			break
		}
	}
}
func (metrics *Metrics) Send(name string, value int) error {
	if !metrics.Ready {
		return fmt.Errorf("metrics are not ready")
	}
	mData := metrics.metricFormat(name, value)
	if metrics.Protocol == "udp" {
		fmt.Fprintf(metrics.conn, mData)
	} else if metrics.Protocol == "tcp" {
		buf := bytes.NewBufferString("")
		buf.WriteString(mData)
		_, err := metrics.conn.Write(buf.Bytes())
		if err != nil {
			return err
		}
	}
	return nil
}