Skip to content

Commit

Permalink
Introduce an observability crate using opentelemetry-rust (#2535) (#2609
Browse files Browse the repository at this point in the history
)

* feat: add observability crate



* fix: fix crate name



* feat: add module files



* feat: create config



* fix: implement from trait



* feat: add tracer and meter macro



* feat: add license



* fix: use full module path



* fix: add shutdown method



* feat: add build method to crate tracer provider and meter provider



* fix: module path



* fix: add export timeout duration and comment



* feat: update interface



* feat: add endpint configuration to root configuration



* fix: update deps



* fix: small refactor



* fix: deleted build method to create trace and metrics provider



---------

Signed-off-by: hlts2 <[email protected]>
  • Loading branch information
hlts2 authored Sep 11, 2024
1 parent 97dc524 commit 626873f
Show file tree
Hide file tree
Showing 4 changed files with 435 additions and 0 deletions.
142 changes: 142 additions & 0 deletions rust/libs/observability/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
//
// Copyright (C) 2019-2024 vdaas.org vald team <[email protected]>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
use std::collections::HashMap;
use std::time::Duration;

use opentelemetry::KeyValue;
use opentelemetry_sdk::{self, Resource};

#[derive(Clone, Debug)]
pub struct Config {
pub enabled: bool,
pub endpoint: String,
pub attributes: HashMap<String, String>,
pub tracer: Tracer,
pub meter: Meter,
}

#[derive(Clone, Debug, Default)]
pub struct Tracer {
pub enabled: bool,
}

#[derive(Clone, Debug)]
pub struct Meter {
pub enabled: bool,
pub export_duration: Duration,
pub export_timeout_duration: Duration,
}

impl Config {
pub fn new() -> Self {
Self::default()
}

pub fn enabled(mut self, enabled: bool) -> Self {
self.enabled = enabled;
self
}

pub fn endpoint(mut self, endpoint: &str) -> Self {
self.endpoint = endpoint.to_string();
self
}

pub fn attributes(mut self, attrs: HashMap<String, String>) -> Self {
self.attributes = attrs;
self
}

pub fn attribute(mut self, key: &str, value: &str) -> Self {
self.attributes.insert(key.to_string(), value.to_string());
self
}

pub fn tracer(mut self, cfg: Tracer) -> Self {
self.tracer = cfg;
self
}

pub fn meter(mut self, cfg: Meter) -> Self {
self.meter = cfg;
self
}
}

impl Default for Config {
fn default() -> Self {
Self {
enabled: false,
endpoint: "".to_string(),
attributes: HashMap::new(),
tracer: Tracer::default(),
meter: Meter::default(),
}
}
}

impl From<&Config> for Resource {
fn from(value: &Config) -> Self {
let key_values: Vec<KeyValue> = value
.attributes
.iter()
.map(|(key, val)| KeyValue::new(key.clone(), val.clone()))
.collect();
Resource::new(key_values)
}
}

impl Tracer {
pub fn new() -> Self {
Tracer::default()
}

pub fn enabled(mut self, enabled: bool) -> Self {
self.enabled = enabled;
self
}
}

impl Meter {
pub fn new() -> Self {
Meter::default()
}

pub fn enabled(mut self, enabled: bool) -> Self {
self.enabled = enabled;
self
}

pub fn export_duration(mut self, dur: Duration) -> Self {
self.export_duration = dur;
self
}

pub fn export_timeout_duration(mut self, dur: Duration) -> Self {
self.export_timeout_duration = dur;
self
}
}

impl Default for Meter {
fn default() -> Self {
Self {
enabled: false,
export_duration: Duration::from_secs(1),
export_timeout_duration: Duration::from_secs(5),
}
}
}
19 changes: 19 additions & 0 deletions rust/libs/observability/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Copyright (C) 2019-2024 vdaas.org vald team <[email protected]>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

pub mod config;
pub mod macros;
pub mod observability;
150 changes: 150 additions & 0 deletions rust/libs/observability/src/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
//
// Copyright (C) 2019-2024 vdaas.org vald team <[email protected]>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#[macro_export]
macro_rules! tracer {
() => {{
tracer!("vald")
}};

($name:expr) => {{
opentelemetry::global::tracer($name)
}};
}

#[macro_export]
macro_rules! ctx_span {
($ctx:expr, $name:expr) => {{
ctx_span!($ctx, $name, opentelemetry::trace::SpanKind::Internal)
}};

($ctx:expr, $name:expr, $kind:expr) => {{
let tracer = tracer!();
let parent_ctx: &opentelemetry::Context = $ctx;
let span = tracer
.span_builder($name)
.with_kind($kind)
.start_with_context(&tracer, parent_ctx);
opentelemetry::Context::current_with_span(span)
}};
}

#[macro_export]
macro_rules! meter {
() => {{
meter!("vald")
}};

($name:expr) => {{
opentelemetry::global::meter($name)
}};
}

#[derive(Debug, PartialEq)]
pub enum InstrumentKind {
UpdownCounter,
Counter,
Histogram,
Gauge,
}

#[macro_export]
macro_rules! instrument {
(InstrumentKind::Counter, $typ:ty, $name:expr, $disc:expr, $unit:expr) => {{
let meter = meter!();
paste::paste! {
meter
.[<$typ _counter>]($name) // typ = f64 or u64
.with_description($disc)
.with_unit($unit)
.init()
}
}};

(InstrumentKind::Counter, $typ:ty, $name:expr, $disc:expr, $unit:expr, $measurement:expr, $key_value:expr) => {{
let meter = meter!();
paste::paste! {
meter
.[<$typ _observable_counter>]($name) // typ = f64 or u64
.with_description($disc)
.with_unit($unit)
.with_callback(|observe| {
observe.observe($measurement, $key_value);
})
.init()
}
}};

(InstrumentKind::UpdownCounter, $typ:ty, $name:expr, $disc:expr, $unit:expr) => {{
let meter = meter!();
paste::paste! {
meter
.[<$typ _up_down_counter>]($name) // typ = f64 or i64
.with_description($disc)
.with_unit($unit)
.init()
}
}};

(InstrumentKind::UpdownCounter, $typ:ty, $name:expr, $disc:expr, $unit:expr, $measurement:expr, $key_value:expr) => {{
let meter = meter!();
paste::paste! {
meter
.[<$typ _observable_up_down_counter>]($name) // typ = f64 or i64
.with_description($disc)
.with_unit($unit)
.with_callback(|observe| {
observe.observe($measurement, $key_value);
})
.init()
}
}};

(InstrumentKind::Histogram, $typ:ty, $name:expr, $disc:expr, $unit:expr) => {{
let meter = meter!();
paste::paste! {
meter
.[<$typ _histogram>]($name) // typ = f64 or i64
.with_description($disc)
.with_unit($unit)
.init()
}
}};

(InstrumentKind::Gauge, $typ:ty, $name:expr, $disc:expr, $unit:expr) => {{
let meter = meter!();
paste::paste! {
meter
.[<$typ _gauge>]($name) // typ = f64 or i64 or u64
.with_description($disc)
.with_unit($unit)
.init()
}
}};

(InstrumentKind::Gauge, $typ:ty, $name:expr, $disc:expr, $unit:expr, $measurement:expr, $key_value:expr) => {{
let meter = meter!();
paste::paste! {
meter
.[<$typ _observable_gauge>]($name) // typ = f64 or u64 or u64
.with_description($disc)
.with_unit($unit)
.with_callback(|observe| {
observe.observe($measurement, $key_value);
})
.init()
}
}};
}
Loading

0 comments on commit 626873f

Please sign in to comment.