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

            
3
#include "envoy/extensions/access_loggers/dynamic_modules/v3/dynamic_modules.pb.validate.h"
4

            
5
#include "source/common/config/utility.h"
6
#include "source/common/protobuf/utility.h"
7
#include "source/common/runtime/runtime_features.h"
8
#include "source/extensions/access_loggers/dynamic_modules/access_log.h"
9

            
10
namespace Envoy {
11
namespace Extensions {
12
namespace AccessLoggers {
13
namespace DynamicModules {
14

            
15
AccessLog::InstanceSharedPtr DynamicModuleAccessLogFactory::createAccessLogInstance(
16
    const Protobuf::Message& config, AccessLog::FilterPtr&& filter,
17
    Server::Configuration::GenericFactoryContext& context,
18
10
    std::vector<Formatter::CommandParserPtr>&&) {
19
10
  const auto& proto_config = MessageUtil::downcastAndValidate<
20
10
      const envoy::extensions::access_loggers::dynamic_modules::v3::DynamicModuleAccessLog&>(
21
10
      config, context.messageValidationVisitor());
22

            
23
10
  const auto& module_config = proto_config.dynamic_module_config();
24
10
  auto dynamic_module_or_error = Extensions::DynamicModules::newDynamicModuleByName(
25
10
      module_config.name(), module_config.do_not_close(), module_config.load_globally());
26

            
27
10
  if (!dynamic_module_or_error.ok()) {
28
1
    throw EnvoyException("Failed to load dynamic module: " +
29
1
                         std::string(dynamic_module_or_error.status().message()));
30
1
  }
31

            
32
  // Use knownAnyToBytes() to properly handle StringValue/BytesValue/Struct types.
33
9
  std::string logger_config_str;
34
9
  if (proto_config.has_logger_config()) {
35
3
    auto config_or_error = MessageUtil::knownAnyToBytes(proto_config.logger_config());
36
3
    if (!config_or_error.ok()) {
37
      throw EnvoyException("Failed to parse logger config: " +
38
                           std::string(config_or_error.status().message()));
39
    }
40
3
    logger_config_str = std::move(config_or_error.value());
41
3
  }
42

            
43
  // Use configured metrics namespace or fall back to the default.
44
9
  const std::string metrics_namespace = module_config.metrics_namespace().empty()
45
9
                                            ? std::string(DefaultMetricsNamespace)
46
9
                                            : module_config.metrics_namespace();
47

            
48
9
  auto access_log_config = newDynamicModuleAccessLogConfig(
49
9
      proto_config.logger_name(), logger_config_str, metrics_namespace,
50
9
      std::move(dynamic_module_or_error.value()), context.serverFactoryContext().scope());
51

            
52
9
  if (!access_log_config.ok()) {
53
5
    throw EnvoyException("Failed to create access logger config: " +
54
5
                         std::string(access_log_config.status().message()));
55
5
  }
56

            
57
  // When the runtime guard is enabled, register the metrics namespace as a custom stat namespace.
58
  // This causes the namespace prefix to be stripped from prometheus output and no envoy_ prefix
59
  // is added. This is the legacy behavior for backward compatibility.
60
4
  if (Runtime::runtimeFeatureEnabled(
61
4
          "envoy.reloadable_features.dynamic_modules_strip_custom_stat_prefix")) {
62
    context.serverFactoryContext().api().customStatNamespaces().registerStatNamespace(
63
        metrics_namespace);
64
  }
65

            
66
4
  return std::make_shared<DynamicModuleAccessLog>(std::move(filter),
67
4
                                                  std::move(access_log_config.value()),
68
4
                                                  context.serverFactoryContext().threadLocal());
69
9
}
70

            
71
6
ProtobufTypes::MessagePtr DynamicModuleAccessLogFactory::createEmptyConfigProto() {
72
6
  return std::make_unique<
73
6
      envoy::extensions::access_loggers::dynamic_modules::v3::DynamicModuleAccessLog>();
74
6
}
75

            
76
REGISTER_FACTORY(DynamicModuleAccessLogFactory, AccessLog::AccessLogInstanceFactory);
77

            
78
} // namespace DynamicModules
79
} // namespace AccessLoggers
80
} // namespace Extensions
81
} // namespace Envoy