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
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

//! Attributes (also referred to as tags or annotations in other telemetry systems) are structured
//! key-value pairs that annotate a span or event. Structured data allows observability backends
//! to index and process telemetry data in ways that simple log messages lack.

use std::collections::HashMap;

/// The valid types of values accepted by [Attributes].
#[non_exhaustive]
#[derive(Clone, Debug, PartialEq)]
pub enum AttributeValue {
    /// Holds an [i64]
    I64(i64),
    /// Holds an [f64]
    F64(f64),
    /// Holds a [String]
    String(String),
    /// Holds a [bool]
    Bool(bool),
}

/// Structured telemetry metadata.
#[non_exhaustive]
#[derive(Clone, Default)]
pub struct Attributes {
    attrs: HashMap<String, AttributeValue>,
}

impl Attributes {
    /// Create a new empty instance of [Attributes].
    pub fn new() -> Self {
        Self::default()
    }

    /// Set an attribute.
    pub fn set(&mut self, key: impl Into<String>, value: impl Into<AttributeValue>) {
        self.attrs.insert(key.into(), value.into());
    }

    /// Get an attribute.
    pub fn get(&self, key: impl Into<String>) -> Option<&AttributeValue> {
        self.attrs.get(&key.into())
    }

    /// Get all of the attribute key value pairs.
    pub fn attributes(&self) -> &HashMap<String, AttributeValue> {
        &self.attrs
    }

    /// Get an owned [Iterator] of ([String], [AttributeValue]).
    pub fn into_attributes(self) -> impl Iterator<Item = (String, AttributeValue)> {
        self.attrs.into_iter()
    }
}

/// Delineates a logical scope that has some beginning and end
/// (e.g. a function or block of code).
pub trait Scope {
    /// invoke when the scope has ended.
    fn end(&self);
}

/// A cross cutting concern for carrying execution-scoped values across API
/// boundaries (both in-process and distributed).
pub trait Context {
    /// Make this context the currently active context.
    /// The returned handle is used to return the previous
    /// context (if one existed) as active.
    fn make_current(&self) -> &dyn Scope;
}

/// Keeps track of the current [Context].
pub trait ContextManager {
    ///Get the currently active context.
    fn current(&self) -> &dyn Context;
}