Skip to content

Commit 8b84549

Browse files
committed
Documentation
1 parent d8d136a commit 8b84549

File tree

10 files changed

+323
-110
lines changed

10 files changed

+323
-110
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "influxdb"
3-
version = "0.1.0"
3+
version = "0.0.1"
44
authors = ["Gero Gerke <[email protected]>"]
55
edition = "2018"
66

@@ -10,7 +10,7 @@ futures = "0.1.27"
1010
tokio = "0.1.20"
1111
itertools = "0.8"
1212
failure = "0.1.5"
13-
serde = { version = "1.0.92", optional = true, features = ["derive"] }
13+
serde = { version = "1.0.92", optional = true }
1414
serde_json = { version = "1.0", optional = true }
1515

1616
[features]

src/client/mod.rs

Lines changed: 56 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
//! Client which can read and write data from InfluxDB.
2+
//!
3+
//! # Arguments
4+
//!
5+
//! * `url`: The URL where InfluxDB is running (ex. `http://localhost:8086`).
6+
//! * `database`: The Database against which queries and writes will be run.
7+
//!
8+
//! # Examples
9+
//!
10+
//! ```rust
11+
//! use influxdb::client::InfluxDbClient;
12+
//!
13+
//! let client = InfluxDbClient::new("http://localhost:8086", "test");
14+
//!
15+
//! assert_eq!(client.database_name(), "test");
16+
//! ```
17+
118
use futures::{Future, Stream};
219
use reqwest::r#async::{Client, Decoder};
320

@@ -6,30 +23,15 @@ use std::mem;
623
use crate::error::InfluxDbError;
724
use crate::query::{InfluxDbQuery, QueryType};
825

9-
/// Client which can read and write data from InfluxDB.
10-
///
11-
/// # Arguments
12-
///
13-
/// * `url`: The URL where InfluxDB is running (ex. `http://localhost:8086`).
14-
/// * `database`: The Database against which queries and writes will be run.
15-
///
16-
/// # Examples
17-
///
18-
/// ```rust
19-
/// use influxdb::client::InfluxDbClient;
20-
///
21-
/// let client = InfluxDbClient::new("http://localhost:8086", "test");
22-
///
23-
/// assert_eq!(client.database_name(), "test");
24-
/// ```
26+
/// Internal Representation of a Client
2527
pub struct InfluxDbClient {
2628
url: String,
2729
database: String,
2830
// auth: Option<InfluxDbAuthentication>
2931
}
3032

3133
impl InfluxDbClient {
32-
/// Instantiates a new [`InfluxDbClient`]
34+
/// Instantiates a new [`InfluxDbClient`](crate::client::InfluxDbClient)
3335
///
3436
/// # Arguments
3537
///
@@ -45,23 +47,28 @@ impl InfluxDbClient {
4547
/// ```
4648
pub fn new<S1, S2>(url: S1, database: S2) -> Self
4749
where
48-
S1: Into<String>,
49-
S2: Into<String>,
50+
S1: ToString,
51+
S2: ToString,
5052
{
5153
InfluxDbClient {
52-
url: url.into(),
53-
database: database.into(),
54+
url: url.to_string(),
55+
database: database.to_string(),
5456
}
5557
}
5658

57-
pub fn database_name<'a>(&'a self) -> &'a str {
59+
/// Returns the name of the database the client is using
60+
pub fn database_name(&self) -> &str {
5861
&self.database
5962
}
6063

61-
pub fn database_url<'a>(&'a self) -> &'a str {
64+
/// Returns the URL of the InfluxDB installation the client is using
65+
pub fn database_url(&self) -> &str {
6266
&self.url
6367
}
6468

