rustfs_obs/entry/
mod.rs

1// Copyright 2024 RustFS Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15pub(crate) mod args;
16pub(crate) mod audit;
17pub(crate) mod base;
18pub(crate) mod unified;
19
20use serde::de::Error;
21use serde::{Deserialize, Deserializer, Serialize, Serializer};
22use tracing_core::Level;
23
24/// ObjectVersion is used across multiple modules
25#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
26pub struct ObjectVersion {
27    #[serde(rename = "name")]
28    pub object_name: String,
29    #[serde(rename = "versionId", skip_serializing_if = "Option::is_none")]
30    pub version_id: Option<String>,
31}
32
33impl ObjectVersion {
34    /// Create a new ObjectVersion object
35    pub fn new() -> Self {
36        ObjectVersion {
37            object_name: String::new(),
38            version_id: None,
39        }
40    }
41
42    /// Create a new ObjectVersion with object name
43    pub fn new_with_object_name(object_name: String) -> Self {
44        ObjectVersion {
45            object_name,
46            version_id: None,
47        }
48    }
49
50    /// Set the object name
51    pub fn set_object_name(mut self, object_name: String) -> Self {
52        self.object_name = object_name;
53        self
54    }
55
56    /// Set the version ID
57    pub fn set_version_id(mut self, version_id: Option<String>) -> Self {
58        self.version_id = version_id;
59        self
60    }
61}
62
63impl Default for ObjectVersion {
64    fn default() -> Self {
65        Self::new()
66    }
67}
68
69/// Log kind/level enum
70#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
71pub enum LogKind {
72    #[serde(rename = "INFO")]
73    #[default]
74    Info,
75    #[serde(rename = "WARNING")]
76    Warning,
77    #[serde(rename = "ERROR")]
78    Error,
79    #[serde(rename = "FATAL")]
80    Fatal,
81}
82
83/// Trait for types that can be serialized to JSON and have a timestamp
84/// This trait is used by `ServerLogEntry` to convert the log entry to JSON
85/// and get the timestamp of the log entry
86/// This trait is implemented by `ServerLogEntry`
87///
88/// # Example
89/// ```
90/// use rustfs_obs::LogRecord;
91/// use chrono::{DateTime, Utc};
92/// use rustfs_obs::ServerLogEntry;
93/// use tracing_core::Level;
94///
95/// let log_entry = ServerLogEntry::new(Level::INFO, "api_handler".to_string());
96/// let json = log_entry.to_json();
97/// let timestamp = log_entry.get_timestamp();
98/// ```
99pub trait LogRecord {
100    fn to_json(&self) -> String;
101    fn get_timestamp(&self) -> chrono::DateTime<chrono::Utc>;
102}
103
104/// Wrapper for `tracing_core::Level` to implement `Serialize` and `Deserialize`
105/// for `ServerLogEntry`
106/// This is necessary because `tracing_core::Level` does not implement `Serialize`
107/// and `Deserialize`
108/// This is a workaround to allow `ServerLogEntry` to be serialized and deserialized
109/// using `serde`
110///
111/// # Example
112/// ```
113/// use rustfs_obs::SerializableLevel;
114/// use tracing_core::Level;
115///
116/// let level = Level::INFO;
117/// let serializable_level = SerializableLevel::from(level);
118/// ```
119#[derive(Debug, Clone, PartialEq, Eq)]
120pub struct SerializableLevel(pub Level);
121
122impl From<Level> for SerializableLevel {
123    fn from(level: Level) -> Self {
124        SerializableLevel(level)
125    }
126}
127
128impl From<SerializableLevel> for Level {
129    fn from(serializable_level: SerializableLevel) -> Self {
130        serializable_level.0
131    }
132}
133
134impl Serialize for SerializableLevel {
135    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
136    where
137        S: Serializer,
138    {
139        serializer.serialize_str(self.0.as_str())
140    }
141}
142
143impl<'de> Deserialize<'de> for SerializableLevel {
144    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
145    where
146        D: Deserializer<'de>,
147    {
148        let s = String::deserialize(deserializer)?;
149        match s.as_str() {
150            "TRACE" => Ok(SerializableLevel(Level::TRACE)),
151            "DEBUG" => Ok(SerializableLevel(Level::DEBUG)),
152            "INFO" => Ok(SerializableLevel(Level::INFO)),
153            "WARN" => Ok(SerializableLevel(Level::WARN)),
154            "ERROR" => Ok(SerializableLevel(Level::ERROR)),
155            _ => Err(D::Error::custom("unknown log level")),
156        }
157    }
158}