| /* |
| * 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 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.processors.metastorage.DistributedMetaStorage; |
| import org.apache.ignite.internal.processors.metastorage.persistence.DistributedMetaStorageImpl; |
| import org.apache.ignite.spi.tracing.Scope; |
| import org.apache.ignite.internal.util.tostring.GridToStringExclude; |
| import org.apache.ignite.internal.util.typedef.internal.LT; |
| 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 { |
| /** */ |
| private static final String TRACING_CONFIGURATION_DISTRIBUTED_METASTORE_KEY_PREFIX = |
| DistributedMetaStorageImpl.IGNITE_INTERNAL_KEY_PREFIX + "tr.config."; |
| |
| /** Map with default configurations. */ |
| private static final Map<TracingConfigurationCoordinates, TracingConfigurationParameters> DEFAULT_CONFIGURATION_MAP; |
| |
| /** */ |
| public static final String WARNING_MSG_METASTORAGE_NOT_AVAILABLE = |
| "Failed to save tracing configuration to meta storage. Meta storage is not available."; |
| |
| /** */ |
| public static final String WARNING_MSG_TO_RESET_CONFIG_METASTORAGE_NOT_AVAILABLE = |
| "Failed to reset tracing configuration for coordinates=[%s] to default. Meta storage is not available."; |
| |
| /** */ |
| public static final String WARNING_MSG_TO_RESET_ALL_CONFIG_METASTORAGE_NOT_AVAILABLE = |
| "Failed to reset tracing configuration for scope=[%s] to default. Meta storage is not available."; |
| |
| /** */ |
| public static final String WARNING_FAILED_TO_RETRIEVE_CONFIG_METASTORAGE_NOT_AVAILABLE = |
| "Failed to retrieve tracing configuration. Meta storage is not available. Default value will be used."; |
| |
| static { |
| Map<TracingConfigurationCoordinates, TracingConfigurationParameters> 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()); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void set( |
| @NotNull TracingConfigurationCoordinates coordinates, |
| @NotNull TracingConfigurationParameters parameters) |
| { |
| DistributedMetaStorage metaStore = distributedMetaStorage( |
| false, |
| WARNING_MSG_METASTORAGE_NOT_AVAILABLE); |
| |
| String scopeSpecificKey = TRACING_CONFIGURATION_DISTRIBUTED_METASTORE_KEY_PREFIX + coordinates.scope().name(); |
| |
| boolean configurationSuccessfullyUpdated = false; |
| |
| try { |
| while (!configurationSuccessfullyUpdated) { |
| HashMap<String, TracingConfigurationParameters> existingScopeSpecificTracingConfiguration = |
| metaStore.read(scopeSpecificKey); |
| |
| HashMap<String, TracingConfigurationParameters> updatedScopeSpecificTracingConfiguration = |
| existingScopeSpecificTracingConfiguration != null ? |
| new HashMap<>(existingScopeSpecificTracingConfiguration) : new |
| HashMap<>(); |
| |
| updatedScopeSpecificTracingConfiguration.put(coordinates.label(), parameters); |
| |
| configurationSuccessfullyUpdated = metaStore.compareAndSet( |
| scopeSpecificKey, |
| existingScopeSpecificTracingConfiguration, |
| updatedScopeSpecificTracingConfiguration); |
| } |
| } |
| catch (IgniteCheckedException e) { |
| log.warning(WARNING_MSG_METASTORAGE_NOT_AVAILABLE, e); |
| |
| throw new IgniteException(WARNING_MSG_METASTORAGE_NOT_AVAILABLE, e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public @NotNull TracingConfigurationParameters get( |
| @NotNull TracingConfigurationCoordinates coordinates) { |
| DistributedMetaStorage metaStore; |
| |
| try { |
| metaStore = ctx.distributedMetastorage(); |
| } |
| catch (Exception e) { |
| LT.warn(log, WARNING_FAILED_TO_RETRIEVE_CONFIG_METASTORAGE_NOT_AVAILABLE); |
| |
| // If metastorage in not available — use scope specific default tracing configuration. |
| return TracingConfigurationManager.super.get(coordinates); |
| } |
| |
| if (metaStore == null) { |
| LT.warn(log, WARNING_FAILED_TO_RETRIEVE_CONFIG_METASTORAGE_NOT_AVAILABLE); |
| |
| // If metastorage in not available — use scope specific default tracing configuration. |
| return TracingConfigurationManager.super.get(coordinates); |
| } |
| |
| String scopeSpecificKey = TRACING_CONFIGURATION_DISTRIBUTED_METASTORE_KEY_PREFIX + coordinates.scope().name(); |
| |
| HashMap<String, TracingConfigurationParameters> scopeSpecificTracingConfiguration; |
| |
| try { |
| scopeSpecificTracingConfiguration = metaStore.read(scopeSpecificKey); |
| } |
| catch (IgniteCheckedException e) { |
| LT.warn( |
| log, |
| e, |
| "Failed to retrieve tracing configuration. Default value will be used.", |
| false, |
| true); |
| |
| // In case of exception during retrieving configuration from metastorage — use scope specific default one. |
| return TracingConfigurationManager.super.get(coordinates); |
| } |
| |
| // If the configuration was not found — use scope specific default one. |
| if (scopeSpecificTracingConfiguration == null) |
| return TracingConfigurationManager.super.get(coordinates); |
| |
| // Retrieving scope + label specific tracing configuration. |
| TracingConfigurationParameters lbBasedTracingConfiguration = |
| scopeSpecificTracingConfiguration.get(coordinates.label()); |
| |
| // If scope + label specific was found — use it. |
| if (lbBasedTracingConfiguration != null) |
| return lbBasedTracingConfiguration; |
| |
| // Retrieving scope specific tracing configuration. |
| TracingConfigurationParameters rawScopedTracingConfiguration = scopeSpecificTracingConfiguration.get(null); |
| |
| // If scope specific was found — use it. |
| if (rawScopedTracingConfiguration != null) |
| return rawScopedTracingConfiguration; |
| |
| // If neither scope + label specific nor just scope specific configuration was found — |
| // use scope specific default one. |
| return TracingConfigurationManager.super.get(coordinates); |
| } |
| |
| /** {@inheritDoc} */ |
| @SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType") |
| @Override public @NotNull Map<TracingConfigurationCoordinates, TracingConfigurationParameters> getAll( |
| @Nullable Scope scope |
| ) { |
| DistributedMetaStorage metaStore = distributedMetaStorage( |
| true, |
| WARNING_FAILED_TO_RETRIEVE_CONFIG_METASTORAGE_NOT_AVAILABLE); |
| |
| if (metaStore == null) |
| return DEFAULT_CONFIGURATION_MAP; |
| |
| Map<TracingConfigurationCoordinates, TracingConfigurationParameters> res = new HashMap<>(); |
| |
| for (Scope scopeToRetrieve : scope == null ? Scope.values() : new Scope[] {scope}) { |
| String scopeSpecificKey = TRACING_CONFIGURATION_DISTRIBUTED_METASTORE_KEY_PREFIX + scopeToRetrieve.name(); |
| |
| try { |
| Map<String, TracingConfigurationParameters> scopeBasedTracingCfg = metaStore.read(scopeSpecificKey); |
| |
| if (scopeBasedTracingCfg == null) { |
| res.put( |
| new TracingConfigurationCoordinates.Builder(scopeToRetrieve).build(), |
| DEFAULT_CONFIGURATION_MAP.get( |
| new TracingConfigurationCoordinates.Builder(scopeToRetrieve).build())); |
| |
| continue; |
| } |
| |
| // Null keys encapsulates scope specific configuration. |
| if (!scopeBasedTracingCfg.containsKey(null)) { |
| res.put( |
| new TracingConfigurationCoordinates.Builder(scopeToRetrieve).build(), |
| DEFAULT_CONFIGURATION_MAP.get( |
| new TracingConfigurationCoordinates.Builder(scopeToRetrieve).build())); |
| } |
| |
| for (Map.Entry<String, TracingConfigurationParameters> entry : |
| ((Map<String, TracingConfigurationParameters>)metaStore.read(scopeSpecificKey)).entrySet()) { |
| res.put( |
| new TracingConfigurationCoordinates.Builder(scopeToRetrieve). |
| withLabel(entry.getKey()).build(), |
| entry.getValue()); |
| } |
| |
| } |
| catch (IgniteCheckedException e) { |
| LT.warn(log, "Failed to retrieve tracing configuration"); |
| } |
| } |
| |
| return res; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void reset(@NotNull TracingConfigurationCoordinates coordinates) { |
| DistributedMetaStorage metaStore = distributedMetaStorage( |
| false, |
| WARNING_MSG_TO_RESET_CONFIG_METASTORAGE_NOT_AVAILABLE, |
| coordinates); |
| |
| String scopeSpecificKey = TRACING_CONFIGURATION_DISTRIBUTED_METASTORE_KEY_PREFIX + coordinates.scope().name(); |
| |
| boolean configurationSuccessfullyUpdated = false; |
| |
| try { |
| while (!configurationSuccessfullyUpdated) { |
| HashMap<String, TracingConfigurationParameters> existingScopeSpecificTracingConfiguration = |
| metaStore.read(scopeSpecificKey); |
| |
| if (existingScopeSpecificTracingConfiguration == null) { |
| // Nothing to do. |
| return; |
| } |
| |
| HashMap<String, TracingConfigurationParameters> updatedScopeSpecificTracingConfiguration = |
| new HashMap<>(existingScopeSpecificTracingConfiguration); |
| |
| if (coordinates.label() != null) |
| updatedScopeSpecificTracingConfiguration.remove(coordinates.label()); |
| else |
| updatedScopeSpecificTracingConfiguration.remove(null); |
| |
| configurationSuccessfullyUpdated = metaStore.compareAndSet( |
| scopeSpecificKey, |
| existingScopeSpecificTracingConfiguration, |
| updatedScopeSpecificTracingConfiguration); |
| } |
| } |
| catch (IgniteCheckedException e) { |
| log.warning(String.format(WARNING_MSG_TO_RESET_CONFIG_METASTORAGE_NOT_AVAILABLE, coordinates)); |
| |
| throw new IgniteException( |
| String.format(WARNING_MSG_TO_RESET_CONFIG_METASTORAGE_NOT_AVAILABLE, coordinates), |
| e); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void resetAll(@Nullable Scope scope) throws IgniteException { |
| DistributedMetaStorage metaStore = distributedMetaStorage( |
| false, |
| WARNING_MSG_TO_RESET_ALL_CONFIG_METASTORAGE_NOT_AVAILABLE, |
| scope); |
| |
| try { |
| for (Scope scopeItem : scope == null ? Scope.values() : new Scope[] {scope}) |
| metaStore.remove(TRACING_CONFIGURATION_DISTRIBUTED_METASTORE_KEY_PREFIX + scopeItem.name()); |
| } |
| catch (IgniteCheckedException e) { |
| log.warning(String.format(WARNING_MSG_TO_RESET_ALL_CONFIG_METASTORAGE_NOT_AVAILABLE, scope)); |
| |
| throw new IgniteException( |
| String.format(WARNING_MSG_TO_RESET_ALL_CONFIG_METASTORAGE_NOT_AVAILABLE, scope), |
| e); |
| } |
| } |
| |
| /** |
| * Checks if metastore if available and return it. |
| * |
| * @param returnNull If {@code true} return null if distributed metastorage isn't available, |
| * otherwise throw {@code IgniteException} |
| * @param warningMsg Warning message to be logged and used in {@code IgniteException} |
| * @param warningMsgFormatArgs Arguments to warning message. |
| * |
| * @return Distributed metastorage if it's available. |
| */ |
| private DistributedMetaStorage distributedMetaStorage(boolean returnNull, String warningMsg, Object...warningMsgFormatArgs) { |
| DistributedMetaStorage metaStore; |
| |
| try { |
| metaStore = ctx.distributedMetastorage(); |
| } |
| catch (Exception e) { |
| log.warning(String.format(warningMsg, warningMsgFormatArgs)); |
| |
| if (returnNull) |
| return null; |
| else |
| throw new IgniteException(String.format(warningMsg, warningMsgFormatArgs), e); |
| } |
| |
| if (metaStore == null) { |
| log.warning(String.format(warningMsg, warningMsgFormatArgs)); |
| |
| if (returnNull) |
| return null; |
| else |
| throw new IgniteException(String.format(warningMsg, warningMsgFormatArgs)); |
| } |
| |
| return metaStore; |
| } |
| } |