Skip to content

Commit

Permalink
Create separate simplified readme
Browse files Browse the repository at this point in the history
  • Loading branch information
frigus02 committed Dec 5, 2021
1 parent 8dd7d69 commit c0fca97
Show file tree
Hide file tree
Showing 6 changed files with 15 additions and 251 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ rand = "0.8.4"
surf = "2.2.0"
test-case = "1.1.0"
tokio = { version = "1.7.0", features = ["rt", "macros", "process", "time"] }
version-sync = "0.9.2"
version-sync = { version = "0.9.2", default-features = false, features = ["html_root_url_updated", "contains_regex"] }

[badges]
github = { repository = "frigus02/opentelemetry-application-insights", workflow = "CI" }
Expand Down
215 changes: 11 additions & 204 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
[![Crates.io 0.18.0](https://img.shields.io/crates/v/opentelemetry-application-insights.svg)](https://crates.io/crates/opentelemetry-application-insights)
[![Documentation 0.18.0](https://docs.rs/opentelemetry-application-insights/badge.svg)](https://docs.rs/opentelemetry-application-insights)
[![Crates.io](https://img.shields.io/crates/v/opentelemetry-application-insights.svg)](https://crates.io/crates/opentelemetry-application-insights)
[![Documentation](https://docs.rs/opentelemetry-application-insights/badge.svg)](https://docs.rs/opentelemetry-application-insights)
[![Workflow Status](https://github.com/frigus02/opentelemetry-application-insights/workflows/CI/badge.svg)](https://github.com/frigus02/opentelemetry-application-insights/actions?query=workflow%3A%22CI%22)

# opentelemetry-application-insights

An [Azure Application Insights] exporter implementation for [OpenTelemetry Rust].

[Azure Application Insights]: https://docs.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview
[OpenTelemetry Rust]: https://github.com/open-telemetry/opentelemetry-rust
An [Azure Application Insights](https://docs.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview) exporter implementation for [OpenTelemetry Rust](https://github.com/open-telemetry/opentelemetry-rust).

**Disclaimer**: This is not an official Microsoft product.

## Usage

Configure a OpenTelemetry pipeline using the Application Insights exporter and start creating
spans (this example requires the **reqwest-client-blocking** feature):
Configure a OpenTelemetry pipeline using the Application Insights exporter and start creating spans (this example requires the **reqwest-client** feature):

```rust
use opentelemetry::trace::Tracer as _;
Expand All @@ -29,213 +25,24 @@ fn main() {
}
```

### Simple or Batch

The functions `build_simple` and `install_simple` build/install a trace pipeline using the
simple span processor. This means each span is processed and exported synchronously at the time
it ends.

The functions `build_batch` and `install_batch` use the batch span processor instead. This
means spans are exported periodically in batches, which can be better for performance. This
feature requires an async runtime such as Tokio or async-std. If you decide to use a batch span
processor, make sure to call `opentelemetry::global::shutdown_tracer_provider()` before your
program exits to ensure all remaining spans are exported properly (this example requires the
**reqwest-client** and **opentelemetry/rt-tokio** features).

```rust
use opentelemetry::trace::Tracer as _;

#[tokio::main]
async fn main() {
let instrumentation_key = std::env::var("INSTRUMENTATION_KEY").unwrap();
let tracer = opentelemetry_application_insights::new_pipeline(instrumentation_key)
.with_client(reqwest::Client::new())
.install_batch(opentelemetry::runtime::Tokio);

tracer.in_span("main", |_cx| {});

opentelemetry::global::shutdown_tracer_provider();
}
```
See documentation for more:

### Async runtimes and HTTP clients

In order to support different async runtimes, the exporter requires you to specify an HTTP
client that works with your chosen runtime. The [`opentelemetry-http`] crate comes with support
for:

- [`surf`] for [`async-std`]: enable the **surf-client** and **opentelemetry/rt-async-std**
features and configure the exporter with `with_client(surf::Client::new())`.
- [`reqwest`] for [`tokio`]: enable the **reqwest-client** and **opentelemetry/rt-tokio**
features and configure the exporter with either `with_client(reqwest::Client::new())` or
`with_client(reqwest::blocking::Client::new())`.

[`async-std`]: https://crates.io/crates/async-std
[`opentelemetry-http`]: https://crates.io/crates/opentelemetry-http
[`reqwest`]: https://crates.io/crates/reqwest
[`surf`]: https://crates.io/crates/surf
[`tokio`]: https://crates.io/crates/tokio

Alternatively you can bring any other HTTP client by implementing the `HttpClient` trait.

### Metrics

Please note: Metrics are still experimental both in the OpenTelemetry specification as well as
Rust implementation.

Please note: The metrics export configuration is still a bit rough in this crate. But once
configured it should work as expected.

This requires the **metrics** feature.

```rust
use opentelemetry::{global, sdk};
use std::time::Duration;

#[tokio::main]
async fn main() {
// Setup exporter
let instrumentation_key = std::env::var("INSTRUMENTATION_KEY").unwrap();
let exporter = opentelemetry_application_insights::Exporter::new(instrumentation_key, ());
let controller = sdk::metrics::controllers::push(
sdk::metrics::selectors::simple::Selector::Exact,
sdk::export::metrics::ExportKindSelector::Stateless,
exporter,
tokio::spawn,
opentelemetry::util::tokio_interval_stream,
)
.with_period(Duration::from_secs(1))
.build();
global::set_meter_provider(controller.provider());

// Record value
let meter = global::meter("example");
let value_recorder = meter.f64_value_recorder("pi").init();
value_recorder.record(3.14, &[]);

// Give exporter some time to export values before exiting
tokio::time::sleep(Duration::from_secs(5)).await;
}
```

## Attribute mapping

OpenTelemetry and Application Insights are using different terminology. This crate tries it's
best to map OpenTelemetry fields to their correct Application Insights pendant.

- [OpenTelemetry specification: Span](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/api.md#span)
- [Application Insights data model](https://docs.microsoft.com/en-us/azure/azure-monitor/app/data-model)

### Spans

The OpenTelemetry SpanKind determines the Application Insights telemetry type:

| OpenTelemetry SpanKind | Application Insights telemetry type |
| -------------------------------- | ----------------------------------- |
| `CLIENT`, `PRODUCER`, `INTERNAL` | Dependency |
| `SERVER`, `CONSUMER` | Request |

The Span's status determines the Success field of a Dependency or Request. Success is `false` if
the status `Error`; otherwise `true`.

The following of the Span's attributes map to special fields in Application Insights (the
mapping tries to follow the OpenTelemetry semantic conventions for [trace] and [resource]).

Note: for `INTERNAL` Spans the Dependency Type is always `"InProc"`.

[trace]: https://github.com/open-telemetry/opentelemetry-specification/tree/master/specification/trace/semantic_conventions
[resource]: https://github.com/open-telemetry/opentelemetry-specification/tree/master/specification/resource/semantic_conventions

| OpenTelemetry attribute key | Application Insights field |
| ------------------------------------------------- | ----------------------------------------------------- |
| `service.version` | Context: Application version (`ai.application.ver`) |
| `enduser.id` | Context: Authenticated user id (`ai.user.authUserId`) |
| `service.namespace` + `service.name` | Context: Cloud role (`ai.cloud.role`) |
| `service.instance.id` | Context: Cloud role instance (`ai.cloud.roleInstance`) |
| `telemetry.sdk.name` + `telemetry.sdk.version` | Context: Internal SDK version (`ai.internal.sdkVersion`) |
| `SpanKind::Server` + `http.method` + `http.route` | Context: Operation Name (`ai.operation.name`) |
| `ai.*` | Context: AppInsights Tag (`ai.*`) |
| `http.url` | Dependency Data |
| `db.statement` | Dependency Data |
| `http.host` | Dependency Target |
| `net.peer.name` + `net.peer.port` | Dependency Target |
| `net.peer.ip` + `net.peer.port` | Dependency Target |
| `db.name` | Dependency Target |
| `http.status_code` | Dependency Result code |
| `db.system` | Dependency Type |
| `messaging.system` | Dependency Type |
| `rpc.system` | Dependency Type |
| `"HTTP"` if any `http.` attribute exists | Dependency Type |
| `"DB"` if any `db.` attribute exists | Dependency Type |
| `http.url` | Request Url |
| `http.scheme` + `http.host` + `http.target` | Request Url |
| `http.client_ip` | Request Source |
| `net.peer.ip` | Request Source |
| `http.status_code` | Request Response code |

All other attributes are directly converted to custom properties.

For Requests the attributes `http.method` and `http.route` override the Name.

### Events

Events are converted into Exception telemetry if the event name equals `"exception"` (see
OpenTelemetry semantic conventions for [exceptions]) with the following mapping:

| OpenTelemetry attribute key | Application Insights field |
| --------------------------- | -------------------------- |
| `exception.type` | Exception type |
| `exception.message` | Exception message |
| `exception.stacktrace` | Exception call stack |

All other events are converted into Trace telemetry.

All other attributes are directly converted to custom properties.

[exceptions]: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/exceptions.md

### Metrics

Metrics get reported to Application Insights as Metric Data. The [`Aggregator`] (chosen through
the [`Selector`] passed to the controller) determines how the data is represented.

| Aggregator | Data representation |
| -------------- | --------------------------------------------------------- |
| Array | list of measurements |
| DDSketch | aggregation with value, min, max and count |
| Histogram | aggregation with sum and count (buckets are not exported) |
| LastValue | one measurement |
| MinMaxSumCount | aggregation with value, min, max and count |
| Sum | aggregation with only a value |

[`Aggregator`]: https://docs.rs/opentelemetry/0.16.0/opentelemetry/sdk/export/metrics/trait.Aggregator.html
[`Selector`]: https://docs.rs/opentelemetry/0.16.0/opentelemetry/sdk/metrics/selectors/simple/enum.Selector.html
- [Simple or Batch](https://docs.rs/opentelemetry-application-insights/latest/opentelemetry_application_insights/#simple-or-batch)
- [Async runtimes and HTTP clients](https://docs.rs/opentelemetry-application-insights/latest/opentelemetry_application_insights/#async-runtimes-and-http-clients)
- [Metrics](https://docs.rs/opentelemetry-application-insights/latest/opentelemetry_application_insights/#metrics)

## Application Insights integration

### Thanks

Huge thanks goes to [Denis Molokanov] for the amazing [appinsights] crate.
Check it out if you want a more direct integration with Application Insights.

[Denis Molokanov]: https://github.com/dmolokanov
[appinsights]: https://github.com/dmolokanov/appinsights-rs
Huge thanks goes to [Denis Molokanov](https://github.com/dmolokanov) for the amazing [appinsights](https://github.com/dmolokanov/appinsights-rs) crate. Check it out if you want a more direct integration with Application Insights.

### Documentation

The only official documentation I could find is this one. Follow the links to
see the data model and endpoint description.
The only official documentation I could find is this one. Follow the links to see the data model and endpoint description.

> Can I send telemetry to the Application Insights portal?
>
> We recommend you use our SDKs and use the [SDK API]. There are variants of
> the SDK for various [platforms]. These SDKs handle buffering, compression,
> throttling, retries, and so on. However, the [ingestion schema] and [endpoint
> protocol] are public.
> We recommend you use our SDKs and use the [SDK API](https://docs.microsoft.com/en-us/azure/azure-monitor/app/api-custom-events-metrics). There are variants of the SDK for various [platforms](https://docs.microsoft.com/en-us/azure/azure-monitor/app/platforms). These SDKs handle buffering, compression, throttling, retries, and so on. However, the [ingestion schema](https://github.com/microsoft/ApplicationInsights-dotnet/tree/master/BASE/Schema/PublicSchema) and [endpoint protocol](https://github.com/Microsoft/ApplicationInsights-Home/blob/master/EndpointSpecs/ENDPOINT-PROTOCOL.md) are public.
>
> -- https://docs.microsoft.com/en-us/azure/azure-monitor/faq#can-i-send-telemetry-to-the-application-insights-portal
[SDK API]: https://docs.microsoft.com/en-us/azure/azure-monitor/app/api-custom-events-metrics
[platforms]: https://docs.microsoft.com/en-us/azure/azure-monitor/app/platforms
[ingestion schema]: https://github.com/microsoft/ApplicationInsights-dotnet/tree/master/BASE/Schema/PublicSchema
[endpoint protocol]: https://github.com/Microsoft/ApplicationInsights-Home/blob/master/EndpointSpecs/ENDPOINT-PROTOCOL.md
36 changes: 0 additions & 36 deletions README.tpl

This file was deleted.

7 changes: 0 additions & 7 deletions docs/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@ In order to release a new version, follow these steps.

1. Update the version number in the `html_root_url` tag in [lib.rs](../src/lib.rs).

1. Update the [README.md](../README.md) by running `cargo readme -o README.md` in the root of the repository.

TODO: I think this has to change. cargo-readme doesn't work with feature-gated docs, which is nice to have for the metrics feature. I'd like to have a code example for it, which will only compile with the metrics feature. But I also want cargo test to work with just the default features.

Parsing cfg_attr in cargo-readme seems quite hard, though. So maybe the solution is to create a shorter, separately updated readme. Then have an integration test that extracts code samples from the readme and compiles them to ensure they keep working.


1. Commit the changes.

1. Tag the commit.
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//! # Usage
//!
//! Configure a OpenTelemetry pipeline using the Application Insights exporter and start creating
//! spans (this example requires the **reqwest-client-blocking** feature):
//! spans (this example requires the **reqwest-client** feature):
//!
//! ```no_run
//! use opentelemetry::trace::Tracer as _;
Expand Down
4 changes: 2 additions & 2 deletions tests/version_numbers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#[test]
fn readme_deps() {
version_sync::assert_markdown_deps_updated!("README.md");
fn changelog() {
version_sync::assert_contains_substring!("CHANGELOG.md", "## [{version}]");
}

#[test]
Expand Down

0 comments on commit c0fca97

Please sign in to comment.