statsd client for Go

Overview

go-statsd-client

Build Status GoDoc Go Report Card License

About

A StatsD client (UDP) for Go.

Docs

Viewable online at godoc.org.

Example

Some examples:

import (
    "log"

    "github.com/cactus/go-statsd-client/v5/statsd"
)

func main() {
    // First create a client config. Here is a simple config that sends one
    // stat per packet (for compatibility).
    config := &statsd.ClientConfig{
        Address: "127.0.0.1:8125",
        Prefix: "test-client",
    }

    /*
    // This one is for a client that re-resolves the hostname ever 30 seconds.
    // Useful if the address of a hostname changes frequently. Note that this
    // type of client has some additional locking overhead for safety.
    // As such, leave ResInetval as the zero value (previous exmaple) if you
    // don't specifically need this functionality.
    config := &statsd.ClientConfig{
        Address: "127.0.0.1:8125",
        Prefix: "test-client",
        ResInterval: 30 * time.Second,
    }

    // This one is for a buffered client, which sends multiple stats in one
    // packet, is recommended when your server supports it (better performance).
    config := &statsd.ClientConfig{
        Address: "127.0.0.1:8125",
        Prefix: "test-client",
        UseBuffered: true,
        // interval to force flush buffer. full buffers will flush on their own,
        // but for data not frequently sent, a max threshold is useful
        FlushInterval: 300*time.Millisecond,
    }

    // This one is for a buffered resolving client, which sends multiple stats
    // in one packet (like previous example), as well as re-resolving the
    // hostname every 30 seconds.
    config := &statsd.ClientConfig{
        Address: "127.0.0.1:8125",
        Prefix: "test-client",
        ResInterval: 30 * time.Second,
        UseBuffered: true,
        FlushInterval: 300*time.Millisecond,
    }

    // This one is an example of configuring "Tag" support
    // Supported formats are:
    //   InfixComma
    //   InfixSemicolon
    //   SuffixOctothorpe
    // The default, if not otherwise specified, is SuffixOctothorpe.
    config := &statsd.ClientConfig{
        Address: "127.0.0.1:8125",
        Prefix: "test-client",
        ResInterval: 30 * time.Second,
        TagFormat: statsd.InfixSemicolon,
    }
    */

    // Now create the client
    client, err := statsd.NewClientWithConfig(config)

    // and handle any initialization errors
    if err != nil {
        log.Fatal(err)
    }

    // make sure to close to clean up when done, to avoid leaks.
    defer client.Close()

    // Send a stat
    client.Inc("stat1", 42, 1.0)

    // Send a stat with "Tags"
    client.Inc("stat2", 41, 1.0, Tag{"mytag", "tagval"})
}

Legacy Example

A legacy client creation method is still supported. This is retained so as not to break or interrupt existing integrations.

import (
    "log"

    "github.com/cactus/go-statsd-client/v5/statsd"
)

func main() {
    // first create a client
    // The basic client sends one stat per packet (for compatibility).
    client, err := statsd.NewClient("127.0.0.1:8125", "test-client")

    // A buffered client, which sends multiple stats in one packet, is
    // recommended when your server supports it (better performance).
    // client, err := statsd.NewBufferedClient("127.0.0.1:8125", "test-client", 300*time.Millisecond, 0)

    // handle any errors
    if err != nil {
        log.Fatal(err)
    }
    // make sure to close to clean up when done, to avoid leaks.
    defer client.Close()

    // Send a stat
    client.Inc("stat1", 42, 1.0)
}

See docs for more info. There is also some additional example code in the test-client directory.

Contributors

See here.

Alternative Implementations

See the statsd wiki for some additional client implementations (scroll down to the Go section).

License

Released under the MIT license. See LICENSE.md file for details.

Comments
  • Not connected, but no error is being returned

    Not connected, but no error is being returned

    I've been doing some test with this package and for some reason, when I try to send stat data, no connection is created (I know this because I'm not even running a server), but no error is returned.

    package main
    
    import (
    	"fmt"
    
    	statsd "github.com/cactus/go-statsd-client/statsd"
    )
    
    func main() {
    
    	conf := statsd.ClientConfig{
    		Address: "127.0.0.1:8125",
    		Prefix:  "",
    	}
    
    	client, err := statsd.NewClientWithConfig(&conf)
    	if err != nil {
    		fmt.Printf("%+v", err)
    		panic(err)
    	}
    
    	err = client.Inc("test", 1, 1.0)
    	if err != nil {
    		fmt.Printf("%+v", err)
    		panic(err)
    	}
    }
    

    When this is run, no error is output.

    There is definately no server running:

    » telnet 127.0.0.1 8125
    Trying 127.0.0.1...
    telnet: connect to address 127.0.0.1: Connection refused
    telnet: Unable to connect to remote host
    

    I'm not sure what is going on here, any help appreciated. I'm using 3.2.0 version of the package:

    [[constraint]]
      name = "github.com/cactus/go-statsd-client"
      version = "3.2.0"
    
    question 
    opened by synackSA 10
  • Ability to create a sub statter

    Ability to create a sub statter

    I would like to propose a new method for the Statter interface, that would create a SubStatter. A SubStatter would use the same Sender as the parent Statter but would have it's own prefix. This would allow users to add instrumentation to utility functions that are used by numerous packages with out having to create a new client. The Sub method that creates the SubStatter would append an additional prefix to the existing Statter prefix.

    I would be happy to implement this if you think it is worthwhile.

    enhancement 
    opened by mckayb24 10
  • Optimization suggestion: Avoid formatting if we're not going to send a packet

    Optimization suggestion: Avoid formatting if we're not going to send a packet

    Right now the message formatting occurs before we decide whether the sample rate will allow the current message to be sent.

    i.e.

    func (s *Client) Inc(stat string, value int64, rate float32) error {
        dap := fmt.Sprintf("%d|c", value) <-- causes CPU work and probably creates garbage
        return s.Raw(stat, dap, rate) // <----- this might do nothing!
    }
    

    I'm assuming that calculating the random sample is faster and causes no GC [citation of benchmark needed ;) ], compared to string formatting, so applications will benefit from having the sample rate checked before formatting on stats that are sent very frequently.

    This will also allow client.Raw to possibly do all formatting in one go, further reducing garbage and CPU.

    Again, if you're interested I'll just go ahead and implement it.

    opened by dvirsky 10
  • Feature request (again): Tags

    Feature request (again): Tags

    Since the last issue over two years ago (https://github.com/cactus/go-statsd-client/issues/38), Graphite, Datadog, and InfluxDB have all accepted tags as relatively important functionality, with slightly different formatting between them (example: https://github.com/smira/go-statsd/pull/29/files). Would it be possible to support this?

    enhancement feature request 
    opened by bconway 8
  • Support DNS changing IP address

    Support DNS changing IP address

    We use DNS to resolve a statsd endpoint IP. If the IP address behind the DNS changes, go-statsd-client will never use the new IP. This means metrics will fail until the application restarts. Ideally if the IP address behind a DNS name changes, the sender will send stats to the new IP.

    It seems to start at this line:

    	ra, err := net.ResolveUDPAddr("udp", addr)
    

    Once ra is resolved, it is never re-resolved. There are a few options for this.

    1. Add a function to SimpleSender that allows me to update ra. I could then call this if I detect a change. This won't fix the problem for future people, but will let me work around it.
    2. Change SimpleSender to execute net.ResolveUDPAddr("udp", addr) each time on Send: this could cause a performance problem. Optionally, we could only update ra every X units of time.
    3. Modify BufferedSender to take a Sender as input. I could then pass my own sender, instead of using the provided one.

    Also, any way we change this, we'll need to extend BufferedSender to call this function on the SimpleSender, or allow BufferedSender to return the wrapped Sender, and I could call it myself on the BufferedSender object.

    enhancement 
    opened by cep21 7
  • [rfc] Stat recording sender

    [rfc] Stat recording sender

    Hey, is this something you'd be interested in me cleaning up for inclusion in your repo?

    It's really only intended for use in tests so likely go-statsd-client/statsd/statsdtest or something in the vein of net/http/httptest would be a more reasonable home than the root package.

    opened by falun 7
  • Support already-sampled data.

    Support already-sampled data.

    I would like to be able to send metrics to statsd with a sample rate attached, without the client actually doing the random sampling. That sounds a little weird, so here are a couple motivating examples, both of which I deal with in real life:

    1. In one case, the sampling happens upstream of me. I'm sending access logs across the network, parsing them and sending the data to a local statsd server. I want to avoid sending too many megabits of log lines across the network so I apply sampling at the remote end. But I would still like the numbers in statsd to be accurate. Since I know the upstream sampling rate, I want to pass it on in the statsd metrics.
    2. In another case, the data is local, but the parsing is expensive. Instead of parsing every line, generating the metrics, and then throwing away 90% of them, I would like to parse 10% of the lines, generate metrics for every one I do parse, and then, again, send them with with @0.1 attached.

    I'm not sure of the best way to add this to the interface, which is why I haven't gone about sending a PR, but perhaps a client could just have a sample rate multiplier field, so that the rate passed into includeStat is still the same rate passed to Inc/Timing/etc, but submit receives rate * s.SampleMultiplier.

    opened by arodland 7
  • Noop Client that would not break if connection failed

    Noop Client that would not break if connection failed

    Thank you for reference statsd client.

    Please, consider merging safe.go from g2s project. It may not look like a big deal, but it makes a difference.

    s, err := g2s.Dial("udp", someEndpoint)
    if err != nil {
        log.Printf("not sending statistics to statsd (%s)", err)
        s = g2s.Noop()
    }
    
    opened by temoto 7
  • incorrect release tags for go modules

    incorrect release tags for go modules

    Similar to #43 but did not want to try to revive a year old closed ticket. I also have some additional information on the problem and what I think is the solution.

    Since go.mod is not at the root of the project, the required tag for the semver would be statsd/v3.2.1, whereas the current release tag is v3.2.1.

    Each module has its own version information. Version tags for modules below the root of the repository must include the relative directory as a prefix. (source)

    Additional Context

    This is the error when trying to use v3 with go modules, which is looking for the missing tag statsd/v3.2.1.

    reading github.com/cactus/go-statsd-client/statsd/statsd/go.mod at revision statsd/v3.2.1: unknown revision statsd/v3.2.1
    
    bug 
    opened by danielhochman 4
  • question to SetInt

    question to SetInt

    hi,

    I have a question to SetInt, lets say I have a for loop and call SetInt multiple times, what value gets displayed in Grafana? my Grafana refreshes a value every 30 sec.

    SetInt("someMetrics", 10, 1.0)
    SetInt("someMetrics", 15, 1.0)
    SetInt("someMetrics", 7, 1.0)
    SetInt("someMetrics", 9, 1.0)
    SetInt("someMetrics", 11, 1.0)
    
    question 
    opened by Arnold1 4
  • Should a stat name with a

    Should a stat name with a ":" error?

    I ran into an issue where I was sending stats to a statname with a host IP/port where I replaced the . in the IP with _ but forgot the port delimiter :, like so: stats.gauges.<service>.production.11_22_33_44:6800

    Because the : is treated as a delimiter in statsd, it was ignoring the gauge value I passed in and logging the statname stats.gauges.<service>.production.11_22_33_44 with the value 6800. Should the statsd client reject a statname with a : (and possibly other delimiters I may not be aware of)?

    enhancement 
    opened by arcoraven 4
Releases(v5.0.0)
  • v5.0.0(Jan 13, 2021)

    • Add Tag support: suffix-octothorpe, infix-comma, infix-semicolon (GH-53)
    • Remove previously deprecated NoopClient. Use a nil *Client Statter as a replacement, if needed. Ex:
      var client Client
      // A nil *Client has noop behavior, so this is safe.
      // It will become a small overhead (just a couple function calls) noop.
      err = client.Inc("stat1", 42, 1.0)
      
    Source code(tar.gz)
    Source code(zip)
  • v5.0.0-alpha.0(Jan 11, 2021)

    • Add Tag support: suffix-octothorpe, infix-comma, infix-semicolon (GH-53)
    • Remove previously deprecated NoopClient. Use a nil *Client Statter as a replacement, if needed. Ex:
      var client Client
      // A nil *Client has noop behavior, so this is safe.
      // It will become a small overhead (just a couple function calls) noop.
      err = client.Inc("stat1", 42, 1.0)
      
    Source code(tar.gz)
    Source code(zip)
  • v4.0.0(Nov 6, 2020)

  • v3.2.1(Jun 23, 2020)

  • v3.2.0(Sep 22, 2019)

    • A new client constructor with "config style" semantics. "legacy" client construction still supported, to retain backwards compat.
    • Add an optional re-resolving client configuration. This sets a schedule for having the client periodically re-resolve the addr to ip. This does add some overhead, so best used only when necessary.
    Source code(tar.gz)
    Source code(zip)
  • v3.1.1(Jan 19, 2018)

  • v3.1.0(May 30, 2016)

    • NewClientWithSender(Sender, string) (Statter, error) method added to enable building a Client from a prefix and an already created Sender.
    • Add stat recording sender in submodule statsdtest (GH-32).
    • Add an example helper stat validation function.
    • Change the way scope joins are done (GH-26).
    • Reorder some structs to avoid middle padding.
    Source code(tar.gz)
    Source code(zip)
  • v3.0.3(Feb 18, 2016)

  • v3.0.2(Jan 13, 2016)

  • v3.0.1(Jan 2, 2016)

  • v3.0.0(Dec 4, 2015)

  • v2.0.2(Oct 16, 2015)

    • remove trailing newline in buffered sends to avoid etsy statsd log messages
    • minor internal code reorganization for clarity (no api changes)
    Source code(tar.gz)
    Source code(zip)
  • v2.0.1(Jul 12, 2015)

    • Add Set and SetInt funcs to support Sets
    • Properly flush BufferedSender on close (bugfix)
    • Add TimingDuration with support for sub-millisecond timing
    • fewer allocations, better performance of BufferedClient
    Source code(tar.gz)
    Source code(zip)
Owner
A place for code
null
Prisma Client Go is an auto-generated and fully type-safe database client

Prisma Client Go Typesafe database access for Go Quickstart • Website • Docs • API reference • Blog • Slack • Twitter Prisma Client Go is an auto-gene

Prisma 1.3k Nov 27, 2022
The Dual-Stack Dynamic DNS client, the world's first dynamic DNS client built for IPv6.

dsddns DsDDNS is the Dual-Stack Dynamic DNS client. A dynamic DNS client keeps your DNS records in sync with the IP addresses associated with your hom

Ryan Young 15 Sep 27, 2022
Go Substrate RPC Client (GSRPC)Go Substrate RPC Client (GSRPC)

Go Substrate RPC Client (GSRPC) Substrate RPC client in Go. It provides APIs and types around Polkadot and any Substrate-based chain RPC calls. This c

Chino Chang 1 Nov 11, 2021
Server and client implementation of the grpc go libraries to perform unary, client streaming, server streaming and full duplex RPCs from gRPC go introduction

Description This is an implementation of a gRPC client and server that provides route guidance from gRPC Basics: Go tutorial. It demonstrates how to u

Joram Wambugu 0 Nov 24, 2021
Godaddy-domains-client-go - Godaddy domains api Client golang - Write automaticly from swagger codegen

Go API client for swagger Overview This API client was generated by the swagger-codegen project. By using the swagger-spec from a remote server, you c

Mickael Stanislas 0 Jan 9, 2022
Tailscale-client-go - A client implementation for the Tailscale HTTP API

tailscale-client-go A client implementation for the Tailscale HTTP API Example p

David Bond 0 Sep 8, 2022
Comunicación de envios de archivos entres cliente-servidor, client-client.

Client - Server - Client Estes es un proyecto simple de comunicacion de envios de archivos del cliente al servidor y viceversamente, y de cliente a cl

Melvin RB 1 Jul 16, 2022
CoAP Client/Server implementing RFC 7252 for the Go Language

Canopus Canopus is a client/server implementation of the Constrained Application Protocol (CoAP) Updates 25.11.2016 I've added basic dTLS Support base

Zubair Hamed 150 Nov 18, 2022
FTP client package for Go

goftp A FTP client package for Go Install go get -u github.com/jlaffaye/ftp Documentation https://pkg.go.dev/github.com/jlaffaye/ftp?tab=doc Example

Julien Laffaye 1k Nov 21, 2022
Go PowerDNS 4.x API Client

PowerDNS 4.x API bindings for Golang This community project provides bindings for the currently latest version of PowerDNS Authoritative Server. Featu

Johannes Eiglsperger 64 Nov 9, 2022
A go implementation of the STUN client (RFC 3489 and RFC 5389)

go-stun go-stun is a STUN (RFC 3489, 5389) client implementation in golang (a.k.a. UDP hole punching). RFC 3489: STUN - Simple Traversal of User Datag

Cong Ding 537 Nov 22, 2022
Simple mDNS client/server library in Golang

mdns Simple mDNS client/server library in Golang. mDNS or Multicast DNS can be used to discover services on the local network without the use of an au

HashiCorp 918 Nov 19, 2022
A LWM2M Client and Server implementation (For Go/Golang)

Betwixt - A LWM2M Client and Server in Go Betwixt is a Lightweight M2M implementation written in Go OMA Lightweight M2M is a protocol from the Open Mo

Zubair Hamed 55 Sep 30, 2022
Go Beanstalkd Client Library

#gobeanstalk Go Beanstalkd client library. INSTALL go get github.com/iwanbk/gobeanstalk USAGE Producer import ( "github.com/iwanbk/gobeanstalk" "lo

Iwan Budi Kusnanto 63 Jun 15, 2022
Golang client for NATS, the cloud native messaging system.

NATS - Go Client A Go client for the NATS messaging system. Installation # Go client go get github.com/nats-io/nats.go/ # Server go get github.com/na

NATS - The Cloud Native Messaging System 4.2k Nov 22, 2022
A STOMP Client package for go developers, supporting all STOMP specification levels.

stompngo - A STOMP 1.0, 1.1 and 1.2 Client Package Features Full support of STOMP protocols: Protocol Level 1.0 Protocol Level 1.1 Protocol Level 1.2

Guy M. Allard 139 Oct 19, 2022
A client software for acme-dns with emphasis on usability and guidance through setup and additional security safeguard mechanisms

acme-dns-client A client software for acme-dns with emphasis on usability and guidance through setup and additional security safeguard mechanisms. It

null 70 Nov 22, 2022
Hummingbard is an experimental client for building decentralized communities on top of Matrix.

Hummingbard is an experimental client for building decentralized communities on top of Matrix.

null 80 Oct 11, 2022