/**
* The MIT License
* Copyright © 2010 JmxTrans team
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.googlecode.jmxtrans.model.output;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.googlecode.jmxtrans.exceptions.LifecycleException;
import com.googlecode.jmxtrans.model.Query;
import com.googlecode.jmxtrans.model.Result;
import com.googlecode.jmxtrans.model.Server;
import com.googlecode.jmxtrans.model.ValidationException;
import com.googlecode.jmxtrans.model.output.support.opentsdb.OpenTSDBMessageFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import static com.google.common.collect.ImmutableList.copyOf;
/**
* Originally written by Balazs Kossovics <bko@witbe.net>. Common base class for OpenTSDBWriter and TCollectorWriter.
* Date: 4/4/13
* Time: 6:00 PM
* <p/>
* Updates by Arthur Naseef
*/
public abstract class OpenTSDBGenericWriter extends BaseOutputWriter {
public static final boolean DEFAULT_MERGE_TYPE_NAMES_TAGS = true;
private static final Logger log = LoggerFactory.getLogger(OpenTSDBGenericWriter.class);
protected final String host;
protected final Integer port;
protected final OpenTSDBMessageFormatter messageFormatter;
@JsonCreator
public OpenTSDBGenericWriter(
@JsonProperty("typeNames") ImmutableList<String> typeNames,
@JsonProperty("booleanAsNumber") boolean booleanAsNumber,
@JsonProperty("debug") Boolean debugEnabled,
@JsonProperty("host") String host,
@JsonProperty("port") Integer port,
@JsonProperty("tags") Map<String, String> tags,
@JsonProperty("tagName") String tagName,
@JsonProperty("mergeTypeNamesTags") Boolean mergeTypeNamesTags,
@JsonProperty("metricNamingExpression") String metricNamingExpression,
@JsonProperty("addHostnameTag") Boolean addHostnameTag,
@JsonProperty("settings") Map<String, Object> settings) throws LifecycleException {
super(typeNames, booleanAsNumber, debugEnabled, settings);
this.host = MoreObjects.firstNonNull(host, (String) getSettings().get(HOST));
this.port = MoreObjects.firstNonNull(port, Settings.getIntegerSetting(getSettings(), PORT, null));
if (metricNamingExpression == null) {
metricNamingExpression = Settings.getStringSetting(this.getSettings(), "metricNamingExpression", null);
}
ImmutableList<String> nonNullTypeNames = copyOf(MoreObjects.firstNonNull(typeNames, Collections.<String>emptyList()));
messageFormatter = new OpenTSDBMessageFormatter(nonNullTypeNames, ImmutableMap.copyOf(
firstNonNull(
tags,
(Map<String, String>) getSettings().get("tags"),
ImmutableMap.<String, String>of())),
firstNonNull(tagName, (String) getSettings().get("tagName"), "type"),
metricNamingExpression,
MoreObjects.firstNonNull(
mergeTypeNamesTags,
Settings.getBooleanSetting(this.getSettings(), "mergeTypeNamesTags", DEFAULT_MERGE_TYPE_NAMES_TAGS)),
addHostnameTag);
}
/**
* Prepare for sending metrics, if needed. For use by subclasses.
*/
protected void prepareSender() throws LifecycleException {
}
/**
* Shutdown the sender, if needed. For use by subclasses.
*/
protected void shutdownSender() throws LifecycleException {
}
/**
* Prepare a batch of results output, if needed. For use by subclasses.
*/
protected void startOutput() throws IOException {
}
/**
* Subclass responsibility: specify the default value for the "addHostnameTag" setting.
*/
protected abstract boolean getAddHostnameTagDefault();
/**
* Subcall responsibility: method to perform the actual output for the given metric line. Every subclass
* <b>must</b> implement this method.
*
* @param metricLine - the line containing the metric name, value, and tags for a single metric; excludes the
* "put" keyword expected by OpenTSDB and the trailing newline character.
*/
protected abstract void sendOutput(String metricLine) throws IOException;
/**
* Complete a batch of results output, if needed. For use by subclasses.
*/
protected void finishOutput() throws IOException {
}
/**
* Write the results of the query.
*
* @param server
* @param query - the query and its results.
* @param results
*/
@Override
public void internalWrite(Server server, Query query, ImmutableList<Result> results) throws Exception {
this.startOutput();
for (String formattedResult : messageFormatter.formatResults(results, server)) {
log.debug("Sending result: {}", formattedResult);
this.sendOutput(formattedResult);
}
this.finishOutput();
}
/**
* Validation per query, after the writer has been start()ed
*/
@Override
public void validateSetup(Server server, Query query) throws ValidationException {
}
/**
* Start the output writer. At this time, the settings are read from the configuration file and saved for later
* use.
*/
@Override
public void start() throws LifecycleException {
this.prepareSender();
}
@Override
public void close() throws LifecycleException {
this.shutdownSender();
}
}