1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use ;
pub use ;
pub use ;
/// Close a given value
///
/// This gives an opportunity do things like stopping timers, collecting fanned-in data, etc.
///
/// If possible, implement this trait for both `&MyValue` and `MyValue`, as this will allow
/// use via smart pointers (e.g. on `Arc<MyValue>`).
///
/// ```
/// use metrique::{CloseValue, CloseValueRef};
///
/// struct MyValue;
///
/// impl CloseValue for &'_ MyValue {
/// type Closed = u32;
/// fn close(self) -> Self::Closed { 42 }
/// }
///
/// impl CloseValue for MyValue {
/// type Closed = u32;
/// fn close(self) -> Self::Closed { self.close_ref() /* delegate to by-ref implementation */ }
/// }
/// ```
///
/// This trait is also used for entries that can be closed as [`CloseEntry`].
///
/// ## Why `CloseValue` is not implemented for `&str` or `&String`
///
/// Since `CloseValue` takes its argument by value, an implementation of `CloseValue`
/// for `&str` or `&String` would have to allocate.
///
/// The most common case this is encountered is when using `#[metrics(subfield)]`:
///
/// ```compile_fail
/// # use std::sync::Arc;
/// use metrique::unit_of_work::metrics;
///
/// #[metrics(subfield)]
/// struct ChildMetrics {
/// field: String,
/// }
///
/// #[metrics]
/// struct MainMetric {
/// // this is allowed when using `#[metrics(subfield)]`
/// #[metrics(flatten)]
/// child: Arc<ChildMetrics>,
/// }
/// ```
///
/// Since `#[metrics(subfield)]` supports taking the fields by reference, as
/// you this would have to allocate and therefore there is no implementation
/// to avoid surprise allocations.
///
/// There are a few options to deal with it:
///
/// 1. Use a `&'static str` or a `#[metrics(value(string))]` enum instead of a `String`, avoiding
/// the allocation.
/// ```rust
/// # use metrique::unit_of_work::metrics;
/// #[metrics(value(string))]
/// enum MyEnum { Foo }
///
/// #[metrics(subfield)]
/// struct ChildMetrics {
/// field_1: &'static str,
/// field_2: MyEnum,
/// }
/// ```
/// 2. Use `#[metrics(subfield_owned)]`, which implements `CloseValue` by value.
/// In that case, you can't use the subfield via an `Arc` but only by-value:
/// ```rust
/// # use metrique::unit_of_work::metrics;
/// #[metrics(subfield_owned)]
/// struct ChildMetrics {
/// field: String,
/// }
///
/// #[metrics]
/// struct MainMetric {
/// // must use by-value
/// #[metrics(flatten)]
/// child: ChildMetrics,
/// }
/// ```
/// 3. If you are fine with allocating, you could make your own string wrapper type.
/// ```rust
/// # use metrique::unit_of_work::metrics;
/// struct StringValue(String);
/// impl metrique::CloseValue for &StringValue {
/// type Closed = String;
///
/// fn close(self) -> String { self.0.clone() }
/// }
///
/// impl metrique::CloseValue for StringValue {
/// type Closed = String;
///
/// fn close(self) -> String { self.0 }
/// }
///
/// #[metrics(subfield)]
/// struct ChildMetrics {
/// field: StringValue,
/// }
/// ```
/// Close a value without taking ownership
///
/// This trait is meant to be used for [`CloseValue`] impls for smart-pointer-like
/// types, as in
///
/// ```
/// use metrique::{CloseValue, CloseValueRef};
///
/// struct Smaht<T>(T);
///
/// impl<T: CloseValueRef> CloseValue for &'_ Smaht<T> {
/// type Closed = T::Closed;
/// fn close(self) -> T::Closed { self.0.close_ref() }
/// }
///
/// impl<T: CloseValueRef> CloseValue for Smaht<T> {
/// type Closed = T::Closed;
/// fn close(self) -> T::Closed { self.0.close_ref() }
/// }
/// ```
///
/// This trait is not to be implemented or called directly. It mostly exists
/// because it makes trait inference a bit smarter (it's also not a full
/// trait alias due to trait inference reasons).
/// An object that can be closed into an [InflectableEntry]. This is the
/// normal way of generating a metric entry - by starting with a a struct
/// that implements this trait (that is generally generated using the `#[metrics]` macro),
/// wrapping it in a [`RootEntry`] to generate an [`Entry`], and then emitting that
/// to an [`EntrySink`].
///
/// This is just a trait alias for `CloseValue<Closed: InflectableEntry>`.
///
/// [close-value]: CloseValue
/// [`Entry`]: metrique_writer_core::Entry
/// [`EntrySink`]: metrique_writer_core::EntrySink
/// [`RootEntry`]: https://docs.rs/metrique/0.1/metrique/struct.RootEntry.html
/// A trait for metric entries where the names of the fields can be "inflected"
/// using a [`NameStyle`]. This defines the interface for metric *sources*
/// that want to be able to generate metric structs that can be renamed
/// without having any string operations happen at runtime.
///
/// Both `InflectableEntry` and [`Entry`] are intended to be "pure" structs - all
/// references to channels, counters and the like are expected to be resolved when
/// creating the `InflectableEntry`.
///
/// An `InflectableEntry` with any specific set of type parameters is equivalent to an
/// [`Entry`]. It should be wrapped by a wrapper that implements [`Entry`] and delegates
/// to it with a particular set of type parameters, for example `RootEntry`, and then
/// emitting that to an [`EntrySink`].
///
/// The normal way of generating a metric entry is by starting with a struct
/// that implements [`CloseEntry`] (that is generally generated
/// using the `#[metrics]` macro), wrapping it in a `RootEntry` to generate an
/// [`Entry`], and then emitting that to an entry sink.
///
/// Design note: in theory you could have a world where `InflectableEntry`
/// and [`Entry`] are the same trait (where the sinks use the default type parameters).
/// In practice, it is desired that the trait [`Entry`] will have very few breaking
/// changes since it needs to be identical throughout a program that wants to emit
/// metrics to a single destination, and therefore `InflectableEntry` is kept separate.
///
/// ## Manual Implementations
///
/// Currently, there is no (stable) non-macro way of generating an [`InflectableEntry`]
/// that actually inflects names. If you want to make a manual entry, it is recommended
/// to implement the [`Entry`] trait, then use a field with `#[metrics(flatten_entry)]`
/// as follows - though note that this will ignore inflections:
///
/// ```
/// use metrique::unit_of_work::metrics;
/// use metrique::writer::{Entry, EntryWriter};
///
/// struct MyCustomEntry;
///
/// impl Entry for MyCustomEntry {
/// fn write<'a>(&'a self, writer: &mut impl EntryWriter<'a>) {
/// writer.value("custom", "custom");
/// }
/// }
///
/// #[metrics]
/// struct MyMetric {
/// #[metrics(flatten_entry, no_close)]
/// field: MyCustomEntry,
/// }
/// ```
///
/// [`Entry`]: metrique_writer_core::Entry
/// [`NameStyle`]: namestyle::NameStyle
/// [`Entry`]: metrique_writer_core::Entry
/// [`EntrySink`]: metrique_writer_core::EntrySink