All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.helidon.webserver.observe.tracing.TracingObserverConfig Maven / Gradle / Ivy

There is a newer version: 4.1.6
Show newest version
/*
 * Copyright (c) 2024 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.webserver.observe.tracing;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;

import io.helidon.builder.api.Prototype;
import io.helidon.common.Errors;
import io.helidon.common.Generated;
import io.helidon.common.config.Config;
import io.helidon.tracing.Tracer;
import io.helidon.tracing.config.TracingConfig;
import io.helidon.webserver.observe.ObserverConfigBase;

/**
 * Configuration of Tracing observer.
 *
 * @see io.helidon.webserver.observe.tracing.TracingObserver#create(io.helidon.webserver.observe.tracing.TracingObserverConfig)
 * @see io.helidon.webserver.observe.tracing.TracingObserver#builder()
 * @see #builder()
 */
@Generated(value = "io.helidon.builder.codegen.BuilderCodegen", trigger = "io.helidon.webserver.observe.tracing.TracingObserverConfigBlueprint")
public interface TracingObserverConfig extends TracingObserverConfigBlueprint, Prototype.Api, ObserverConfigBase {

    /**
     * Create a new fluent API builder to customize configuration.
     *
     * @return a new builder
     */
    static TracingObserverConfig.Builder builder() {
        return new TracingObserverConfig.Builder();
    }

    /**
     * Create a new fluent API builder from an existing instance.
     *
     * @param instance an existing instance used as a base for the builder
     * @return a builder based on an instance
     */
    static TracingObserverConfig.Builder builder(TracingObserverConfig instance) {
        return TracingObserverConfig.builder().from(instance);
    }

    /**
     * Create a new instance from configuration.
     *
     * @param config used to configure the new instance
     * @return a new instance configured from configuration
     */
    static TracingObserverConfig create(Config config) {
        return TracingObserverConfig.builder().config(config).buildPrototype();
    }

    /**
     * Fluent API builder base for {@link TracingObserver}.
     *
     * @param  type of the builder extending this abstract builder
     * @param  type of the prototype interface that would be built by {@link #buildPrototype()}
     */
    abstract class BuilderBase, PROTOTYPE extends TracingObserverConfig> extends ObserverConfigBase.BuilderBase implements Prototype.ConfiguredBuilder {

        private final List pathConfigs = new ArrayList(List.of(PathTracingConfig.builder()
                                          .path("/metrics/*")
                                          .tracingConfig(TracingConfig.DISABLED)
                                          .build(), 
                                          PathTracingConfig.builder()
                                          .path("/observe/metrics/*")
                                          .tracingConfig(TracingConfig.DISABLED)
                                          .build(), 
                                          PathTracingConfig.builder()
                                          .path("/health/*")
                                          .tracingConfig(TracingConfig.DISABLED)
                                          .build(), 
                                          PathTracingConfig.builder()
                                          .path("/observe/health/*")
                                          .tracingConfig(TracingConfig.DISABLED)
                                          .build(), 
                                          PathTracingConfig.builder()
                                          .path("/openapi/*")
                                          .tracingConfig(TracingConfig.DISABLED)
                                          .build(), 
                                          PathTracingConfig.builder()
                                          .path("/observe/openapi/*")
                                          .tracingConfig(TracingConfig.DISABLED)
                                          .build()));
        private final Set sockets = new LinkedHashSet<>();
        private boolean isPathConfigsMutated;
        private Config config;
        private double weight = 900.0;
        private Tracer tracer;
        private TracingConfig envConfig = TracingConfig.ENABLED;

        /**
         * Protected to support extensibility.
         */
        protected BuilderBase() {
            name("tracing");
        }

        /**
         * Update this builder from an existing prototype instance. This method disables automatic service discovery.
         *
         * @param prototype existing prototype to update this builder from
         * @return updated builder instance
         */
        public BUILDER from(TracingObserverConfig prototype) {
            super.from(prototype);
            envConfig(prototype.envConfig());
            if (!isPathConfigsMutated) {
                pathConfigs.clear();
            }
            addPathConfigs(prototype.pathConfigs());
            tracer(prototype.tracer());
            weight(prototype.weight());
            addSockets(prototype.sockets());
            return self();
        }

        /**
         * Update this builder from an existing prototype builder instance.
         *
         * @param builder existing builder prototype to update this builder from
         * @return updated builder instance
         */
        public BUILDER from(TracingObserverConfig.BuilderBase builder) {
            super.from(builder);
            envConfig(builder.envConfig());
            if (isPathConfigsMutated) {
                if (builder.isPathConfigsMutated) {
                    addPathConfigs(builder.pathConfigs);
                }
            } else {
                pathConfigs.clear();
                addPathConfigs(builder.pathConfigs);
            }
            builder.tracer().ifPresent(this::tracer);
            weight(builder.weight());
            addSockets(builder.sockets);
            return self();
        }

        /**
         * Update builder from configuration (node of this type).
         * If a value is present in configuration, it would override currently configured values.
         *
         * @param config configuration instance used to obtain values to update this builder
         * @return updated builder instance
         */
        @Override
        public BUILDER config(Config config) {
            Objects.requireNonNull(config);
            this.config = config;
            super.config(config);
            config.map(TracingConfig::create).ifPresent(this::envConfig);
            config.get("paths").mapList(io.helidon.webserver.observe.tracing.PathTracingConfig::create).ifPresent(this::pathConfigs);
            config.get("weight").as(Double.class).ifPresent(this::weight);
            return self();
        }

        /**
         * Use the provided configuration as a default for any request.
         *
         * @param envConfig default web server tracing configuration
         * @return updated builder instance
         * @see #envConfig()
         */
        public BUILDER envConfig(TracingConfig envConfig) {
            Objects.requireNonNull(envConfig);
            this.envConfig = envConfig;
            return self();
        }

        /**
         * Use the provided configuration as a default for any request.
         *
         * @param consumer consumer of builder for
         *                 default web server tracing configuration
         * @return updated builder instance
         * @see #envConfig()
         */
        public BUILDER envConfig(Consumer consumer) {
            Objects.requireNonNull(consumer);
            var builder = TracingConfig.builder();
            consumer.accept(builder);
            this.envConfig(builder.build());
            return self();
        }

        /**
         * Use the provided configuration as a default for any request.
         *
         * @param supplier supplier of
         *                 default web server tracing configuration
         * @return updated builder instance
         * @see #envConfig()
         */
        public BUILDER envConfig(Supplier supplier) {
            Objects.requireNonNull(supplier);
            this.envConfig(supplier.get());
            return self();
        }

        /**
         * Path specific configuration of tracing.
         *
         * @param pathConfigs configuration of tracing for specific paths
         * @return updated builder instance
         * @see #pathConfigs()
         */
        public BUILDER pathConfigs(List pathConfigs) {
            Objects.requireNonNull(pathConfigs);
            isPathConfigsMutated = true;
            this.pathConfigs.clear();
            this.pathConfigs.addAll(pathConfigs);
            return self();
        }

        /**
         * Path specific configuration of tracing.
         *
         * @param pathConfigs configuration of tracing for specific paths
         * @return updated builder instance
         * @see #pathConfigs()
         */
        public BUILDER addPathConfigs(List pathConfigs) {
            Objects.requireNonNull(pathConfigs);
            isPathConfigsMutated = true;
            this.pathConfigs.addAll(pathConfigs);
            return self();
        }

        /**
         * Path specific configuration of tracing.
         *
         * @param pathConfig configuration of tracing for specific paths
         * @return updated builder instance
         * @see #pathConfigs()
         */
        public BUILDER addPathConfig(PathTracingConfig pathConfig) {
            Objects.requireNonNull(pathConfig);
            this.pathConfigs.add(pathConfig);
            isPathConfigsMutated = true;
            return self();
        }

        /**
         * Path specific configuration of tracing.
         *
         * @param consumer configuration of tracing for specific paths
         * @return updated builder instance
         * @see #pathConfigs()
         */
        public BUILDER addPathConfig(Consumer consumer) {
            Objects.requireNonNull(consumer);
            var builder = PathTracingConfig.builder();
            consumer.accept(builder);
            this.pathConfigs.add(builder.build());
            return self();
        }

        /**
         * Tracer to use to extract inbound span context.
         *
         * @param tracer tracer to use
         * @return updated builder instance
         * @see #tracer()
         */
        public BUILDER tracer(Tracer tracer) {
            Objects.requireNonNull(tracer);
            this.tracer = tracer;
            return self();
        }

        /**
         * Weight of the feature registered with WebServer.
         * Changing weight may cause tracing to be executed at a different time (such as after security, or even after
         * all routes). Please understand feature weights before changing this order.
         *
         * @param weight weight of tracing feature
         * @return updated builder instance
         * @see #weight()
         */
        public BUILDER weight(double weight) {
            this.weight = weight;
            return self();
        }

