structured.h 5.4 KB

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