• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The Abseil Authors.
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 //      https://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 //
15 // -----------------------------------------------------------------------------
16 // File: log/internal/structured.h
17 // -----------------------------------------------------------------------------
18 
19 #ifndef ABSL_LOG_INTERNAL_STRUCTURED_H_
20 #define ABSL_LOG_INTERNAL_STRUCTURED_H_
21 
22 #include <ostream>
23 #include <string>
24 
25 #include "absl/base/attributes.h"
26 #include "absl/base/config.h"
27 #include "absl/functional/any_invocable.h"
28 #include "absl/log/internal/log_message.h"
29 #include "absl/log/internal/structured_proto.h"
30 #include "absl/strings/str_cat.h"
31 #include "absl/strings/string_view.h"
32 
33 namespace absl {
34 ABSL_NAMESPACE_BEGIN
35 namespace log_internal {
36 
37 class [[nodiscard]] AsLiteralImpl final {
38  public:
AsLiteralImpl(absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND)39   explicit AsLiteralImpl(absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND)
40       : str_(str) {}
41   AsLiteralImpl(const AsLiteralImpl&) = default;
42   AsLiteralImpl& operator=(const AsLiteralImpl&) = default;
43 
44  private:
45   absl::string_view str_;
46 
47   friend std::ostream& operator<<(std::ostream& os,
48                                   AsLiteralImpl&& as_literal) {
49     return os << as_literal.str_;
50   }
AddToMessage(log_internal::LogMessage & m)51   void AddToMessage(log_internal::LogMessage& m) {
52     m.CopyToEncodedBuffer<log_internal::LogMessage::StringType::kLiteral>(str_);
53   }
54   friend log_internal::LogMessage& operator<<(log_internal::LogMessage& m,
55                                               AsLiteralImpl as_literal) {
56     as_literal.AddToMessage(m);
57     return m;
58   }
59 };
60 
61 enum class StructuredStringType {
62   kLiteral,
63   kNotLiteral,
64 };
65 
66 // Structured log data for a string and associated structured proto field,
67 // both of which must outlive this object.
68 template <StructuredStringType str_type>
69 class [[nodiscard]] AsStructuredStringTypeImpl final {
70  public:
AsStructuredStringTypeImpl(absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND,StructuredProtoField field ABSL_ATTRIBUTE_LIFETIME_BOUND)71   constexpr AsStructuredStringTypeImpl(
72       absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND,
73       StructuredProtoField field ABSL_ATTRIBUTE_LIFETIME_BOUND)
74       : str_(str), field_(field) {}
75 
76  private:
77   absl::string_view str_;
78   StructuredProtoField field_;
79 
80   friend std::ostream& operator<<(std::ostream& os,
81                                   const AsStructuredStringTypeImpl& impl) {
82     return os << impl.str_;
83   }
AddToMessage(LogMessage & m)84   void AddToMessage(LogMessage& m) const {
85     if (str_type == StructuredStringType::kLiteral) {
86       return m.CopyToEncodedBufferWithStructuredProtoField<
87           log_internal::LogMessage::StringType::kLiteral>(field_, str_);
88     } else {
89       return m.CopyToEncodedBufferWithStructuredProtoField<
90           log_internal::LogMessage::StringType::kNotLiteral>(field_, str_);
91     }
92   }
93   friend LogMessage& operator<<(LogMessage& m,
94                                 const AsStructuredStringTypeImpl& impl) {
95     impl.AddToMessage(m);
96     return m;
97   }
98 };
99 
100 using AsStructuredLiteralImpl =
101     AsStructuredStringTypeImpl<StructuredStringType::kLiteral>;
102 using AsStructuredNotLiteralImpl =
103     AsStructuredStringTypeImpl<StructuredStringType::kNotLiteral>;
104 
105 // Structured log data for a stringifyable type T and associated structured
106 // proto field, both of which must outlive this object.
107 template <typename T>
108 class [[nodiscard]] AsStructuredValueImpl final {
109  public:
110   using ValueFormatter = absl::AnyInvocable<std::string(T) const>;
111 
112   constexpr AsStructuredValueImpl(
113       T value ABSL_ATTRIBUTE_LIFETIME_BOUND,
114       StructuredProtoField field ABSL_ATTRIBUTE_LIFETIME_BOUND,
115       ValueFormatter value_formatter =
116           [](T value) { return absl::StrCat(value); })
value_(value)117       : value_(value),
118         field_(field),
119         value_formatter_(std::move(value_formatter)) {}
120 
121  private:
122   T value_;
123   StructuredProtoField field_;
124   ValueFormatter value_formatter_;
125 
126   friend std::ostream& operator<<(std::ostream& os,
127                                   const AsStructuredValueImpl& impl) {
128     return os << impl.value_formatter_(impl.value_);
129   }
AddToMessage(LogMessage & m)130   void AddToMessage(LogMessage& m) const {
131     m.CopyToEncodedBufferWithStructuredProtoField<
132         log_internal::LogMessage::StringType::kNotLiteral>(
133         field_, value_formatter_(value_));
134   }
135   friend LogMessage& operator<<(LogMessage& m,
136                                 const AsStructuredValueImpl& impl) {
137     impl.AddToMessage(m);
138     return m;
139   }
140 };
141 
142 // Template deduction guide so `AsStructuredValueImpl(42, data)` works
143 // without specifying the template type.
144 template <typename T>
145 AsStructuredValueImpl(T value, StructuredProtoField field)
146     -> AsStructuredValueImpl<T>;
147 
148 // Template deduction guide so `AsStructuredValueImpl(42, data, formatter)`
149 // works without specifying the template type.
150 template <typename T>
151 AsStructuredValueImpl(
152     T value, StructuredProtoField field,
153     typename AsStructuredValueImpl<T>::ValueFormatter value_formatter)
154     -> AsStructuredValueImpl<T>;
155 
156 }  // namespace log_internal
157 ABSL_NAMESPACE_END
158 }  // namespace absl
159 
160 #endif  // ABSL_LOG_INTERNAL_STRUCTURED_H_
161