pyo3-tracing-subscriber 0.1.0

A Python module for configuring and initializing tracing subscribers from Python.
Documentation
# PyO3 Tracing Subscriber 

## Background

### What this is

`pyo3_tracing_subscriber` provides a `PyModule` that can be added to upstream `pyo3` extension modules in order to support the configuration and initialization of Rust tracing subscribers from Python.

### What this is not

* Any initialized tracing subscriber imported from your upstream package will _not_ collect traces from any other `pyo3` extension module. In other words, any `pyo3` extension module will need to separately export tracing configuration and context managers, which in turn must be separately initialized in order to capture Rust traces from respective `pyo3` extension modules.
* Currently, only three tracing subcriber layers are supported:
    * `tracing_subscriber::fmt` which writes traces to file (or stdout) in a human readable format.
    * `opentelemetry-stdout` which writes traces to file (or stdout) in OTLP format. Available only with the `layer-otel-otlp-file` feature.
    * `opentelemetry-otlp` which sends traces to an OpenTelemetry OTLP endpoint. Available only with the `layer-otel-otlp` feature.
* This does not propagate OpenTelemetry contexts from Python into Rust (or vice versa). Use the `pyo3-opentelemetry` crate for that feature.

## Usage

> For a complete functioning example, see the `examples/pyo3-opentelemetry-lib/src/lib.rs` example within this crate's repository.

Given a `pyo3` extension module named "my_module" that would like to expose the tracing subscriber configuration and context manager classes from "my_module._tracing_subscriber", from Rust:

```rust
use pyo3::prelude::*;

#[pymodule]
fn my_module(py: Python, m: &PyModule) -> PyResult<()> {
    // Add your own Python classes, functions and modules.

    pyo3_tracing_subscriber::add_submodule(
        "my_module",
        "_tracing_subscriber",
        py,
        m,
    )?;
    Ok(())
}
```

Then a user could initialize a tracing subscriber that logged to stdout from Python:

```python
import my_module
from my_module._tracing_subscriber import (
    GlobalTracingConfig,
    SimpleConfig,
    Tracing,
    subscriber,
)
from pyo3_opentelemetry_lib._tracing_subscriber.layers import file


def main():
    tracing_configuration = GlobalTracingConfig(
        export_process=SimpleConfig(
            subscriber=subscriber.Config(
                layer=file.Config()
            )
        )
    )
    with Tracing(config=config):
        result = my_module.example_function()
        my_module.other_example_function(result)

if __name__ == '__main__':
    main()
```

### Building Python Stub Files

This crate provides a convenient method for adding stub files to your Python source code with the `stubs` feature.

Given a `pyo3` extension module named "my_module" that uses the `pyo3-tracing-subscriber` crate to expose tracing subscriber configuration and context manager classes from "my_module._tracing_subscriber", in the upstream `build.rs` file:

```rust
use pyo3_tracing_subscriber_stubs::write_stub_files;

fn main() {
    let target_dir = std::path::Path::new("./my_module/_tracing_subscriber");
    std::fs::remove_dir_all(target_dir).unwrap();
    write_stub_files(
        "my_module",
        "_tracing_subscriber",
        target_dir,
        true, // layer_otel_otlp_file feature enabled
        true, // layer_otel_otlp feature enabled
    )
    .unwrap();
}
```