Datadog stats plugin

Hi,

I’m looking for a plugin for Datadog, If not exists, I can develop it. But before, I would like to know if a plugin can read these data from the “core” :

  • [optional] Caddy version
  • Current active connections count
  • Connection status (reading, writing, waiting)

Sincerly

Not yet, but hopefully when Caddy gets an API, this information will become available to plugins more easily. I think a Datadog plugin would be great!

Nice, Knowing the number of active connections is important, it can detect leak on API client or detect an DDOS attack where attacker just open connection but not send any http query.

Ok I will looking how to develop plugin for Caddy.

Do you have any links / refs to start plugin development for Caddy ?

1 Like

I agree, those are important things.

The User Guide has a link to the developer wiki: https://github.com/mholt/caddy/wiki - this is where you can learn how to write plugins. :+1:

1 Like

Hi matt,

I’m facing a strange issue, I can’t add a new directive on the configuration file and the action defined in the plugin is never call.

Note: I’m using GO 1.8

zero ~$ caddy.exe -conf conf.conf
> Register Datadog plugin
2017/05/04 21:11:09 conf.conf:4 - Parse error: Unknown directive 'datadog'

The configuration

:80 {
tls off
datadog {
statsd 127.0.0.1:8125
tags tag1 tag2 tag3
toto 198
}
}

Here my main.go file :

package caddy_datadog

import "fmt"
import "strings"
import "github.com/mholt/caddy"

func init() {
	fmt.Println("> Register Datadog plugin")
	caddy.RegisterPlugin("datadog", caddy.Plugin{
		ServerType: "http",
		Action:     initializeDatadogHQ,
	})
}

type DatadogSettings struct {
	daemonAddress string
	tags          []string
}

//
//  datadog {
//    statsd 127.0.0.1:8125
//    tags tag1 tag2 tag3
//  }
//
func initializeDatadogHQ(controller *caddy.Controller) error {
	fmt.Println("> Initialize Datadog plugin")
	settings := DatadogSettings{
		daemonAddress: "127.0.0.1:8125",
		tags:          []string{},
	}
	for controller.NextBlock() {
		switch controller.Val() {
		case "statsd":
			settings.daemonAddress = controller.Val()
		case "tags":
			settings.tags = strings.Split(controller.Val(), ",")
		default:
			return controller.Errf("datadoghq: unknown key: %s", controller.Val())
		}
	}

	return nil
}

Are you sure you followed all the instructions?

Since it looks like you’re writing a directive, you need to follow these: https://github.com/mholt/caddy/wiki/Writing-a-Plugin:-Directives - there are 4 steps. Did you do all those? Or was anything confusing that we could word better?

Very nice, it seems working.

About the directive, why use a “static” list ? Is not something that the plugin should provide by itself ?

@zero-x-baadf00d

The wiki page explains:

This is important because other directives may set up more primitive configuration that you rely on, so the order that the directives are executed cannot be arbitrary.

You can’t just run your code in an arbitrary order and expect it to work. :confused:

1 Like

Hi @matt

Is it possible to declare a plugin as global ? Usually, if I enable datadog monitoring, it’s for Caddy server not juste for one virtual host. The issue is that the directive “datadog” have to be duplicated on each virtual host just to activate http server handling for this virtualhost.

site-a.local:80 {
tls off

datadog {
statsd 127.0.0.1:8125
tags tag1 tag2 tag3
rate 1
}
}

site-b.local:80 {
tls off

datadog {
statsd 127.0.0.1:8125
tags tag1 tag2 tag3
rate 1
}
}

Thanks

No, a user has to explicitly turn that feature on for every site they want it on for.

Some people use import to share configuration between sites.

If you truly need a “global” plugin, you don’t have to use a directive, but you’ll have to load the configuration some other way. The Caddyfile has no global scope.

Ok matt, Is something that is planned within next releases ? Or it will never have a global namespace ?

I have no plans at this time to change the Caddyfile.

Have you considered trying to leverage the work done for the prometheus plugin? I hate to see a new stats plugin for every new source. What if something central became the authority for collecting stats, and other plugins take care of packaging and exporting to various tsdb backends?

This would allow you to setup datadog export in only a single host, while still instrumenting them all.

Alternately, we could add a central stats interface to caddy itself, so any handler or middleware can add or record stats, and individual plugins take track of “listening” to stat events and storing and relaying them as appropriate.

I’m mostly concerned with the propigation of different plugins to collect the same data in slightly different ways.

1 Like

Hi @captncraig, I have read the source codes of Prometheus, but is not working correctly. When a proxy is used, it will always report a 500 Error and send 1 UDP or TCP packet / query (lot of overhead). And it break the plugin chain by modifying the returned status code.

The datadog plugin is build on top of statsd, it working very well with and without proxy usage and avoid network overhead. In our company, we are using Datadog but I think it can work with all reporting tools backed by statsd. I can, if needed, rename plugin to “statsd” rather thant “datadog”.

Sincerly