mirror of
https://github.com/pezkuwichain/pezkuwi-telemetry.git
synced 2026-06-12 03:01:09 +00:00
Merge pull request #291 from paritytech/mh-actix3
Upgrade backend to actix-web 3.0
This commit is contained in:
Generated
+1363
-962
File diff suppressed because it is too large
Load Diff
+5
-10
@@ -6,11 +6,11 @@ edition = "2018"
|
||||
license = "GPL-3.0"
|
||||
|
||||
[dependencies]
|
||||
actix = "0.8"
|
||||
actix-web = { git = "https://github.com/maciejhirsz/actix-web" }
|
||||
actix-web-actors = { git = "https://github.com/maciejhirsz/actix-web" }
|
||||
actix-http = { git = "https://github.com/maciejhirsz/actix-web" }
|
||||
bytes = "0.4"
|
||||
actix = "0.10.0"
|
||||
actix-web = "3.0.2"
|
||||
actix-web-actors = "3.0.0"
|
||||
actix-http = "2.0.0"
|
||||
bytes = "0.5.6"
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
fnv = "1.0.6"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
@@ -27,8 +27,3 @@ clap = "3.0.0-beta.1"
|
||||
[profile.release]
|
||||
lto = true
|
||||
panic = "abort"
|
||||
|
||||
[patch.crates-io]
|
||||
actix-web = { git = "https://github.com/maciejhirsz/actix-web" }
|
||||
actix-web-actors = { git = "https://github.com/maciejhirsz/actix-web" }
|
||||
actix-http = { git = "https://github.com/maciejhirsz/actix-web" }
|
||||
|
||||
+17
-15
@@ -104,6 +104,7 @@ impl Actor for Aggregator {
|
||||
|
||||
/// Message sent from the NodeConnector to the Aggregator upon getting all node details
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct AddNode {
|
||||
pub node: NodeDetails,
|
||||
pub network_id: Option<Label>,
|
||||
@@ -112,23 +113,24 @@ pub struct AddNode {
|
||||
|
||||
/// Message sent from the Chain to the Aggregator when the Chain loses all nodes
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct DropChain(pub ChainId);
|
||||
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct RenameChain(pub ChainId, pub Label);
|
||||
|
||||
/// Message sent from the FeedConnector to the Aggregator when subscribing to a new chain
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "bool")]
|
||||
pub struct Subscribe {
|
||||
pub chain: Label,
|
||||
pub feed: Addr<FeedConnector>,
|
||||
}
|
||||
|
||||
impl Message for Subscribe {
|
||||
type Result = bool;
|
||||
}
|
||||
|
||||
/// Message sent from the FeedConnector to the Aggregator consensus requested
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct SendFinality {
|
||||
pub chain: Label,
|
||||
pub fid: FeedId,
|
||||
@@ -136,6 +138,7 @@ pub struct SendFinality {
|
||||
|
||||
/// Message sent from the FeedConnector to the Aggregator no more consensus required
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct NoMoreFinality {
|
||||
pub chain: Label,
|
||||
pub fid: FeedId,
|
||||
@@ -143,30 +146,29 @@ pub struct NoMoreFinality {
|
||||
|
||||
/// Message sent from the FeedConnector to the Aggregator when first connected
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct Connect(pub Addr<FeedConnector>);
|
||||
|
||||
/// Message sent from the FeedConnector to the Aggregator when disconnecting
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct Disconnect(pub FeedId);
|
||||
|
||||
/// Message sent from the Chain to the Aggergator when the node count on the chain changes
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct NodeCount(pub ChainId, pub usize);
|
||||
|
||||
/// Message sent to the Aggregator to get the network state of a particular node
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "Option<Request<Chain, GetNodeNetworkState>>")]
|
||||
pub struct GetNetworkState(pub Box<str>, pub NodeId);
|
||||
|
||||
/// Message sent to the Aggregator to get a health check
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "usize")]
|
||||
pub struct GetHealth;
|
||||
|
||||
impl Message for GetNetworkState {
|
||||
type Result = Option<Request<Chain, GetNodeNetworkState>>;
|
||||
}
|
||||
|
||||
impl Message for GetHealth {
|
||||
type Result = usize;
|
||||
}
|
||||
|
||||
impl Handler<AddNode> for Aggregator {
|
||||
type Result = ();
|
||||
|
||||
@@ -205,7 +207,7 @@ impl Handler<DropChain> for Aggregator {
|
||||
}
|
||||
|
||||
self.serializer.push(feed::RemovedChain(label));
|
||||
info!("Dropped chain [{}] from the aggregator", label);
|
||||
log::info!("Dropped chain [{}] from the aggregator", label);
|
||||
self.broadcast();
|
||||
}
|
||||
|
||||
@@ -284,7 +286,7 @@ impl Handler<Connect> for Aggregator {
|
||||
|
||||
let fid = self.feeds.add(connector.clone());
|
||||
|
||||
info!("Feed #{} connected", fid);
|
||||
log::info!("Feed #{} connected", fid);
|
||||
|
||||
connector.do_send(Connected(fid));
|
||||
|
||||
@@ -307,7 +309,7 @@ impl Handler<Disconnect> for Aggregator {
|
||||
fn handle(&mut self, msg: Disconnect, _: &mut Self::Context) {
|
||||
let Disconnect(fid) = msg;
|
||||
|
||||
info!("Feed #{} disconnected", fid);
|
||||
log::info!("Feed #{} disconnected", fid);
|
||||
|
||||
self.feeds.remove(fid);
|
||||
}
|
||||
|
||||
+11
-3
@@ -46,7 +46,7 @@ pub struct Chain {
|
||||
|
||||
impl Chain {
|
||||
pub fn new(cid: ChainId, aggregator: Addr<Aggregator>, label: Label) -> Self {
|
||||
info!("[{}] Created", label);
|
||||
log::info!("[{}] Created", label);
|
||||
|
||||
Chain {
|
||||
cid,
|
||||
@@ -192,6 +192,7 @@ impl Actor for Chain {
|
||||
|
||||
/// Message sent from the Aggregator to the Chain when new Node is connected
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct AddNode {
|
||||
pub node: NodeDetails,
|
||||
pub rec: Recipient<Initialize>,
|
||||
@@ -199,6 +200,7 @@ pub struct AddNode {
|
||||
|
||||
/// Message sent from the NodeConnector to the Chain when it receives new telemetry data
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct UpdateNode {
|
||||
pub nid: NodeId,
|
||||
pub msg: NodeMessage,
|
||||
@@ -207,24 +209,30 @@ pub struct UpdateNode {
|
||||
|
||||
/// Message sent from the NodeConnector to the Chain when the connector disconnects
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct RemoveNode(pub NodeId);
|
||||
|
||||
/// Message sent from the Aggregator to the Chain when the connector wants to subscribe to that chain
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct Subscribe(pub Addr<FeedConnector>);
|
||||
|
||||
/// Message sent from the FeedConnector before it subscribes to a new chain, or if it disconnects
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct Unsubscribe(pub FeedId);
|
||||
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct SendFinality(pub FeedId);
|
||||
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct NoMoreFinality(pub FeedId);
|
||||
|
||||
/// Message sent from the NodeConnector to the Chain when it receives location data
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct LocateNode {
|
||||
pub nid: NodeId,
|
||||
pub location: Arc<NodeLocation>,
|
||||
@@ -271,7 +279,7 @@ impl Chain {
|
||||
if node.update_block(*block) {
|
||||
if block.height > self.best.height {
|
||||
self.best = *block;
|
||||
info!(
|
||||
log::info!(
|
||||
"[{}] [{}/{}] new best block ({}) {:?}",
|
||||
self.label.0,
|
||||
nodes_len,
|
||||
@@ -418,7 +426,7 @@ impl Handler<RemoveNode> for Chain {
|
||||
}
|
||||
|
||||
if self.nodes.is_empty() {
|
||||
info!("[{}] Lost all nodes, dropping...", self.label.0);
|
||||
log::info!("[{}] Lost all nodes, dropping...", self.label.0);
|
||||
ctx.stop();
|
||||
}
|
||||
|
||||
|
||||
+6
-7
@@ -1,3 +1,4 @@
|
||||
use std::mem;
|
||||
use serde::Serialize;
|
||||
use serde::ser::{Serializer, SerializeTuple};
|
||||
|
||||
@@ -20,17 +21,15 @@ pub struct FeedMessageSerializer {
|
||||
buffer: Vec<u8>,
|
||||
}
|
||||
|
||||
const BUFCAP: usize = 128;
|
||||
|
||||
impl FeedMessageSerializer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
buffer: Vec::new(),
|
||||
buffer: Vec::with_capacity(BUFCAP),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.buffer.clear();
|
||||
}
|
||||
|
||||
pub fn push<Message>(&mut self, msg: Message)
|
||||
where
|
||||
Message: FeedMessage,
|
||||
@@ -52,8 +51,8 @@ impl FeedMessageSerializer {
|
||||
}
|
||||
|
||||
self.buffer.push(b']');
|
||||
let bytes = self.buffer[..].into();
|
||||
self.clear();
|
||||
|
||||
let bytes = mem::replace(&mut self.buffer, Vec::with_capacity(BUFCAP)).into();
|
||||
|
||||
Some(Serialized(bytes))
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ impl FeedConnector {
|
||||
// stop actor
|
||||
ctx.stop();
|
||||
} else {
|
||||
ctx.ping("")
|
||||
ctx.ping(b"")
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -94,8 +94,7 @@ impl FeedConnector {
|
||||
// Chain not found, reset hash
|
||||
_ => actor.chain_hash = 0,
|
||||
}
|
||||
|
||||
fut::ok(())
|
||||
async {}.into_actor(actor)
|
||||
})
|
||||
.wait(ctx);
|
||||
}
|
||||
@@ -124,13 +123,16 @@ impl FeedConnector {
|
||||
|
||||
/// Message sent form Chain to the FeedConnector upon successful subscription
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct Subscribed(pub FeedId, pub Recipient<Unsubscribe>);
|
||||
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct Unsubscribed;
|
||||
|
||||
/// Message sent from Aggregator to FeedConnector upon successful connection
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct Connected(pub FeedId);
|
||||
|
||||
/// Message sent from either Aggregator or Chain to FeedConnector containing
|
||||
@@ -138,28 +140,33 @@ pub struct Connected(pub FeedId);
|
||||
///
|
||||
/// Since Bytes is ARC'ed, this is cheap to clone
|
||||
#[derive(Message, Clone)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct Serialized(pub Bytes);
|
||||
|
||||
impl StreamHandler<ws::Message, ws::ProtocolError> for FeedConnector {
|
||||
fn handle(&mut self, msg: ws::Message, ctx: &mut Self::Context) {
|
||||
impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for FeedConnector {
|
||||
fn handle(&mut self, msg: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
|
||||
match msg {
|
||||
ws::Message::Ping(msg) => {
|
||||
Ok(ws::Message::Ping(msg)) => {
|
||||
self.hb = Instant::now();
|
||||
ctx.pong(&msg);
|
||||
}
|
||||
ws::Message::Pong(_) => self.hb = Instant::now(),
|
||||
ws::Message::Text(text) => {
|
||||
Ok(ws::Message::Pong(_)) => self.hb = Instant::now(),
|
||||
Ok(ws::Message::Text(text)) => {
|
||||
if let Some(idx) = text.find(':') {
|
||||
let cmd = &text[..idx];
|
||||
let payload = &text[idx+1..];
|
||||
|
||||
info!("New FEED message: {}", cmd);
|
||||
log::info!("New FEED message: {}", cmd);
|
||||
|
||||
self.handle_cmd(cmd, payload, ctx);
|
||||
}
|
||||
}
|
||||
ws::Message::Close(_) => ctx.stop(),
|
||||
_ => (),
|
||||
Ok(ws::Message::Close(_)) => ctx.stop(),
|
||||
Ok(_) => (),
|
||||
Err(error) => {
|
||||
log::error!("{:?}", error);
|
||||
ctx.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+54
-43
@@ -1,13 +1,11 @@
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use actix::prelude::*;
|
||||
use actix_http::ws::Codec;
|
||||
use actix_web::{web, App, Error, HttpRequest, HttpResponse, HttpServer};
|
||||
use actix_web::{web, get, middleware, App, Error, HttpRequest, HttpResponse, HttpServer};
|
||||
use actix_web_actors::ws;
|
||||
use clap::Clap;
|
||||
use simple_logger::SimpleLogger;
|
||||
|
||||
mod aggregator;
|
||||
mod chain;
|
||||
@@ -40,13 +38,14 @@ struct Opts {
|
||||
}
|
||||
|
||||
/// Entry point for connecting nodes
|
||||
fn node_route(
|
||||
#[get("/submit/")]
|
||||
async fn node_route(
|
||||
req: HttpRequest,
|
||||
stream: web::Payload,
|
||||
aggregator: web::Data<Addr<Aggregator>>,
|
||||
locator: web::Data<Addr<Locator>>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
let ip = req.connection_info().remote().and_then(|mut addr| {
|
||||
let ip = req.connection_info().realip_remote_addr().and_then(|mut addr| {
|
||||
if let Some(port_idx) = addr.find(":") {
|
||||
addr = &addr[..port_idx];
|
||||
}
|
||||
@@ -65,7 +64,8 @@ fn node_route(
|
||||
}
|
||||
|
||||
/// Entry point for connecting feeds
|
||||
fn feed_route(
|
||||
#[get("/feed/")]
|
||||
async fn feed_route(
|
||||
req: HttpRequest,
|
||||
stream: web::Payload,
|
||||
aggregator: web::Data<Addr<Aggregator>>,
|
||||
@@ -77,63 +77,74 @@ fn feed_route(
|
||||
)
|
||||
}
|
||||
|
||||
fn state_route(
|
||||
/// Entry point for network state dump
|
||||
#[get("/network_state/{chain}/{nid}/")]
|
||||
async fn state_route(
|
||||
path: web::Path<(Box<str>, NodeId)>,
|
||||
aggregator: web::Data<Addr<Aggregator>>,
|
||||
) -> impl Future<Item = HttpResponse, Error = Error> {
|
||||
) -> Result<HttpResponse, Error> {
|
||||
let (chain, nid) = path.into_inner();
|
||||
|
||||
aggregator
|
||||
.send(GetNetworkState(chain, nid))
|
||||
.flatten()
|
||||
.from_err()
|
||||
.and_then(|data| match data.and_then(|nested| nested) {
|
||||
Some(body) => HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
.body(body),
|
||||
None => HttpResponse::Ok()
|
||||
.body("Node has disconnected or has not submitted its network state yet"),
|
||||
})
|
||||
let res = match aggregator.send(GetNetworkState(chain, nid)).await {
|
||||
Ok(Some(res)) => res.await,
|
||||
Ok(None) => Ok(None),
|
||||
Err(error) => Err(error)
|
||||
};
|
||||
|
||||
match res {
|
||||
Ok(Some(body)) => {
|
||||
HttpResponse::Ok().content_type("application/json").body(body).await
|
||||
},
|
||||
Ok(None) => {
|
||||
HttpResponse::Ok().body("Node has disconnected or has not submitted its network state yet").await
|
||||
},
|
||||
Err(error) => {
|
||||
log::error!("Network state mailbox error: {:?}", error);
|
||||
|
||||
HttpResponse::InternalServerError().await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn health(
|
||||
aggregator: web::Data<Addr<Aggregator>>,
|
||||
) -> impl Future<Item = HttpResponse, Error = Error> {
|
||||
aggregator.send(GetHealth).from_err().and_then(|count| {
|
||||
let body = format!("Connected chains: {}", count);
|
||||
/// Entry point for health check monitoring bots
|
||||
#[get("/health/")]
|
||||
async fn health(aggregator: web::Data<Addr<Aggregator>>) -> Result<HttpResponse, Error> {
|
||||
match aggregator.send(GetHealth).await {
|
||||
Ok(count) => {
|
||||
let body = format!("Connected chains: {}", count);
|
||||
|
||||
HttpResponse::Ok().body(body)
|
||||
})
|
||||
HttpResponse::Ok().body(body).await
|
||||
},
|
||||
Err(error) => {
|
||||
log::error!("Health check mailbox error: {:?}", error);
|
||||
|
||||
HttpResponse::InternalServerError().await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Telemetry entry point. Listening by default on 127.0.0.1:8000.
|
||||
/// This can be changed using the `PORT` and `BIND` ENV variables.
|
||||
fn main() -> std::io::Result<()> {
|
||||
use web::{get, resource};
|
||||
|
||||
simple_logger::init_with_level(log::Level::Info).expect("Must be able to start a logger");
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
SimpleLogger::new().with_level(log::LevelFilter::Info).init().expect("Must be able to start a logger");
|
||||
|
||||
let opts: Opts = Opts::parse();
|
||||
let sys = System::new("substrate-telemetry");
|
||||
let aggregator = Aggregator::new().start();
|
||||
let factory = LocatorFactory::new();
|
||||
let locator = SyncArbiter::start(4, move || factory.create());
|
||||
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.wrap(middleware::NormalizePath::default())
|
||||
.data(aggregator.clone())
|
||||
.data(locator.clone())
|
||||
.service(resource("/submit").route(get().to(node_route)))
|
||||
.service(resource("/submit/").route(get().to(node_route)))
|
||||
.service(resource("/feed").route(get().to(feed_route)))
|
||||
.service(resource("/feed/").route(get().to(feed_route)))
|
||||
.service(resource("/network_state/{chain}/{nid}").route(get().to_async(state_route)))
|
||||
.service(resource("/network_state/{chain}/{nid}/").route(get().to_async(state_route)))
|
||||
.service(resource("/health").route(get().to_async(health)))
|
||||
.service(resource("/health/").route(get().to_async(health)))
|
||||
.service(node_route)
|
||||
.service(feed_route)
|
||||
.service(state_route)
|
||||
.service(health)
|
||||
})
|
||||
.bind(format!("{}", opts.socket))?
|
||||
.start();
|
||||
|
||||
sys.run()
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
|
||||
+1
-1
@@ -226,7 +226,7 @@ impl Node {
|
||||
if let Ok(stringified) = serde_json::from_str::<String>(json) {
|
||||
Some(stringified.into())
|
||||
} else {
|
||||
Some(json.into())
|
||||
Some(json.to_owned().into())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ impl NodeConnector {
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct Initialize(pub NodeId, pub Addr<Chain>);
|
||||
|
||||
impl Handler<Initialize> for NodeConnector {
|
||||
@@ -130,23 +131,32 @@ impl Handler<Initialize> for NodeConnector {
|
||||
}
|
||||
}
|
||||
|
||||
impl StreamHandler<ws::Message, ws::ProtocolError> for NodeConnector {
|
||||
fn handle(&mut self, msg: ws::Message, ctx: &mut Self::Context) {
|
||||
impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for NodeConnector {
|
||||
fn handle(&mut self, msg: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
|
||||
self.hb = Instant::now();
|
||||
|
||||
let data = match msg {
|
||||
ws::Message::Ping(msg) => {
|
||||
Ok(ws::Message::Ping(msg)) => {
|
||||
ctx.pong(&msg);
|
||||
return;
|
||||
}
|
||||
ws::Message::Pong(_) => return,
|
||||
ws::Message::Text(text) => text.into(),
|
||||
ws::Message::Binary(data) => data,
|
||||
ws::Message::Close(_) => {
|
||||
Ok(ws::Message::Pong(_)) => return,
|
||||
Ok(ws::Message::Text(text)) => text.into(),
|
||||
Ok(ws::Message::Binary(data)) => data,
|
||||
Ok(ws::Message::Close(_)) => {
|
||||
ctx.stop();
|
||||
return;
|
||||
}
|
||||
Ok(ws::Message::Nop) => return,
|
||||
Ok(ws::Message::Continuation(_)) => {
|
||||
log::error!("Continuation not supported");
|
||||
return;
|
||||
}
|
||||
Err(error) => {
|
||||
log::error!("{:?}", error);
|
||||
ctx.stop();
|
||||
return;
|
||||
}
|
||||
ws::Message::Nop => return,
|
||||
};
|
||||
|
||||
match serde_json::from_slice(&data) {
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::node::NodeDetails;
|
||||
use crate::types::{Block, BlockNumber, BlockHash};
|
||||
|
||||
#[derive(Deserialize, Debug, Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct NodeMessage {
|
||||
pub level: Level,
|
||||
pub ts: DateTime<Utc>,
|
||||
|
||||
@@ -47,6 +47,7 @@ impl Actor for Locator {
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct LocateRequest {
|
||||
pub ip: Ipv4Addr,
|
||||
pub nid: NodeId,
|
||||
@@ -97,7 +98,7 @@ impl Handler<LocateRequest> for Locator {
|
||||
|
||||
let location = match self.iplocate(ip) {
|
||||
Ok(location) => location,
|
||||
Err(err) => return debug!("GET error for ip location: {:?}", err),
|
||||
Err(err) => return log::debug!("GET error for ip location: {:?}", err),
|
||||
};
|
||||
|
||||
self.cache.write().insert(ip, location.clone());
|
||||
@@ -139,7 +140,7 @@ impl Locator {
|
||||
match self.client.get(url).send()?.json::<T>() {
|
||||
Ok(result) => Ok(Some(result)),
|
||||
Err(err) => {
|
||||
debug!("JSON error for ip location: {:?}", err);
|
||||
log::debug!("JSON error for ip location: {:?}", err);
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user