69+
/// Pings the InfluxDB Server
70+
///
71+
/// Returns a tuple of build type and version number
6572
pub fn ping(&self) -> impl Future<Item = (String, String), Error = InfluxDbError> {
6673
Client::new()
6774
.get(format!("{}/ping", self.url).as_str())
@@ -82,11 +89,31 @@ impl InfluxDbClient {
8289

8390
(String::from(build), String::from(version))
8491
})
85-
.map_err(|err| InfluxDbError::UnspecifiedError {
92+
.map_err(|err| InfluxDbError::ProtocolError {
8693
error: format!("{}", err),
8794
})
8895
}
8996

97+
/// Sends a [`InfluxDbReadQuery`](crate::query::read_query::InfluxDbReadQuery) or [`InfluxDbWriteQuery`](crate::query::write_query::InfluxDbWriteQuery) to the InfluxDB Server.InfluxDbError
98+
///
99+
/// A version capable of parsing the returned string is available under the [serde_integration](crate::integrations::serde_integration)
100+
///
101+
/// # Arguments
102+
///
103+
/// * `q`: Query of type [`InfluxDbReadQuery`](crate::query::read_query::InfluxDbReadQuery) or [`InfluxDbWriteQuery`](crate::query::write_query::InfluxDbWriteQuery)
104+
///
105+
/// # Examples
106+
///
107+
/// ```rust
108+
/// use influxdb::client::InfluxDbClient;
109+
/// use influxdb::query::InfluxDbQuery;
110+
///
111+
/// let client = InfluxDbClient::new("http://localhost:8086", "test");
112+
/// let _future = client.query(
113+
/// InfluxDbQuery::write_query("weather")
114+
/// .add_field("temperature", 82)
115+
/// );
116+
/// ```
90117
pub fn query<Q>(&self, q: Q) -> Box<dyn Future<Item = String, Error = InfluxDbError>>
91118
where
92119
Q: InfluxDbQuery,
@@ -101,7 +128,7 @@ impl InfluxDbClient {
101128

102129
let query = match q.build() {
103130
Err(err) => {
104-
let error = InfluxDbError::UnspecifiedError {
131+
let error = InfluxDbError::InvalidQueryError {
105132
error: format!("{}", err),
106133
};
107134
return Box::new(future::err::<String, InfluxDbError>(error));
@@ -146,7 +173,7 @@ impl InfluxDbClient {
146173
let body = mem::replace(res.body_mut(), Decoder::empty());
147174
body.concat2()
148175
})
149-
.map_err(|err| InfluxDbError::UnspecifiedError {
176+
.map_err(|err| InfluxDbError::ProtocolError {
150177
error: format!("{}", err),
151178
})
152179
.and_then(|body| {
@@ -155,16 +182,16 @@ impl InfluxDbClient {
155182

156183
// todo: improve error parsing without serde
157184
if s.contains("\"error\"") {
158-
return futures::future::err(InfluxDbError::UnspecifiedError {
185+
return futures::future::err(InfluxDbError::DatabaseError {
159186
error: format!("influxdb error: \"{}\"", s),
160187
});
161188
}
162189

163190
return futures::future::ok(s);
164191
}
165192

166-
futures::future::err(InfluxDbError::UnspecifiedError {
167-
error: "some other error has happened here!".to_string(),
193+
futures::future::err(InfluxDbError::DeserializationError {
194+
error: "response could not be converted to UTF-8".to_string(),
168195
})
169196
}),
170197
)

src/error.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1+
//! Errors that might happen in the crate
2+
13
#[derive(Debug, Fail)]
2-
/// Errors that might happen in the crate
34
pub enum InfluxDbError {
4-
#[fail(display = "query must contain at least one field")]
5-
/// Error happens when query has zero fields
6-
InvalidQueryError,
5+
#[fail(display = "query is invalid: {}", error)]
6+
/// Error happens when a query is invalid
7+
InvalidQueryError { error: String },
8+
9+
#[fail(display = "http protocol error: {}", error)]
10+
/// Error happens when a query is invalid
11+
ProtocolError { error: String },
712

8-
#[fail(
9-
display = "an error happened: \"{}\". this case should be handled better, please file an issue.",
10-
error
11-
)]
12-
/// todo: Error which is a placeholder for more meaningful errors. This should be refactored away.
13-
UnspecifiedError { error: String },
13+
#[fail(display = "http protocol error: {}", error)]
14+
/// Error happens when Serde cannot deserialize the response
15+
DeserializationError { error: String },
1416

1517
#[fail(display = "InfluxDB encountered the following error: {}", error)]
1618
/// Error which has happened inside InfluxDB

src/integrations/serde_integration.rs

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,52 @@
1+
//! Serde Integration for InfluxDB. Provides deserialization of query returns.
2+
//!
3+
//! When querying multiple series in the same query (e.g. with a regex query), it might be desirable to flat map
4+
//! the resulting series into a single `Vec` like so. The example assumes, that there are weather readings in multiple
5+
//! series named `weather_<city_name>` (e.g. `weather_berlin`, or `weather_london`). Since we're using a Regex query,
6+
//! we don't actually know which series will be returned. To assign the city name to the series, we can use the series
7+
//! `name`, InfluxDB provides alongside query results.
8+
//!
9+
//! ```rust,no_run
10+
//! use influxdb::query::InfluxDbQuery;
11+
//! use influxdb::client::InfluxDbClient;
12+
//! use serde::Deserialize;
13+
//!
14+
//! #[derive(Deserialize)]
15+
//! struct WeatherWithoutCityName {
16+
//! temperature: i32
17+
//! }
18+
//!
19+
//! #[derive(Deserialize)]
20+
//! struct Weather {
21+
//! city_name: String,
22+
//! weather: WeatherWithoutCityName,
23+
//! }
24+
//!
25+
//! let mut rt = tokio::runtime::current_thread::Runtime::new().unwrap();
26+
//! let client = InfluxDbClient::new("http://localhost:8086", "test");
27+
//! let query = InfluxDbQuery::raw_read_query("SELECT temperature FROM /weather_[a-z]*$/ WHERE time > now() - 1m ORDER BY DESC");
28+
//! let _result = rt.block_on(client.json_query::<WeatherWithoutCityName, _>(query))
29+
//! .map(|it| {
30+
//! it.map(|series_vec| {
31+
//! series_vec
32+
//! .into_iter()
33+
//! .map(|mut city_series| {
34+
//! let city_name = city_series.name.split("_").collect::<Vec<&str>>().remove(2);
35+
//! Weather { weather: city_series.values.remove(0), city_name: city_name.to_string() }
36+
//! }).collect::<Vec<Weather>>()
37+
//! })
38+
//! });
39+
140
use crate::client::InfluxDbClient;
241

342
use serde::de::DeserializeOwned;
443

544
use futures::{Future, Stream};
645
use reqwest::r#async::{Client, Decoder};
46+
use std::mem;
747

8-
use serde_json;
948
use serde::Deserialize;
10-
use std::mem;
49+
use serde_json;
1150

1251
use crate::error::InfluxDbError;
1352
use crate::query::{InfluxDbQuery, QueryType};
@@ -31,14 +70,17 @@ pub struct InfluxDbReturn<T> {
3170
}
3271

3372
#[derive(Deserialize, Debug)]
34-
#[doc(hidden)]
73+
/// Represents a returned series from InfluxDB
3574
pub struct InfluxDbSeries<T> {
3675
pub name: String,
3776
pub values: Vec<T>,
3877
}
3978

4079
impl InfluxDbClient {
41-
pub fn json_query<T: 'static, Q>(&self, q: Q) -> Box<dyn Future<Item = Option<Vec<InfluxDbSeries<T>>>, Error = InfluxDbError>>
80+
pub fn json_query<T: 'static, Q>(
81+
&self,
82+
q: Q,
83+
) -> Box<dyn Future<Item = Option<Vec<InfluxDbSeries<T>>>, Error = InfluxDbError>>
4284
where
4385
Q: InfluxDbQuery,
4486
T: DeserializeOwned,
@@ -53,10 +95,12 @@ impl InfluxDbClient {
5395

5496
let query = match q.build() {
5597
Err(err) => {
56-
let error = InfluxDbError::UnspecifiedError {
98+
let error = InfluxDbError::InvalidQueryError {
5799
error: format!("{}", err),
58100
};
59-
return Box::new(future::err::<Option<Vec<InfluxDbSeries<T>>>, InfluxDbError>(error));
101+
return Box::new(
102+
future::err::<Option<Vec<InfluxDbSeries<T>>>, InfluxDbError>(error),
103+
);
60104
}
61105
Ok(query) => query,
62106
};
@@ -98,29 +142,31 @@ impl InfluxDbClient {
98142
let body = mem::replace(res.body_mut(), Decoder::empty());
99143
body.concat2()
100144
})
101-
.map_err(|err| InfluxDbError::UnspecifiedError {
102-
error: format!("{}", err)
145+
.map_err(|err| InfluxDbError::ProtocolError {
146+
error: format!("{}", err),
103147
})
104148
.and_then(|body| {
105149
// Try parsing InfluxDBs { "error": "error message here" }
106150
if let Ok(error) = serde_json::from_slice::<_DatabaseError>(&body) {
107151
return futures::future::err(InfluxDbError::DatabaseError {
108-
error: error.error.to_string()
109-
})
152+
error: error.error.to_string(),
153+
});
110154
} else {
111-
// Json has another structure, let's try actually parsing it to the type we're deserializing
155+
// Json has another structure, let's try actually parsing it to the type we're deserializing
112156
let from_slice = serde_json::from_slice::<DatabaseQueryResult<T>>(&body);
113157

114158
let mut deserialized = match from_slice {
115159
Ok(deserialized) => deserialized,
116-
Err(err) => return futures::future::err(InfluxDbError::UnspecifiedError {
117-
error: format!("serde error: {}", err)
118-
})
160+
Err(err) => {
161+
return futures::future::err(InfluxDbError::DeserializationError {
162+
error: format!("serde error: {}", err),
163+
})
164+
}
119165
};
120166

121167
return futures::future::result(Ok(deserialized.results.remove(0).series));
122168
}
123-
})
169+
}),
124170
)
125171
}
126172
}

0 commit comments

Comments
 (0)