Skip to content

Commit

Permalink
Introduced configuration option to include or exclude operation names…
Browse files Browse the repository at this point in the history
… to or from tracing.

Signed-off-by: Juergen Fickel <juergen.fickel@bosch.io>
  • Loading branch information
Juergen Fickel committed Oct 25, 2022
1 parent 0477748 commit e49b641
Show file tree
Hide file tree
Showing 11 changed files with 599 additions and 15 deletions.
37 changes: 37 additions & 0 deletions internal/utils/config/src/main/resources/ditto-tracing.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,41 @@ ditto.tracing {

propagation-channel = "default"
propagation-channel = ${?DITTO_TRACING_PROPAGATION_CHANNEL}

# A filter which determines for which operation names tracing is performed if
# tracing is enabled at all.
# If filter is not configured or left empty, all operation names are accepted
# for tracing.
#
# Tracing is performed for any operation name that matches at least one of
# the *includes* patterns and does not match any of the *excludes* patterns.
# By default all patterns are considered to be glob-like pattern that accept
# literal string values to be matched and the following wildcards:
#
# - `*` match any number of characters up to the next `/` character found in
# the test string.
# - `?` match exactly one character, other than `/`.
# - `**` match any number of characters, regardless of any `/` character
# found after this wildcard.
#
# Additionally, a matcher type prefix can be added to select a different type
# of matcher.
# The only two supported matcher types are:
#
# - `glob:` specifies that the remaining of the string is a glob-like
# pattern.
# - `regex:` specifies that the remaining of the string is a regular
# expression pattern.
#
# Examples:
#
# filter {
# includes = [ "myOperation" ]
# excludes = []
# }
#
# filter {
# includes = [ "glob:hello/**", "regex:test[0-9]" ]
# excludes = [ "goodbye" ]
filter = {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.ditto.internal.utils.config.DittoConfigError;
import org.eclipse.ditto.internal.utils.metrics.instruments.timer.StartedTimer;
import org.eclipse.ditto.internal.utils.tracing.config.TracingConfig;
import org.eclipse.ditto.internal.utils.tracing.filter.TracingFilter;
import org.eclipse.ditto.internal.utils.tracing.span.KamonHttpContextPropagation;
import org.eclipse.ditto.internal.utils.tracing.span.PreparedSpan;
import org.eclipse.ditto.internal.utils.tracing.span.SpanOperationName;
Expand Down Expand Up @@ -151,7 +152,10 @@ public void init(final TracingConfig tracingConfig) {
if (tracingConfig.isTracingEnabled()) {
final var propagationChannelName = tracingConfig.getPropagationChannel();
newStateConsumer.accept(
new TracingEnabledState(tryToGetKamonHttpContextPropagation(propagationChannelName))
new TracingEnabledState(
tryToGetKamonHttpContextPropagation(propagationChannelName),
tracingConfig.getTracingFilter()
)
);
LOGGER.info("Ditto tracing initialized and enabled using propagation channel <{}>.",
propagationChannelName);
Expand Down Expand Up @@ -190,25 +194,43 @@ public StartedSpan newStartedSpanByTimer(final Map<String, String> headers, fina
private static final class TracingEnabledState implements DittoTracingState {

private final KamonHttpContextPropagation kamonHttpContextPropagation;
private final TracingFilter tracingFilter;

private TracingEnabledState(final KamonHttpContextPropagation kamonHttpContextPropagation) {
private TracingEnabledState(
final KamonHttpContextPropagation kamonHttpContextPropagation,
final TracingFilter tracingFilter
) {
this.kamonHttpContextPropagation = checkNotNull(kamonHttpContextPropagation, "kamonHttpContextPropagation");
this.tracingFilter = tracingFilter;
}

@Override
public PreparedSpan newPreparedSpan(final Map<String, String> headers, final SpanOperationName operationName) {
return TracingSpans.newPreparedKamonSpan(headers, operationName, kamonHttpContextPropagation);
final PreparedSpan result;
if (tracingFilter.accept(operationName)) {
result = TracingSpans.newPreparedKamonSpan(headers, operationName, kamonHttpContextPropagation);
} else {
result = TracingSpans.emptyPreparedSpan(operationName);
}
return result;
}

@Override
public StartedSpan newStartedSpanByTimer(final Map<String, String> headers, final StartedTimer startedTimer) {
checkNotNull(startedTimer, "startedTimer");
final var preparedKamonSpan = TracingSpans.newPreparedKamonSpan(
headers,
SpanOperationName.of(startedTimer.getName()),
kamonHttpContextPropagation
);
return preparedKamonSpan.startBy(startedTimer);
final StartedSpan result;
final var operationName = SpanOperationName.of(startedTimer.getName());
if (tracingFilter.accept(operationName)) {
final var preparedKamonSpan = TracingSpans.newPreparedKamonSpan(
headers,
operationName,
kamonHttpContextPropagation
);
result = preparedKamonSpan.startBy(startedTimer);
} else {
result = TracingSpans.emptyStartedSpan(operationName);
}
return result;
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@
*/
package org.eclipse.ditto.internal.utils.tracing.config;

import java.text.MessageFormat;
import java.util.Objects;

import javax.annotation.concurrent.Immutable;

import org.eclipse.ditto.internal.utils.config.ConfigWithFallback;
import org.eclipse.ditto.internal.utils.config.DittoConfigError;
import org.eclipse.ditto.internal.utils.tracing.filter.KamonTracingFilter;
import org.eclipse.ditto.internal.utils.tracing.filter.AcceptAllTracingFilter;
import org.eclipse.ditto.internal.utils.tracing.filter.TracingFilter;

import com.typesafe.config.Config;

Expand All @@ -30,11 +35,36 @@ public final class DefaultTracingConfig implements TracingConfig {

private final boolean tracingEnabled;
private final String propagationChannel;
private final TracingFilter tracingFilter;

private DefaultTracingConfig(final ConfigWithFallback tracingScopedConfig) {
tracingEnabled = tracingScopedConfig.getBoolean(TracingConfigValue.TRACING_ENABLED.getConfigPath());
propagationChannel =
tracingScopedConfig.getString(TracingConfigValue.TRACING_PROPAGATION_CHANNEL.getConfigPath());
tracingFilter = getConfigBasedTracingFilterOrThrow(tracingScopedConfig);
}

private static TracingFilter getConfigBasedTracingFilterOrThrow(final ConfigWithFallback tracingScopedConfig) {
final TracingFilter result;
final var filterConfig = tracingScopedConfig.getConfig(TracingConfigValue.FILTER.getConfigPath());
if (filterConfig.isEmpty()) {
result = AcceptAllTracingFilter.getInstance();
} else {
final var kamonTracingFilterTry = KamonTracingFilter.tryFromConfig(filterConfig);
if (kamonTracingFilterTry.isSuccess()) {
result = kamonTracingFilterTry.get();
} else {
final var failed = kamonTracingFilterTry.failed();
final var failure = failed.get();
throw new DittoConfigError(
MessageFormat.format("Failed to get {0} from config: {1}",
TracingFilter.class.getSimpleName(),
failure.getMessage()),
failure
);
}
}
return result;
}

/**
Expand All @@ -46,7 +76,8 @@ private DefaultTracingConfig(final ConfigWithFallback tracingScopedConfig) {
*/
public static DefaultTracingConfig of(final Config config) {
return new DefaultTracingConfig(
ConfigWithFallback.newInstance(config, CONFIG_PATH, TracingConfigValue.values()));
ConfigWithFallback.newInstance(config, CONFIG_PATH, TracingConfigValue.values())
);
}

@Override
Expand All @@ -59,6 +90,11 @@ public String getPropagationChannel() {
return propagationChannel;
}

@Override
public TracingFilter getTracingFilter() {
return tracingFilter;
}

@Override
public boolean equals(final Object o) {
if (this == o) {
Expand All @@ -67,21 +103,24 @@ public boolean equals(final Object o) {
if (o == null || getClass() != o.getClass()) {
return false;
}
final DefaultTracingConfig that = (DefaultTracingConfig) o;
final var that = (DefaultTracingConfig) o;
return tracingEnabled == that.tracingEnabled &&
Objects.equals(propagationChannel, that.propagationChannel);
Objects.equals(propagationChannel, that.propagationChannel) &&
Objects.equals(tracingFilter, that.tracingFilter);
}

@Override
public int hashCode() {
return Objects.hash(tracingEnabled, propagationChannel);
return Objects.hash(tracingEnabled, propagationChannel, tracingFilter);
}

@Override
public String toString() {
return getClass().getSimpleName() + " [" +
"tracingEnabled=" + tracingEnabled +
", propagationChannel=" + propagationChannel +
", tracingFilter=" + tracingFilter +
"]";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@
*/
package org.eclipse.ditto.internal.utils.tracing.config;

import java.util.Map;

import javax.annotation.concurrent.Immutable;

import org.eclipse.ditto.internal.utils.config.KnownConfigValue;
import org.eclipse.ditto.internal.utils.tracing.filter.TracingFilter;

/**
* Provides the configuration settings of tracing.
Expand All @@ -36,6 +39,13 @@ public interface TracingConfig {
*/
String getPropagationChannel();

/**
* Returns a {@link TracingFilter} which is derived from configuration.
*
* @return the TracingFilter.
*/
TracingFilter getTracingFilter();

/**
* An enumeration of the known config path expressions and their associated default values for
* {@code TracingConfig}.
Expand All @@ -51,12 +61,18 @@ enum TracingConfigValue implements KnownConfigValue {
* Determines which propagation channel to use. The configured channel has to be configured at
* {@code kamon.propagation.http.<channel>}.
*/
TRACING_PROPAGATION_CHANNEL("propagation-channel", "default");
TRACING_PROPAGATION_CHANNEL("propagation-channel", "default"),

/**
* Defines include and exclude patterns to determine whether to trace matching operation names.
* By default, all operation names are accepted for tracing – if tracing is enabled at all.
*/
FILTER("filter", Map.of());

private final String path;
private final Object defaultValue;

TracingConfigValue(final String thePath, final Object theDefaultValue) {
private TracingConfigValue(final String thePath, final Object theDefaultValue) {
path = thePath;
defaultValue = theDefaultValue;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2022 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.ditto.internal.utils.tracing.filter;

import javax.annotation.concurrent.Immutable;

import org.eclipse.ditto.internal.utils.tracing.span.SpanOperationName;

/**
* This implementation of {@link TracingFilter} accepts all provided operation names.
*/
@Immutable
public final class AcceptAllTracingFilter implements TracingFilter {

private AcceptAllTracingFilter() {
super();
}

/**
* Returns an instance of {@code AcceptAllTracingFilter}.
*
* @return the instance.
*/
public static AcceptAllTracingFilter getInstance() {
return new AcceptAllTracingFilter();
}

@Override
public boolean accept(final SpanOperationName operationName) {
return true;
}

@Override
public String toString() {
return getClass().getSimpleName() + "[]";
}

}
Loading

0 comments on commit e49b641

Please sign in to comment.