feat(stackdriver): Add initial Stackdriver API type definitions

This commit is contained in:
Vincent Ambo 2018-05-28 22:24:32 +02:00
parent 0db4512df4
commit ef638bfa20
4 changed files with 1138 additions and 1 deletions

1031
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -9,6 +9,12 @@ failure = "0.1"
systemd = "0.3" systemd = "0.3"
log = "0.4" log = "0.4"
env_logger = "0.5" env_logger = "0.5"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
reqwest = "0.8"
chrono = { version = "0.4", features = ["serde"] }
hyper = "*" # whatever reqwest drags in
[build-dependencies] [build-dependencies]
pkg-config = "0.3" pkg-config = "0.3"

View file

@ -1,8 +1,16 @@
// #[macro_use] extern crate failure; #[macro_use] extern crate failure;
#[macro_use] extern crate hyper;
#[macro_use] extern crate log; #[macro_use] extern crate log;
#[macro_use] extern crate serde_derive;
extern crate chrono;
extern crate env_logger; extern crate env_logger;
extern crate systemd; extern crate systemd;
extern crate serde;
extern crate serde_json;
extern crate reqwest;
mod stackdriver;
use systemd::journal::*; use systemd::journal::*;
use std::process; use std::process;

92
src/stackdriver.rs Normal file
View file

@ -0,0 +1,92 @@
//! This module defines types and functions for submitting log entries
//! to the Stackdriver Logging API.
//!
//! Initially this will use the HTTP & JSON API instead of gRPC.
//!
//! Documentation for the relevant endpoint is available at:
//! https://cloud.google.com/logging/docs/reference/v2/rest/v2/entries/write
use chrono::{DateTime, Utc};
use failure::{Error, ResultExt};
use std::collections::HashMap;
use reqwest::Client;
const WRITE_ENTRY_URL: &str = "https://logging.googleapis.com/v2/entries:write";
const TOKEN_URL: &str = "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token";
/// Represents an OAuth 2 access token as returned by Google's APIs.
#[derive(Deserialize)]
struct Token {
access_token: String,
expires_in: usize,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
struct MonitoredResource {
/// The monitored resource type. This field must match the type
/// field of a MonitoredResourceDescriptor object.
#[serde(rename = "type")]
resource_type: String,
/// Values for all of the labels listed in the associated
/// monitored resource descriptor.
labels: HashMap<String, String>,
}
/// This type represents a single Stackdriver log entry.
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
struct LogEntry<'a> {
/// The resource name of the log to which this log entry belongs.
log_name: String,
/// The primary monitored resource associated with this log entry.
resource: &'a MonitoredResource,
/// The time the event described by the log entry occurred.
timestamp: DateTime<Utc>,
/// A set of user-defined (key, value) data that provides
/// additional information about the log entry.
labels: HashMap<String, String>,
}
/// This type represents the request sent to the Stackdriver API to
/// insert a batch of log records.
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
struct WriteEntriesRequest<'a> {
/// The log entries to send to Stackdriver Logging.
entries: Vec<LogEntry<'a>>,
/// Whether valid entries should be written even if some other
/// entries fail due to `INVALID_ARGUMENT` or `PERMISSION_DENIED`
/// errors.
partial_success: bool,
/// Default labels that are added to the labels field of all log
/// entries in entries. If a log entry already has a label with
/// the same key as a label in this parameter, then the log
/// entry's label is not changed.
labels: HashMap<String, String>,
/// The log entry payload, represented as a Unicode string.
text_payload: String,
}
// Define the metadata header required by Google's service:
header! { (MetadataFlavor, "Metadata-Flavor") => [String] }
/// This function is used to fetch a new authentication token from
/// Google. Currently only tokens retrieved via instance metadata are
/// supported.
fn fetch_token() -> Result<Token, Error> {
let token: Token = Client::new()
.get(TOKEN_URL)
.header(MetadataFlavor("Google".to_string()))
.send().context("Requesting token failed")?
.json().context("Deserializing token failed")?;
Ok(token)
}