Skip to content

Commit 07839dc

Browse files
committed
chore: instrument
1 parent 14e0926 commit 07839dc

File tree

11 files changed

+72
-20
lines changed

11 files changed

+72
-20
lines changed

crates/synd_api/src/args.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::path::PathBuf;
22

3-
use clap::Parser;
3+
use clap::{ArgAction, Parser};
44

55
#[derive(Parser, Debug)]
66
#[command(version, propagate_version = true, disable_help_subcommand = true)]
@@ -9,6 +9,8 @@ pub struct Args {
99
pub kvsd: KvsdOptions,
1010
#[command(flatten)]
1111
pub tls: TlsOptions,
12+
#[command(flatten)]
13+
pub o11y: ObservabilityOptions,
1214
}
1315

1416
#[derive(clap::Args, Debug)]
@@ -35,6 +37,26 @@ pub struct TlsOptions {
3537
pub private_key: PathBuf,
3638
}
3739

40+
#[derive(clap::Args, Debug)]
41+
#[command(next_help_heading = "Observability options")]
42+
pub struct ObservabilityOptions {
43+
/// Show code location(file, line number) in logs
44+
#[arg(long, env = "SYND_LOG_SHOW_LOCATION", default_value_t = false, action = ArgAction::Set )]
45+
pub show_code_location: bool,
46+
47+
/// Show event target(module in default) in logs
48+
#[arg(long, env = "SYND_LOG_SHOW_TARGET", default_value_t = true, action = ArgAction::Set)]
49+
pub show_target: bool,
50+
51+
/// Opentelemetry otlp exporter endpoint
52+
#[arg(long, env = "OTEL_EXPORTER_OTLP_ENDPOINT")]
53+
pub otlp_endpoint: Option<String>,
54+
55+
/// Opentelemetry trace sampler ratio
56+
#[arg(long, env = "OTEL_TRACES_SAMPLER_ARG", default_value_t = 1.0)]
57+
pub trace_sampler_ratio: f64,
58+
}
59+
3860
#[must_use]
3961
pub fn parse() -> Args {
4062
Args::parse()

crates/synd_api/src/client/github/client.rs

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ impl GithubClient {
3737
}
3838
}
3939

