org.appenders.log4j2.elasticsearch.ahc.ClientProviderPoliciesRegistry Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of log4j2-elasticsearch-ahc Show documentation
Show all versions of log4j2-elasticsearch-ahc Show documentation
Log4j2 Appender plugin pushing logs in batches to Elasticsearch (2.x/5.x/6.x/7.x/8.x) clusters
The newest version!
package org.appenders.log4j2.elasticsearch.ahc;
/*-
* #%L
* log4j2-elasticsearch
* %%
* Copyright (C) 2022 Rafal Foltynski
* %%
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
* #L%
*/
import org.appenders.log4j2.elasticsearch.ClientProvider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
import static org.appenders.core.logging.InternalLogging.getLogger;
/**
* Stores and retrieves {@link ClientProviderPolicy}-ies.
*/
public class ClientProviderPoliciesRegistry {
private final Map> copyingPolicies = new HashMap<>();
public ClientProviderPoliciesRegistry() {
register(new InheritServerUrisConfig());
register(new InheritSecurityConfig());
}
/**
* @return list of available policies
*/
final List availablePolicies() {
final List validPolicies = new ArrayList<>(Arrays.asList("shared", "none"));
validPolicies.addAll(copyingPolicies.keySet());
return validPolicies;
}
/**
* Registers given {@link CopyingConfigPolicy}.
*
* @param policy policy to register
*/
final void register(final CopyingConfigPolicy policy) {
copyingPolicies.put(policy.getName(), policy);
}
/**
* Resolves {@link ClientProviderPolicy} from given policy list.
*
* By default, following policies are available:
*
* - serverList - copies uris config from applied {@link ClientProvider} to initial {@link ClientProvider}
* - security - copies security config from applied {@link ClientProvider} to initial {@link ClientProvider}
* - shared - reuses applied {@link ClientProvider} and ignores initial {@link ClientProvider}
* - none - ignores applied {@link ClientProvider} and uses initial {@link ClientProvider}
*
*
* shared and none can only be used exclusively, e.g. ["shared"] or ["none"]. If any other policy is present in the given list, exception will be thrown.
*
* serverList and security are {@link CopyingConfigPolicy}-ies and can be mixed with other {@link CopyingConfigPolicy}-ies, e.g.: ["serverList", "security", "myCustomCopyingPolicy"].
*
* @param policies policy names
* @param initialClientProvider {@link ClientProviderPolicy} to apply the changes to
* @return resolved {@link ClientProviderPolicy} if policies list was valid, throws otherwise
*
*/
public final ClientProviderPolicy get(final Set policies, final HttpClientProvider initialClientProvider) {
validatePolicyList(policies);
if (isValidExclusivePolicy(policies, "shared")) {
return new SharedHttpClient();
}
if (isValidExclusivePolicy(policies, "none")) {
return new NewHttpClient(initialClientProvider);
}
final CopyingConfigPolicyChain propertiesProcessor = new CopyingConfigPolicyChain(initialClientProvider);
for (String policyName : policies) {
propertiesProcessor.add(copyingPolicies.get(policyName));
}
return propertiesProcessor;
}
private void validatePolicyList(final Set policies) {
if (policies == null || policies.isEmpty()) {
throw new IllegalArgumentException("Policy list must present. Valid policies: " + availablePolicies());
}
final List availablePolicies = availablePolicies();
for (String policyName: policies) {
if (!availablePolicies.contains(policyName)) {
throw new IllegalArgumentException("Invalid policy specified: [" + policyName + "]. Available policies: " + availablePolicies);
}
}
}
private boolean isValidExclusivePolicy(final Set policies, final String shared) {
if (policies.contains(shared)) {
ensureNoOtherPolicies(policies, shared);
return true;
}
return false;
}
private void ensureNoOtherPolicies(final Set policies, final String policyName) {
if (policies.size() > 1) {
throw new IllegalArgumentException("Cannot apply other policies when [" + policyName + "] policy is used");
}
}
/**
* Allows to define mapping between two {@link ClientProvider} instances.
*
* @param client type
*/
public interface CopyingConfigPolicy {
/**
* @return policy name to use on {@link #get(Set, HttpClientProvider)} calls.
*/
String getName();
/**
* Copies properties from {@code source} to {@code target}.
*
* @param source source
* @param target target
*/
void copy(ClientProvider source, ClientProvider target);
}
/**
* This API is highly experimental. Consider private.
*/
static class PropertiesMapper {
private PropertiesMapper() {
// utility class
}
static void copyProperty(final String propertyName, final Supplier sourceValueProvider, final Supplier targetValueProvider, final Consumer valueConsumer) {
if (!isEmpty(targetValueProvider.get())) {
getLogger().debug("{}: Skipping [{}] as target value is not empty",
PropertiesMapper.class.getSimpleName(),
propertyName);
return;
}
if (isEmpty(sourceValueProvider.get())) {
getLogger().debug("{}: Skipping [{}] as source value is empty",
PropertiesMapper.class.getSimpleName(),
propertyName);
return;
}
valueConsumer.accept(sourceValueProvider.get());
}
private static boolean isEmpty(final T value) {
if (value == null) {
return true;
}
if (value instanceof String) {
return ((String)value).trim().isEmpty();
}
if (value instanceof Collection) {
return ((Collection)value).isEmpty();
}
return false;
}
}
private static class CopyingConfigPolicyChain implements ClientProviderPolicy {
private final List> policies = new ArrayList<>();
private final ClientProvider target;
public CopyingConfigPolicyChain(final ClientProvider target) {
this.target = target;
}
void add(final CopyingConfigPolicy policy) {
this.policies.add(policy);
}
@Override
public ClientProvider apply(final ClientProvider source) {
process(source, target);
getLogger().info("{}: Properties processed. Resolved config: {}",
CopyingConfigPolicyChain.class.getSimpleName(),
target);
return target;
}
private void process(final ClientProvider source, final ClientProvider target) {
for (CopyingConfigPolicy policy : policies) {
policy.copy(source, target);
}
}
}
private static class NewHttpClient implements ClientProviderPolicy {
private final HttpClientProvider target;
private NewHttpClient(final HttpClientProvider httpClientProvider) {
this.target = httpClientProvider;
}
@Override
public ClientProvider apply(final ClientProvider source) {
getLogger().info("{}: Parent config ignored. Resolved config: {}", NewHttpClient.class, target);
return target;
}
}
private static class SharedHttpClient implements ClientProviderPolicy {
@Override
public ClientProvider apply(final ClientProvider source) {
getLogger().info("{}: Parent config reused. Resolved config: {}",
SharedHttpClient.class.getSimpleName(),
source);
return source;
}
}
private static class InheritServerUrisConfig implements CopyingConfigPolicy {
@Override
public String getName() {
return "serverList";
}
@Override
public void copy(final ClientProvider source, final ClientProvider target) {
final HttpClientFactory.Builder src = ((HttpClientProvider)source).getHttpClientFactoryBuilder();
final HttpClientFactory.Builder builder = ((HttpClientProvider)target).getHttpClientFactoryBuilder();
PropertiesMapper.copyProperty("serverList", () -> src.serverList, () -> builder.serverList, builder::withServerList);
}
}
private static class InheritSecurityConfig implements CopyingConfigPolicy {
@Override
public String getName() {
return "security";
}
@Override
public void copy(final ClientProvider source, final ClientProvider target) {
final HttpClientFactory.Builder src = ((HttpClientProvider)source).getHttpClientFactoryBuilder();
final HttpClientFactory.Builder builder = ((HttpClientProvider)target).getHttpClientFactoryBuilder();
PropertiesMapper.copyProperty("auth", () -> src.auth, () -> builder.auth, builder::withAuth);
PropertiesMapper.copyProperty("realm", () -> src.realm, () -> builder.realm, builder::withRealm);
PropertiesMapper.copyProperty("sslEngineFactory", () -> src.sslEngineFactory, () -> builder.sslEngineFactory, builder::withSslEngineFactory);
}
}
}