Source code

Revision control

Copy as Markdown

Other Tools

// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/internal/structured.h
// -----------------------------------------------------------------------------
#ifndef ABSL_LOG_INTERNAL_STRUCTURED_H_
#define ABSL_LOG_INTERNAL_STRUCTURED_H_
#include <ostream>
#include <string>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/functional/any_invocable.h"
#include "absl/log/internal/log_message.h"
#include "absl/log/internal/structured_proto.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace log_internal {
class [[nodiscard]] AsLiteralImpl final {
public:
explicit AsLiteralImpl(absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND)
: str_(str) {}
AsLiteralImpl(const AsLiteralImpl&) = default;
AsLiteralImpl& operator=(const AsLiteralImpl&) = default;
private:
absl::string_view str_;
friend std::ostream& operator<<(std::ostream& os,
AsLiteralImpl&& as_literal) {
return os << as_literal.str_;
}
void AddToMessage(log_internal::LogMessage& m) {
m.CopyToEncodedBuffer<log_internal::LogMessage::StringType::kLiteral>(str_);
}
friend log_internal::LogMessage& operator<<(log_internal::LogMessage& m,
AsLiteralImpl as_literal) {
as_literal.AddToMessage(m);
return m;
}
};
enum class StructuredStringType {
kLiteral,
kNotLiteral,
};
// Structured log data for a string and associated structured proto field,
// both of which must outlive this object.
template <StructuredStringType str_type>
class [[nodiscard]] AsStructuredStringTypeImpl final {
public:
constexpr AsStructuredStringTypeImpl(
absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND,
StructuredProtoField field ABSL_ATTRIBUTE_LIFETIME_BOUND)
: str_(str), field_(field) {}
private:
absl::string_view str_;
StructuredProtoField field_;
friend std::ostream& operator<<(std::ostream& os,
const AsStructuredStringTypeImpl& impl) {
return os << impl.str_;
}
void AddToMessage(LogMessage& m) const {
if (str_type == StructuredStringType::kLiteral) {
return m.CopyToEncodedBufferWithStructuredProtoField<
log_internal::LogMessage::StringType::kLiteral>(field_, str_);
} else {
return m.CopyToEncodedBufferWithStructuredProtoField<
log_internal::LogMessage::StringType::kNotLiteral>(field_, str_);
}
}
friend LogMessage& operator<<(LogMessage& m,
const AsStructuredStringTypeImpl& impl) {
impl.AddToMessage(m);
return m;
}
};
using AsStructuredLiteralImpl =
AsStructuredStringTypeImpl<StructuredStringType::kLiteral>;
using AsStructuredNotLiteralImpl =
AsStructuredStringTypeImpl<StructuredStringType::kNotLiteral>;
// Structured log data for a stringifyable type T and associated structured
// proto field, both of which must outlive this object.
template <typename T>
class [[nodiscard]] AsStructuredValueImpl final {
public:
using ValueFormatter = absl::AnyInvocable<std::string(T) const>;
constexpr AsStructuredValueImpl(
T value ABSL_ATTRIBUTE_LIFETIME_BOUND,
StructuredProtoField field ABSL_ATTRIBUTE_LIFETIME_BOUND,
ValueFormatter value_formatter =
[](T value) { return absl::StrCat(value); })
: value_(value),
field_(field),
value_formatter_(std::move(value_formatter)) {}
private:
T value_;
StructuredProtoField field_;
ValueFormatter value_formatter_;
friend std::ostream& operator<<(std::ostream& os,
const AsStructuredValueImpl& impl) {
return os << impl.value_formatter_(impl.value_);
}
void AddToMessage(LogMessage& m) const {
m.CopyToEncodedBufferWithStructuredProtoField<
log_internal::LogMessage::StringType::kNotLiteral>(
field_, value_formatter_(value_));
}
friend LogMessage& operator<<(LogMessage& m,
const AsStructuredValueImpl& impl) {
impl.AddToMessage(m);
return m;
}
};
// Template deduction guide so `AsStructuredValueImpl(42, data)` works
// without specifying the template type.
template <typename T>
AsStructuredValueImpl(T value, StructuredProtoField field)
-> AsStructuredValueImpl<T>;
// Template deduction guide so `AsStructuredValueImpl(42, data, formatter)`
// works without specifying the template type.
template <typename T>
AsStructuredValueImpl(
T value, StructuredProtoField field,
typename AsStructuredValueImpl<T>::ValueFormatter value_formatter)
-> AsStructuredValueImpl<T>;
} // namespace log_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOG_INTERNAL_STRUCTURED_H_