libeko 0.1.5

Create a command line interface binary with some common dependencies ((clap || docopt) and error_chain)
Documentation
//! `Echo Event Format` Data Structures
use serde::{Serialize, Serializer};
use std::collections::HashMap;
use std::hash::Hash;
use uuid::Uuid;

/// The `type` field that describes the message.
pub enum Type {
    /// Any message that should be associated with a non-normal action or situation that the system processed.
    Error,
    /// Any message that should be associated with a normal action or situation that the system processed.
    Info,
    /// Any message that associates speed or time taken with which any action or situation that the system processed.
    Performance,
    /// Any message that tries to correlate two (or more) events or data points that is not associated.
    Tracking,
    /// Internally used for client machine performance data (CPU utilization, JVM heap usage, ect)
    System,
}

impl Default for Type {
    fn default() -> Self {
        Type::Info
    }
}

impl Serialize for Type {
    fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let type_str = match *self {
            Type::Error => "ERROR",
            Type::Info => "INFO",
            Type::Performance => "PERFORMANCE",
            Type::Tracking => "TRACKING",
            Type::System => "SYSTEM",
        };
        serializer.serialize_str(type_str)
    }
}

#[derive(Default, Serialize, Setters)]
#[serde(rename_all = "camelCase")]
/// The Echo Event Format items.
pub struct Message {
    /// The `routing_key` is what identifies the message with an application.
    /// It will become the ElasticSearch index. Valid characters are lowercase alpha numeric and '-'.
    /// The key should follow the format <application group>-<application name>-<environment>.
    routing_key: String,
    /// The message type.
    /// Additional types may be added in the future.
    #[set = "pub"]
    #[serde(rename = "type")]
    level: Type,
    /// A simple string message.  Most messages should be one line of information.
    /// If you have secondary, deeper information to store, put it in the `message_detail`.
    message: String,
    /// Hostname where the message originated.
    #[serde(skip_serializing_if = "Option::is_none")]
    host: Option<String>,
    /// A place to store custom key/value pairs in the message, typically used when there isn't an appropriate root-level field.
    #[serde(skip_serializing_if = "Option::is_none")]
    message_detail: Option<HashMap<String, String>>,
    /// The timestamp of the event.
    ///
    /// If producing your own messages, the format of the date should be either of:
    ///
    /// * An ISO-8601 date/time string (e.g. 2018-04-06T17:23:00-04:00)
    /// * A number representing *milliseconds* since epoch (e.g. 1491514054000).  Note many timestamps are *seconds* since
    /// the epoch.   That is incorrect for this usage.
    #[set = "pub"]
    timestamp: i64,
    /// The UUID that should be used to correlate message that are part of the same request or processing event.
    /// This can be used to correlate events across applications.
    #[set = "pub"]
    #[serde(skip_serializing_if = "Option::is_none")]
    correlation_id: Option<Uuid>,
    /// Sets the version of the application that is creating this message.
    #[serde(skip_serializing_if = "Option::is_none")]
    application_version: Option<String>,
    /// The hostname of a client if this message is involving an external system calling into your system.
    #[serde(skip_serializing_if = "Option::is_none")]
    client_hostname: Option<String>,
    /// The hostname of a destination system if this message is involving your system calling an external system.
    #[serde(skip_serializing_if = "Option::is_none")]
    destination_hostname: Option<String>,
    /// The path being called on a destination system if this message is involving your system calling an external system.
    #[serde(skip_serializing_if = "Option::is_none")]
    destination_path: Option<String>,
    /// Sets the start time (timestamp of millis since the epoch) for the time at which this event started.
    #[set = "pub"]
    #[serde(skip_serializing_if = "Option::is_none")]
    start_timestamp: Option<i64>,
    /// Sets the start time (timestamp of millis since the epoch) for the time at which this event finished.
    #[set = "pub"]
    #[serde(skip_serializing_if = "Option::is_none")]
    end_timestamp: Option<i64>,
    /// Sets the duration (time in milliseconds) that passed during this event.
    #[set = "pub"]
    #[serde(skip_serializing_if = "Option::is_none")]
    duration: Option<u64>,
    /// The HTTP response code returned by a performance event.
    #[set = "pub"]
    #[serde(skip_serializing_if = "Option::is_none")]
    response_code: Option<u16>,
    /// The size of a request payload, typically associated with performance events.
    #[set = "pub"]
    #[serde(skip_serializing_if = "Option::is_none")]
    payload_size: Option<u64>,
    /// A more generic response used when a HTTP response code doesn't make sense. Typical values might be "success" or "failure".
    #[serde(skip_serializing_if = "Option::is_none")]
    response: Option<String>,
}

impl Message {
    /// Set the routing key.
    pub fn set_routing_key<S>(&mut self, routing_key: S) -> &mut Self
    where
        S: Into<String>,
    {
        self.routing_key = routing_key.into();
        self
    }

    /// Set the message.
    pub fn set_message<S>(&mut self, message: S) -> &mut Self
    where
        S: Into<String>,
    {
        self.message = message.into();
        self
    }

    /// Set the host.
    pub fn set_host<S>(&mut self, host: Option<S>) -> &mut Self
    where
        S: Into<String>,
    {
        self.host = host.map(|s| s.into());
        self
    }

    /// Set the message detail KV map.
    pub fn set_message_detail<S>(&mut self, message_detail: Option<HashMap<S, S>>) -> &mut Self
    where
        S: Into<String> + Clone + Eq + Hash,
    {
        if let Some(message_detail) = message_detail {
            self.message_detail = Some(
                message_detail
                    .iter()
                    .map(|(k, v)| ((*k).clone().into(), (*v).clone().into()))
                    .collect::<HashMap<String, String>>(),
            );
        }
        self
    }

    /// Set the application version.
    pub fn set_application_version<S>(&mut self, application_version: Option<S>) -> &mut Self
    where
        S: Into<String>,
    {
        self.application_version = application_version.map(|s| s.into());
        self
    }

    /// Set the client hostname.
    pub fn set_client_hostname<S>(&mut self, client_hostname: Option<S>) -> &mut Self
    where
        S: Into<String>,
    {
        self.client_hostname = client_hostname.map(|s| s.into());
        self
    }

    /// Set the destination hostname.
    pub fn set_destination_hostname<S>(&mut self, destination_hostname: Option<S>) -> &mut Self
    where
        S: Into<String>,
    {
        self.destination_hostname = destination_hostname.map(|s| s.into());
        self
    }

    /// Set the destination path.
    pub fn set_destination_path<S>(&mut self, destination_path: Option<S>) -> &mut Self
    where
        S: Into<String>,
    {
        self.destination_path = destination_path.map(|s| s.into());
        self
    }

    /// Set the response.
    pub fn set_response<S>(&mut self, response: Option<S>) -> &mut Self
    where
        S: Into<String>,
    {
        self.response = response.map(|s| s.into());
        self
    }
}