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

Add Logz.io support #74

Open
wants to merge 57 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
d986d80
first
May 31, 2018
8a00ac8
queue in workspace
Jun 3, 2018
de18b60
deleting comments
Jun 3, 2018
4ef9a2f
PR fixes
Jun 4, 2018
8c185d6
change dir path
Jun 4, 2018
6c7d6a6
using tmp dir
Jun 4, 2018
9b7621d
change @timestamp field name
Jun 4, 2018
5075433
using stream
Jun 5, 2018
fa317c1
Merge pull request #1 from idohalevi/first
idohalevi Jun 5, 2018
bf87eec
Update Logzio.java
idohalevi Jun 6, 2018
6d53f29
add debug info
Jun 17, 2018
4d9134d
change queue location
Jun 18, 2018
54cd262
change const
Jun 18, 2018
7a9164d
add debug
Jun 19, 2018
959f715
debug prints
Jun 20, 2018
03cb931
debug
Jun 24, 2018
035fb68
gzip logs
Jul 3, 2018
53ffac5
Merge branch 'master' of https://github.com/jenkinsci/logstash-plugin
Jul 3, 2018
84aed45
delete debug print
Jul 3, 2018
193f057
fixing for travis tests (#2)
idohalevi Jul 3, 2018
4dbe73e
Fix travis (#3)
idohalevi Jul 4, 2018
89a41e9
Use a container for more repeatable builds (#4)
tomwillfixit Jul 9, 2018
25c63b4
sync with upstream
Aug 22, 2018
bdab1a3
stream is back
Jul 4, 2018
488037f
logzio in memory https client
Aug 22, 2018
144e922
adding in memory http sender, local logger and updating README
Aug 23, 2018
30ccd6b
remove docker from readme install
Aug 23, 2018
bf200ca
delete comma
Aug 23, 2018
f2dc75e
Merge pull request #5 from idohalevi/PR
idohalevi Aug 23, 2018
ad75e1e
Ranges -> Range
jakub-bochenski Aug 23, 2018
6c27e9b
deleting mail
Aug 23, 2018
84d2051
adding static class/fields - travis findbugs
Aug 23, 2018
bd0ba73
adding charset - travis findbugs
Aug 23, 2018
22d88bc
change reporter class to static class
Aug 23, 2018
63647d6
change LOGGER to static member
Aug 23, 2018
6a70412
delete unused imports
Sep 5, 2018
f57f163
delete unused imports - test
Sep 5, 2018
bd062d0
add flatten data explanation
Sep 6, 2018
594c37d
send logs before size limit reached
Sep 6, 2018
07fcdb4
adding warning about thread safety
Sep 6, 2018
e2fb882
move LogzioHttpsClient to a top-level class
Sep 6, 2018
74fa7f6
fix spelling
Sep 6, 2018
93732e3
change key to token
Sep 12, 2018
203eca1
change messages list to Collections.synchronizedList
Sep 12, 2018
d31850b
style + typo
Sep 12, 2018
b3ffe89
rename help file
Sep 12, 2018
77577d9
change to capital
Sep 12, 2018
e7b056e
delete run-fast script
Sep 13, 2018
1508b3f
Merge branch 'master' of https://github.com/jenkinsci/logstash-plugin…
HananEgbaria Jan 30, 2019
3e37735
Merge pull request #6 from idohalevi/dev
HananEgbaria Feb 5, 2019
605a76c
add close method
HananEgbaria Feb 12, 2019
f5e9581
add "synchronized" to push method to resolve multi-threading (multi-j…
HananEgbaria Mar 5, 2019
1aec70e
update maven dependencies versions
HananEgbaria Mar 11, 2019
84c3602
remove unimportant comments
HananEgbaria Mar 11, 2019
93a5cd2
Merge pull request #7 from idohalevi/fix_comments
idohalevi Mar 18, 2019
b1dc099
remove unused methods
HananEgbaria Mar 19, 2019
261f22c
Merge pull request #8 from idohalevi/fix_comments
idohalevi Mar 19, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Jenkins Logstash Plugin
Travis: [![Build Status](https://travis-ci.org/jenkinsci/logstash-plugin.svg?branch=master)](https://travis-ci.org/jenkinsci/logstash-plugin)
Jenkins: [![Build Status](https://ci.jenkins.io/job/Plugins/job/logstash-plugin/job/master/badge/icon)](https://ci.jenkins.io/job/Plugins/job/logstash-plugin/job/master/)

This plugin adds support for sending a job's console log to Logstash indexers such as [Elastic Search](https://www.elastic.co/products/elasticsearch), [Logstash](https://www.elastic.co/de/products/logstash), [RabbitMQ](https://www.rabbitmq.com), [Redis](https://redis.io/) or to Syslog.
This plugin adds support for sending a job's console log to Logstash indexers such as [Logzio](https://logz.io/), [Elastic Search](https://www.elastic.co/products/elasticsearch), [Logstash](https://www.elastic.co/de/products/logstash), [RabbitMQ](https://www.rabbitmq.com), [Redis](https://redis.io/) or to Syslog.

* see [Jenkins wiki](https://wiki.jenkins-ci.org/display/JENKINS/Logstash+Plugin) for detailed feature descriptions
* use [JIRA](https://issues.jenkins-ci.org) to report issues / feature requests
Expand All @@ -15,6 +15,7 @@ Install
* Generate the `hpi` file with the command: `mvn package`

* Put the `hpi` file in the directory `$JENKINS_HOME/plugins`

* Restart jenkins

Configure
Expand All @@ -27,6 +28,7 @@ Currently supported methods of input/output:
* Redis {format => 'json_event'}
* RabbitMQ {mechanism => PLAIN}
* Syslog {format => cee/json ([RFC-5424](https://tools.ietf.org/html/rfc5424),[RFC-3164](https://tools.ietf.org/html/rfc3164)), protocol => UDP}
* Logz.io

Pipeline
========
Expand Down
37 changes: 21 additions & 16 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@
<artifactId>amqp-client</artifactId>
<version>3.3.5</version>
</dependency>
<dependency>
<groupId>io.logz.sender</groupId>
<artifactId>logzio-sender</artifactId>
<version>1.0.14</version>
</dependency>

<dependency>
<groupId>com.github.wnameless</groupId>
<artifactId>json-flattener</artifactId>
<version>0.6.0</version>
</dependency>

<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
Expand Down Expand Up @@ -110,10 +122,15 @@
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-step-api</artifactId>
<version>2.15</version>
<optional>true</optional>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>script-security</artifactId>
<version>1.39</version>
idohalevi marked this conversation as resolved.
Show resolved Hide resolved
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>3.1.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
Expand All @@ -133,18 +150,6 @@
<version>2.0.0-beta.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>script-security</artifactId>
<version>1.39</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>mask-passwords</artifactId>
Expand Down
88 changes: 44 additions & 44 deletions src/main/java/jenkins/plugins/logstash/LogstashBuildWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,60 +48,60 @@
public class LogstashBuildWrapper extends BuildWrapper
{

/**
* Create a new {@link LogstashBuildWrapper}.
*/
@DataBoundConstructor
public LogstashBuildWrapper()
{}

/**
* {@inheritDoc}
*/
@Override
public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener listener)
throws IOException, InterruptedException
{
return new Environment()
{
};
}

@Override
public DescriptorImpl getDescriptor()
{
return (DescriptorImpl)super.getDescriptor();
}

/**
* Registers {@link LogstashBuildWrapper} as a {@link BuildWrapper}.
*/
@Extension
public static class DescriptorImpl extends BuildWrapperDescriptor
{

public DescriptorImpl()
{
super(LogstashBuildWrapper.class);
load();
}
/**
* Create a new {@link LogstashBuildWrapper}.
*/
@DataBoundConstructor
public LogstashBuildWrapper()
{}

/**
* {@inheritDoc}
*/
@Override
public String getDisplayName()
public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener listener)
throws IOException, InterruptedException
{
return Messages.DisplayName();
return new Environment()
{
};
}

@Override
public DescriptorImpl getDescriptor()
{
return (DescriptorImpl)super.getDescriptor();
}

/**
* {@inheritDoc}
* Registers {@link LogstashBuildWrapper} as a {@link BuildWrapper}.
*/
@Override
public boolean isApplicable(AbstractProject<?, ?> item)
@Extension
public static class DescriptorImpl extends BuildWrapperDescriptor
{
return false;

public DescriptorImpl()
{
super(LogstashBuildWrapper.class);
load();
}

/**
* {@inheritDoc}
*/
@Override
public String getDisplayName()
{
return Messages.DisplayName();
}

/**
* {@inheritDoc}
*/
@Override
public boolean isApplicable(AbstractProject<?, ?> item)
{
return false;
}
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert the complete file to its original state. You just changed indentation.

}
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public void flush() throws IOException {
*/
@Override
public void close() throws IOException {
logstash.close();
delegate.close();
super.close();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* The MIT License
*
* Copyright 2017 Red Hat inc, and individual contributors
*
* 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 jenkins.plugins.logstash;

import net.sf.json.JSONObject;

/**
* Interface describing processors of persisted payload.
*/
public interface LogstashPayloadProcessor {
/**
* Modifies a JSON payload compatible with the Logstash schema.
*
* @param payload the JSON payload that has been constructed so far.
* @return The formatted JSON object, can be null to ignore this payload.
*/
JSONObject process(JSONObject payload) throws Exception;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we actually only need the finish() method, not process().

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jakub-bochenski
Currently, finish() uses process(). How would you like it to be instead?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIR finish only uses process to call it with null arg. Anyhow check the comment above (#74 (comment)) it might make this point moot


/**
* Finalizes any operations, for example returns cashed lines at end of build.
*
* @return A formatted JSON object, can be null when it has nothing.
*/
JSONObject finish() throws Exception;
}
109 changes: 109 additions & 0 deletions src/main/java/jenkins/plugins/logstash/LogstashScriptProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* The MIT License
*
* Copyright 2017 Red Hat inc. and individual contributors
*
* 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 jenkins.plugins.logstash;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import groovy.lang.Binding;
import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
import org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript;
import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.Whitelisted;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.OutputStream;

/**
* This class is handling custom groovy script processing of JSON payload.
* Each call to process executes the script provided in job configuration.
* Script is executed under the same binding each time so that it has ability
* to persist data during build execution if desired by script author.
* When build is finished, script will receive null as the payload and can
* return any cached but non-sent data back for persisting.
* The return value of script is the payload to be persisted unless null.
*/
public class LogstashScriptProcessor implements LogstashPayloadProcessor{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need this implmentation, just the interface

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even the interface is not needed. Actually the complete #71 should be taken out of here.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a close hook for the build. It's not available on master, so I suggested to use the same approach as #71

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What helps an interface when there is no implementation?
The close is added to the LogstashWriter in order to properly terminate the LogstashPayloadProcessor.
#71 modifies the ConsoleLogFilter to add the PayloadProcessor to the LogstashWriter.
There is nothing comparable here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you suggest we should continue with this?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me try to explain again.
This code needs to perform actions on build close as per #74 (comment)
AFAIK we have currently no way to notify an IndexerDao that a build has finished.
#71 added a way to do it, so I suggested to reuse the same approach.

Maybe at this point the best way to proceed is to forget about #71 and just add a way to notify the IndexerDao.
We can worry about the overlap with #71 when/if it's merged

Copy link

@mwinter69 mwinter69 Mar 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#71 added a feature to close the LogstashWriter, which is specific to a build but it is not interacting with the Dao as the scriptprocessor is only used in the writer.
The dao is a kind of a singleton in Jenkins. We only create a new Dao, when we have a configuration change and the new will only be used for new builds.
If I understand it right the shipper has to be used in the dao. So when the writer calls dao.push which does the actual writing to the indexer, how does the dao know which shipper to use? I don't see any nice solution here other than having a dao per build. But this would be a change in concept how this plugin is working. The writer would hold the reference to the dao and can be easily closed.
This is a bigger change in how the plugin works.
But even then one will need synchronization as in pipeline jobs you also have parallel execution within a single build and thus concurrent calls to the list.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I think I meant the LogstashWriter instead of IndexerDao
The idea is to create a new shipper instance per build to avoid concurrency issues. Not sure if that would work for parallel stages in pipeline though.

On a different note: I'm rather busy lately and don't want to block it. I would be happy to accept whatever solution you and @idohalevi can agree on

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jakub-bochenski @mwinter69
How do you suggest to continue?

@Nonnull
private final SecureGroovyScript script;

@Nonnull
private final OutputStream consoleOut;

/** Groovy binding for script execution */
@Nonnull
private final Binding binding;

/** Classloader for script execution */
@Nonnull
private final ClassLoader classLoader;

public LogstashScriptProcessor(SecureGroovyScript script, OutputStream consoleOut) {
this.script = script;
this.consoleOut = consoleOut;

// TODO: should we put variables in the binding like manager, job, etc.?
binding = new Binding();
binding.setVariable("console", new BuildConsoleWrapper());

// not sure what the diff is compared to getClass().getClassLoader();
final Jenkins jenkins = Jenkins.getInstance();
classLoader = jenkins.getPluginManager().uberClassLoader;
}

/**
* Helper method to allow logging to build console.
*/
@SuppressFBWarnings(
value="DM_DEFAULT_ENCODING",
justification="TODO: not sure how to fix this")
private void buildLogPrintln(Object o) throws IOException {
consoleOut.write(o.toString().getBytes());
consoleOut.write("\n".getBytes());
consoleOut.flush();
}

@Override
public JSONObject process(JSONObject payload) throws Exception {
binding.setVariable("payload", payload);
script.evaluate(classLoader, binding);
return (JSONObject) binding.getVariable("payload");
}

@Override
public JSONObject finish() throws Exception {
buildLogPrintln("Tearing down Script Log Processor..");
return process(null);
}

/**
* Helper to allow access from sandboxed script to output messages to console.
*/
private class BuildConsoleWrapper {
@Whitelisted
public void println(Object o) throws IOException {
buildLogPrintln(o);
}
}
}
Loading