-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
- Loading branch information
1 parent
b5a24d1
commit a66dac0
Showing
8 changed files
with
364 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
name: Sanity Check codebase | ||
|
||
on: | ||
push: | ||
branches: [main] | ||
pull_request: | ||
branches: [main] | ||
|
||
jobs: | ||
check: | ||
name: Build | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
node: [stable, beta, nightly] | ||
steps: | ||
- name: Checkout sources | ||
uses: actions/checkout@v2 | ||
|
||
- name: Install toolchain | ||
uses: actions-rs/toolchain@v1 | ||
with: | ||
profile: minimal | ||
toolchain: ${{ matrix.node }} | ||
override: true | ||
|
||
- name: Run cargo check | ||
uses: actions-rs/cargo@v1 | ||
with: | ||
command: check | ||
|
||
- name: Run cargo test | ||
run: make check | ||
|
||
lints: | ||
name: Lints | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout sources | ||
uses: actions/checkout@v2 | ||
|
||
- name: Install stable toolchain | ||
uses: actions-rs/toolchain@v1 | ||
with: | ||
profile: minimal | ||
toolchain: stable | ||
override: true | ||
components: rustfmt, clippy | ||
|
||
- name: Run cargo fmt | ||
uses: actions-rs/cargo@v1 | ||
with: | ||
command: fmt | ||
args: --all -- --check |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
[package] | ||
name = "opentelemetry-common" | ||
version = "0.1.0" | ||
edition = "2021" | ||
authors = ["Vincent <vincenzopalazzo@member.fsf.org>"] | ||
description = "A common library for OpenTelemetry logging in Rust." | ||
license = "GPL-2.0" | ||
repository = "https://github.com/vincent/opentelemetry-log" | ||
documentation = "https://docs.rs/opentelemetry-common" | ||
homepage = "https://github.com/vincent/opentelemetry-log" | ||
keywords = ["opentelemetry", "logging", "log", "rust"] | ||
categories = ["development-tools"] | ||
|
||
[dependencies] | ||
opentelemetry = { version = "0.25", features = ["logs"] } | ||
opentelemetry-appender-log = { version = "0.25", default-features = false } | ||
opentelemetry_sdk = { version = "0.25", features = [ "logs", "rt-tokio" ] } | ||
opentelemetry-otlp = { version = "0.25", features = [ "http-proto", "reqwest-client", "reqwest-rustls", "logs" ] } | ||
opentelemetry-semantic-conventions = { version = "0.25.0" } | ||
anyhow = "^1" | ||
log = { version = "0.4", features = ["std"] } | ||
|
||
[dev-dependencies] | ||
clap = { version = "4.0.26", features = ["derive"] } | ||
tokio = { version = "^1.29.1", features = ["rt-multi-thread", "parking_lot"] } | ||
env_logger = "0.11.3" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
CC=cargo | ||
FMT=fmt | ||
|
||
OPTIONS= | ||
|
||
default: fmt | ||
$(CC) build | ||
@make clippy | ||
|
||
fmt: | ||
$(CC) fmt --all | ||
|
||
check: | ||
$(CC) test --all | ||
|
||
example: | ||
@echo "No example for the moment" | ||
|
||
clean: | ||
$(CC) clean | ||
|
||
clippy: | ||
$(CC) clippy --all --tests | ||
|
||
coffee: | ||
$(CC) build --release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,43 @@ | ||
# opentelemetry-log | ||
A minimal and simple opentelemetry log adapter that allow you to export your rust log to an opentelemetry collector | ||
|
||
[![CI](https://github.com/vincent/open-source/opentelemetry-log/actions/workflows/ci.yml/badge.svg)](https://github.com/vincent/open-source/opentelemetry-log/actions/workflows/ci.yml) | ||
[![Latest Version](https://img.shields.io/crates/v/opentelemetry-log.svg)](https://crates.io/crates/opentelemetry-log) | ||
[![License](https://img.shields.io/crates/l/opentelemetry-log.svg)](https://github.com/vincent/open-source/opentelemetry-log/blob/main/LICENSE) | ||
|
||
A minimal and simple OpenTelemetry log adapter that allows you to export your Rust logs to an OpenTelemetry collector. | ||
|
||
## Features | ||
|
||
- Export Rust logs to an OpenTelemetry collector | ||
- Minimal and simple adapter | ||
- Easy integration with existing logging (just `log` for now) frameworks | ||
|
||
## Installation | ||
|
||
Add this to your `Cargo.toml`: | ||
|
||
```toml | ||
[dependencies] | ||
opentelemetry-log = "0.1" | ||
``` | ||
|
||
## Usage | ||
|
||
```rust | ||
use opentelemetry_common::Opentelemetry; | ||
|
||
fn main() { | ||
let mut manager = Opentelemetry::new(); | ||
manager.init_log("example", &args.level, &url)?; | ||
// Your application code | ||
} | ||
``` | ||
|
||
## License | ||
|
||
This project is licensed under the GNU General Public License. See the [LICENSE](LICENSE) file for details. | ||
|
||
## How to Deploy OpenTelemetry with Grafana | ||
|
||
How to inspect the logs is something that is dependent on the user, but if you are starting from scratch and | ||
you want to learn how to work with Grafana and OpenTelemetry, I suggest starting from here: https://github.com/grafana/docker-otel-lgtm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
use clap::Parser; | ||
|
||
use opentelemetry_common::Opentelemetry; | ||
|
||
#[derive(Debug, Parser)] | ||
#[clap(name = "opentelemetry.rs")] | ||
pub struct Args { | ||
#[clap(short, long, value_parser)] | ||
pub url: String, | ||
#[clap(short, long, value_parser)] | ||
pub message: String, | ||
#[clap(short, long)] | ||
pub level: String, | ||
} | ||
|
||
// the async main is not required by our application | ||
// but the opentelemetry app is requiring to be | ||
// in an async context, so we use this | ||
#[tokio::main] | ||
async fn main() -> anyhow::Result<()> { | ||
let args = Args::parse(); | ||
let url = args.url; | ||
|
||
let mut manager = Opentelemetry::new(); | ||
manager.init_log("example", &args.level, &url)?; | ||
|
||
match args.level.as_str() { | ||
"info" => log::info!("{}", args.message), | ||
"debug" => log::debug!("{}", args.message), | ||
_ => anyhow::bail!("level `{}` not found", args.level), | ||
} | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
//! # OpenTelemetry Log Integration | ||
//! | ||
//! This crate provides integration with OpenTelemetry for logging purposes. It allows you to | ||
//! initialize and manage loggers that are compatible with the OpenTelemetry SDK. | ||
//! | ||
//! ## Features | ||
//! | ||
//! - Initialize loggers with specific tags, levels, and exporter endpoints. | ||
//! - Automatically manage the lifecycle of loggers, ensuring proper shutdown. | ||
//! | ||
//! ## Usage | ||
//! | ||
//! Add this crate to your `Cargo.toml`: | ||
//! | ||
//! ```toml | ||
//! [dependencies] | ||
//! opentelemetry-log = "0.1" | ||
//! ``` | ||
//! | ||
//! Import and use the `Opentelemetry` struct to manage your loggers: | ||
//! | ||
//! ```rust | ||
//! use opentelemetry_log::Opentelemetry; | ||
Check failure on line 23 in src/lib.rs GitHub Actions / Build (beta)
|
||
//! | ||
//! fn main() { | ||
//! let mut otel = Opentelemetry::new(); | ||
//! otel.init_log("my_app", "info", "http://localhost:4317").unwrap(); // Please do not unwrap in production code | ||
//! // Your application logic here | ||
//! } | ||
//! ``` | ||
//! | ||
//! ## Modules | ||
//! | ||
//! - `log`: Contains the log initialization logic. | ||
//! | ||
//! ## Structs | ||
//! | ||
//! - `Opentelemetry`: Main struct for managing OpenTelemetry loggers. | ||
//! | ||
//! ## Traits | ||
//! | ||
//! - `Default`: Provides a default implementation for `Opentelemetry`. | ||
//! - `Drop`: Ensures proper shutdown of loggers when `Opentelemetry` instances are dropped. | ||
//! | ||
//! ## Errors | ||
//! | ||
//! This crate uses the `anyhow` crate for error handling. Ensure you handle errors appropriately | ||
//! when initializing and using loggers. | ||
pub mod log; | ||
pub use anyhow; | ||
|
||
use std::sync::Arc; | ||
|
||
use opentelemetry_sdk::logs as sdklogs; | ||
|
||
/// Main struct for managing OpenTelemetry loggers, when you init the logger | ||
/// remember to keep this alive for all the lifetime of the application. | ||
/// | ||
/// An example can be found in the `examples` directory. | ||
#[derive(Debug, Clone)] | ||
pub struct Opentelemetry { | ||
pub(crate) logger: Option<Arc<sdklogs::LoggerProvider>>, | ||
} | ||
|
||
impl Default for Opentelemetry { | ||
fn default() -> Self { | ||
Self::new() | ||
} | ||
} | ||
|
||
impl Opentelemetry { | ||
pub fn new() -> Self { | ||
Opentelemetry { logger: None } | ||
} | ||
|
||
/// Initialize a new logger with the provided tag, level, and exporter endpoint. | ||
/// this is assuming tat your application is using `log` crate | ||
pub fn init_log( | ||
&mut self, | ||
tag: &str, | ||
level: &str, | ||
exporter_endpoint: &str, | ||
) -> anyhow::Result<()> { | ||
log::init(self, tag.to_owned(), level, exporter_endpoint)?; | ||
Ok(()) | ||
} | ||
} | ||
|
||
impl Drop for Opentelemetry { | ||
fn drop(&mut self) { | ||
let Some(Err(err)) = self.logger.as_ref().map(|log| log.shutdown()) else { | ||
return; | ||
}; | ||
panic!("Failed to shutdown logger: {:?}", err); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
//! This module provides functionality to initialize and configure a logger that exports logs | ||
//! using OpenTelemetry. The logger can be configured with different levels and exporter endpoints. | ||
//! | ||
//! # Functions | ||
//! | ||
//! - `init`: Initializes a new logger exported with OpenTelemetry. It sets up the logger provider, | ||
//! configures the log appender, and sets the global logger. | ||
//! - `http_exporter`: Creates a new HTTP exporter builder for OpenTelemetry. | ||
//! | ||
//! # Usage | ||
//! | ||
//! To use this module, call the `init` function with the appropriate parameters to set up the logger. | ||
//! The logger will then export logs to the specified endpoint using the configured protocol. | ||
//! | ||
//! # Example | ||
//! | ||
//! ```rust | ||
//! use crate::log::init; | ||
Check failure on line 18 in src/log.rs GitHub Actions / Build (beta)
|
||
//! use crate::Opentelemetry; | ||
Check failure on line 19 in src/log.rs GitHub Actions / Build (beta)
|
||
//! | ||
//! let mut manager = Opentelemetry::new(); | ||
//! let tag = "my_service".to_string(); | ||
//! let level = "info"; | ||
//! let exporter_endpoint = "http://localhost:4317"; | ||
//! | ||
//! init(&mut manager, tag, level, exporter_endpoint).expect("Failed to initialize logger"); | ||
//! ``` | ||
//! | ||
//! # Dependencies | ||
//! | ||
//! This module depends on the following crates: | ||
//! | ||
//! - `opentelemetry` | ||
//! - `opentelemetry_appender_log` | ||
//! - `opentelemetry_otlp` | ||
//! - `opentelemetry_sdk` | ||
//! - `log` | ||
//! - `anyhow` | ||
use std::str::FromStr; | ||
use std::sync::Arc; | ||
|
||
use opentelemetry::KeyValue; | ||
use opentelemetry_appender_log::OpenTelemetryLogBridge; | ||
use opentelemetry_otlp::HttpExporterBuilder; | ||
use opentelemetry_otlp::Protocol; | ||
use opentelemetry_otlp::WithExportConfig; | ||
use opentelemetry_sdk::Resource; | ||
|
||
use crate::Opentelemetry; | ||
|
||
/// Initialize a new logger exported with open telemetry. | ||
pub fn init( | ||
manager: &mut Opentelemetry, | ||
tag: String, | ||
level: &str, | ||
exporter_endpoint: &str, | ||
) -> anyhow::Result<()> { | ||
let logger_provider = opentelemetry_otlp::new_pipeline() | ||
.logging() | ||
.with_resource(Resource::new(vec![KeyValue::new( | ||
opentelemetry_semantic_conventions::resource::SERVICE_NAME, | ||
tag, | ||
)])) | ||
.with_exporter( | ||
http_exporter() | ||
.with_protocol(Protocol::HttpBinary) //can be changed to `Protocol::HttpJson` to export in JSON format | ||
.with_endpoint(format!("{exporter_endpoint}/v1/logs")), | ||
) | ||
.install_batch(opentelemetry_sdk::runtime::Tokio)?; | ||
manager.logger = Some(Arc::new(logger_provider.clone())); | ||
|
||
// Setup Log Appender for the log crate. | ||
let otel_log_appender = OpenTelemetryLogBridge::new(&logger_provider); | ||
|
||
// the install method set a global provider, that we can use now | ||
log::set_boxed_logger(Box::new(otel_log_appender)).map_err(|err| anyhow::anyhow!("{err}"))?; | ||
let level = log::Level::from_str(level)?; | ||
log::set_max_level(level.to_level_filter()); | ||
Ok(()) | ||
} | ||
|
||
fn http_exporter() -> HttpExporterBuilder { | ||
opentelemetry_otlp::new_exporter().http() | ||
} |