diesel_tracing/lib.rs
1/*!
2`diesel-tracing` provides connection structures that can be used as drop in
3replacements for diesel connections with extra tracing and logging.
4
5# Usage
6
7## Feature flags
8
9Just like diesel this crate relies on some feature flags to specify which
10database driver to support. Just as in diesel configure this in your
11`Cargo.toml`
12
13```toml
14[dependencies]
15diesel-tracing = { version = "<version>", features = ["<postgres|mysql|sqlite>"] }
16```
17
18# Establishing a connection
19
20`diesel-tracing` has several instrumented connection structs that wrap the underlying
21`diesel` implementations of the connection. As these structs also implement the
22`diesel::Connection` trait, establishing a connection is done in the same way as
23the `diesel` crate. For example, with the `postgres` feature flag:
24
25```
26#[cfg(feature = "postgres")]
27{
28 use diesel_tracing::pg::InstrumentedPgConnection;
29
30 let conn = InstrumentedPgConnection::establish("postgresql://example");
31}
32```
33
34This connection can then be used with diesel dsl methods such as
35`diesel::prelude::RunQueryDsl::execute` or `diesel::prelude::RunQueryDsl::get_results`.
36
37# Code reuse
38
39In some applications it may be desirable to be able to use both instrumented and
40uninstrumented connections. For example, in the tests for a library. To achieve this
41you can use the `diesel::Connection` trait.
42
43```
44fn use_connection(
45 conn: &impl diesel::Connection<Backend = diesel::pg::Pg>,
46) -> () {}
47```
48
49Will accept both `diesel::PgConnection` and the `InstrumentedPgConnection`
50provided by this crate and this works similarly for other implementations
51of `Connection` if you change the parametized Backend marker in the
52function signature.
53
54Unfortunately there are some methods specific to backends which are not
55encapsulated by the `diesel::Connection` trait, so in those places it is
56likely that you will just need to replace your connection type with the
57Instrumented version.
58
59## Connection Pooling
60
61`diesel-tracing` supports the `r2d2` connection pool, through the `r2d2`
62feature flag. See `diesel::r2d2` for details of usage.
63
64# Notes
65
66## Fields
67
68Currently the few fields that are recorded are a subset of the `OpenTelemetry`
69semantic conventions for [databases](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/database.md).
70This was chosen for compatibility with the `tracing-opentelemetry` crate, but
71if it makes sense for other standards to be available this could be set by
72feature flag later.
73
74Database statements may optionally be recorded by enabling the
75`statement-fields` feature. This uses [`diesel::debug_query`](https://docs.rs/diesel/latest/diesel/fn.debug_query.html)
76to convert the query into a string. As this may expose sensitive information,
77the feature is not enabled by default.
78
79It would be quite useful to be able to parse connection strings to be able
80to provide more information, but this may be difficult if it requires use of
81diesel feature flags by default to access the underlying C bindings.
82
83## Levels
84
85All logged traces are currently set to DEBUG level, potentially this could be
86changed to a different default or set to be configured by feature flags. At
87them moment this crate is quite new and it's unclear what a sensible default
88would be.
89
90## Errors
91
92Errors in Result objects returned by methods on the connection should be
93automatically logged through the `err` directive in the `instrument` macro.
94
95## Sensitive Information
96
97As statements may contain sensitive information they are currently not recorded
98explicitly, unless you opt in by enabling the `statement-fields` feature.
99Finding a way to filter statements intelligently to solve this problem is a
100TODO.
101
102Similarly connection strings are not recorded in spans as they may contain
103passwords
104
105## TODO
106
107- [ ] Record and log connection information (filtering out sensitive fields)
108- [ ] Provide a way of filtering statements, maybe based on regex?
109
110*/
111#![warn(clippy::all, clippy::pedantic)]
112
113#[cfg(feature = "mysql")]
114pub mod mysql;
115#[cfg(feature = "postgres")]
116pub mod pg;
117#[cfg(feature = "sqlite")]
118pub mod sqlite;