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

Add a graphite listener. #23

Merged
merged 3 commits into from Oct 23, 2012
Merged

Add a graphite listener. #23

merged 3 commits into from Oct 23, 2012

Conversation

pyr
Copy link
Contributor

@pyr pyr commented Oct 19, 2012

This will obviously be less efficient than the protobuf tcp-server
or udp-server. But it will allow easy set up with other tools
in the monitoring chain - collectd, statsd for instance -
with very little configuration.

In the configuration, a graphite server is simply started by
issuing (graphite-server). The server will yield events with
only service, metric and timestamp filled. NaN values will be
discarded.

Should you want to do additional handling on the values you
can feed graphite-server a parser-fn yielding a map to
merge onto the event. For instance if you emit data
from collectd using the write_graphite output with the following
configuration:

<LoadPlugin write_graphite>
<Plugin write_graphite>
<Carbon>
        Prefix "collectd."
    Host "localhost"
    Port 2003
</Carbon>
</Plugin>

You can use the following to have a nicer event, containing hostname
and tags:

(graphite-server
 :parser-fn (fn [{:keys [service] :as event}]
              (if-let [[src host service & tags]
                       (clojure.string/split service #"\.")]
                {:host (clojure.string/replace host #"_" ".")
                 :service (clojure.string/join "." (concat [service] tags))
                 :tags (concat tags [src])})))

This will obviously be less efficient than the protobuf tcp-server
or udp-server. But it will allow easy set up with other tools
in the monitoring chain - collectd, statsd for instance -
with very little configuration.

In the configuration, a graphite server is simply started by
issuing `(graphite-server)`. The server will yield events with
only service, metric and timestamp filled. NaN values will be
discarded.

Should you want to do additional handling on the values you
can feed graphite-server a parser-fn yielding a map to
merge onto the event. For instance if you emit data
from collectd using the write_graphite output with the following
configuration:

```
<LoadPlugin write_graphite>
<Plugin write_graphite>
<Carbon>
        Prefix "collectd."
	Host "localhost"
	Port 2003
</Carbon>
</Plugin>
```

You can use the following to have a nicer event, containing hostname
and tags:

```clojure
(graphite-server
 :parser-fn (fn [{:keys [service] :as event}]
              (if-let [[src host service & tags]
                       (clojure.string/split service #"\.")]
                {:host (clojure.string/replace host #"_" ".")
                 :service (clojure.string/join "." (concat [service] tags))
                 :tags (concat tags [src])})))
```
@b20n
Copy link
Contributor

b20n commented Oct 19, 2012

The cleaner way to do this would be to pass your "graphite-frame-decoder" as the message decoder for a standard tcp-server. That's why the :message-decoder option was created. Then you'd start up your graphite listener in your config with something like this:

(tcp-server :message-decoder graphite-frame-decoder :port 2003 :host "127.0.0.1")

You'd also be able to open up a UDP Graphite listener by passing those args to udp-server instead.

AFAICT your graphite-handler and graphite-cpf are not significantly different from their tcp- counterparts.

@pyr
Copy link
Contributor Author

pyr commented Oct 19, 2012

Agreed hence the comment in the code. The problem with tcp-server is that the pipeline is hardcoded. If you guys are all aboard I could go with a diff that implements pluggable pipelines, but I'd rather start with this and move on with the refactoring later on.

@b20n
Copy link
Contributor

b20n commented Oct 19, 2012

Ah, sorry, I missed the intent of that comment. You need the framer and the handler/decoder to be parameterized. I'd be +1 on doing the refactoring now (no one's waiting on this work, right?) but that's @aphyr's bag, not mine.

It seems that it would be appropriate to supply a line-oriented framer for protocols like this, but I'm -1 on actually including in the project the semantics of translating a Graphite metric into a Riemann event. There are a lot of protocols out there. It's easy to include them in your config, and would be even easier if there were easier ways to manage config files. :)

@pyr
Copy link
Contributor Author

pyr commented Oct 19, 2012

Graphite seems to be an already well integrated solution with riemann since output functions are already there, which is why I thought a listener had some chance of getting in.

@b20n
Copy link
Contributor

b20n commented Oct 19, 2012

Graphite seems to be an already well integrated solution with riemann since output functions are already there, which is why I thought a listener had some chance of getting in.

Totally good point. /defers

@aphyr
Copy link
Collaborator

aphyr commented Oct 22, 2012

I like this, but could you do me a favor and drop all the graphite-specific functions in riemann.graphite? I think I'd like to keep external integration in their own namespaces for now.

@pyr
Copy link
Contributor Author

pyr commented Oct 23, 2012

This should be better

aphyr added a commit that referenced this pull request Oct 23, 2012
@aphyr aphyr merged commit 2773abb into riemann:master Oct 23, 2012
@aphyr
Copy link
Collaborator

aphyr commented Oct 23, 2012

Great work, thank you!

@obfuscurity
Copy link

🍰 and 🍦

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants