Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

statsd support #76

Merged
merged 4 commits into from
Oct 26, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions nsqadmin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@ Command Line Options
--------------------

Usage of ./nsqadmin:
-graphite-url="": URL to graphite HTTP address
-http-address="0.0.0.0:4171": <addr>:<port> to listen on for HTTP clients
-lookupd-http-address=[]: lookupd HTTP address (may be given multiple times)
-nsqd-http-address=[]: nsqd HTTP address (may be given multiple times)
-template-dir="templates": path to templates directory
-use-statsd-prefixes=true: expect statsd prefixed keys in graphite (ie: 'stats_counts.')
-version=false: print version string

### Statsd / Graphite Integration

When using `nsqd --statsd-address=...` you can specify a `nsqadmin --graphite-url=http://graphite.yourdomain.com`
to enable graphite charts in nsqadmin. If using a statsd clone (like [gographite](https://github.com/bitly/gographite))
that does not prefix keys, also specify `--use-statsd-prefix=false`.
85 changes: 52 additions & 33 deletions nsqadmin/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,17 @@ func commafy(i interface{}) string {
return fmt.Sprintf("%d", n)
}

// formats a host + port for use in a graphite host key
func graphiteHostKey(h string) string {
s := strings.Replace(h, ".", "_", -1)
return strings.Replace(s, ":", "_", -1)
}

func loadTemplates() {
var err error
t := template.New("nsqadmin").Funcs(template.FuncMap{
"commafy": commafy,
"commafy": commafy,
"graphiteHostKey": graphiteHostKey,
})
templates, err = t.ParseGlob(fmt.Sprintf("%s/*.html", *templateDir))
if err != nil {
Expand Down Expand Up @@ -88,13 +95,17 @@ func indexHandler(w http.ResponseWriter, req *http.Request) {
topics, _ = getNSQDTopics(nsqdHTTPAddrs)
}
p := struct {
Title string
Topics []string
Version string
Title string
GraphiteUrl string
GraphiteKeyPrefix string
Topics []string
Version string
}{
Title: "NSQ",
Topics: topics,
Version: util.BINARY_VERSION,
Title: "NSQ",
GraphiteUrl: *graphiteUrl,
GraphiteKeyPrefix: graphiteKeyPrefix,
Topics: topics,
Version: util.BINARY_VERSION,
}
err := templates.ExecuteTemplate(w, "index.html", p)
if err != nil {
Expand Down Expand Up @@ -131,21 +142,25 @@ func topicHandler(w http.ResponseWriter, req *http.Request) {
}

p := struct {
Title string
Version string
Topic string
TopicProducers []string
TopicHostStats []*TopicHostStats
GlobalTopicStats *TopicHostStats
ChannelStats map[string]*ChannelStats
Title string
GraphiteUrl string
GraphiteKeyPrefix string
Version string
Topic string
TopicProducers []string
TopicHostStats []*TopicHostStats
GlobalTopicStats *TopicHostStats
ChannelStats map[string]*ChannelStats
}{
Title: fmt.Sprintf("NSQ %s", topic),
Version: util.BINARY_VERSION,
Topic: topic,
TopicProducers: producers,
TopicHostStats: topicHostStats,
GlobalTopicStats: globalTopicStats,
ChannelStats: channelStats,
Title: fmt.Sprintf("NSQ %s", topic),
GraphiteUrl: *graphiteUrl,
GraphiteKeyPrefix: graphiteKeyPrefix,
Version: util.BINARY_VERSION,
Topic: topic,
TopicProducers: producers,
TopicHostStats: topicHostStats,
GlobalTopicStats: globalTopicStats,
ChannelStats: channelStats,
}
err := templates.ExecuteTemplate(w, "topic.html", p)
if err != nil {
Expand All @@ -165,19 +180,23 @@ func channelHandler(w http.ResponseWriter, req *http.Request, topic string, chan
channelStats := allChannelStats[channel]

p := struct {
Title string
Version string
Topic string
Channel string
TopicProducers []string
ChannelStats *ChannelStats
Title string
GraphiteUrl string
GraphiteKeyPrefix string
Version string
Topic string
Channel string
TopicProducers []string
ChannelStats *ChannelStats
}{
Title: fmt.Sprintf("NSQ %s / %s", topic, channel),
Version: util.BINARY_VERSION,
Topic: topic,
Channel: channel,
TopicProducers: producers,
ChannelStats: channelStats,
Title: fmt.Sprintf("NSQ %s / %s", topic, channel),
GraphiteUrl: *graphiteUrl,
GraphiteKeyPrefix: graphiteKeyPrefix,
Version: util.BINARY_VERSION,
Topic: topic,
Channel: channel,
TopicProducers: producers,
ChannelStats: channelStats,
}

err := templates.ExecuteTemplate(w, "channel.html", p)
Expand Down
18 changes: 13 additions & 5 deletions nsqadmin/nsqadmin.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,22 @@ import (
)

var (
showVersion = flag.Bool("version", false, "print version string")
httpAddress = flag.String("http-address", "0.0.0.0:4171", "<addr>:<port> to listen on for HTTP clients")
templateDir = flag.String("template-dir", "", "path to templates directory")
lookupdHTTPAddrs = util.StringArray{}
nsqdHTTPAddrs = util.StringArray{}
showVersion = flag.Bool("version", false, "print version string")
httpAddress = flag.String("http-address", "0.0.0.0:4171", "<addr>:<port> to listen on for HTTP clients")
templateDir = flag.String("template-dir", "", "path to templates directory")
graphiteUrl = flag.String("graphite-url", "", "URL to graphite HTTP address")
useStatsdPrefixes = flag.Bool("use-statsd-prefixes", true, "expect statsd prefixed keys in graphite (ie: 'stats_counts.')")
lookupdHTTPAddrs = util.StringArray{}
nsqdHTTPAddrs = util.StringArray{}
)

func init() {
flag.Var(&lookupdHTTPAddrs, "lookupd-http-address", "lookupd HTTP address (may be given multiple times)")
flag.Var(&nsqdHTTPAddrs, "nsqd-http-address", "nsqd HTTP address (may be given multiple times)")
}

var graphiteKeyPrefix string

func main() {
var waitGroup util.WaitGroupWrapper

Expand Down Expand Up @@ -53,6 +57,10 @@ func main() {
log.Fatalf("use --nsqd-http-address or --lookupd-http-address not both")
}

if *useStatsdPrefixes {
graphiteKeyPrefix = "stats_counts."
}

exitChan := make(chan int)
signalChan := make(chan os.Signal, 1)

Expand Down
33 changes: 32 additions & 1 deletion nsqadmin/templates/channel.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@

{{template "header.html" .}}
{{$g := .GraphiteUrl}}
{{$gp := .GraphiteKeyPrefix}}
{{$topic := .Topic}}
{{$channel := .Channel}}

<ul class="breadcrumb">
<li><a href="/">Streams</a> <span class="divider">/</span></li>
Expand Down Expand Up @@ -71,6 +74,20 @@ <h3>Channel Message Queue</h3>
<td>{{$c.MessageCount | commafy}}</td>
<td>{{$c.ClientCount}}</td>
</tr>
{{if $g}}
<tr>
<td></td>
<td><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target={{$gp}}nsq.{{$c.HostAddress | graphiteHostKey}}.topic.{{$topic}}.channel.{{$channel}}.depth"></td>
<td></td>
<td><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target={{$gp}}nsq.{{$c.HostAddress | graphiteHostKey}}.topic.{{$topic}}.channel.{{$channel}}.in_flight_count"></td>
<td><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target={{$gp}}nsq.{{$c.HostAddress | graphiteHostKey}}.topic.{{$topic}}.channel.{{$channel}}.deferred_count"></td>
<td><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target={{$gp}}nsq.{{$c.HostAddress | graphiteHostKey}}.topic.{{$topic}}.channel.{{$channel}}.requeue_count"></td>
<td><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target={{$gp}}nsq.{{$c.HostAddress | graphiteHostKey}}.topic.{{$topic}}.channel.{{$channel}}.timeout_count"></td>
<td><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target={{$gp}}nsq.{{$c.HostAddress | graphiteHostKey}}.topic.{{$topic}}.channel.{{$channel}}.message_count"></td>
<td><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target={{$gp}}nsq.{{$c.HostAddress | graphiteHostKey}}.topic.{{$topic}}.channel.{{$channel}}.clients"></td>
</tr>
{{end}}

{{ end }}
{{ with $c := .ChannelStats }}
<tr class="info">
Expand All @@ -84,6 +101,20 @@ <h3>Channel Message Queue</h3>
<td>{{$c.MessageCount | commafy}}</td>
<td>{{$c.ClientCount}}</td>
</tr>
{{if $g}}
<tr class="info">
<td></td>
<td><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target=sumSeries({{$gp}}nsq.*.topic.{{$topic}}.channel.{{$channel}}.depth)"></td>
<td></td>
<td><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target=sumSeries({{$gp}}nsq.*.topic.{{$topic}}.channel.{{$channel}}.in_flight_count)"></td>
<td><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target=sumSeries({{$gp}}nsq.*.topic.{{$topic}}.channel.{{$channel}}.deferred_count)"></td>
<td><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target=sumSeries({{$gp}}nsq.*.topic.{{$topic}}.channel.{{$channel}}.requeue_count)"></td>
<td><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target=sumSeries({{$gp}}nsq.*.topic.{{$topic}}.channel.{{$channel}}.timeout_count)"></td>
<td><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target=sumSeries({{$gp}}nsq.*.topic.{{$topic}}.channel.{{$channel}}.message_count)"></td>
<td><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target=sumSeries({{$gp}}nsq.*.topic.{{$topic}}.channel.{{$channel}}.clients)"></td>
</tr>
{{end}}

{{ end }}
</table>
</div></div>
Expand Down
13 changes: 9 additions & 4 deletions nsqadmin/templates/index.html
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
{{template "header.html" .}}
{{$g := .GraphiteUrl}}
{{$gp := .GraphiteKeyPrefix}}

<div class="row-fluid"><div class="span12">
<h1>Topics</h1>
</div></div>


<div class="row-fluid"><div class="span12">
<div class="row-fluid"><div class="span3">
{{if .Topics}}
<ul>
<table class="table table-condensed table-bordered">
{{range .Topics}}
<li><a href="/topic/{{.}}">{{.}}</a></li>
<tr>
{{if $g}}<td><a href="/topic/{{.}}"><img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=white&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target=sumSeries({{$gp}}nsq.*.topic.{{.}}.message_count)"></a></td>{{end}}
<td><a href="/topic/{{.}}">{{.}}</a></td>
</tr>
{{end}}
</ul>
</table>
{{else}}
<p><span class="label label-warning">Warning</span> No Topics Found</p>
{{ end }}
Expand Down
31 changes: 24 additions & 7 deletions nsqadmin/templates/topic.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@

{{template "header.html" .}}
{{$g := .GraphiteUrl}}
{{$gp := .GraphiteKeyPrefix}}
{{$topic := .Topic}}

<ul class="breadcrumb">
<li><a href="/">Streams</a> <span class="divider">/</span></li>
Expand Down Expand Up @@ -30,18 +32,29 @@ <h3>Topic Message Queue</h3>
{{range .TopicHostStats }}
<tr>
<td>{{.HostAddress}}</td>
<td>{{.Depth | commafy}}</td>
<td>
{{if $g}}<img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target={{$gp}}nsq.{{.HostAddress | graphiteHostKey}}.topic.{{$topic}}.depth">{{end}}
{{.Depth | commafy}}</td>
<td>{{.MemoryDepth | commafy}} + {{.BackendDepth | commafy}}</td>
<td>{{.MessageCount | commafy}}</td>
<td>
{{if $g}}<img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target={{$gp}}nsq.{{.HostAddress | graphiteHostKey}}.topic.{{$topic}}.message_count">{{end}}
{{.MessageCount | commafy}}
</td>
<td>{{.ChannelCount}}</td>
</tr>
{{ end }}
{{ with .GlobalTopicStats }}
<tr class="info">
<td>Total:</td>
<td>{{.Depth | commafy}}</td>
<td>
{{if $g}}<img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target=sumSeries({{$gp}}nsq.*.topic.{{$topic}}.depth)">{{end}}
{{.Depth | commafy}}
</td>
<td>{{.MemoryDepth | commafy}} + {{.BackendDepth | commafy}}</td>
<td>{{.MessageCount | commafy}}</td>
<td>
{{if $g}}<img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target=sumSeries({{$gp}}nsq.*.topic.{{$topic}}.message_count)">{{end}}
{{.MessageCount | commafy}}
</td>
<td>{{.ChannelCount}}</td>
</tr>
{{ end }}
Expand Down Expand Up @@ -72,14 +85,18 @@ <h3>Channel Message Queues</h3>
<th><a href="/topic/{{$c.Topic}}/{{$c.ChannelName | urlquery}}">{{$c.ChannelName}}</a>
{{if $c.Paused}}<span class="label label-important">paused</span>{{end}}
</th>
<td>{{$c.Depth | commafy}}</td>
<td>
{{if $g}}<img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target=sumSeries({{$gp}}nsq.*.topic.{{$topic}}.channel.{{$c.ChannelName}}.depth)">{{end}}
{{$c.Depth | commafy}}</td>
<td>{{$c.MemoryDepth | commafy}} + {{$c.BackendDepth | commafy}}</td>
<td>{{$c.InFlightCount | commafy}}</td>
<td>{{$c.DeferredCount | commafy}}</td>
<td>{{$c.RequeueCount | commafy}}</td>
<td>{{$c.TimeoutCount | commafy}}</td>
<td>{{$c.MessageCount | commafy}}</td>
<td>{{$c.ClientCount}}</td>
<td>
{{if $g}}<img src="{{$g}}/render?from=-120min&height=20&until=-1min&width=120&hideGrid=true&hideLegend=true&hideAxes=true&bgcolor=ff000000&fgcolor=black&margin=0&colorList=blue&drawNullAsZero=true&target=sumSeries({{$gp}}nsq.*.topic.{{$topic}}.channel.{{$c.ChannelName}}.clients)">{{end}}
{{$c.ClientCount}}</td>
</tr>
{{ end }}
</table>
Expand Down
27 changes: 27 additions & 0 deletions nsqd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,34 @@ It listens on two TCP ports, one for clients and another for the HTTP API.
-mem-queue-size=10000: number of messages to keep in memory (per topic)
-msg-timeout=60000: time (ms) to wait before auto-requeing a message
-sync-every=2500: number of messages between diskqueue syncs
-statsd-address="": UDP <addr>:<port> of a statsd daemon for writing stats
-statsd-interval=30: seconds between pushing to statsd
-tcp-address="0.0.0.0:4150": <addr>:<port> to listen on for TCP clients
-verbose=false: enable verbose logging
-version=false: print version string
-worker-id=0: unique identifier (int) for this worker (will default to a hash of hostname)

### Statsd / Graphite Integration

When using `--statsd-address` specify the UDP `<addr>:<port>` for [statsd](https://github.com/etsy/statsd) (or a port
of statsd like [gographite](https://github.com/bitly/gographite)), nsqd will push metrics to statsd periodically based
on the interval specified in `--statsd-interval`. With this enabled nsqadmin can be configured to display charts
directly from graphite.

We recommend the following configuration for graphite `storage-schemas.conf`

```
[nsq]
pattern = ^nsq\..*
retentions = 1m:1d,5m:30d,15m:1y
````

And the following for `storage-aggregation.conf`

```
[default_nsq]
pattern = ^nsq\..*
xFilesFactor = 0.2
aggregationMethod = average
```

20 changes: 10 additions & 10 deletions nsqd/client_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,16 @@ func (c *ClientV2) String() string {

func (c *ClientV2) Stats() ClientStats {
return ClientStats{
version: "V2",
address: c.RemoteAddr().String(),
name: c.ShortIdentifier,
state: atomic.LoadInt32(&c.State),
readyCount: atomic.LoadInt64(&c.ReadyCount),
inFlightCount: atomic.LoadInt64(&c.InFlightCount),
messageCount: atomic.LoadUint64(&c.MessageCount),
finishCount: atomic.LoadUint64(&c.FinishCount),
requeueCount: atomic.LoadUint64(&c.RequeueCount),
connectTime: c.ConnectTime,
Version: "V2",
RemoteAddress: c.RemoteAddr().String(),
Name: c.ShortIdentifier,
State: atomic.LoadInt32(&c.State),
ReadyCount: atomic.LoadInt64(&c.ReadyCount),
InFlightCount: atomic.LoadInt64(&c.InFlightCount),
MessageCount: atomic.LoadUint64(&c.MessageCount),
FinishCount: atomic.LoadUint64(&c.FinishCount),
RequeueCount: atomic.LoadUint64(&c.RequeueCount),
ConnectTime: c.ConnectTime.Unix(),
}
}

Expand Down
Loading