/* * Copyright 2014 Netflix, Inc. * * 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 com.netflix.servo.monitor; import com.netflix.servo.tag.BasicTagList; import com.netflix.servo.tag.SmallTagMap; import com.netflix.servo.tag.Tag; import com.netflix.servo.tag.TagList; import com.netflix.servo.tag.Tags; import com.netflix.servo.util.Preconditions; import com.netflix.servo.util.UnmodifiableList; import java.util.Collection; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /** * Configuration settings associated with a monitor. A config consists of a name that is required * and an optional set of tags. */ public final class MonitorConfig { /** * A builder to assist in creating monitor config objects. */ public static class Builder { private final String name; private SmallTagMap.Builder tagsBuilder = SmallTagMap.builder(); private PublishingPolicy policy = DefaultPublishingPolicy.getInstance(); /** * Create a new builder initialized with the specified config. */ public Builder(MonitorConfig config) { this(config.getName()); withTags(config.getTags()); withPublishingPolicy(config.getPublishingPolicy()); } /** * Create a new builder initialized with the specified name. */ public Builder(String name) { this.name = name; } /** * Add a tag to the config. */ public Builder withTag(String key, String val) { tagsBuilder.add(Tags.newTag(key, val)); return this; } /** * Add a tag to the config. */ public Builder withTag(Tag tag) { tagsBuilder.add(tag); return this; } /** * Add all tags in the list to the config. */ public Builder withTags(TagList tagList) { if (tagList != null) { for (Tag t : tagList) { tagsBuilder.add(t); } } return this; } /** * Add all tags in the list to the config. */ public Builder withTags(Collection<Tag> tagCollection) { tagsBuilder.addAll(tagCollection); return this; } /** * Add all tags from a given SmallTagMap. */ public Builder withTags(SmallTagMap.Builder tagsBuilder) { this.tagsBuilder = tagsBuilder; return this; } /** * Add the publishing policy to the config. */ public Builder withPublishingPolicy(PublishingPolicy policy) { this.policy = policy; return this; } /** * Create the monitor config object. */ public MonitorConfig build() { return new MonitorConfig(this); } /** * Get the name for this monitor config. */ public String getName() { return name; } /** * Get the list of tags for this monitor config. */ public List<Tag> getTags() { return UnmodifiableList.copyOf(tagsBuilder.result()); } /** * Get the publishingPolicy. */ public PublishingPolicy getPublishingPolicy() { return policy; } } /** * Return a builder instance with the specified name. */ public static Builder builder(String name) { return new Builder(name); } private final String name; private final TagList tags; private final PublishingPolicy policy; /** * Config is immutable, cache the hash code to improve performance. */ private final AtomicInteger cachedHashCode = new AtomicInteger(0); /** * Creates a new instance with a given name and tags. If {@code tags} is * null an empty tag list will be used. */ private MonitorConfig(Builder builder) { this.name = Preconditions.checkNotNull(builder.name, "name"); this.tags = (builder.tagsBuilder.isEmpty()) ? BasicTagList.EMPTY : new BasicTagList(builder.tagsBuilder.result()); this.policy = builder.policy; } /** * Returns the name of the metric. */ public String getName() { return name; } /** * Returns the tags associated with the metric. */ public TagList getTags() { return tags; } /** * Returns the publishing policy. */ public PublishingPolicy getPublishingPolicy() { return policy; } /** * {@inheritDoc} */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || !(obj instanceof MonitorConfig)) { return false; } MonitorConfig m = (MonitorConfig) obj; return name.equals(m.getName()) && tags.equals(m.getTags()) && policy.equals(m.getPublishingPolicy()); } /** * This class is immutable so we cache the hash code after the first time it is computed. The * value 0 is used as an indicator that the hash code has not yet been computed, this means the * cache won't work for a small set of inputs, but the impact should be minimal for a decent * hash function. Similar technique is used for java String class. */ @Override public int hashCode() { int hash = cachedHashCode.get(); if (hash == 0) { hash = name.hashCode(); hash = 31 * hash + tags.hashCode(); hash = 31 * hash + policy.hashCode(); cachedHashCode.set(hash); } return hash; } /** * {@inheritDoc} */ @Override public String toString() { return "MonitorConfig{name=" + name + ", tags=" + tags + ", policy=" + policy + '}'; } /** * Returns a copy of the current MonitorConfig. */ private MonitorConfig.Builder copy() { return MonitorConfig.builder(name).withTags(tags).withPublishingPolicy(policy); } /** * Returns a copy of the monitor config with an additional tag. */ public MonitorConfig withAdditionalTag(Tag tag) { return copy().withTag(tag).build(); } /** * Returns a copy of the monitor config with additional tags. */ public MonitorConfig withAdditionalTags(TagList newTags) { return copy().withTags(newTags).build(); } }