1
#include "source/extensions/access_loggers/fluentd/config.h"
2

            
3
#include <memory>
4

            
5
#include "envoy/registry/registry.h"
6
#include "envoy/server/filter_config.h"
7

            
8
#include "source/common/common/logger.h"
9
#include "source/common/config/utility.h"
10
#include "source/common/formatter/substitution_format_string.h"
11
#include "source/common/formatter/substitution_formatter.h"
12
#include "source/common/protobuf/protobuf.h"
13
#include "source/extensions/access_loggers/fluentd/fluentd_access_log_impl.h"
14

            
15
namespace Envoy {
16
namespace Extensions {
17
namespace AccessLoggers {
18
namespace Fluentd {
19

            
20
// Singleton registration via macro defined in envoy/singleton/manager.h
21
SINGLETON_MANAGER_REGISTRATION(fluentd_access_logger_cache);
22

            
23
FluentdAccessLoggerCacheSharedPtr
24
7
getAccessLoggerCacheSingleton(Server::Configuration::ServerFactoryContext& context) {
25
7
  return context.singletonManager().getTyped<FluentdAccessLoggerCacheImpl>(
26
7
      SINGLETON_MANAGER_REGISTERED_NAME(fluentd_access_logger_cache),
27
7
      [&context] {
28
7
        return std::make_shared<FluentdAccessLoggerCacheImpl>(
29
7
            context.clusterManager(), context.scope(), context.threadLocal());
30
7
      },
31
7
      /* pin = */ true);
32
7
}
33

            
34
AccessLog::InstanceSharedPtr FluentdAccessLogFactory::createAccessLogInstance(
35
    const Protobuf::Message& config, AccessLog::FilterPtr&& filter,
36
    Server::Configuration::GenericFactoryContext& context,
37
10
    std::vector<Formatter::CommandParserPtr>&& command_parsers) {
38
10
  const auto& proto_config = MessageUtil::downcastAndValidate<
39
10
      const envoy::extensions::access_loggers::fluentd::v3::FluentdAccessLogConfig&>(
40
10
      config, context.messageValidationVisitor());
41

            
42
10
  absl::Status status = context.serverFactoryContext().clusterManager().checkActiveStaticCluster(
43
10
      proto_config.cluster());
44
10
  if (!status.ok()) {
45
1
    throw EnvoyException(fmt::format("cluster '{}' was not found", proto_config.cluster()));
46
1
  }
47

            
48
9
  if (proto_config.has_retry_options() && proto_config.retry_options().has_backoff_options()) {
49
2
    status = BackOffStrategyUtils::validateBackOffStrategyConfig(
50
2
        proto_config.retry_options().backoff_options(), DefaultBaseBackoffIntervalMs,
51
2
        DefaultMaxBackoffIntervalFactor);
52
2
    if (!status.ok()) {
53
1
      throw EnvoyException(
54
1
          "max_backoff_interval must be greater or equal to base_backoff_interval");
55
1
    }
56
2
  }
57

            
58
  // Supporting nested object serialization is more complex with MessagePack.
59
  // Using an already existing JSON formatter, and later converting the JSON string to a msgpack
60
  // payload.
61
  // TODO(ohadvano): Improve the formatting operation by creating a dedicated formatter that
62
  //                 will directly serialize the record to msgpack payload.
63
8
  auto commands =
64
8
      THROW_OR_RETURN_VALUE(Formatter::SubstitutionFormatStringUtils::parseFormatters(
65
8
                                proto_config.formatters(), context, std::move(command_parsers)),
66
8
                            std::vector<Formatter::CommandParserPtr>);
67

            
68
8
  Formatter::FormatterPtr json_formatter =
69
8
      Formatter::SubstitutionFormatStringUtils::createJsonFormatter(proto_config.record(), false,
70
8
                                                                    commands);
71
8
  FluentdFormatterPtr fluentd_formatter =
72
8
      std::make_unique<FluentdFormatterImpl>(std::move(json_formatter));
73

            
74
8
  return std::make_shared<FluentdAccessLog>(
75
8
      std::move(filter), std::move(fluentd_formatter),
76
8
      std::make_shared<FluentdAccessLogConfig>(proto_config),
77
8
      context.serverFactoryContext().threadLocal(),
78
8
      context.serverFactoryContext().api().randomGenerator(),
79
8
      getAccessLoggerCacheSingleton(context.serverFactoryContext()));
80
9
}
81

            
82
13
ProtobufTypes::MessagePtr FluentdAccessLogFactory::createEmptyConfigProto() {
83
13
  return std::make_unique<envoy::extensions::access_loggers::fluentd::v3::FluentdAccessLogConfig>();
84
13
}
85

            
86
23
std::string FluentdAccessLogFactory::name() const { return "envoy.access_loggers.fluentd"; }
87

            
88
/**
89
 * Static registration for the fluentd access log. @see RegisterFactory.
90
 */
91
REGISTER_FACTORY(FluentdAccessLogFactory,
92
                 AccessLog::AccessLogInstanceFactory){"envoy.fluentd_access_log"};
93

            
94
} // namespace Fluentd
95
} // namespace AccessLoggers
96
} // namespace Extensions
97
} // namespace Envoy