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}