// Cadence - An extensible Statsd client for Rust!
//
// Copyright 2015-2016 TSH Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


//! An extensible Statsd client for Rust!
//!
//! [Statsd](https://github.com/etsy/statsd) is a network server that listens for
//! metrics (things like counters and timers) sent over UDP and sends aggregates of
//! these metrics to a backend service of some kind (often
//! [Graphite](http://graphite.readthedocs.org/)).
//!
//! Cadence is a client written in Rust for interacting with a Statsd server. You
//! might want to emit metrics (using Cadence, sending them to a Statsd server) in
//! your Rust server application.
//!
//! For example, if you are running a Rust web service you might want to record:
//!
//! * Number of succesful requests
//! * Number of error requests
//! * Time taken for each request
//!
//! Cadence is a flexible and easy way to do this!
//!
//! ## Features
//!
//! * Support for emitting counters, timers, gauges, and meters to Statsd over UDP.
//! * Support for alternate backends via the `MetricSink` trait.
//! * A simple yet flexible API for sending metrics.
//!
//! ## Install
//!
//! To make use of Cadence in your project, add it as a dependency in your `Cargo.toml`
//! file.
//!
//! ``` toml
//! [dependencies]
//! cadence = "x.y.z"
//! ```
//!
//! Then, link to it in your library or application.
//!
//! ``` rust,no_run
//! // bin.rs or lib.rs
//! extern crate cadence;
//!
//! // rest of your library or application
//! ```
//!
//! ## Usage
//!
//! Some examples of how to use Cadence are shown below.
//!
//! ### Simple Use
//!
//! Simple usage of Cadence is shown below. In this example, we just import the client,
//! create an instance that will write to some imaginary metrics server, and send a few
//! metrics.
//!
//! ``` rust,no_run
//! // Import the client.
//! use cadence::prelude::*;
//! use cadence::{StatsdClient, UdpMetricSink, DEFAULT_PORT};
//!
//! fn main() {
//!     // Create client that will write to the given host over UDP.
//!     //
//!     // Note that you'll probably want to actually handle any errors creating the client
//!     // when you use it for real in your application. We're just using .unwrap() here
//!     // since this is an example!
//!     let host = ("metrics.example.com", DEFAULT_PORT);
//!     let client = StatsdClient::<UdpMetricSink>::from_udp_host(
//!         "my.metrics", host).unwrap();
//!
//!     // Emit metrics!
//!     client.incr("some.counter");
//!     client.time("some.methodCall", 42);
//!     client.gauge("some.thing", 7);
//!     client.meter("some.value", 5);
//! }
//! ```
//!
//! ### Counted, Timed, Gauged, and Metered Traits
//!
//! Each of the methods that the Cadence `StatsdClient` struct uses to send metrics are
//! implemented as a trait. If we want, we can just use the trait type to refer to the
//! client instance. This might be useful to you if you'd like to swap out the actual
//! Cadence client with a dummy version when you are unit testing your code.
//!
//! Each of these traits are exported in the prelude module. They are also available
//! in the main module but aren't typically used like that.
//!
//! ``` rust,no_run
//! use cadence::prelude::*;
//! use cadence::{StatsdClient, UdpMetricSink, DEFAULT_PORT};
//!
//!
//! pub struct User {
//!     id: u64,
//!     username: String,
//!     email: String
//! }
//!
//!
//! // Here's a simple DAO (Data Access Object) that doesn't do anything but
//! // uses a counter to keep track of the number of times the 'getUserById'
//! // method gets called.
//! pub struct MyUserDao<T: Counted> {
//!     counter: T
//! }
//!
//!
//! impl<T: Counted> MyUserDao<T> {
//!     // Create a new instance that will use the counter / client
//!     pub fn new(counter: T) -> MyUserDao<T> {
//!         MyUserDao{counter: counter}
//!     }
//!
//!     /// Get a new user by their ID
//!     pub fn get_user_by_id(&self, id: u64) -> Option<User> {
//!         self.counter.incr("getUserById");
//!         None
//!     }
//! }
//!
//!
//! fn main() {
//!     // Create a new Statsd client that writes to "metrics.example.com"
//!     let host = ("metrics.example.com", DEFAULT_PORT);
//!     let counter = StatsdClient::<UdpMetricSink>::from_udp_host(
//!         "counter.example", host).unwrap();
//!
//!     // Create a new instance of the DAO that will use the client
//!     let dao = MyUserDao::new(counter);
//!
//!     // Try to lookup a user by ID!
//!     match dao.get_user_by_id(123) {
//!         Some(u) => println!("Found a user!"),
//!         None => println!("No user!")
//!     };
//! }
//! ```
//!
//! ### Custom Metric Sinks
//!
//! The Cadence `StatsdClient` uses implementations of the `MetricSink` trait to
//! send metrics to a metric server. Most users of the Candence library probably
//! want to use the `UdpMetricSink` implementation. This is the way people typically
//! interact with a Statsd server, sending packets over UDP.
//!
//! However, maybe you'd like to do something custom: use a thread pool, send multiple
//! metrics at the same time, or something else. An example of creating a custom sink
//! is below.
//!
//! ``` rust,no_run
//! use std::io;
//! use cadence::prelude::*;
//! use cadence::{StatsdClient, MetricSink, DEFAULT_PORT};
//!
//! pub struct MyMetricSink;
//!
//!
//! impl MetricSink for MyMetricSink {
//!     fn emit(&self, metric: &str) -> io::Result<usize> {
//!         // Your custom metric sink implementation goes here!
//!         Ok(0)
//!     }
//! }
//!
//!
//! fn main() {
//!     let sink = MyMetricSink;
//!     let client = StatsdClient::from_sink("my.prefix", sink);
//!
//!     client.count("my.counter.thing", 42);
//!     client.time("my.method.time", 25);
//!     client.incr("some.other.counter");
//! }
//! ```
//!


#[macro_use]
extern crate log;


pub const DEFAULT_PORT: u16 = 8125;


pub use self::client::{Counted, Timed, Gauged, Metered, StatsdClient};


pub use self::sinks::{MetricSink, ConsoleMetricSink, LoggingMetricSink, NopMetricSink,
                      UdpMetricSink};


pub use self::types::{MetricResult, MetricError, ErrorKind, Counter, Timer, Gauge, Meter};


pub mod prelude;
mod client;
mod sinks;
mod types;
