/* * 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 gobblin.metrics.broker; import com.typesafe.config.ConfigValue; import gobblin.broker.ResourceInstance; import gobblin.broker.iface.ConfigView; import gobblin.broker.iface.NoSuchScopeException; import gobblin.broker.iface.NotConfiguredException; import gobblin.broker.iface.ScopeType; import gobblin.broker.iface.ScopedConfigView; import gobblin.broker.iface.SharedResourceFactory; import gobblin.broker.iface.SharedResourceFactoryResponse; import gobblin.broker.iface.SharedResourcesBroker; import gobblin.metrics.MetricContext; import gobblin.metrics.RootMetricContext; import gobblin.metrics.Tag; import gobblin.util.ConfigUtils; import java.util.Collection; import java.util.Map; import java.util.UUID; /** * A {@link SharedResourceFactory} to create {@link MetricContext}. * * The created {@link MetricContext} tree will mimic a sub-tree of the scopes DAG. If each scope has a unique parent, * the metric contexts will have the corresponding parents. If a scope has multiple parents (which is not supported by * {@link MetricContext}), the factory will chose the first parent of the scope. * * Tags can be injected using the configuration {@link Tag}. */ public class MetricContextFactory<S extends ScopeType<S>> implements SharedResourceFactory<MetricContext, MetricContextKey, S> { public static final String NAME = "metricContext"; public static final String TAG_KEY = "tag"; @Override public String getName() { return NAME; } @Override public SharedResourceFactoryResponse<MetricContext> createResource(SharedResourcesBroker<S> broker, ScopedConfigView<S, MetricContextKey> config) throws NotConfiguredException { try { if (config.getKey() instanceof SubTaggedMetricContextKey) { SubTaggedMetricContextKey key = (SubTaggedMetricContextKey) config.getKey(); MetricContext parent = broker.getSharedResource(this, new MetricContextKey()); MetricContext.Builder builder = parent.childBuilder(key.getMetricContextName()); for (Map.Entry<String, String> entry : key.getTags().entrySet()) { builder.addTag(new Tag<>(entry.getKey(), entry.getValue())); } return new ResourceInstance<>(builder.build()); } MetricContext parentMetricContext = RootMetricContext.get(); Collection<S> parents = config.getScope().parentScopes(); if (parents != null && !parents.isEmpty()) { S parentScope = parents.iterator().next(); parentMetricContext = broker.getSharedResourceAtScope(this, config.getKey(), parentScope); } // If this is the root scope, append a UUID to the name. This allows having a separate root context per broker. String metricContextName = parents == null ? config.getScope().name() + "_" + UUID.randomUUID().toString() : broker.selfScope().getScopeId(); MetricContext.Builder builder = parentMetricContext.childBuilder(metricContextName); builder.addTag(new Tag<>(config.getScope().name(), broker.getScope(config.getScope()).getScopeId())); for (Map.Entry<String, ConfigValue> entry : ConfigUtils.getConfigOrEmpty(config.getConfig(), TAG_KEY).entrySet()) { builder.addTag(new Tag<>(entry.getKey(), entry.getValue().unwrapped())); } return new ResourceInstance<>(builder.build()); } catch (NoSuchScopeException nsse) { throw new RuntimeException("Could not create MetricContext.", nsse); } } @Override public S getAutoScope(SharedResourcesBroker<S> broker, ConfigView<S, MetricContextKey> config) { return broker.selfScope().getType(); } }