From fc3bcf9098700e9b82c380e8202a3bb25c3607f7 Mon Sep 17 00:00:00 2001 From: sanpwc Date: Mon, 29 Jun 2020 20:17:26 +0300 Subject: [PATCH 1/2] IGNITE-13060 Tracing configuration. --- .../main/java/org/apache/ignite/Ignite.java | 17 ++ .../apache/ignite/internal/IgniteKernal.java | 14 ++ .../managers/tracing/GridTracingManager.java | 83 +++++-- .../processors/tracing/NoopTracing.java | 7 + .../internal/processors/tracing/Tracing.java | 15 ++ .../DistributedTracingConfiguration.java | 49 ++++ .../GridTracingConfigurationManager.java | 214 ++++++++++++++++++ .../NoopTracingConfigurationManager.java | 67 ++++++ .../TracingConfigurationCoordinates.java | 146 ++++++++++++ .../tracing/TracingConfigurationManager.java | 159 +++++++++++++ .../TracingConfigurationParameters.java | 157 +++++++++++++ .../processors/igfs/IgfsIgniteMock.java | 8 + .../testframework/junits/IgniteMock.java | 8 + .../junits/multijvm/IgniteProcessProxy.java | 7 + .../TracingConfigurationValidationTest.java | 125 ++++++++++ .../org/apache/ignite/IgniteSpringBean.java | 9 + 16 files changed, 1068 insertions(+), 17 deletions(-) create mode 100644 modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/DistributedTracingConfiguration.java create mode 100644 modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/GridTracingConfigurationManager.java create mode 100644 modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/NoopTracingConfigurationManager.java create mode 100644 modules/core/src/main/java/org/apache/ignite/spi/tracing/TracingConfigurationCoordinates.java create mode 100644 modules/core/src/main/java/org/apache/ignite/spi/tracing/TracingConfigurationManager.java create mode 100644 modules/core/src/main/java/org/apache/ignite/spi/tracing/TracingConfigurationParameters.java create mode 100644 modules/opencensus/src/test/java/org/apache/ignite/TracingConfigurationValidationTest.java diff --git a/modules/core/src/main/java/org/apache/ignite/Ignite.java b/modules/core/src/main/java/org/apache/ignite/Ignite.java index 7332eaa91a0415..194a7e993d0c3a 100644 --- a/modules/core/src/main/java/org/apache/ignite/Ignite.java +++ b/modules/core/src/main/java/org/apache/ignite/Ignite.java @@ -31,11 +31,14 @@ import org.apache.ignite.configuration.DataStorageConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.configuration.NearCacheConfiguration; +import org.apache.ignite.lang.IgniteExperimental; +import org.apache.ignite.spi.tracing.TracingConfigurationManager; import org.apache.ignite.internal.util.typedef.G; import org.apache.ignite.lang.IgniteProductVersion; import org.apache.ignite.plugin.IgnitePlugin; import org.apache.ignite.plugin.PluginNotFoundException; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; /** * Main entry-point for all Ignite APIs. @@ -741,4 +744,18 @@ public IgniteQueue queue(String name, int cap, @Nullable CollectionConfig * @return Snapshot manager. */ public IgniteSnapshot snapshot(); + + /** + * Returns the {@link TracingConfigurationManager} instance that allows to + *
    + *
  • Configure tracing parameters such as sampling rate for the specific tracing coordinates + * such as scope and label.
  • + *
  • Retrieve the most specific tracing parameters for the specified tracing coordinates (scope and label)
  • + *
  • Restore the tracing parameters for the specified tracing coordinates to the default.
  • + *
  • List all pairs of tracing configuration coordinates and tracing configuration parameters.
  • + *
+ * @return {@link TracingConfigurationManager} instance. + */ + @IgniteExperimental + public @NotNull TracingConfigurationManager tracingConfiguration(); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java index 90f5ffee08fdbd..5f657ed98123cc 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java @@ -192,6 +192,7 @@ import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor; import org.apache.ignite.internal.processors.task.GridTaskProcessor; import org.apache.ignite.internal.processors.timeout.GridTimeoutProcessor; +import org.apache.ignite.spi.tracing.TracingConfigurationManager; import org.apache.ignite.internal.suggestions.GridPerformanceSuggestions; import org.apache.ignite.internal.suggestions.JvmConfigurationSuggestions; import org.apache.ignite.internal.suggestions.OsConfigurationSuggestions; @@ -233,6 +234,7 @@ import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi; import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode; import org.apache.ignite.thread.IgniteStripedThreadPoolExecutor; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import static org.apache.ignite.IgniteSystemProperties.IGNITE_BINARY_MARSHALLER_USE_STRING_SERIALIZATION_VER_2; @@ -3999,6 +4001,18 @@ private Collection baselineNodes() { } } + /** {@inheritDoc} */ + @Override public @NotNull TracingConfigurationManager tracingConfiguration() { + guard(); + + try { + return ctx.tracing().configuration(); + } + finally { + unguard(); + } + } + /** {@inheritDoc} */ @Override public IgniteEncryption encryption() { return ctx.encryption(); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/tracing/GridTracingManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/tracing/GridTracingManager.java index 0a225b612480f1..470df42eb83dca 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/tracing/GridTracingManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/tracing/GridTracingManager.java @@ -1,11 +1,12 @@ /* - * Copyright 2019 GridGain Systems, Inc. and Contributors. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 * - * Licensed under the GridGain Community Edition License (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license + * 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, @@ -17,7 +18,6 @@ package org.apache.ignite.internal.managers.tracing; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.apache.ignite.IgniteCheckedException; @@ -27,6 +27,7 @@ import org.apache.ignite.internal.processors.tracing.DeferredSpan; import org.apache.ignite.internal.processors.tracing.NoopTracing; import org.apache.ignite.internal.processors.tracing.SpanImpl; +import org.apache.ignite.internal.processors.tracing.configuration.GridTracingConfigurationManager; import org.apache.ignite.internal.processors.tracing.NoopSpan; import org.apache.ignite.spi.tracing.NoopTracingSpi; import org.apache.ignite.spi.tracing.Scope; @@ -34,7 +35,10 @@ import org.apache.ignite.internal.processors.tracing.SpanTags; import org.apache.ignite.internal.processors.tracing.SpanType; import org.apache.ignite.internal.processors.tracing.Tracing; +import org.apache.ignite.spi.tracing.TracingConfigurationCoordinates; +import org.apache.ignite.spi.tracing.TracingConfigurationManager; import org.apache.ignite.spi.tracing.TracingSpi; +import org.apache.ignite.spi.tracing.TracingConfigurationParameters; import org.apache.ignite.internal.processors.tracing.messages.TraceableMessagesHandler; import org.apache.ignite.internal.util.typedef.internal.LT; import org.apache.ignite.logger.NullLogger; @@ -43,6 +47,8 @@ import org.jetbrains.annotations.Nullable; import static org.apache.ignite.internal.processors.tracing.SpanTags.NODE; +import static org.apache.ignite.spi.tracing.TracingConfigurationParameters.SAMPLING_RATE_ALWAYS; +import static org.apache.ignite.spi.tracing.TracingConfigurationParameters.SAMPLING_RATE_NEVER; import static org.apache.ignite.internal.util.GridClientByteUtils.bytesToInt; import static org.apache.ignite.internal.util.GridClientByteUtils.bytesToShort; import static org.apache.ignite.internal.util.GridClientByteUtils.intToBytes; @@ -85,6 +91,9 @@ public class GridTracingManager extends GridManagerAdapter implement /** Traceable messages handler. */ private final TraceableMessagesHandler msgHnd; + /** Tracing configuration */ + private final TracingConfigurationManager tracingConfiguration; + /** * Major span serialization protocol version. * Within same major protocol version span serialization should be backward compatible. @@ -113,6 +122,8 @@ public GridTracingManager(GridKernalContext ctx, boolean useNoopTracingSpi) { super(ctx, useNoopTracingSpi ? new NoopTracingSpi() : ctx.config().getTracingSpi()); msgHnd = new TraceableMessagesHandler(this, ctx.log(GridTracingManager.class)); + + tracingConfiguration = new GridTracingConfigurationManager(ctx); } /** @@ -167,9 +178,16 @@ private Span enrichWithLocalNodeParameters(@Nullable Span span) { /** {@inheritDoc} */ @Override public Span create(@NotNull SpanType spanType, @Nullable Span parentSpan) { + // Optimization for noop spi. if (noop) return NoopSpan.INSTANCE; + // Optimization for zero sampling rate == 0. + if ((parentSpan == NoopSpan.INSTANCE || parentSpan == null) && + tracingConfiguration.get(new TracingConfigurationCoordinates.Builder(spanType.scope()).build()). + samplingRate() == SAMPLING_RATE_NEVER) + return NoopSpan.INSTANCE; + return enrichWithLocalNodeParameters( generateSpan( parentSpan, @@ -179,9 +197,16 @@ private Span enrichWithLocalNodeParameters(@Nullable Span span) { /** {@inheritDoc} */ @Override public Span create(@NotNull SpanType spanType, @Nullable byte[] serializedParentSpan) { + // Optimization for noop spi. if (noop) return NoopSpan.INSTANCE; + // Optimization for zero sampling rate == 0. + if ((serializedParentSpan.length == 0 || serializedParentSpan == null) && + tracingConfiguration.get(new TracingConfigurationCoordinates.Builder(spanType.scope()).build()). + samplingRate() == SAMPLING_RATE_NEVER) + return NoopSpan.INSTANCE; + // 1 byte: special flags; // 1 bytes: spi type; // 2 bytes: major protocol version; @@ -195,7 +220,7 @@ private Span enrichWithLocalNodeParameters(@Nullable Span span) { Span span; try { - if (serializedParentSpan == null || serializedParentSpan == NoopTracing.NOOP_SERIALIZED_SPAN) + if (serializedParentSpan == null || serializedParentSpan.length == 0) return create(spanType, NoopSpan.INSTANCE); // First byte of the serializedSpan is reserved for special flags - it's not used right now. @@ -310,9 +335,17 @@ private Span enrichWithLocalNodeParameters(@Nullable Span span) { @Nullable Span parentSpan, @Nullable String lb ) { + // Optimization for noop spi. if (noop) return NoopSpan.INSTANCE; + // Optimization for zero sampling rate == 0. + if ((parentSpan == NoopSpan.INSTANCE || parentSpan == null) && + tracingConfiguration.get( + new TracingConfigurationCoordinates.Builder(spanType.scope()).withLabel(lb).build()). + samplingRate() == SAMPLING_RATE_NEVER) + return NoopSpan.INSTANCE; + return enrichWithLocalNodeParameters( generateSpan( parentSpan, @@ -321,10 +354,16 @@ private Span enrichWithLocalNodeParameters(@Nullable Span span) { } /** {@inheritDoc} */ + @SuppressWarnings("unchecked") @Override public byte[] serialize(@NotNull Span span) { + // Optimization for noop spi. if (noop) return NoopTracing.NOOP_SERIALIZED_SPAN; + // Optimization for NoopSpan. + if (span == NoopSpan.INSTANCE) + return NoopTracing.NOOP_SERIALIZED_SPAN; + // 1 byte: special flags; // 1 bytes: spi type; // 2 bytes: major protocol version; @@ -338,10 +377,6 @@ private Span enrichWithLocalNodeParameters(@Nullable Span span) { if (span instanceof DeferredSpan) return ((DeferredSpan)span).serializedSpan(); - // Optimization for NoopSpan. - if (span == NoopSpan.INSTANCE) - return NoopTracing.NOOP_SERIALIZED_SPAN; - // Spi specific serialized span. byte[] spiSpecificSerializedSpan = getSpi().serialize(((SpanImpl)span).spiSpecificSpan()); @@ -421,6 +456,7 @@ private Span enrichWithLocalNodeParameters(@Nullable Span span) { * @param spanTypeToCreate Span type to create. * @param lb Label. */ + @SuppressWarnings("unchecked") private @NotNull Span generateSpan( @Nullable Span parentSpan, @NotNull SpanType spanTypeToCreate, @@ -429,16 +465,23 @@ private Span enrichWithLocalNodeParameters(@Nullable Span span) { if (parentSpan instanceof DeferredSpan) return create(spanTypeToCreate, ((DeferredSpan)parentSpan).serializedSpan()); - if (parentSpan == null || parentSpan == NoopSpan.INSTANCE) { + if (parentSpan == NoopSpan.INSTANCE || parentSpan == null) { if (spanTypeToCreate.rootSpan()) { + // Get tracing configuration. + TracingConfigurationParameters tracingConfigurationParameters = tracingConfiguration.get( + new TracingConfigurationCoordinates.Builder(spanTypeToCreate.scope()).withLabel(lb).build()); + + // Optimization + if (tracingConfigurationParameters.samplingRate() == SAMPLING_RATE_NEVER) + return NoopSpan.INSTANCE; return new SpanImpl( getSpi().create( spanTypeToCreate.spanName(), null, - 1), + tracingConfigurationParameters.samplingRate()), spanTypeToCreate, - Collections.emptySet()); + tracingConfigurationParameters.includedScopes()); } else return NoopSpan.INSTANCE; @@ -457,7 +500,7 @@ private Span enrichWithLocalNodeParameters(@Nullable Span span) { getSpi().create( spanTypeToCreate.spanName(), ((SpanImpl)parentSpan).spiSpecificSpan(), - 1), + SAMPLING_RATE_ALWAYS), spanTypeToCreate, mergedIncludedScopes); } @@ -470,9 +513,15 @@ private Span enrichWithLocalNodeParameters(@Nullable Span span) { /** {@inheritDoc} */ @Override public TraceableMessagesHandler messages() { + // Optimization for noop spi. if (noop) return NOOP_TRACEABLE_MSG_HANDLER; return msgHnd; } -} \ No newline at end of file + + /** {@inheritDoc} */ + @Override public @NotNull TracingConfigurationManager configuration() { + return tracingConfiguration; + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/NoopTracing.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/NoopTracing.java index 5aa8a72f3114bf..0427bb0de81025 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/NoopTracing.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/NoopTracing.java @@ -17,6 +17,8 @@ package org.apache.ignite.internal.processors.tracing; +import org.apache.ignite.internal.processors.tracing.configuration.NoopTracingConfigurationManager; +import org.apache.ignite.spi.tracing.TracingConfigurationManager; import org.apache.ignite.internal.processors.tracing.messages.TraceableMessagesHandler; import org.apache.ignite.logger.NullLogger; import org.jetbrains.annotations.NotNull; @@ -66,4 +68,9 @@ public NoopTracing() { @Override public byte[] serialize(@NotNull Span span) { return NOOP_SERIALIZED_SPAN; } + + /** {@inheritDoc} */ + @Override public @NotNull TracingConfigurationManager configuration() { + return NoopTracingConfigurationManager.INSTANCE; + } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/Tracing.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/Tracing.java index bc957c54cc29b2..8bc9a804511090 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/Tracing.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/Tracing.java @@ -18,6 +18,8 @@ package org.apache.ignite.internal.processors.tracing; import org.apache.ignite.internal.processors.tracing.messages.TraceableMessagesHandler; +import org.apache.ignite.spi.tracing.TracingConfigurationManager; +import org.jetbrains.annotations.NotNull; /** * Tracing sub-system interface. @@ -27,4 +29,17 @@ public interface Tracing extends SpanManager { * @return Helper to handle traceable messages. */ public TraceableMessagesHandler messages(); + + /** + * Returns the {@link TracingConfigurationManager} instance that allows to + *
    + *
  • Configure tracing parameters such as sampling rate for the specific tracing coordinates + * such as scope and label.
  • + *
  • Retrieve the most specific tracing parameters for the specified tracing coordinates (scope and label)
  • + *
  • Restore the tracing parameters for the specified tracing coordinates to the default.
  • + *
  • List all pairs of tracing configuration coordinates and tracing configuration parameters.
  • + *
+ * @return {@link TracingConfigurationManager} instance. + */ + public @NotNull TracingConfigurationManager configuration(); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/DistributedTracingConfiguration.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/DistributedTracingConfiguration.java new file mode 100644 index 00000000000000..fd74c84569f157 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/DistributedTracingConfiguration.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.ignite.internal.processors.tracing.configuration; + +import java.util.HashMap; +import org.apache.ignite.internal.processors.configuration.distributed.SimpleDistributedProperty; +import org.apache.ignite.spi.tracing.TracingConfigurationCoordinates; +import org.apache.ignite.spi.tracing.TracingConfigurationParameters; +import org.apache.ignite.internal.processors.configuration.distributed.DistributedConfigurationProcessor; + +/** + * The wrapper of {@code HashMap} + * for the distributed metastorage binding. + */ +public class DistributedTracingConfiguration + extends SimpleDistributedProperty> { + /** */ + private static final String TRACING_CONFIGURATION_DISTRIBUTED_METASTORE_KEY = "tr.config"; + + /** + * Constructor. + */ + public DistributedTracingConfiguration() { + super(TRACING_CONFIGURATION_DISTRIBUTED_METASTORE_KEY); + } + + /** + * @return A new property that is detached from {@link DistributedConfigurationProcessor}. + * This means distributed updates are not accessible. + */ + public static DistributedTracingConfiguration detachedProperty() { + return new DistributedTracingConfiguration(); + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/GridTracingConfigurationManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/GridTracingConfigurationManager.java new file mode 100644 index 00000000000000..cd03738efee1ff --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/GridTracingConfigurationManager.java @@ -0,0 +1,214 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.ignite.internal.processors.tracing.configuration; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.IgniteException; +import org.apache.ignite.IgniteLogger; +import org.apache.ignite.internal.GridKernalContext; +import org.apache.ignite.internal.util.tostring.GridToStringExclude; +import org.apache.ignite.spi.tracing.Scope; +import org.apache.ignite.spi.tracing.TracingConfigurationCoordinates; +import org.apache.ignite.spi.tracing.TracingConfigurationManager; +import org.apache.ignite.spi.tracing.TracingConfigurationParameters; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Tracing configuration manager implementation that uses distributed meta storage + * in order to store tracing configuration. + */ +public class GridTracingConfigurationManager implements TracingConfigurationManager { + /** Map with default configurations. */ + private static final Map DEFAULT_CONFIGURATION_MAP; + + /** */ + public static final String WARNING_MSG_TRACING_CONFIG_UPDATE_FAILED_COORDINATES = + "Failed to update tracing configuration for coordinates=[%s]."; + + /** */ + public static final String WARNING_MSG_TRACING_CONFIG_UPDATE_FAILED_SCOPE = + "Failed to update tracing configuration for scope=[%s]."; + + /** Tracing configuration distributed property. */ + private final DistributedTracingConfiguration distributedTracingConfiguration = + DistributedTracingConfiguration.detachedProperty(); + + /** Tracing configuration. */ + private volatile Map tracingConfiguration = + DEFAULT_CONFIGURATION_MAP; + + /** Mutex for updating local tracing configuration. */ + @GridToStringExclude + private final Object mux = new Object(); + + static { + Map tmpDfltConfigurationMap = new HashMap<>(); + + tmpDfltConfigurationMap.put( + new TracingConfigurationCoordinates.Builder(Scope.TX).build(), + TracingConfigurationManager.DEFAULT_TX_CONFIGURATION); + + tmpDfltConfigurationMap.put( + new TracingConfigurationCoordinates.Builder(Scope.COMMUNICATION).build(), + TracingConfigurationManager.DEFAULT_COMMUNICATION_CONFIGURATION); + + tmpDfltConfigurationMap.put( + new TracingConfigurationCoordinates.Builder(Scope.EXCHANGE).build(), + TracingConfigurationManager.DEFAULT_EXCHANGE_CONFIGURATION); + + tmpDfltConfigurationMap.put( + new TracingConfigurationCoordinates.Builder(Scope.DISCOVERY).build(), + TracingConfigurationManager.DEFAULT_DISCOVERY_CONFIGURATION); + + DEFAULT_CONFIGURATION_MAP = Collections.unmodifiableMap(tmpDfltConfigurationMap); + } + + /** Kernal context. */ + @GridToStringExclude + protected final GridKernalContext ctx; + + /** Grid logger. */ + @GridToStringExclude + protected final IgniteLogger log; + + /** + * Constructor. + * + * @param ctx Context. + */ + public GridTracingConfigurationManager(@NotNull GridKernalContext ctx) { + this.ctx = ctx; + + log = ctx.log(getClass()); + + ctx.internalSubscriptionProcessor().registerDistributedConfigurationListener(dispatcher -> { + distributedTracingConfiguration.addListener((name, oldVal, newVal) -> { + synchronized (mux) { + if (log.isDebugEnabled()) + log.debug("Tracing configuration was updated [oldVal= " + oldVal + ", newVal=" + newVal + "]"); + + if (newVal != null && !newVal.isEmpty()) + tracingConfiguration = newVal; + } + }); + + dispatcher.registerProperty(distributedTracingConfiguration); + }); + } + + /** {@inheritDoc} */ + @Override public void set( + @NotNull TracingConfigurationCoordinates coordinates, + @NotNull TracingConfigurationParameters parameters) + { + HashMap newTracingConfiguration = + new HashMap<>(tracingConfiguration); + + newTracingConfiguration.put(coordinates, parameters); + + try { + distributedTracingConfiguration.propagate(newTracingConfiguration); + } + catch (IgniteCheckedException e) { + String warningMsg = String.format(WARNING_MSG_TRACING_CONFIG_UPDATE_FAILED_COORDINATES, coordinates); + + log.warning(warningMsg, e); + + throw new IgniteException(warningMsg, e); + } + } + + /** {@inheritDoc} */ + @Override public @NotNull TracingConfigurationParameters get(@NotNull TracingConfigurationCoordinates coordinates) { + TracingConfigurationParameters coordinateSpecificParameters = tracingConfiguration.get(coordinates); + + // If parameters for the specified coordinates (both scope and label) were not found use only scope specific one. + // If there are no custom scope specific parameters, default one will be used. + return coordinateSpecificParameters == null ? + tracingConfiguration.get(new TracingConfigurationCoordinates.Builder(coordinates.scope()).build()) : + coordinateSpecificParameters; + } + + /** {@inheritDoc} */ + @SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType") + @Override public @NotNull Map getAll( + @Nullable Scope scope) { + return scope != null ? + tracingConfiguration.entrySet().stream(). + filter(e -> e.getKey().scope() == scope). + collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) : + tracingConfiguration; + } + + /** {@inheritDoc} */ + @Override public void reset(@NotNull TracingConfigurationCoordinates coordinates) { + HashMap newTracingConfiguration = + new HashMap<>(tracingConfiguration); + + if (coordinates.label() != null) + newTracingConfiguration.remove(coordinates); + else + newTracingConfiguration.put(coordinates, DEFAULT_CONFIGURATION_MAP.get(new TracingConfigurationCoordinates.Builder(coordinates.scope()).build())); + + try { + distributedTracingConfiguration.propagate(newTracingConfiguration); + } + catch (IgniteCheckedException e) { + String warningMsg = String.format(WARNING_MSG_TRACING_CONFIG_UPDATE_FAILED_COORDINATES, coordinates); + + log.warning(warningMsg, e); + + throw new IgniteException(warningMsg, e); + } + } + + /** {@inheritDoc} */ + @Override public void resetAll(@Nullable Scope scope) throws IgniteException { + HashMap newTracingConfiguration; + + if (scope != null) { + newTracingConfiguration = new HashMap<>(tracingConfiguration.entrySet().stream(). + filter(e -> e.getKey().scope() != scope). + collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); + + TracingConfigurationCoordinates scopeSpecificCoordinates = + new TracingConfigurationCoordinates.Builder(scope).build(); + + newTracingConfiguration.put(scopeSpecificCoordinates, + DEFAULT_CONFIGURATION_MAP.get(scopeSpecificCoordinates)); + } + else + newTracingConfiguration = new HashMap<>(DEFAULT_CONFIGURATION_MAP); + + try { + distributedTracingConfiguration.propagate(newTracingConfiguration); + } + catch (IgniteCheckedException e) { + String warningMsg = String.format(WARNING_MSG_TRACING_CONFIG_UPDATE_FAILED_SCOPE, scope); + + log.warning(warningMsg, e); + + throw new IgniteException(warningMsg, e); + } + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/NoopTracingConfigurationManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/NoopTracingConfigurationManager.java new file mode 100644 index 00000000000000..3345148f5c6d58 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/NoopTracingConfigurationManager.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.ignite.internal.processors.tracing.configuration; + +import java.util.Collections; +import java.util.Map; + +import org.apache.ignite.IgniteException; +import org.apache.ignite.spi.tracing.Scope; +import org.apache.ignite.spi.tracing.TracingConfigurationCoordinates; +import org.apache.ignite.spi.tracing.TracingConfigurationManager; +import org.apache.ignite.spi.tracing.TracingConfigurationParameters; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Noop tracing configuration manager. + * To be used mainly with {@link org.apache.ignite.internal.processors.tracing.NoopTracing}. + */ +public final class NoopTracingConfigurationManager implements TracingConfigurationManager { + /** */ + public static final NoopTracingConfigurationManager INSTANCE = new NoopTracingConfigurationManager(); + + /** {@inheritDoc} */ + @Override public void set(@NotNull TracingConfigurationCoordinates coordinates, + @NotNull TracingConfigurationParameters parameters) { + // No-op. + } + + /** {@inheritDoc} */ + @Override public @NotNull TracingConfigurationParameters get( + @NotNull TracingConfigurationCoordinates coordinates) { + return TracingConfigurationManager.NOOP_CONFIGURATION; + } + + /** {@inheritDoc} */ + @Override public @NotNull Map getAll( + @Nullable Scope scope + ) { + return Collections.emptyMap(); + } + + /** {@inheritDoc} */ + @Override public void reset(@NotNull TracingConfigurationCoordinates coordinates) { + // No-op. + } + + /** {@inheritDoc} */ + @Override public void resetAll(@Nullable Scope scope) throws IgniteException { + // No-op. + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/spi/tracing/TracingConfigurationCoordinates.java b/modules/core/src/main/java/org/apache/ignite/spi/tracing/TracingConfigurationCoordinates.java new file mode 100644 index 00000000000000..7611d4e2d82d43 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/spi/tracing/TracingConfigurationCoordinates.java @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.ignite.spi.tracing; + +import org.apache.ignite.internal.util.typedef.internal.S; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.Serializable; + +/** + * Specifies to which traces, specific configuration will be applied. In other words it's a sort of tracing + * configuration locator. + */ +public class TracingConfigurationCoordinates implements Serializable { + + /** */ + private static final long serialVersionUID = 0L; + + /** + * Specifies the {@link Scope} of a trace's root span to which some specific tracing configuration will be applied. + * It's a mandatory attribute. + */ + private final Scope scope; + + /** + * Specifies the label of a traced operation. It's an optional attribute. + */ + private final String lb; + + /** + * Private constructor to be used with builder. + * + * @param scope scope Specifies the {@link Scope} of a trace's root span to which some specific + * tracing configuration will be applied. + * @param lb Specifies the label of a traced operation. + */ + private TracingConfigurationCoordinates(@NotNull Scope scope, @Nullable String lb) { + this.scope = scope; + this.lb = lb; + } + + /** + * @return {@link Scope} of a trace's root span to which some specific tracing configuration will be applied. + */ + @NotNull public Scope scope() { + return scope; + } + + /** + * @return Label of a traced operation, to which some specific tracing configuration will be applied. + */ + @Nullable public String label() { + return lb; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + TracingConfigurationCoordinates that = (TracingConfigurationCoordinates)o; + + if (scope != that.scope) + return false; + + return lb != null ? lb.equals(that.lb) : that.lb == null; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = scope != null ? scope.hashCode() : 0; + + res = 31 * res + (lb != null ? lb.hashCode() : 0); + + return res; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(TracingConfigurationCoordinates.class, this); + } + + /** + * {@code TracingConfigurationCoordinates} builder. + */ + @SuppressWarnings("PublicInnerClass") public static class Builder { + /** Counterpart of {@code TracingConfigurationCoordinator}'s scope. */ + private final Scope scope; + + /** Counterpart of {@code TracingConfigurationCoordinator}'s lb. */ + private String lb; + + /** + * Constructor. + * + * @param scope Mandatory scope attribute. + * @throws IllegalArgumentException if null scope is specified. + */ + public Builder(Scope scope) { + if (scope == null) + throw new IllegalArgumentException("Null scope is not valid for tracing coordinates."); + + this.scope = scope; + } + + /** + * Builder method that allows to set optional label attribute. + * + * @param lb Label of traced operation. It's an optional attribute. + * @return Current {@code TracingConfigurationCoordinates} instance. + */ + public @NotNull Builder withLabel(@Nullable String lb) { + this.lb = lb; + + return this; + } + + /** + * Builder's build() method. + * + * @return {@code TracingConfigurationCoordinates} instance. + */ + public TracingConfigurationCoordinates build() { + return new TracingConfigurationCoordinates(scope, lb); + } + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/spi/tracing/TracingConfigurationManager.java b/modules/core/src/main/java/org/apache/ignite/spi/tracing/TracingConfigurationManager.java new file mode 100644 index 00000000000000..cfc2279486b955 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/spi/tracing/TracingConfigurationManager.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.ignite.spi.tracing; + +import java.util.Collections; +import java.util.Map; +import org.apache.ignite.IgniteException; +import org.apache.ignite.lang.IgniteExperimental; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Allows to configure tracing, read the configuration and restore it to the defaults. + */ +@IgniteExperimental +public interface TracingConfigurationManager { + /** Default transaction tracing configuration. */ + static final TracingConfigurationParameters DEFAULT_TX_CONFIGURATION = + new TracingConfigurationParameters.Builder(). + withSamplingRate(0d). + withIncludedScopes(Collections.emptySet()). + build(); + + /** Default exchange configuration. */ + static final TracingConfigurationParameters DEFAULT_EXCHANGE_CONFIGURATION = + new TracingConfigurationParameters.Builder(). + withSamplingRate(0d). + withIncludedScopes(Collections.emptySet()). + build(); + + /** Default discovery configuration. */ + static final TracingConfigurationParameters DEFAULT_DISCOVERY_CONFIGURATION = + new TracingConfigurationParameters.Builder(). + withSamplingRate(0d). + withIncludedScopes(Collections.emptySet()). + build(); + + /** Default communication configuration. */ + static final TracingConfigurationParameters DEFAULT_COMMUNICATION_CONFIGURATION = + new TracingConfigurationParameters.Builder(). + withSamplingRate(0d). + withIncludedScopes(Collections.emptySet()). + build(); + + /** Default noop configuration. */ + static final TracingConfigurationParameters NOOP_CONFIGURATION = + new TracingConfigurationParameters.Builder(). + withSamplingRate(0d). + withIncludedScopes(Collections.emptySet()). + build(); + + /** + * Set new tracing configuration for the specific tracing coordinates (scope, label, etc.). + * If tracing configuration with specified coordinates already exists it'll be overrided, + * otherwise new one will be created. + * + * @param coordinates {@link TracingConfigurationCoordinates} Specific set of locators like {@link Scope} and label, + * that defines subset of traces and/or spans that'll use given configuration. + * @param parameters {@link TracingConfigurationParameters} e.g. sampling rate, set of included scopes etc. + * @throws IgniteException If failed to set tracing configuration. + */ + void set(@NotNull TracingConfigurationCoordinates coordinates, + @NotNull TracingConfigurationParameters parameters) throws IgniteException; + + /** + * Get the most specific tracing parameters for the specified tracing coordinates (scope, label, etc.). + * The most specific means: + *
    + *
  • + * If there's tracing configuration that matches all tracing configuration attributes (scope and label) — + * it'll be returned. + *
  • + *
  • + * If there's no tracing configuration with specified label, or label wasn't specified — + * scope specific tracing configuration will be returned. + *
  • + *
  • + * If there's no tracing configuration with specified scope — + * default scope specific configuration will be returned. + *
  • + *
+ * + * @param coordinates {@link TracingConfigurationCoordinates} Specific set of locators like {@link Scope} and label + * that defines a subset of traces and/or spans that'll use given configuration. + * @return {@link TracingConfigurationParameters} instance. + * @throws IgniteException If failed to get tracing configuration. + */ + default @NotNull TracingConfigurationParameters get( + @NotNull TracingConfigurationCoordinates coordinates) throws IgniteException + { + switch (coordinates.scope()) { + case TX: { + return DEFAULT_TX_CONFIGURATION; + } + + case EXCHANGE: { + return DEFAULT_EXCHANGE_CONFIGURATION; + } + + case DISCOVERY: { + return DEFAULT_DISCOVERY_CONFIGURATION; + } + + case COMMUNICATION: { + return DEFAULT_COMMUNICATION_CONFIGURATION; + } + + default: { + return NOOP_CONFIGURATION; + } + } + } + + /** + * List all pairs of tracing configuration coordinates and tracing configuration parameters + * or list all pairs of tracing configuration and parameters for the specific scope. + * + * @param scope Nullable scope of tracing configuration to be retrieved. + * If null - all configuration will be returned. + * @return The whole set of tracing configuration. + * @throws IgniteException If failed to get tracing configuration. + */ + @NotNull Map getAll( + @Nullable Scope scope) throws IgniteException; + + /** + * Reset tracing configuration for the specific tracing coordinates (scope, label, etc.) to default values. + * Please pay attention, that there's no default values for label specific coordinates, + * so such kinds of configurations will be removed. + * + * @param coordinates {@link TracingConfigurationCoordinates} specific set of locators like {@link Scope} and label + * that defines a subset of traces and/or spans that will be reset. + * @throws IgniteException If failed to reset tracing configuration. + */ + void reset(@NotNull TracingConfigurationCoordinates coordinates) throws IgniteException; + + /** + * Reset tracing configuration for the specific scope, or all tracing configurations if scope not specified. + * + * @param scope {@link Scope} that defines a set of applicable tracing configurations. + * @throws IgniteException If failed to reset tracing configuration. + */ + void resetAll(@Nullable Scope scope) throws IgniteException; +} diff --git a/modules/core/src/main/java/org/apache/ignite/spi/tracing/TracingConfigurationParameters.java b/modules/core/src/main/java/org/apache/ignite/spi/tracing/TracingConfigurationParameters.java new file mode 100644 index 00000000000000..b4c90ac6dd40fd --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/spi/tracing/TracingConfigurationParameters.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.ignite.spi.tracing; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Set; +import org.apache.ignite.internal.processors.tracing.Span; +import org.jetbrains.annotations.NotNull; + +/** + * Set of tracing configuration parameters like sampling rate or included scopes. + */ +public class TracingConfigurationParameters implements Serializable { + /** */ + private static final long serialVersionUID = 0L; + + /** Min valid sampling rate with special meaning that span won't be created. */ + public static final double SAMPLING_RATE_NEVER = 0d; + + /** Max valid sampling rate with special meaning that span will be always created. */ + public static final double SAMPLING_RATE_ALWAYS = 1d; + + /** + * Number between 0 and 1 that more or less reflects the probability of sampling a specific trace. + * 0 and 1 have special meaning here, 0 means never 1 means always. Default value is 0 (never). + */ + private final double samplingRate; + + /** + * Set of {@link Scope} that defines which sub-traces will be included in a given trace. + * In other words, if the child's span scope is equal to parent's scope + * or it belongs to the parent's span included scopes, then the given child span will be attached to the current trace, + * otherwise it'll be skipped. + * See {@link Span#isChainable(Scope)} for more details. + */ + private final Set includedScopes; + + /** + * Constructor. + * + * @param samplingRate Number between 0 and 1 that more or less reflects the probability of sampling specific trace. + * 0 and 1 have special meaning here, 0 means never 1 means always. Default value is 0 (never). + * @param includedScopes Set of {@link Scope} that defines which sub-traces will be included in given trace. + * In other words, if child's span scope is equals to parent's scope + * or it belongs to the parent's span included scopes, then given child span will be attached to the current trace, + * otherwise it'll be skipped. + * See {@link Span#isChainable(Scope)} for more details. + */ + private TracingConfigurationParameters(double samplingRate, + Set includedScopes) { + this.samplingRate = samplingRate; + this.includedScopes = Collections.unmodifiableSet(includedScopes); + } + + /** + * @return Number between 0 and 1 that more or less reflects the probability of sampling specific trace. + * 0 and 1 have special meaning here, 0 means never 1 means always. Default value is 0 (never). + */ + public double samplingRate() { + return samplingRate; + } + + /** + * @return Set of {@link Scope} that defines which sub-traces will be included in given trace. + * In other words, if child's span scope is equals to parent's scope + * or it belongs to the parent's span included scopes, then given child span will be attached to the current trace, + * otherwise it'll be skipped. + * See {@link Span#isChainable(Scope)} for more details. + * If no scopes are specified, empty set will be returned. + */ + public @NotNull Set includedScopes() { + return Collections.unmodifiableSet(includedScopes); + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + TracingConfigurationParameters that = (TracingConfigurationParameters)o; + + if (Double.compare(that.samplingRate, samplingRate) != 0) + return false; + return includedScopes != null ? includedScopes.equals(that.includedScopes) : that.includedScopes == null; + } + + /** + * {@code TracingConfigurationParameters} builder. + */ + @SuppressWarnings("PublicInnerClass") public static class Builder { + /** Counterpart of {@code TracingConfigurationParameters} samplingRate. */ + private double samplingRate; + + /** Counterpart of {@code TracingConfigurationParameters} includedScopes. */ + private Set includedScopes = Collections.emptySet(); + + /** + * Builder method that allows to set sampling rate. + * + * @param samplingRate Number between 0 and 1 that more or less reflects the probability of sampling specific trace. + * 0 and 1 have special meaning here, 0 means never 1 means always. Default value is 0 (never). + * @return {@code TracingConfigurationParameters} instance. + */ + public @NotNull Builder withSamplingRate(double samplingRate) { + if (samplingRate < SAMPLING_RATE_NEVER || samplingRate > SAMPLING_RATE_ALWAYS) { + throw new IllegalArgumentException("Specified sampling rate=[" + samplingRate + "] has invalid value." + + " Should be between 0 and 1 including boundaries."); + } + this.samplingRate = samplingRate; + + return this; + } + + /** + * Builder method that allows to set included scopes. + * + * @param includedScopes Set of {@link Scope} that defines which sub-traces will be included in given trace. + * In other words, if child's span scope is equals to parent's scope + * or it belongs to the parent's span included scopes, then given child span will be attached to the current trace, + * otherwise it'll be skipped. + * See {@link Span#isChainable(Scope)} for more details. + * @return {@code TracingConfigurationParameters} instance. + */ + public @NotNull Builder withIncludedScopes(Set includedScopes) { + this.includedScopes = includedScopes == null ? Collections.emptySet() : includedScopes; + + return this; + } + + /** + * Builder's build() method. + * + * @return {@code TracingConfigurationParameters} instance. + */ + public TracingConfigurationParameters build() { + return new TracingConfigurationParameters(samplingRate, includedScopes); + } + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsIgniteMock.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsIgniteMock.java index bd7b913d79a965..4c7e984f18e446 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsIgniteMock.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsIgniteMock.java @@ -64,12 +64,15 @@ import org.apache.ignite.internal.processors.cache.GridCacheUtilityKey; import org.apache.ignite.internal.processors.cache.IgniteInternalCache; import org.apache.ignite.internal.processors.hadoop.Hadoop; +import org.apache.ignite.internal.processors.tracing.configuration.NoopTracingConfigurationManager; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.lang.IgniteBiTuple; import org.apache.ignite.lang.IgnitePredicate; import org.apache.ignite.lang.IgniteProductVersion; import org.apache.ignite.plugin.IgnitePlugin; import org.apache.ignite.plugin.PluginNotFoundException; +import org.apache.ignite.spi.tracing.TracingConfigurationManager; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -623,6 +626,11 @@ public IgfsIgniteMock(@Nullable String name, IgniteFileSystem igfs) { return null; } + /** {@inheritDoc} */ + @Override public @NotNull TracingConfigurationManager tracingConfiguration() { + return NoopTracingConfigurationManager.INSTANCE; + } + /** {@inheritDoc} */ @Override public Collection memoryMetrics() { return DataRegionMetricsAdapter.collectionOf(dataRegionMetrics()); diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteMock.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteMock.java index 30d220f03f8834..1306d8003ef660 100644 --- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteMock.java +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteMock.java @@ -67,12 +67,15 @@ import org.apache.ignite.internal.binary.BinaryMarshaller; import org.apache.ignite.internal.binary.builder.BinaryObjectBuilderImpl; import org.apache.ignite.internal.processors.cacheobject.NoOpBinary; +import org.apache.ignite.internal.processors.tracing.configuration.NoopTracingConfigurationManager; +import org.apache.ignite.spi.tracing.TracingConfigurationManager; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.lang.IgniteProductVersion; import org.apache.ignite.logger.NullLogger; import org.apache.ignite.marshaller.Marshaller; import org.apache.ignite.plugin.IgnitePlugin; import org.apache.ignite.plugin.PluginNotFoundException; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -499,6 +502,11 @@ public IgniteMock( return null; } + /** {@inheritDoc} */ + @Override public @NotNull TracingConfigurationManager tracingConfiguration() { + return NoopTracingConfigurationManager.INSTANCE; + } + /** {@inheritDoc} */ @Override public Collection memoryMetrics() { return DataRegionMetricsAdapter.collectionOf(dataRegionMetrics()); diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteProcessProxy.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteProcessProxy.java index 1f64f4cb4a54c0..344c31ebd07c4f 100644 --- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteProcessProxy.java +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteProcessProxy.java @@ -82,6 +82,7 @@ import org.apache.ignite.internal.processors.cache.GridCacheUtilityKey; import org.apache.ignite.internal.processors.cache.IgniteInternalCache; import org.apache.ignite.internal.processors.hadoop.Hadoop; +import org.apache.ignite.spi.tracing.TracingConfigurationManager; import org.apache.ignite.internal.util.GridJavaProcess; import org.apache.ignite.internal.util.lang.IgnitePredicateX; import org.apache.ignite.internal.util.typedef.G; @@ -99,6 +100,7 @@ import org.apache.ignite.plugin.PluginNotFoundException; import org.apache.ignite.resources.IgniteInstanceResource; import org.apache.ignite.testframework.junits.IgniteTestResources; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -847,6 +849,11 @@ public void kill() throws Exception { return DataStorageMetricsAdapter.valueOf(dataStorageMetrics()); } + /** {@inheritDoc} */ + @Override public @NotNull TracingConfigurationManager tracingConfiguration() { + throw new UnsupportedOperationException("Operation isn't supported yet."); + } + /** {@inheritDoc} */ @Override public void close() throws IgniteException { if (localJvmGrid() != null) { diff --git a/modules/opencensus/src/test/java/org/apache/ignite/TracingConfigurationValidationTest.java b/modules/opencensus/src/test/java/org/apache/ignite/TracingConfigurationValidationTest.java new file mode 100644 index 00000000000000..753311d3f0851b --- /dev/null +++ b/modules/opencensus/src/test/java/org/apache/ignite/TracingConfigurationValidationTest.java @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.ignite; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Stream; + +import org.apache.ignite.spi.tracing.Scope; +import org.apache.ignite.spi.tracing.TracingConfigurationCoordinates; +import org.apache.ignite.spi.tracing.TracingConfigurationParameters; +import org.apache.ignite.testframework.GridTestUtils; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.junit.Test; + +import static org.apache.ignite.spi.tracing.Scope.COMMUNICATION; +import static org.apache.ignite.spi.tracing.Scope.DISCOVERY; +import static org.apache.ignite.spi.tracing.Scope.EXCHANGE; +import static org.apache.ignite.spi.tracing.Scope.TX; + +/** + * Tests for tracing configuration validation rules. + */ +@SuppressWarnings("ThrowableNotThrown") +public class TracingConfigurationValidationTest extends GridCommonAbstractTest { + /** + * Ensure that in case of null scope as part of tracing coordinates {@code IllegalArgumentException} is thrown with + * message "Null scope is not valid for tracing coordinates." + */ + @Test + public void testThatItsNotPossibleToSetNullAsScopeForTracingCoordinates() { + GridTestUtils.assertThrows( + log, + () -> new TracingConfigurationCoordinates.Builder(null).build(), + IllegalArgumentException.class, + "Null scope is not valid for tracing coordinates."); + } + + /** + * Ensure that it's possible to set any non-null {@link Scope} as part of TracingConfigurationCoordinates. + */ + @Test + public void testThatItsPossibleToSpecifyAnyScopeAsPartOfTracingConfigurationCoordinates() { + for (Scope scope : Scope.values()) + new TracingConfigurationCoordinates.Builder(scope).build(); + } + + /** + * Ensure that it's possible to set any string as label as part of TracingConfigurationCoordinates. + */ + @Test + public void testThatItsPossibleToSpecifyAnyStringAsLabelAsPartOfTracingConfigurationCoordinates() { + Stream.of( + null, + "", + "label", "Some really long label with spaces, Some really long label with spaces," + + " Some really long label with spaces, Some really long label with spaces," + + " Some really long label with spaces").forEach( + lb -> new TracingConfigurationCoordinates.Builder(TX).withLabel(lb).build()); + } + + /** + * Ensure that it's possible to set any 0<= double <= 1 as sampling rate as part of TracingConfigurationParameters. + */ + @Test + public void testThatItsPossibleToSpecifyAnyDoubleBetweenZeroAndOneIncludingAsSamplingRate() { + for (double validSamplingRate : new double[] { + 0, + 0.1, + 0.11, + 0.1234567890, + 1}) + new TracingConfigurationParameters.Builder().withSamplingRate(validSamplingRate).build(); + } + + /** + * Ensure that in case of invalid sampling rate {@code IllegalArgumentException} is thrown with message "Specified + * sampling rate=[invalidVal] has invalid value.Should be between 0 and 1 including boundaries." + */ + @Test + public void testThatItsPossibleToSpecifyOnlyValidSamplingRate() { + for (Double invalidSamplingRate : new double[] { + -1d, + 10d}) + { + GridTestUtils.assertThrows( + log, + () -> new TracingConfigurationParameters.Builder().withSamplingRate(invalidSamplingRate).build(), + IllegalArgumentException.class, + "Specified sampling rate=[" + invalidSamplingRate + + "] has invalid value. Should be between 0 and 1 including boundaries."); + } + } + + /** + * Ensure that it's possible to set any set of {@code Scope} as included scopes as part of + * {@link TracingConfigurationParameters}. + */ + @Test @SuppressWarnings("unchecked") + public void testThatItsPossibleToSpecifyAnySetincludedScopesAsPartOfTracingConfigurationParameters() { + for (Set validincludedScopes : new Set[] { + null, + Collections.emptySet(), + Collections.singleton(COMMUNICATION), + new HashSet<>(Arrays.asList(COMMUNICATION, DISCOVERY, TX, EXCHANGE))}) + new TracingConfigurationParameters.Builder().withIncludedScopes(validincludedScopes).build(); + } +} diff --git a/modules/spring/src/main/java/org/apache/ignite/IgniteSpringBean.java b/modules/spring/src/main/java/org/apache/ignite/IgniteSpringBean.java index 38c5a6b192ed31..1866706aa7144b 100644 --- a/modules/spring/src/main/java/org/apache/ignite/IgniteSpringBean.java +++ b/modules/spring/src/main/java/org/apache/ignite/IgniteSpringBean.java @@ -30,11 +30,13 @@ import org.apache.ignite.configuration.CollectionConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.configuration.NearCacheConfiguration; +import org.apache.ignite.spi.tracing.TracingConfigurationManager; import org.apache.ignite.internal.util.typedef.G; import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.lang.IgniteProductVersion; import org.apache.ignite.plugin.IgnitePlugin; import org.apache.ignite.plugin.PluginNotFoundException; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.springframework.beans.BeansException; import org.springframework.beans.factory.DisposableBean; @@ -321,6 +323,13 @@ public ApplicationContext getApplicationContext() throws BeansException { return g.snapshot(); } + /** {@inheritDoc} */ + @Override public @NotNull TracingConfigurationManager tracingConfiguration() { + checkIgnite(); + + return g.tracingConfiguration(); + } + /** {@inheritDoc} */ @Override public Collection memoryMetrics() { return DataRegionMetricsAdapter.collectionOf(dataRegionMetrics()); From c624ae2c050ed84fe6d8c6718719752e75e7abfb Mon Sep 17 00:00:00 2001 From: sanpwc Date: Fri, 3 Jul 2020 09:00:30 +0300 Subject: [PATCH 2/2] IGNITE-13060 Make performance drop dependent on sampling-rate. # Conflicts: # modules/core/src/main/java/org/apache/ignite/internal/managers/tracing/GridTracingManager.java # modules/opencensus/src/main/java/org/apache/ignite/spi/tracing/opencensus/OpenCensusTracingSpi.java --- .../managers/tracing/GridTracingManager.java | 37 +++++++++++-------- .../ignite/spi/tracing/NoopTracingSpi.java | 3 +- .../apache/ignite/spi/tracing/TracingSpi.java | 6 +-- .../opencensus/OpenCensusTracingSpi.java | 20 +--------- 4 files changed, 26 insertions(+), 40 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/tracing/GridTracingManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/tracing/GridTracingManager.java index 470df42eb83dca..f359f18e4c3d33 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/tracing/GridTracingManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/tracing/GridTracingManager.java @@ -35,6 +35,7 @@ import org.apache.ignite.internal.processors.tracing.SpanTags; import org.apache.ignite.internal.processors.tracing.SpanType; import org.apache.ignite.internal.processors.tracing.Tracing; +import org.apache.ignite.spi.tracing.SpiSpecificSpan; import org.apache.ignite.spi.tracing.TracingConfigurationCoordinates; import org.apache.ignite.spi.tracing.TracingConfigurationManager; import org.apache.ignite.spi.tracing.TracingSpi; @@ -47,7 +48,6 @@ import org.jetbrains.annotations.Nullable; import static org.apache.ignite.internal.processors.tracing.SpanTags.NODE; -import static org.apache.ignite.spi.tracing.TracingConfigurationParameters.SAMPLING_RATE_ALWAYS; import static org.apache.ignite.spi.tracing.TracingConfigurationParameters.SAMPLING_RATE_NEVER; import static org.apache.ignite.internal.util.GridClientByteUtils.bytesToInt; import static org.apache.ignite.internal.util.GridClientByteUtils.bytesToShort; @@ -471,17 +471,14 @@ private Span enrichWithLocalNodeParameters(@Nullable Span span) { TracingConfigurationParameters tracingConfigurationParameters = tracingConfiguration.get( new TracingConfigurationCoordinates.Builder(spanTypeToCreate.scope()).withLabel(lb).build()); - // Optimization - if (tracingConfigurationParameters.samplingRate() == SAMPLING_RATE_NEVER) - return NoopSpan.INSTANCE; - - return new SpanImpl( - getSpi().create( - spanTypeToCreate.spanName(), - null, - tracingConfigurationParameters.samplingRate()), - spanTypeToCreate, - tracingConfigurationParameters.includedScopes()); + return shouldSample(tracingConfigurationParameters.samplingRate()) ? + new SpanImpl( + getSpi().create( + spanTypeToCreate.spanName(), + (SpiSpecificSpan)null), + spanTypeToCreate, + tracingConfigurationParameters.includedScopes()) : + NoopSpan.INSTANCE; } else return NoopSpan.INSTANCE; @@ -499,8 +496,7 @@ private Span enrichWithLocalNodeParameters(@Nullable Span span) { return new SpanImpl( getSpi().create( spanTypeToCreate.spanName(), - ((SpanImpl)parentSpan).spiSpecificSpan(), - SAMPLING_RATE_ALWAYS), + ((SpanImpl)parentSpan).spiSpecificSpan()), spanTypeToCreate, mergedIncludedScopes); } @@ -524,4 +520,15 @@ private Span enrichWithLocalNodeParameters(@Nullable Span span) { @Override public @NotNull TracingConfigurationManager configuration() { return tracingConfiguration; } -} + + /** + * @param samlingRate Sampling rate. + * @return {@code true} if according to given sampling-rate span should be sampled. + */ + private boolean shouldSample(double samlingRate) { + if (samlingRate == SAMPLING_RATE_NEVER) + return false; + + return Math.random() <= samlingRate; + } +} \ No newline at end of file diff --git a/modules/core/src/main/java/org/apache/ignite/spi/tracing/NoopTracingSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/tracing/NoopTracingSpi.java index dfb785a026b43c..9ddb63d936b82a 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/tracing/NoopTracingSpi.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/tracing/NoopTracingSpi.java @@ -42,8 +42,7 @@ public class NoopTracingSpi extends IgniteSpiAdapter implements TracingSpi extends IgniteSpi { * * @param name Name of span to create. * @param parentSpan Parent span. - * @param samplingRate Number between 0 and 1 that more or less reflects the probability of sampling specific trace. - * 0 and 1 have special meaning here, 0 means never 1 means always. Default value is 0 (never). - * @return Created span. */ @NotNull S create( @NotNull String name, - @Nullable S parentSpan, - double samplingRate); + @Nullable S parentSpan); /** * Serializes span to byte array to send context over network. diff --git a/modules/opencensus/src/main/java/org/apache/ignite/spi/tracing/opencensus/OpenCensusTracingSpi.java b/modules/opencensus/src/main/java/org/apache/ignite/spi/tracing/opencensus/OpenCensusTracingSpi.java index 65e29770c97437..166d96b463023f 100644 --- a/modules/opencensus/src/main/java/org/apache/ignite/spi/tracing/opencensus/OpenCensusTracingSpi.java +++ b/modules/opencensus/src/main/java/org/apache/ignite/spi/tracing/opencensus/OpenCensusTracingSpi.java @@ -20,7 +20,6 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; -import io.opencensus.trace.Sampler; import io.opencensus.trace.Tracing; import io.opencensus.trace.export.SpanExporter; import io.opencensus.trace.samplers.Samplers; @@ -104,34 +103,19 @@ public OpenCensusTracingSpi(SpanExporter.Handler... exporters) { /** {@inheritDoc} */ @Override public @NotNull OpenCensusSpanAdapter create( @NotNull String name, - @Nullable OpenCensusSpanAdapter parentSpan, - double samplingRate) { + @Nullable OpenCensusSpanAdapter parentSpan) { try { io.opencensus.trace.Span openCensusParent = null; if (parentSpan != null) openCensusParent = parentSpan.impl(); - Sampler sampler; - - if (Double.compare(samplingRate, 0) == 0) { - // We should never get here, because of an optimization that produces {@code NoopSpan.Instance} - // instead of a span with {@code SAMPLING_RATE_NEVER} sampling rate. It is useful cause in case - // of {@code NoopSpan.Instance} we will not send span data over the network.assert false; - - sampler = Samplers.neverSample(); // Just in case. - } - else if (Double.compare(samplingRate, 1) == 0) - sampler = Samplers.alwaysSample(); - else - sampler = Samplers.probabilitySampler(samplingRate); - return new OpenCensusSpanAdapter( Tracing.getTracer().spanBuilderWithExplicitParent( name, openCensusParent ) - .setSampler(sampler) + .setSampler(Samplers.alwaysSample()) .startSpan() ); }