io.helidon.tracing.config.ComponentTracingConfig Maven / Gradle / Ivy
/*
* Copyright (c) 2019, 2023 Oracle and/or its affiliates.
*
* 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.
*/
package io.helidon.tracing.config;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import io.helidon.common.config.Config;
/**
* A component is a single "layer" of the application that can trace.
* Component examples:
*
* - web-server: webServer adds the root tracing span + two additional spans (content-read and content-write)
* - security: security adds the overall request security span, a span for authentication ("security:atn"), a span for
* authorization "security:atz", and a span for response processing ("security:response")
* - jax-rs: JAX-RS integration adds spans for overall resource invocation
*
*/
public abstract class ComponentTracingConfig extends Traceable {
/**
* Disabled component - all subsequent calls return disabled spans and logs.
*/
public static final ComponentTracingConfig DISABLED = ComponentTracingConfig.builder("disabled").enabled(false).build();
/**
* Enabled component - all subsequent calls return enabled spans and logs.
*/
public static final ComponentTracingConfig ENABLED = ComponentTracingConfig.builder("enabled").build();
/**
* A new named component.
*
* @param name name of the component
*/
protected ComponentTracingConfig(String name) {
super(name);
}
/**
* Merge configuration of two traced components. This enabled hierarchical configuration
* with common, default configuration in one traced component and override in another.
*
* @param older the older configuration with "defaults"
* @param newer the newer configuration to override defaults in older
* @return merged component
*/
static ComponentTracingConfig merge(ComponentTracingConfig older, ComponentTracingConfig newer) {
return new ComponentTracingConfig(newer.name()) {
@Override
public Optional getSpan(String spanName) {
if (!enabled()) {
return Optional.of(SpanTracingConfig.DISABLED);
}
Optional newSpan = newer.getSpan(spanName);
Optional oldSpan = older.getSpan(spanName);
// both configured
if (newSpan.isPresent() && oldSpan.isPresent()) {
return Optional.of(SpanTracingConfig.merge(oldSpan.get(), newSpan.get()));
}
// only newer
if (newSpan.isPresent()) {
return newSpan;
}
return oldSpan;
}
@Override
public Optional isEnabled() {
return newer.isEnabled()
.or(older::isEnabled);
}
};
}
/**
* Get a traced span configuration for a named span.
*
* @param spanName name of the span in this component
* @return configuration of that span if present
*/
protected abstract Optional getSpan(String spanName);
/**
* Get a traced span configuration for a named span.
*
* @param spanName name of a span in this component
* @return configuration of the span, or enabled configuration if not configured
* @see #span(String, boolean)
*/
public SpanTracingConfig span(String spanName) {
return span(spanName, true);
}
/**
* Get a traced span configuration for a named span.
*
* @param spanName name of a span in this component
* @param enabledByDefault whether the result is enabled if a configuration is not present
* @return configuration of the span, or a span configuration enabled or disabled depending on {@code enabledByDefault} if
* not configured
*/
public SpanTracingConfig span(String spanName, boolean enabledByDefault) {
if (enabled()) {
return getSpan(spanName).orElseGet(() -> enabledByDefault ? SpanTracingConfig.ENABLED : SpanTracingConfig.DISABLED);
}
return SpanTracingConfig.DISABLED;
}
/**
* Fluent API builder for traced component.
*
* @param name the name of the component
* @return a new builder instance
*/
public static Builder builder(String name) {
return new Builder(name);
}
/**
* Create a new traced component configuration from {@link Config}.
*
* @param name name of the component
* @param config config for a new component
* @return a new traced component configuration
*/
public static ComponentTracingConfig create(String name, Config config) {
return builder(name)
.config(config)
.build();
}
/**
* Fluent API builder for {@link ComponentTracingConfig}.
*/
public static final class Builder implements io.helidon.common.Builder {
private final Map tracedSpans = new HashMap<>();
private Optional enabled = Optional.empty();
private final String name;
private Builder(String name) {
this.name = name;
}
@Override
public ComponentTracingConfig build() {
// immutability
final Optional finalEnabled = enabled;
final Map finalSpans = new HashMap<>(tracedSpans);
return new ComponentTracingConfig(name) {
@Override
public Optional getSpan(String spanName) {
if (enabled.orElse(true)) {
return Optional.ofNullable(finalSpans.get(spanName));
} else {
return Optional.of(SpanTracingConfig.DISABLED);
}
}
@Override
public Optional isEnabled() {
return finalEnabled;
}
};
}
/**
* Update this builder from {@link io.helidon.common.config.Config}.
*
* @param config configuration of a traced component
* @return updated builder instance
*/
public Builder config(Config config) {
config.get("enabled").asBoolean().ifPresent(this::enabled);
config.get("spans").asNodeList().ifPresent(spanConfigList -> {
spanConfigList.forEach(spanConfig -> {
// span name is mandatory
addSpan(SpanTracingConfig.create(spanConfig.get("name").asString().get(), spanConfig));
});
});
return this;
}
/**
* Add a new traced span configuration.
*
* @param span configuration of a traced span
* @return updated builder instance
*/
public Builder addSpan(SpanTracingConfig span) {
this.tracedSpans.put(span.name(), span);
return this;
}
/**
* Configure whether this component is enabled or disabled.
*
* @param enabled if disabled, all spans and logs will be disabled
* @return updated builder instance
*/
public Builder enabled(boolean enabled) {
this.enabled = Optional.of(enabled);
return this;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy