Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send all metrics as one bulk batch points call #2

Merged
merged 1 commit into from Aug 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
150 changes: 82 additions & 68 deletions src/main/java/jenkinsci/plugins/influxdb/InfluxDbPublisher.java
@@ -1,61 +1,63 @@
package jenkinsci.plugins.influxdb;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.lang.System;

import org.influxdb.InfluxDB;
import org.influxdb.InfluxDB.ConsistencyLevel;
import org.influxdb.InfluxDBFactory;
import org.influxdb.dto.BatchPoints;
import org.influxdb.dto.Point;

import jenkins.tasks.SimpleBuildStep;
import jenkinsci.plugins.influxdb.models.BuildData;
import jenkinsci.plugins.influxdb.models.Target;
import jenkinsci.plugins.influxdb.generators.CoberturaPointGenerator;
import jenkinsci.plugins.influxdb.generators.JenkinsBasePointGenerator;
import jenkinsci.plugins.influxdb.generators.RobotFrameworkPointGenerator;
//import jenkinsci.plugins.influxdb.generators.ZAProxyPointGenerator;
import jenkinsci.plugins.influxdb.generators.PointGenerator;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import hudson.Extension;
import hudson.Launcher;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Notifier;
import hudson.tasks.Publisher;

import jenkins.tasks.SimpleBuildStep;
import jenkinsci.plugins.influxdb.generators.CoberturaPointGenerator;
import jenkinsci.plugins.influxdb.generators.JenkinsBasePointGenerator;
import jenkinsci.plugins.influxdb.generators.RobotFrameworkPointGenerator;
import jenkinsci.plugins.influxdb.models.BuildData;
import jenkinsci.plugins.influxdb.models.Target;
import org.influxdb.InfluxDB;
import org.influxdb.InfluxDB.ConsistencyLevel;
import org.influxdb.InfluxDBFactory;
import org.influxdb.dto.BatchPoints;
import org.influxdb.dto.Point;
import org.kohsuke.stapler.DataBoundConstructor;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

//import jenkinsci.plugins.influxdb.generators.ZAProxyPointGenerator;

public class InfluxDbPublisher extends Notifier implements SimpleBuildStep{

/** The logger. **/
private static final Logger logger = Logger.getLogger(InfluxDbPublisher.class.getName());

private static final String INFLUX_MEASUREMENT_PREFIX = "build";
private static final String INFLUX_FIELDNAME_JOBDURATION = "jobduration";

@Extension
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();

private String selectedTarget;
private String coberturaReportLocation;

//default - unless overridden
private String coberturaReportLocation = "target/cobertura/cobertura.ser";

public InfluxDbPublisher() {
}

@DataBoundConstructor
public InfluxDbPublisher(String target) {
this.selectedTarget = target;
}

public String getSelectedTarget() {
String ipTemp = selectedTarget;
if (ipTemp == null) {
Expand All @@ -66,92 +68,97 @@ public String getSelectedTarget() {
}
return ipTemp;
}

public void setSelectedTarget(String target) {
Preconditions.checkNotNull(target);
this.selectedTarget = target;
}

public String getCoberturaReportLocation() {
return this.coberturaReportLocation;
return this.coberturaReportLocation;
}

public void setCoberturaReportLocation(String location) {
Preconditions.checkNotNull(location);
this.coberturaReportLocation = location;
}


public Target getTarget() {
Target[] targets = DESCRIPTOR.getTargets();
if (selectedTarget == null && targets.length > 0) {
return targets[0];
}
for (Target target : targets) {
String targetInfo = target.getUrl() + "," + target.getDatabase();
String targetInfo = target.getUrl() + "," + target.getDatabase();
if (targetInfo.equals(selectedTarget)) {
return target;
}
}
return null;
}

//@Override
public boolean prebuild(Run<?, ?> build, TaskListener listener) {
return true;
}

@Override
public boolean needsToRunAfterFinalized() {
return true;
}

@Override
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.NONE;
}

@Override
public BuildStepDescriptor<Publisher> getDescriptor() {
return DESCRIPTOR;
}

@Override
public void perform(Run<?, ?> build, FilePath workspace, Launcher launcher, TaskListener listener)
throws InterruptedException, IOException {

// get the target from the job's config
Target target = getTarget();
if (target==null) {
throw new RuntimeException("Target was null!");
}
}
// extract the required buildData from the build context
BuildData buildData = getBuildData(build);

// prepare a meaningful logmessage
String logMessage = "publishing data: " + buildData.toString() + " to " + target.toString();

// write to jenkins logger
logger.log(Level.INFO, logMessage);
// write to jenkins console
listener.getLogger().println(logMessage);

// connect to InfluxDB
InfluxDB influxDB = InfluxDBFactory.connect(target.getUrl(), target.getUsername(), target.getPassword());
List<Point> pointsToWrite = new ArrayList<>();

// finally write to InfluxDB
influxDB.write(generateInfluxData(buildData, target));
pointsToWrite.addAll(generateInfluxData(buildData));

JenkinsBasePointGenerator jGen = new JenkinsBasePointGenerator(build);
writeDataToDatabase(influxDB, target, jGen.generate());
pointsToWrite.addAll(Arrays.asList(jGen.generate()));

CoberturaPointGenerator cGen = new CoberturaPointGenerator(build, workspace, coberturaReportLocation);
if (cGen.hasReport()) {
listener.getLogger().println("Cobertura data found. Writing to InfluxDB...");
writeDataToDatabase(influxDB, target, cGen.generate());
pointsToWrite.addAll(Arrays.asList(cGen.generate()));
}


RobotFrameworkPointGenerator rfGen = new RobotFrameworkPointGenerator(build);
if (rfGen.hasReport()) {
listener.getLogger().println("Robot Framework data found. Writing to InfluxDB...");
writeDataToDatabase(influxDB, target, rfGen.generate());
pointsToWrite.addAll(Arrays.asList(rfGen.generate()));
}
/*
ZAProxyPointGenerator zGen = new ZAProxyPointGenerator(build, workspace);
Expand All @@ -160,33 +167,40 @@ public void perform(Run<?, ?> build, FilePath workspace, Launcher launcher, Task
writeDataToDatabase(influxDB, target, zGen.generate());
}
*/
}
writeToInflux(target, influxDB, pointsToWrite);


