nebula.plugin.metrics.dispatcher.AbstractESMetricsDispatcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-metrics-plugin Show documentation
Show all versions of gradle-metrics-plugin Show documentation
Gradle Metrics plugin: Collects gradle metrics and publishes to ElasticSearch HTTP/Splunk/REST endpoints
/*
* Copyright 2015-2016 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 nebula.plugin.metrics.dispatcher;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.LoggingEvent;
import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.base.Throwables;
import com.google.common.collect.FluentIterable;
import nebula.plugin.metrics.MetricsPluginExtension;
import net.logstash.logback.composite.JsonProviders;
import net.logstash.logback.composite.loggingevent.MdcJsonProvider;
import net.logstash.logback.layout.LogstashLayout;
import org.apache.commons.io.IOUtils;
import org.gradle.internal.logging.events.LogEvent;
import org.slf4j.Logger;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
public abstract class AbstractESMetricsDispatcher extends AbstractMetricsDispatcher {
private final ch.qos.logback.classic.Logger logbackLogger = new LoggerContext().getLogger(Logger.ROOT_LOGGER_NAME);
private final Supplier logstashLayoutSupplier = Suppliers.memoize(new Supplier() {
@Override
public LogstashLayout get() {
checkState(buildId.isPresent(), "buildId has not been set");
final LogstashLayout layout = new LogstashLayout();
/**
* Gradle doesn't include a complete SLF4J implementation, so when the provider tries to access MDC
* features a warning is output. So we need to expose a method to remove the provider.
*/
JsonProviders providers = layout.getProviders();
MdcJsonProvider provider = FluentIterable.from(providers.getProviders()).filter(MdcJsonProvider.class).first().get();
layout.getProviders().removeProvider(provider);
layout.setTimeZone("UTC");
layout.setCustomFields(String.format("{\"@source\":\"%s\"}", buildId.get()));
layout.start();
return layout;
}
});
public AbstractESMetricsDispatcher(MetricsPluginExtension extension, boolean async) {
super(extension, async);
}
private LogstashLayout safeLogstashLayoutGet() {
try {
return logstashLayoutSupplier.get();
} catch (Exception e) {
logger.debug("Unable to log event due to errors in initialization", e);
return null;
}
}
@Override
protected void postShutDown() throws Exception {
super.postShutDown();
try {
LogstashLayout logstashLayout = safeLogstashLayoutGet();
if (logstashLayout != null) {
logstashLayout.stop();
}
} catch (Exception ignored) {}
}
@Override
public Optional receipt() {
if (buildId.isPresent()) {
String file = "/" + extension.getIndexName() + "/" + BUILD_TYPE + "/" + buildId.get();
URL url;
try {
url = new URL("http", extension.getHostname(), extension.getHttpPort(), file);
} catch (MalformedURLException e) {
throw Throwables.propagate(e);
}
return Optional.of("You can find the metrics for this build at " + url);
} else {
return Optional.absent();
}
}
private String readFromFileOrDefault(String file, String defaultFile) throws IOException {
InputStream input = (file == null || "".equals(file)) ? this.getClass().getResourceAsStream(defaultFile) : new FileInputStream(file);
StringWriter sw = new StringWriter();
IOUtils.copy(input, sw);
return sw.toString();
}
@Override
protected void initDatastore() {
String indexName = extension.getIndexName();
try {
if (!exists(indexName)) {
String mapping = readFromFileOrDefault(extension.getMetricsIndexMappingFile(), "/default-build-metrics-mappings.json");
logger.info(String.format("Creating index %s for metrics", indexName));
createIndex(indexName, mapping);
} else {
logger.info(String.format("Using index %s for metrics", indexName));
}
} catch (IOException e) {
logger.debug("Error creating index(es)", e);
}
}
@Override
protected String getCollectionName() {
return extension.getIndexName();
}
protected abstract void createIndex(String indexName, String source);
protected abstract boolean exists(String indexName);
}