1
#pragma once
2

            
3
#include <list>
4
#include <string>
5
#include <vector>
6

            
7
#include "envoy/formatter/substitution_formatter.h"
8
#include "envoy/stream_info/stream_info.h"
9

            
10
#include "opentelemetry/proto/common/v1/common.pb.h"
11

            
12
namespace Envoy {
13
namespace Extensions {
14
namespace AccessLoggers {
15
namespace OpenTelemetry {
16

            
17
// Helper classes for OpenTelemetryFormatter::OpenTelemetryMapFormatVisitor.
18
template <class... Ts> struct OpenTelemetryFormatMapVisitorHelper : Ts... {
19
  using Ts::operator()...;
20
};
21
template <class... Ts>
22
OpenTelemetryFormatMapVisitorHelper(Ts...) -> OpenTelemetryFormatMapVisitorHelper<Ts...>;
23

            
24
/**
25
 * A formatter for OpenTelemetry logs, which returns a KeyValueList proto.
26
 */
27
class OpenTelemetryFormatter {
28
public:
29
  OpenTelemetryFormatter(const ::opentelemetry::proto::common::v1::KeyValueList& format_mapping,
30
                         const std::vector<Formatter::CommandParserPtr>& commands);
31

            
32
  ::opentelemetry::proto::common::v1::KeyValueList format(const Formatter::Context& context,
33
                                                          const StreamInfo::StreamInfo& info) const;
34

            
35
private:
36
  struct OpenTelemetryFormatMapWrapper;
37
  struct OpenTelemetryFormatListWrapper;
38
  using OpenTelemetryFormatValue =
39
      absl::variant<const std::vector<Formatter::FormatterProviderPtr>,
40
                    const OpenTelemetryFormatMapWrapper, const OpenTelemetryFormatListWrapper>;
41
  // We use std::list to keep the order of the repeated "values" field in the OpenTelemetry
42
  // KeyValueList.
43
  using OpenTelemetryFormatMap = std::list<std::pair<std::string, OpenTelemetryFormatValue>>;
44
  using OpenTelemetryFormatMapPtr = std::unique_ptr<OpenTelemetryFormatMap>;
45
  struct OpenTelemetryFormatMapWrapper {
46
    OpenTelemetryFormatMapPtr value_;
47
  };
48

            
49
  using OpenTelemetryFormatList = std::list<OpenTelemetryFormatValue>;
50
  using OpenTelemetryFormatListPtr = std::unique_ptr<OpenTelemetryFormatList>;
51
  struct OpenTelemetryFormatListWrapper {
52
    OpenTelemetryFormatListPtr value_;
53
  };
54

            
55
  using OpenTelemetryFormatMapVisitor = OpenTelemetryFormatMapVisitorHelper<
56
      std::function<::opentelemetry::proto::common::v1::AnyValue(
57
          const std::vector<Formatter::FormatterProviderPtr>&)>,
58
      std::function<::opentelemetry::proto::common::v1::AnyValue(
59
          const OpenTelemetryFormatter::OpenTelemetryFormatMapWrapper&)>,
60
      std::function<::opentelemetry::proto::common::v1::AnyValue(
61
          const OpenTelemetryFormatter::OpenTelemetryFormatListWrapper&)>>;
62

            
63
  // Methods for building the format map.
64
  class FormatBuilder {
65
  public:
66
    explicit FormatBuilder(const std::vector<Formatter::CommandParserPtr>& commands)
67
57
        : commands_(commands) {}
68
    std::vector<Formatter::FormatterProviderPtr>
69
    toFormatStringValue(const std::string& string_format) const;
70
    OpenTelemetryFormatMapWrapper
71
    toFormatMapValue(const ::opentelemetry::proto::common::v1::KeyValueList& struct_format) const;
72
    OpenTelemetryFormatListWrapper toFormatListValue(
73
        const ::opentelemetry::proto::common::v1::ArrayValue& list_value_format) const;
74

            
75
  private:
76
    const std::vector<Formatter::CommandParserPtr>& commands_;
77
  };
78

            
79
  // Methods for doing the actual formatting.
80
  ::opentelemetry::proto::common::v1::AnyValue
81
  providersCallback(const std::vector<Formatter::FormatterProviderPtr>& providers,
82
                    const Formatter::Context& context, const StreamInfo::StreamInfo& info) const;
83
  ::opentelemetry::proto::common::v1::AnyValue openTelemetryFormatMapCallback(
84
      const OpenTelemetryFormatter::OpenTelemetryFormatMapWrapper& format_map,
85
      const OpenTelemetryFormatMapVisitor& visitor) const;
86
  ::opentelemetry::proto::common::v1::AnyValue openTelemetryFormatListCallback(
87
      const OpenTelemetryFormatter::OpenTelemetryFormatListWrapper& format_list,
88
      const OpenTelemetryFormatMapVisitor& visitor) const;
89

            
90
  const OpenTelemetryFormatMapWrapper kv_list_output_format_;
91
};
92

            
93
} // namespace OpenTelemetry
94
} // namespace AccessLoggers
95
} // namespace Extensions
96
} // namespace Envoy