40+
#[tracing::instrument(name = "github::authenticate", skip_all)]
4041
pub async fn authenticate(&self, access_token: &str) -> anyhow::Result<String> {
4142
let variables = query::authenticate::Variables {};
4243
let request = query::Authenticate::build_query(variables);

crates/synd_api/src/gql/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mod query;
22
pub use query::Query;
33

44
mod mutation;
5-
use async_graphql::{extensions::Tracing, EmptySubscription, Schema, SchemaBuilder};
5+
use async_graphql::{EmptySubscription, Schema, SchemaBuilder};
66
pub use mutation::Mutation;
77

88
use crate::{principal::Principal, usecase};
@@ -45,7 +45,9 @@ pub fn schema_builder() -> SchemaBuilder<Query, Mutation, EmptySubscription> {
4545
#[cfg(not(feature = "introspection"))]
4646
let schema = Schema::build(Query, Mutation, EmptySubscription).disable_introspection();
4747

48-
schema.extension(Tracing)
48+
// disabled
49+
// schema.extension(Tracing)
50+
schema
4951
}
5052

5153
impl<'a> usecase::Context for &async_graphql::Context<'a> {

crates/synd_api/src/main.rs

+13-15
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ use synd_o11y::{
55
use tracing::{error, info};
66

77
use synd_api::{
8-
args::{self, Args},
8+
args::{self, Args, ObservabilityOptions},
99
config,
1010
dependency::Dependency,
1111
repository::kvsd::ConnectKvsdFailed,
1212
serve::listen_and_serve,
1313
shutdown::Shutdown,
1414
};
1515

16-
fn init_tracing() -> Option<OpenTelemetryGuard> {
16+
fn init_tracing(options: &ObservabilityOptions) -> Option<OpenTelemetryGuard> {
1717
use synd_o11y::{
1818
opentelemetry::init_propagation,
1919
tracing_subscriber::{audit, otel_log, otel_trace},
@@ -27,21 +27,19 @@ fn init_tracing() -> Option<OpenTelemetryGuard> {
2727
use supports_color::Stream;
2828
supports_color::on(Stream::Stdout).is_some()
2929
};
30-
let show_src = true;
31-
let show_target = !show_src;
30+
let show_src = options.show_code_location;
31+
let show_target = options.show_target;
3232

3333
let (opentelemetry_layers, guard) = {
34-
match std::env::var("OTEL_EXPORTER_OTLP_ENDPOINT").ok() {
35-
None => (None, None),
36-
Some(endpoint) if endpoint.is_empty() => (None, None),
34+
match options.otlp_endpoint.as_deref() {
35+
None | Some("") => (None, None),
3736
Some(endpoint) => {
3837
let resource = synd_o11y::opentelemetry::resource(config::NAME, config::VERSION);
3938

40-
tracing::info!(endpoint, ?resource, "Export opentelemetry signals");
41-
42-
let trace_layer = otel_trace::layer(resource.clone());
39+
let trace_layer =
40+
otel_trace::layer(endpoint, resource.clone(), options.trace_sampler_ratio);
4341
let log_layer = otel_log::layer(endpoint, resource.clone());
44-
let metrics_layer = otel_metrics::layer(resource);
42+
let metrics_layer = otel_metrics::layer(endpoint, resource);
4543

4644
(
4745
Some(trace_layer.and_then(log_layer).and_then(metrics_layer)),
@@ -62,7 +60,7 @@ fn init_tracing() -> Option<OpenTelemetryGuard> {
6260
.with_filter(metrics_event_filter())
6361
.and_then(opentelemetry_layers)
6462
.with_filter(
65-
EnvFilter::try_from_default_env()
63+
EnvFilter::try_from_env("SYND_LOG")
6664
.or_else(|_| EnvFilter::try_new("info"))
6765
.unwrap()
6866
.add_directive(audit::Audit::directive()),
@@ -77,18 +75,18 @@ fn init_tracing() -> Option<OpenTelemetryGuard> {
7775
guard
7876
}
7977

80-
async fn run(Args { kvsd, tls }: Args, shutdown: Shutdown) -> anyhow::Result<()> {
78+
async fn run(Args { kvsd, tls, o11y }: Args, shutdown: Shutdown) -> anyhow::Result<()> {
8179
let dep = Dependency::new(kvsd, tls).await?;
8280

83-
info!(version = config::VERSION, "Runinng...");
81+
info!(version = config::VERSION, otlp_endpoint=?o11y.otlp_endpoint, "Runinng...");
8482

8583
listen_and_serve(dep, shutdown).await
8684
}
8785

8886
#[tokio::main]
8987
async fn main() {
9088
let args = args::parse();
91-
let _guard = init_tracing();
89+
let _guard = init_tracing(&args.o11y);
9290
let shutdown = Shutdown::watch_signal();
9391

9492
if let Err(err) = run(args, shutdown).await {

crates/synd_api/src/repository/kvsd.rs

+3
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ impl KvsdClient {
109109

110110
#[async_trait]
111111
impl SubscriptionRepository for KvsdClient {
112+
#[tracing::instrument(skip_all)]
112113
async fn put_feed_subscription(
113114
&self,
114115
feed: repository::types::FeedSubscription,
@@ -131,6 +132,7 @@ impl SubscriptionRepository for KvsdClient {
131132
Self::set(&mut client, key, urls).await
132133
}
133134

135+
#[tracing::instrument(skip_all)]
134136
async fn delete_feed_subscription(
135137
&self,
136138
feed: repository::types::FeedSubscription,
@@ -148,6 +150,7 @@ impl SubscriptionRepository for KvsdClient {
148150
Self::set(&mut client, key, urls).await
149151
}
150152

153+
#[tracing::instrument(skip_all)]
151154
async fn fetch_subscribed_feed_urls(&self, user_id: &str) -> RepositoryResult<Vec<String>> {
152155
let key = Self::feed_subscription_key(user_id);
153156

crates/synd_api/src/serve/auth.rs

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ impl Authenticator {
3535
}
3636

3737
/// Authenticate from given token
38+
#[tracing::instrument(skip_all)]
3839
pub async fn authenticate<S>(&self, token: S) -> Result<Principal, ()>
3940
where
4041
S: AsRef<str>,

crates/synd_api/src/serve/layer/request_metrics.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ use std::{
22
convert::Infallible,
33
pin::Pin,
44
task::{Context, Poll},
5+
time::Instant,
56
};
67

7-
use axum::{extract::Request, response::Response};
8+
use axum::{extract::Request, http::Method, response::Response};
89
use futures_util::Future;
910
use synd_o11y::metric;
1011
use tower::{Layer, Service};
@@ -46,15 +47,31 @@ where
4647
}
4748

4849
fn call(&mut self, req: Request) -> Self::Future {
50+
let start = Instant::now();
4951
let path = req.uri().path().to_owned();
52+
let method = req.method().clone();
5053

5154
let mut this = self.clone();
5255
Box::pin(async move {
5356
let response = this.inner.call(req).await.unwrap();
5457
let status = response.status().as_u16();
5558

59+
// https://opentelemetry.io/docs/specs/semconv/http/http-metrics/
60+
// should be http.server.request ?
5661
metric!(monotonic_counter.request = 1, path, status);
5762

63+
// instrument graphql latency
64+
if path == "/graphql" && method == Method::POST {
65+
// f64 is matter
66+
// The type of the field that MetricsVisitor visits when on_event() is called is pre defined.
67+
// If u128 which is returned from elapsed() is used, it will not be visited, resulting in no metrics recorded.
68+
// Spec say "When instruments are measuring durations, seconds SHOULD be used"
69+
// https://opentelemetry.io/docs/specs/semconv/general/metrics/#instrument-units
70+
let elapsed: f64 = start.elapsed().as_secs_f64();
71+
// is there any semantic conventions?
72+
metric!(histogram.graphql.duration = elapsed);
73+
}
74+
5875
Ok(response)
5976
})
6077
}

crates/synd_api/src/shutdown.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ impl Shutdown {
2222
Err(err) => tracing::error!("Failed to handle signal {err}"),
2323
}
2424
// Signal graceful shutdown to axum_server
25-
handle2.graceful_shutdown(Some(Duration::from_secs(10)));
25+
handle2.graceful_shutdown(Some(Duration::from_secs(3)));
2626
tx2.send(()).ok();
2727
});
2828

crates/synd_api/src/usecase/fetch_entries.rs

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ impl Usecase for FetchEntries {
5050
Ok(principal)
5151
}
5252

53+
#[tracing::instrument(name = "fetch_entries", skip(self, principal))]
5354
async fn usecase(
5455
&self,
5556
Input {

crates/synd_api/src/usecase/subscribe_feed.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::sync::Arc;
22

33
use synd_feed::{feed::cache::FetchCachedFeed, types::Feed};
4+
use synd_o11y::metric;
45

56
use crate::{
67
principal::Principal,
@@ -70,6 +71,8 @@ impl Usecase for SubscribeFeed {
7071
})
7172
.await?;
7273

74+
metric!(counter.feed.subscription = 1);
75+
7376
Ok(Output {
7477
output: SubscribeFeedOutput { feed },
7578
})

crates/synd_api/src/usecase/unsubscribe_feed.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use std::sync::Arc;
22

3+
use synd_o11y::metric;
4+
35
use crate::{
46
principal::Principal,
57
repository::{self, SubscriptionRepository},
@@ -56,6 +58,8 @@ impl Usecase for UnsubscribeFeed {
5658
})
5759
.await?;
5860

61+
metric!(counter.feed.subscription = -1);
62+
5963
Ok(Output {
6064
output: UnsubscribeFeedOutput {},
6165
})

0 commit comments

Comments
 (0)