// Write multiple points from an array.
private void writeDataToDatabase(InfluxDB influxDB, Target target, Point[] data) {
for (Point p : data) {
influxDB.write(target.getDatabase(), "default", p);
}
}

private BatchPoints generateInfluxData(BuildData buildData, Target target) {
// create the list of batchpoints
BatchPoints batchPoints = BatchPoints.database(target.getDatabase())

private void writeToInflux(Target target, InfluxDB influxDB, List<Point> pointsToWrite) {
/**
* build batchpoints for a single write.
*/
BatchPoints batchPoints = BatchPoints
.database(target.getDatabase())
.points(pointsToWrite.toArray(new Point[0]))
.retentionPolicy(target.getRetentionPolicy())
.tag("async", "true")
.retentionPolicy("default")
.consistency(ConsistencyLevel.ALL)
.build();
influxDB.write(batchPoints);
}


private List<Point> generateInfluxData(BuildData buildData) {
// prepare the measurement point for the timeseries
Point point = Point.measurement(INFLUX_MEASUREMENT_PREFIX + "_" + buildData.getJobName())
Point point = Point.measurement(INFLUX_MEASUREMENT_PREFIX + "_" + jobName(buildData))
.time(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
.field(INFLUX_FIELDNAME_JOBDURATION, buildData.getJobDurationSeconds())
.build();

batchPoints.point(point);
return batchPoints;
return Lists.newArrayList(point);
}

//influx disallows "-" in measurements.
private String jobName(BuildData buildData) {
return buildData.getJobName().replaceAll("-", "_");
}

@Deprecated
private BuildData getBuildData(AbstractBuild<?, ?> build) {
BuildData buildData = new BuildData();
Expand Down
Expand Up @@ -18,4 +18,9 @@ protected void addJenkinsBuildNumber(Run<?, ?> build, List<String> columnNames,
columnNames.add(BUILD_NUMBER);
values.add(build.getNumber());
}

protected String measurementName(String measurement) {
//influx disallows "-" in measurement names.
return measurement.replaceAll("-", "_");
}
}
Expand Up @@ -4,10 +4,6 @@
import hudson.tasks.test.AbstractTestResultAction;
import org.influxdb.dto.Point;

import java.util.ArrayList;
import java.util.List;
import java.lang.System;

public class JenkinsBasePointGenerator extends AbstractPointGenerator {

public static final String BUILD_TIME = "build_time";
Expand Down Expand Up @@ -37,7 +33,7 @@ public Point[] generate() {
}

private Point generatePointWithoutTestResults(long dt) {
Point point = Point.measurement("jenkins_data")
Point point = Point.measurement(measurementName("jenkins_data"))
.field(BUILD_NUMBER, build.getNumber())
.field(PROJECT_NAME, build.getParent().getName())
.field(BUILD_TIME, build.getDuration() == 0 ? dt : build.getDuration())
Expand All @@ -49,7 +45,7 @@ private Point generatePointWithoutTestResults(long dt) {
}

private Point generatePointWithTestResults(long dt) {
Point point = Point.measurement("jenkins_data")
Point point = Point.measurement(measurementName("jenkins_data"))
.field(BUILD_NUMBER, build.getNumber())
.field(PROJECT_NAME, build.getParent().getName())
.field(BUILD_TIME, build.getDuration() == 0 ? dt : build.getDuration())
Expand Down
Expand Up @@ -7,9 +7,10 @@
import hudson.plugins.robot.model.RobotSuiteResult;
import org.influxdb.dto.Point;

import java.awt.*;
import java.util.*;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

public class RobotFrameworkPointGenerator extends AbstractPointGenerator {

Expand Down Expand Up @@ -52,7 +53,7 @@ public Point[] generate() {
}

private Point generateOverviewPoint(RobotBuildAction robotBuildAction) {
Point point = Point.measurement("rf_results")
Point point = Point.measurement(measurementName("rf_results"))
.field(BUILD_NUMBER, build.getNumber())
.field(PROJECT_NAME, build.getParent().getName())
.field(RF_FAILED, robotBuildAction.getResult().getOverallFailed())
Expand Down Expand Up @@ -118,7 +119,7 @@ private boolean casePointExists(List<Point> subPoints, Point point) {
}

private Point generateCasePoint(RobotCaseResult caseResult) {
Point point = Point.measurement("testcase_point")
Point point = Point.measurement(measurementName("testcase_point"))
.field(BUILD_NUMBER, build.getNumber())
.field(PROJECT_NAME, build.getParent().getName())
.field(RF_NAME, caseResult.getName())
Expand Down Expand Up @@ -166,7 +167,7 @@ private void markTagResult(String tag, RobotCaseResult caseResult) {
}

private Point generateTagPoint(RobotTagResult tagResult) {
Point point = Point.measurement("tag_point")
Point point = Point.measurement(measurementName("tag_point"))
.field(RF_CRITICAL_FAILED, tagResult.criticalFailed)
.field(RF_CRITICAL_PASSED, tagResult.criticalPassed)
.field(RF_CRITICAL_TOTAL, tagResult.criticalPassed + tagResult.criticalFailed)
Expand All @@ -180,7 +181,7 @@ private Point generateTagPoint(RobotTagResult tagResult) {
}

private Point generateSuitePoint(RobotSuiteResult suiteResult) {
Point point = Point.measurement("suite_result")
Point point = Point.measurement(measurementName("suite_result"))
.field(BUILD_NUMBER, build.getNumber())
.field(PROJECT_NAME, build.getParent().getName())
.field(RF_SUITE_NAME, suiteResult.getName())
Expand Down
13 changes: 11 additions & 2 deletions src/main/java/jenkinsci/plugins/influxdb/models/Target.java
Expand Up @@ -7,7 +7,8 @@ public class Target {
String username;
String password;
String database;

String retentionPolicy;

public Target(){
//nop
}
Expand Down Expand Up @@ -51,7 +52,15 @@ public String getDatabase() {
public void setDatabase(String database) {
this.database = database;
}


public String getRetentionPolicy() {
return retentionPolicy;
}

public void setRetentionPolicy(String retentionPolicy) {
this.retentionPolicy = retentionPolicy;
}

@Override
public String toString() {
return "Target [url=" + this.url + ", description=" + this.description + ", username=" + this.username
Expand Down
Expand Up @@ -30,7 +30,11 @@
<f:entry title="database" field="database" >
<f:textbox name="targetBinding.database" value="${currentTarget.database}" />
</f:entry>


<f:entry title="retentionPolicy" field="retentionPolicy" >
<f:textbox name="targetBinding.retentionPolicy" value="${currentTarget.retentionPolicy}" default="default" />
</f:entry>

<f:entry title="delete target" >
<div align="right">
<f:repeatableDeleteButton value="delete target"/>
Expand Down