google_cloud_logging/
lib.rs

1//! This crate contains structures for
2//! [Google Cloud Structured logging](https://cloud.google.com/logging/docs/structured-logging).
3//! This allows for adding more metadata to log statements that will be interpreted by the
4//! [Google Cloud "Logging"][Cloud_Logging] service and can be viewed in the "Logs Explorer".
5//!
6//! Some errors can also be formatted so the ["Error Reporting"][Error_Reporting] service will group them.
7//!
8//! [Cloud_Logging]: https://cloud.google.com/logging/
9//! [Error_Reporting]: https://cloud.google.com/error-reporting/
10#![forbid(unsafe_code)]
11#![deny(clippy::all)]
12
13// The code below contains documentation from both this library and the
14// [Google Docs](https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry)
15
16use chrono::{DateTime, Utc};
17use serde::{Deserialize, Serialize};
18use std::collections::HashMap;
19
20/// The format expected by Google Cloud Platform logging service
21/// https://cloud.google.com/logging/docs/structured-logging
22#[derive(Serialize, Deserialize, Clone, Debug, Default)]
23#[serde(rename_all = "camelCase")]
24pub struct GoogleCloudStructLog<'a> {
25    /// The Logging agent attempts to match a variety of common severity strings,
26    /// which includes the list of LogSeverity strings recognized by the Logging API.
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub severity: Option<GCLogSeverity>,
29    /// The message that appears on the log entry line in the Logs Explorer.
30    ///
31    /// Optionally add a backtrace here using following format (including newlines):
32    /// ```text
33    /// My normal log message goes here:
34    ///    at services::module_name::he77c0bac773c93b4 line: 42
35    ///    at services::module_name::h7ad5e699ac5d6658
36    /// ```
37    /// Note the `:` at the end of the log message and the 3 space and `at ` before each line of the
38    /// backtrace. The ` line: <Nr>` is optional.
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub message: Option<String>,
41    /// Can be used to set for Error reporting
42    /// More info see: https://cloud.google.com/error-reporting/docs/formatting-error-messages#@type
43    #[serde(rename = "@type")]
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub report_type: Option<String>,
46    /// A structured record in the format of the LogEntry HttpRequest field.
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub http_request: Option<GCHttpRequest>,
49    /// Time of the log message
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub time: Option<DateTime<Utc>>,
52    /// A unique identifier for the log entry.
53    /// If you provide a value, then Logging considers other log entries in the same project,
54    /// with the same timestamp, and with the same insertId to be duplicates which are removed
55    /// in a single query result. However, there are no guarantees of de-duplication
56    /// in the export of logs.
57    #[serde(rename = "logging.googleapis.com/insertId")]
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub insert_id: Option<String>,
60    /// A map of key, value pairs that provides additional information about the log entry.
61    /// The labels can be user-defined or system-defined.
62    #[serde(rename = "logging.googleapis.com/labels")]
63    #[serde(skip_serializing_if = "HashMap::is_empty")]
64    pub labels: HashMap<String, String>,
65    /// Information about an operation associated with the log entry, if applicable.
66    #[serde(rename = "logging.googleapis.com/operation")]
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub operation: Option<GCOperation<'a>>,
69    /// Additional information about the source code location that produced the log entry.
70    #[serde(rename = "logging.googleapis.com/sourceLocation")]
71    #[serde(skip_serializing_if = "Option::is_none")]
72    pub source_location: Option<GCSourceLocation<'a>>,
73    /// The span ID within the trace associated with the log entry.
74    ///
75    /// For Trace spans, this is the same format that the Trace API v2 uses:
76    /// a 16-character hexadecimal encoding of an 8-byte array, such as `000000000000004a`.
77    #[serde(rename = "logging.googleapis.com/spanId")]
78    #[serde(skip_serializing_if = "Option::is_none")]
79    pub span_id: Option<String>,
80    /// Resource name of the trace associated with the log entry, if any.
81    /// If it contains a relative resource name, the name is assumed to be relative to
82    /// `//tracing.googleapis.com`.
83    /// Example: `projects/my-projectid/traces/06796866738c859f2f19b7cfb3214824`
84    #[serde(rename = "logging.googleapis.com/trace")]
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub trace: Option<String>,
87    /// The sampling decision of the trace associated with the log entry.
88    ///
89    /// `true` means that the trace resource name in the trace field was sampled for
90    /// storage in a trace backend. `false` means that the trace was not sampled for storage
91    /// when this log entry was written, or the sampling decision was unknown at the time.
92    /// A non-sampled trace value is still useful as a request correlation identifier.
93    /// The default is `false`.
94    #[serde(rename = "logging.googleapis.com/trace_sampled")]
95    #[serde(skip_serializing_if = "Option::is_none")]
96    pub trace_sampled: Option<bool>,
97    /// Just to keep track of lifetime
98    #[serde(skip_serializing)]
99    pub phantom: Option<&'a str>,
100}
101
102/// The severity of the event described in a log entry, expressed as one of the standard severity
103/// levels listed below.
104#[derive(Serialize, Deserialize, Clone, Copy, Debug)]
105#[serde(rename_all = "camelCase")]
106pub enum GCLogSeverity {
107    /// The log entry has no assigned severity level.
108    Default,
109    /// Debug or trace information.
110    Debug,
111    /// Routine information, such as ongoing status or performance.
112    Info,
113    /// Normal but significant events, such as start up, shut down, or a configuration change.
114    Notice,
115    /// Warning events might cause problems.
116    Warning,
117    /// Error events are likely to cause problems.
118    Error,
119    /// Critical events cause more severe problems or outages.
120    Critical,
121    /// A person must take an action immediately.
122    Alert,
123    /// One or more systems are unusable.
124    Emergency,
125}
126
127impl Default for GCLogSeverity {
128    fn default() -> Self {
129        GCLogSeverity::Default
130    }
131}
132
133// Some values where not added because they will not be used.
134#[derive(Serialize, Deserialize, Clone, Debug, Default)]
135#[serde(rename_all = "camelCase")]
136pub struct GCHttpRequest {
137    /// The request method. Examples: "GET", "HEAD", "PUT", "POST".
138    #[serde(skip_serializing_if = "Option::is_none")]
139    pub request_method: Option<GCHttpMethod>,
140    /// The scheme (http, https), the host name, the path and the query portion of
141    /// the URL that was requested. Example: "http://example.com/some/info?color=red".
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub request_url: Option<String>,
144    /// The size of the HTTP request message in bytes,
145    /// including the request headers and the request body.
146    #[serde(skip_serializing_if = "Option::is_none")]
147    pub request_size: Option<String>,
148    /// The response code indicating the status of response. Examples: 200, 404.
149    #[serde(skip_serializing_if = "Option::is_none")]
150    pub status: Option<u16>,
151    /// The size of the HTTP response message sent back to the client, in bytes,
152    /// including the response headers and the response body.
153    #[serde(skip_serializing_if = "Option::is_none")]
154    pub response_size: Option<String>,
155    /// The user agent sent by the client.
156    /// Example: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; .NET CLR 1.0.3705)".
157    #[serde(skip_serializing_if = "Option::is_none")]
158    pub user_agent: Option<String>,
159    /// The IP address (IPv4 or IPv6) of the client that issued the HTTP request.
160    /// This field can include port information.
161    /// Examples: "192.168.1.1", "10.0.0.1:80", "FE80::0202:B3FF:FE1E:8329".
162    #[serde(skip_serializing_if = "Option::is_none")]
163    pub remote_ip: Option<String>,
164    /// The IP address (IPv4 or IPv6) of the origin server that the request was sent to.
165    /// This field can include port information.
166    /// Examples: "192.168.1.1", "10.0.0.1:80", "FE80::0202:B3FF:FE1E:8329".
167    #[serde(skip_serializing_if = "Option::is_none")]
168    pub server_ip: Option<String>,
169    /// The request processing latency on the server,
170    /// from the time the request was received until the response was sent.
171    ///
172    /// A duration in seconds with up to nine fractional digits, terminated by 's'.
173    /// Example: "3.5s".
174    #[serde(skip_serializing_if = "Option::is_none")]
175    pub latency: Option<String>,
176    /// Protocol used for the request. Examples: "HTTP/1.1", "HTTP/2", "websocket"
177    #[serde(skip_serializing_if = "Option::is_none")]
178    pub protocol: Option<String>,
179}
180
181#[derive(Serialize, Deserialize, Clone, Copy, Debug)]
182#[serde(rename_all = "camelCase")]
183pub enum GCHttpMethod {
184    Get,
185    Head,
186    Put,
187    Post,
188}
189
190impl Default for GCHttpMethod {
191    fn default() -> Self {
192        GCHttpMethod::Get
193    }
194}
195
196#[derive(Serialize, Deserialize, Clone, Debug, Default)]
197#[serde(rename_all = "camelCase")]
198pub struct GCOperation<'a> {
199    /// An arbitrary operation identifier.
200    /// Log entries with the same identifier are assumed to be part of the same operation.
201    #[serde(skip_serializing_if = "Option::is_none")]
202    pub id: Option<&'a str>,
203    /// An arbitrary producer identifier. The combination of id and producer must be globally unique.
204    /// Examples for producer: "MyDivision.MyBigCompany.com", "github.com/MyProject/MyApplication".
205    #[serde(skip_serializing_if = "Option::is_none")]
206    pub producer: Option<&'a str>,
207    /// Set this to `true` if this is the first log entry in the operation.
208    #[serde(skip_serializing_if = "Option::is_none")]
209    pub first: Option<bool>,
210    /// Set this to `true` if this is the last log entry in the operation.
211    #[serde(skip_serializing_if = "Option::is_none")]
212    pub last: Option<bool>,
213}
214
215#[derive(Serialize, Deserialize, Clone, Debug, Default)]
216#[serde(rename_all = "camelCase")]
217pub struct GCSourceLocation<'a> {
218    /// Source file name. Depending on the runtime environment,
219    /// this might be a simple name or a fully-qualified name.
220    #[serde(skip_serializing_if = "Option::is_none")]
221    pub file: Option<&'a str>,
222    /// Line within the source file. 1-based; 0 indicates no line number available.
223    #[serde(skip_serializing_if = "Option::is_none")]
224    pub line: Option<String>,
225    /// Human-readable name of the function or method being invoked,
226    /// with optional context such as the class or package name.
227    /// This information may be used in contexts such as the logs viewer,
228    /// where a file and line number are less meaningful. The format can vary by language.
229    /// For example: qual.if.ied.Class.method (Java), dir/package.func (Go), function (Python).
230    #[serde(skip_serializing_if = "Option::is_none")]
231    pub function: Option<&'a str>,
232}