        /**
         * Sockets to trace.
         * 

* If empty, all sockets will be traced. The default socket without any tag, additional sockets with a tag with the * socket name. * * @param sockets set of sockets to trace * @return updated builder instance * @see #sockets() */ public BUILDER sockets(Set sockets) { Objects.requireNonNull(sockets); this.sockets.clear(); this.sockets.addAll(sockets); return self(); } /** * Sockets to trace. *

* If empty, all sockets will be traced. The default socket without any tag, additional sockets with a tag with the * socket name. * * @param sockets set of sockets to trace * @return updated builder instance * @see #sockets() */ public BUILDER addSockets(Set sockets) { Objects.requireNonNull(sockets); this.sockets.addAll(sockets); return self(); } /** * Sockets to trace. *

* If empty, all sockets will be traced. The default socket without any tag, additional sockets with a tag with the * socket name. * * @param socket set of sockets to trace * @return updated builder instance * @see #sockets() */ public BUILDER addSocket(String socket) { Objects.requireNonNull(socket); this.sockets.add(socket); return self(); } /** * Use the provided configuration as a default for any request. * * @return the env config */ public TracingConfig envConfig() { return envConfig; } /** * Path specific configuration of tracing. * * @return the path configs */ public List pathConfigs() { return pathConfigs; } /** * Tracer to use to extract inbound span context. * * @return the tracer */ public Optional tracer() { return Optional.ofNullable(tracer); } /** * Weight of the feature registered with WebServer. * Changing weight may cause tracing to be executed at a different time (such as after security, or even after * all routes). Please understand feature weights before changing this order. * * @return the weight */ public double weight() { return weight; } /** * Sockets to trace. *

* If empty, all sockets will be traced. The default socket without any tag, additional sockets with a tag with the * socket name. * * @return the sockets */ public Set sockets() { return sockets; } /** * If this instance was configured, this would be the config instance used. * * @return config node used to configure this builder, or empty if not configured */ public Optional config() { return Optional.ofNullable(config); } @Override public String toString() { return "TracingObserverConfigBuilder{" + "envConfig=" + envConfig + "," + "pathConfigs=" + pathConfigs + "," + "tracer=" + tracer + "," + "weight=" + weight + "," + "sockets=" + sockets + "};" + super.toString(); } /** * Handles providers and decorators. */ protected void preBuildPrototype() { super.preBuildPrototype(); new TracingObserverSupport.TracingObserverDecorator().decorate(this); } /** * Validates required properties. */ protected void validatePrototype() { super.validatePrototype(); Errors.Collector collector = Errors.collector(); if (tracer == null) { collector.fatal(getClass(), "Property \"tracer\" is required, but not set"); } collector.collect().checkValid(); } /** * Generated implementation of the prototype, can be extended by descendant prototype implementations. */ protected static class TracingObserverConfigImpl extends ObserverConfigBaseImpl implements TracingObserverConfig, Supplier { private final double weight; private final List pathConfigs; private final Set sockets; private final Tracer tracer; private final TracingConfig envConfig; /** * Create an instance providing a builder. * * @param builder extending builder base of this prototype */ protected TracingObserverConfigImpl(TracingObserverConfig.BuilderBase builder) { super(builder); this.envConfig = builder.envConfig(); this.pathConfigs = List.copyOf(builder.pathConfigs()); this.tracer = builder.tracer().get(); this.weight = builder.weight(); this.sockets = Collections.unmodifiableSet(new LinkedHashSet<>(builder.sockets())); } @Override public TracingObserver build() { return TracingObserver.create(this); } @Override public TracingObserver get() { return build(); } @Override public TracingConfig envConfig() { return envConfig; } @Override public List pathConfigs() { return pathConfigs; } @Override public Tracer tracer() { return tracer; } @Override public double weight() { return weight; } @Override public Set sockets() { return sockets; } @Override public String toString() { return "TracingObserverConfig{" + "envConfig=" + envConfig + "," + "pathConfigs=" + pathConfigs + "," + "tracer=" + tracer + "," + "weight=" + weight + "," + "sockets=" + sockets + "};" + super.toString(); } @Override public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof TracingObserverConfig other)) { return false; } return super.equals(other) && Objects.equals(envConfig, other.envConfig()) && Objects.equals(pathConfigs, other.pathConfigs()) && Objects.equals(tracer, other.tracer()) && weight == other.weight() && Objects.equals(sockets, other.sockets()); } @Override public int hashCode() { return 31 * super.hashCode() + Objects.hash(envConfig, pathConfigs, tracer, weight, sockets); } } } /** * Fluent API builder for {@link TracingObserver}. */ class Builder extends TracingObserverConfig.BuilderBase implements io.helidon.common.Builder { private Builder() { } @Override public TracingObserverConfig buildPrototype() { preBuildPrototype(); validatePrototype(); return new TracingObserverConfigImpl(this); } @Override public TracingObserver build() { return TracingObserver.create(this.buildPrototype()); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy