-
Notifications
You must be signed in to change notification settings - Fork 0
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
Switch back to kingpin for arg parsing #2
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,76 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"os" | ||
"os/signal" | ||
"strconv" | ||
"time" | ||
|
||
// "os" | ||
// "os/signal" | ||
"strings" | ||
"sync" | ||
|
||
// "time" | ||
"github.com/pkg/errors" | ||
|
||
"github.com/Shopify/sarama" | ||
"github.com/quipo/statsd" | ||
"github.com/alecthomas/kingpin" | ||
"github.com/pkg/errors" | ||
"github.com/segmentio/go-log" | ||
// "github.com/wvanbergen/kazoo-go" | ||
"gopkg.in/alexcesaro/statsd.v2" | ||
) | ||
|
||
var ( | ||
brokers = flag.String("brokers", "127.0.0.1:12008", "Kafka addresses (e.g. host1:9092,host2:9092)") | ||
statsdAddr = flag.String("statsd-addr", "127.0.0.1:8125", "Statsd address") | ||
statsdPrefix = flag.String("statsd-prefix", "kafka.", "Statsd prefix") | ||
interval = flag.Int("refresh-interval", 5, "Interval to refresh offset lag in seconds") | ||
useTags = flag.Bool("use-tags", true, "Use tags if your StatsD client supports them (like DataDog and InfluxDB)") | ||
brokers = kingpin.Flag("broker", "A kafka broker to connect to. Specify multiple times for multiple brokers. (e.g. host1:9092)").HintOptions("host1:9092").Short('b').Envar("KSTATSD_BROKERS").Required().Strings() | ||
statsdAddr = kingpin.Flag("statsd-addr", "Statsd address").Short('s').Default("127.0.0.1").Envar("KSTATSD_STATSD_ADDR").String() | ||
statsdPort = kingpin.Flag("statsd-port", "Statsd port").Short('P').Default("8125").Envar("KSTATSD_STATSD_PORT").String() | ||
statsdPrefix = kingpin.Flag("statsd-prefix", "Statsd prefix").Short('p').Envar("KSTATSD_STATSD_PREFIX").String() | ||
interval = kingpin.Flag("refresh-interval", "Interval to refresh offset lag in seconds").Short('i').Default("5").Envar("KSTATSD_INTERVAL").Int() | ||
tagType = kingpin.Flag("tag-format", "Format to use when encoding tags (Options: none, influxdb, datadog)").HintOptions(statsdTagOptionsEnum()...).Default("none").Envar("KSTATSD_USE_TAGS").Enum(statsdTagOptionsEnum()...) | ||
includeTags = kingpin.Flag("tag", "Tags to include. Specify multiple times for multiple tags. (e.g. tagname:value)").HintOptions("tagname:value").Envar("KSTATSD_TAGS").Strings() | ||
) | ||
|
||
var statsdTagFormat = map[string]statsd.TagFormat{ | ||
"influxdb": statsd.InfluxDB, | ||
"datadog": statsd.Datadog, | ||
"none": 0, | ||
} | ||
|
||
func statsdTagOptionsEnum() []string { | ||
res := make([]string, 0, len(statsdTagFormat)) | ||
for k := range statsdTagFormat { | ||
res = append(res, k) | ||
} | ||
return res | ||
} | ||
|
||
func newStatsdClient() (*statsd.Client, error) { | ||
tags := make([]string, 0, len(*includeTags)*2) | ||
for _, tag := range *includeTags { | ||
splitTag := strings.SplitN(tag, ":", 2) | ||
tags = append(tags, splitTag...) | ||
} | ||
|
||
opts := []statsd.Option{ | ||
statsd.Address(strings.Join([]string{*statsdAddr, *statsdPort}, ":")), | ||
statsd.ErrorHandler(func(err error) { | ||
log.Error("Statsd error: %s", err) | ||
}), | ||
} | ||
|
||
if *statsdPrefix != "" { | ||
opts = append(opts, statsd.Prefix(*statsdPrefix)) | ||
} | ||
|
||
if len(tags) > 0 { | ||
opts = append(opts, statsd.Tags(tags...)) | ||
} | ||
|
||
tagFormat := statsdTagFormat[*tagType] | ||
if tagFormat != 0 { | ||
opts = append(opts, statsd.TagsFormat(tagFormat)) | ||
} | ||
|
||
return statsd.New(opts...) | ||
} | ||
|
||
type ClusterState struct { | ||
// List of consumer groups that exist in the cluster | ||
ConsumerGroups []string | ||
|
@@ -38,20 +80,16 @@ type ClusterState struct { | |
} | ||
|
||
func main() { | ||
flag.Parse() | ||
kingpin.Parse() | ||
|
||
statsdClient := statsd.NewStatsdClient(*statsdAddr, *statsdPrefix) | ||
err := statsdClient.CreateSocket() | ||
statsdClient, err := newStatsdClient() | ||
if err != nil { | ||
log.Error("Error creating statsd client: %s", err) | ||
return | ||
} | ||
stats := statsd.NewStatsdBuffer(time.Second, statsdClient) | ||
defer stats.Close() | ||
defer statsdClient.Close() | ||
|
||
brokerList := strings.Split(*brokers, ",") | ||
|
||
client, err := sarama.NewClient(brokerList, nil) | ||
client, err := sarama.NewClient(*brokers, nil) | ||
if err != nil { | ||
log.Error("Error connecting to Kafka (client): %s", err) | ||
return | ||
|
@@ -60,7 +98,7 @@ func main() { | |
|
||
config := sarama.NewConfig() | ||
config.Version = sarama.V2_0_0_0 | ||
admin, err := sarama.NewClusterAdmin(brokerList, config) | ||
admin, err := sarama.NewClusterAdmin(*brokers, config) | ||
if err != nil { | ||
log.Error("Error connecting to Kafka (admin): %s", err) | ||
return | ||
|
@@ -114,12 +152,14 @@ func main() { | |
|
||
lag := offset - partitionOffsets[partitionID] | ||
|
||
if *useTags { | ||
var tags []string | ||
tags = append(tags, "topic="+topic) | ||
tags = append(tags, fmt.Sprintf("partition=%d", partitionID)) | ||
tags = append(tags, "consumer_group="+cg) | ||
stats.Gauge(fmt.Sprintf("consumer_lag,%s", strings.Join(tags, ",")), lag) | ||
stats := statsdClient.Clone( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does Go garbage collect automatically? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, go is a garbage collected language. The cloned client also doesn't need to be |
||
statsd.Tags("topic", topic), | ||
statsd.Tags("partition", strconv.FormatInt(int64(partitionID), 10)), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any risk of this throwing? Say There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
statsd.Tags("consumer_group", cg), | ||
) | ||
|
||
if *tagType != "none" { | ||
stats.Gauge("consumer_lag", lag) | ||
} else { | ||
stats.Gauge(fmt.Sprintf("topic.%s.partition.%d.consumer_group.%s.lag", topic, partitionID, cg), lag) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be
statsd.New(), nil
or does statsd.New return an(instance, error)
itself?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
statsd.New
returns(instance, error)