logstash-input-log4j 1.0.0-java → 2.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1ab88bef150e74e2f22c7bb03d3bdcdbd7d5a553
4
- data.tar.gz: 58d7c26b34abc5f90007625d6837d45d813b527e
3
+ metadata.gz: 774f1acdc7c060981ab35fe6c00004b554363589
4
+ data.tar.gz: 9b7193a589bac96a74407fe3f89acba434dbe103
5
5
  SHA512:
6
- metadata.gz: 0c309848b6639a2a9f1a5e0b96f16a3919d23b3c876644d977613b8638b6dc71abeb0db2b965c905dee882450719b8f4f80087e5d221e6e4d13716d19d472e29
7
- data.tar.gz: abdafa2a2547ab35ea4d9ee92340b13919393b0e38dadc4bcd4ce4d79606e20a02f9946574fc79fd6d260382f63b9176fb617fbf0e7344467c85258a690a63c5
6
+ metadata.gz: 6d3f400870d90165e36b6ae6ae52182ec0bffbaff788ede37ae2ab0331c68ff8b2c1a0a5dd9264818e4ea80961df25b44de149ff047b6bb94e635e974791643a
7
+ data.tar.gz: 14871fb9b6d28ff05e85b596be48669b6db190da5d1af8c3687bdb1668d159708f39cc053c5c8cb000f8f07704f8beaa82c3bb06adc03ccc63f456dd2c851483
data/CHANGELOG.md CHANGED
@@ -0,0 +1,2 @@
1
+ # 1.0.1
2
+ - refactor test to allow unit testing of logstash event creation
data/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # Logstash Plugin
2
2
 
3
- This is a plugin for [Logstash](https://github.com/elasticsearch/logstash).
3
+ This is a plugin for [Logstash](https://github.com/elastic/logstash).
4
4
 
5
5
  It is fully free and fully open source. The license is Apache 2.0, meaning you are pretty much free to use it however you want in whatever way.
6
6
 
7
7
  ## Documentation
8
8
 
9
- Logstash provides infrastructure to automatically generate documentation for this plugin. We use the asciidoc format to write documentation so any comments in the source code will be first converted into asciidoc and then into html. All plugin documentation are placed under one [central location](http://www.elasticsearch.org/guide/en/logstash/current/).
9
+ Logstash provides infrastructure to automatically generate documentation for this plugin. We use the asciidoc format to write documentation so any comments in the source code will be first converted into asciidoc and then into html. All plugin documentation are placed under one [central location](http://www.elastic.co/guide/en/logstash/current/).
10
10
 
11
11
  - For formatting code or config example, you can use the asciidoc `[source,ruby]` directive
12
- - For more asciidoc formatting tips, see the excellent reference here https://github.com/elasticsearch/docs#asciidoc-guide
12
+ - For more asciidoc formatting tips, see the excellent reference here https://github.com/elastic/docs#asciidoc-guide
13
13
 
14
14
  ## Need Help?
15
15
 
@@ -83,4 +83,4 @@ Programming is not a required skill. Whatever you've seen about open source and
83
83
 
84
84
  It is more important to the community that you are able to contribute.
85
85
 
86
- For more information about contributing, see the [CONTRIBUTING](https://github.com/elasticsearch/logstash/blob/master/CONTRIBUTING.md) file.
86
+ For more information about contributing, see the [CONTRIBUTING](https://github.com/elastic/logstash/blob/master/CONTRIBUTING.md) file.
@@ -14,6 +14,21 @@ require 'logstash-input-log4j_jars'
14
14
  # depending on `mode`. Depending on which `mode` is configured,
15
15
  # you need a matching SocketAppender or a SocketHubAppender
16
16
  # on the remote side.
17
+ #
18
+ # One event is created per received log4j LoggingEvent with the following schema:
19
+ #
20
+ # * `timestamp` => the number of milliseconds elapsed from 1/1/1970 until logging event was created.
21
+ # * `path` => the name of the logger
22
+ # * `priority` => the level of this event
23
+ # * `logger_name` => the name of the logger
24
+ # * `thread` => the thread name making the logging request
25
+ # * `class` => the fully qualified class name of the caller making the logging request.
26
+ # * `file` => the source file name and line number of the caller making the logging request in a colon-separated format "fileName:lineNumber".
27
+ # * `method` => the method name of the caller making the logging request.
28
+ # * `NDC` => the NDC string
29
+ # * `stack_trace` => the multi-line stack-trace
30
+ #
31
+ # Also if the original log4j LoggingEvent contains MDC hash entries, they will be merged in the event as fields.
17
32
  class LogStash::Inputs::Log4j < LogStash::Inputs::Base
18
33
 
19
34
  config_name "log4j"
@@ -42,7 +57,6 @@ class LogStash::Inputs::Log4j < LogStash::Inputs::Base
42
57
 
43
58
  public
44
59
  def register
45
- # LogStash::Environment.load_elasticsearch_jars!
46
60
  require "java"
47
61
  require "jruby/serialization"
48
62
 
@@ -59,41 +73,45 @@ class LogStash::Inputs::Log4j < LogStash::Inputs::Base
59
73
  @logger.info("Log4j input")
60
74
  end # def register
61
75
 
76
+ public
77
+ def create_event(log4j_obj)
78
+ # NOTE: log4j_obj is org.apache.log4j.spi.LoggingEvent
79
+ event = LogStash::Event.new("message" => log4j_obj.getRenderedMessage)
80
+ event["timestamp"] = log4j_obj.getTimeStamp
81
+ event["path"] = log4j_obj.getLoggerName
82
+ event["priority"] = log4j_obj.getLevel.toString
83
+ event["logger_name"] = log4j_obj.getLoggerName
84
+ event["thread"] = log4j_obj.getThreadName
85
+ event["class"] = log4j_obj.getLocationInformation.getClassName
86
+ event["file"] = log4j_obj.getLocationInformation.getFileName + ":" + log4j_obj.getLocationInformation.getLineNumber
87
+ event["method"] = log4j_obj.getLocationInformation.getMethodName
88
+ event["NDC"] = log4j_obj.getNDC if log4j_obj.getNDC
89
+ event["stack_trace"] = log4j_obj.getThrowableStrRep.to_a.join("\n") if log4j_obj.getThrowableInformation
90
+
91
+ # Add the MDC context properties to event
92
+ if log4j_obj.getProperties
93
+ log4j_obj.getPropertyKeySet.each do |key|
94
+ event[key] = log4j_obj.getProperty(key)
95
+ end
96
+ end
97
+ return event
98
+ end # def create_event
99
+
62
100
  private
63
101
  def handle_socket(socket, output_queue)
64
102
  begin
65
- # JRubyObjectInputStream uses JRuby class path to find the class to de-serialize to
66
- ois = JRubyObjectInputStream.new(java.io.BufferedInputStream.new(socket.to_inputstream))
67
- loop do
68
- # NOTE: log4j_obj is org.apache.log4j.spi.LoggingEvent
69
- log4j_obj = ois.readObject
70
- event = LogStash::Event.new("message" => log4j_obj.getRenderedMessage)
71
- decorate(event)
103
+ ois = socket_to_inputstream(socket)
104
+ while !stop?
105
+ event = create_event(ois.readObject)
72
106
  event["host"] = socket.peer
73
- event["path"] = log4j_obj.getLoggerName
74
- event["priority"] = log4j_obj.getLevel.toString
75
- event["logger_name"] = log4j_obj.getLoggerName
76
- event["thread"] = log4j_obj.getThreadName
77
- event["class"] = log4j_obj.getLocationInformation.getClassName
78
- event["file"] = log4j_obj.getLocationInformation.getFileName + ":" + log4j_obj.getLocationInformation.getLineNumber
79
- event["method"] = log4j_obj.getLocationInformation.getMethodName
80
- event["NDC"] = log4j_obj.getNDC if log4j_obj.getNDC
81
- event["stack_trace"] = log4j_obj.getThrowableStrRep.to_a.join("\n") if log4j_obj.getThrowableInformation
82
-
83
- # Add the MDC context properties to '@fields'
84
- if log4j_obj.getProperties
85
- log4j_obj.getPropertyKeySet.each do |key|
86
- event[key] = log4j_obj.getProperty(key)
87
- end
88
- end
89
-
107
+ decorate(event)
90
108
  output_queue << event
91
109
  end # loop do
92
110
  rescue => e
93
- @logger.debug("Closing connection", :client => socket.peer,
111
+ @logger.debug? && @logger.debug("Closing connection", :client => socket.peer,
94
112
  :exception => e)
95
113
  rescue Timeout::Error
96
- @logger.debug("Closing connection after read timeout",
114
+ @logger.debug? && @logger.debug("Closing connection after read timeout",
97
115
  :client => socket.peer)
98
116
  end # begin
99
117
  ensure
@@ -104,6 +122,12 @@ class LogStash::Inputs::Log4j < LogStash::Inputs::Base
104
122
  end # begin
105
123
  end
106
124
 
125
+ private
126
+ def socket_to_inputstream(socket)
127
+ # JRubyObjectInputStream uses JRuby class path to find the class to de-serialize to
128
+ JRubyObjectInputStream.new(java.io.BufferedInputStream.new(socket.to_inputstream))
129
+ end
130
+
107
131
  private
108
132
  def server?
109
133
  @mode == "server"
@@ -114,26 +138,29 @@ class LogStash::Inputs::Log4j < LogStash::Inputs::Base
114
138
  line = socket.readline
115
139
  end # def readline
116
140
 
141
+ public
142
+ # method used to stop the plugin and unblock
143
+ # pending blocking operatings like sockets and others.
144
+ def stop
145
+ @server_socket.close if @server_socket && !@server_socket.closed?
146
+ end
147
+
117
148
  public
118
149
  def run(output_queue)
119
150
  if server?
120
- loop do
121
- # Start a new thread for each connection.
151
+ while !stop?
122
152
  Thread.start(@server_socket.accept) do |s|
123
- # TODO(sissel): put this block in its own method.
124
-
125
- # monkeypatch a 'peer' method onto the socket.
126
153
  s.instance_eval { class << self; include ::LogStash::Util::SocketPeer end }
127
- @logger.debug("Accepted connection", :client => s.peer,
154
+ @logger.debug? && @logger.debug("Accepted connection", :client => s.peer,
128
155
  :server => "#{@host}:#{@port}")
129
156
  handle_socket(s, output_queue)
130
157
  end # Thread.start
131
158
  end # loop
132
159
  else
133
- loop do
160
+ while !stop?
134
161
  client_socket = TCPSocket.new(@host, @port)
135
162
  client_socket.instance_eval { class << self; include ::LogStash::Util::SocketPeer end }
136
- @logger.debug("Opened connection", :client => "#{client_socket.peer}")
163
+ @logger.debug? && @logger.debug("Opened connection", :client => "#{client_socket.peer}")
137
164
  handle_socket(client_socket, output_queue)
138
165
  end # loop
139
166
  end
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-input-log4j'
4
- s.version = '1.0.0'
4
+ s.version = '2.0.0'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "Read events over a TCP socket from a Log4j SocketAppender"
7
7
  s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.require_paths = ["lib"]
12
12
 
13
13
  # Files
14
- s.files = `git ls-files`.split($\)
14
+ s.files = Dir['lib/**/*','spec/**/*','vendor/**/*','*.gemspec','*.md','CONTRIBUTORS','Gemfile','LICENSE','NOTICE.TXT']
15
15
 
16
16
  # Tests
17
17
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
23
23
 
24
24
  s.add_runtime_dependency 'logstash-codec-plain'
25
25
 
26
- s.add_runtime_dependency "logstash-core", '>= 1.4.0', '< 2.0.0'
26
+ s.add_runtime_dependency "logstash-core", "~> 2.0.0.snapshot"
27
27
 
28
28
  s.add_development_dependency 'logstash-devutils'
29
29
  end
@@ -1,8 +1,9 @@
1
1
  # encoding: utf-8
2
-
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "logstash/inputs/log4j"
3
4
  require "logstash/plugin"
4
5
 
5
- describe "inputs/log4j" do
6
+ describe LogStash::Inputs::Log4j do
6
7
 
7
8
  it "should register" do
8
9
  input = LogStash::Plugin.lookup("input", "log4j").new("mode" => "client")
@@ -10,4 +11,74 @@ describe "inputs/log4j" do
10
11
  # register will try to load jars and raise if it cannot find jars or if org.apache.log4j.spi.LoggingEvent class is not present
11
12
  expect {input.register}.to_not raise_error
12
13
  end
14
+
15
+ context "when interrupting the plugin" do
16
+
17
+ it_behaves_like "an interruptible input plugin" do
18
+ let(:config) { { "mode" => "server" } }
19
+ end
20
+
21
+ it_behaves_like "an interruptible input plugin" do
22
+ let(:config) { { "mode" => "client" } }
23
+ let(:socket) { double("socket") }
24
+ let(:ois) { double("ois") }
25
+ before(:each) do
26
+ allow(socket).to receive(:peer).and_return("localhost")
27
+ allow(ois).to receive(:readObject).and_return({})
28
+ allow(TCPSocket).to receive(:new).and_return(socket)
29
+ expect(subject).to receive(:socket_to_inputstream).with(socket).and_return(ois)
30
+ expect(subject).to receive(:create_event).and_return(LogStash::Event.new).at_least(:once)
31
+ end
32
+ end
33
+ end
34
+
35
+ context "reading general information from a org.apache.log4j.spi.LoggingEvent" do
36
+ let (:input) { LogStash::Plugin.lookup("input", "log4j").new("mode" => "client") }
37
+ let (:log_obj) {
38
+ org.apache.log4j.spi.LoggingEvent.new(
39
+ "org.apache.log4j.Logger",
40
+ org.apache.log4j.Logger.getLogger("org.apache.log4j.LayoutTest"),
41
+ 1426366971,
42
+ org.apache.log4j.Level::INFO,
43
+ "Hello, World",
44
+ nil
45
+ )
46
+ }
47
+
48
+ let (:log_obj_with_stacktrace) {
49
+ org.apache.log4j.spi.LoggingEvent.new(
50
+ "org.apache.log4j.Logger",
51
+ org.apache.log4j.Logger.getLogger("org.apache.log4j.LayoutTest"),
52
+ 1426366971,
53
+ org.apache.log4j.Level::INFO,
54
+ "Hello, World",
55
+ java.lang.IllegalStateException.new()
56
+ )
57
+ }
58
+
59
+ it "creates event with general information" do
60
+ subject = input.create_event(log_obj)
61
+ expect(subject["timestamp"]).to eq(1426366971)
62
+ expect(subject["path"]).to eq("org.apache.log4j.LayoutTest")
63
+ expect(subject["priority"]).to eq("INFO")
64
+ expect(subject["logger_name"]).to eq("org.apache.log4j.LayoutTest")
65
+ expect(subject["thread"]).to eq("main")
66
+ expect(subject["message"]).to eq("Hello, World")
67
+ # checks locationInformation is collected, but testing exact values is not meaningful in jruby
68
+ expect(subject["class"]).not_to be_empty
69
+ expect(subject["file"]).not_to be_empty
70
+ expect(subject["method"]).not_to be_empty
71
+ end
72
+
73
+ it "creates event without stacktrace" do
74
+ subject = input.create_event(log_obj)
75
+ expect(subject["stack_trace"]).to be_nil
76
+ end
77
+
78
+ it "creates event with stacktrace" do
79
+ subject = input.create_event(log_obj_with_stacktrace)
80
+ #checks stack_trace is collected, exact value is too monstruous
81
+ expect(subject["stack_trace"]).not_to be_empty
82
+ end
83
+ end
13
84
  end
metadata CHANGED
@@ -1,77 +1,69 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-input-log4j
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: java
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-24 00:00:00.000000000 Z
11
+ date: 2015-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: logstash-codec-plain
15
- version_requirements: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - '>='
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
14
  requirement: !ruby/object:Gem::Requirement
21
15
  requirements:
22
16
  - - '>='
23
17
  - !ruby/object:Gem::Version
24
18
  version: '0'
19
+ name: logstash-codec-plain
25
20
  prerelease: false
26
21
  type: :runtime
27
- - !ruby/object:Gem::Dependency
28
- name: logstash-core
29
22
  version_requirements: !ruby/object:Gem::Requirement
30
23
  requirements:
31
24
  - - '>='
32
25
  - !ruby/object:Gem::Version
33
- version: 1.4.0
34
- - - <
35
- - !ruby/object:Gem::Version
36
- version: 2.0.0
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
37
28
  requirement: !ruby/object:Gem::Requirement
38
29
  requirements:
39
- - - '>='
30
+ - - ~>
40
31
  - !ruby/object:Gem::Version
41
- version: 1.4.0
42
- - - <
43
- - !ruby/object:Gem::Version
44
- version: 2.0.0
32
+ version: 2.0.0.snapshot
33
+ name: logstash-core
45
34
  prerelease: false
46
35
  type: :runtime
47
- - !ruby/object:Gem::Dependency
48
- name: logstash-devutils
49
36
  version_requirements: !ruby/object:Gem::Requirement
50
37
  requirements:
51
- - - '>='
38
+ - - ~>
52
39
  - !ruby/object:Gem::Version
53
- version: '0'
40
+ version: 2.0.0.snapshot
41
+ - !ruby/object:Gem::Dependency
54
42
  requirement: !ruby/object:Gem::Requirement
55
43
  requirements:
56
44
  - - '>='
57
45
  - !ruby/object:Gem::Version
58
46
  version: '0'
47
+ name: logstash-devutils
59
48
  prerelease: false
60
49
  type: :development
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
61
55
  description: This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program
62
56
  email: info@elastic.co
63
57
  executables: []
64
58
  extensions: []
65
59
  extra_rdoc_files: []
66
60
  files:
67
- - .gitignore
68
61
  - CHANGELOG.md
69
62
  - CONTRIBUTORS
70
63
  - Gemfile
71
64
  - LICENSE
72
65
  - NOTICE.TXT
73
66
  - README.md
74
- - Rakefile
75
67
  - lib/logstash-input-log4j_jars.rb
76
68
  - lib/logstash/inputs/log4j.rb
77
69
  - logstash-input-log4j.gemspec
@@ -99,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
91
  version: '0'
100
92
  requirements: []
101
93
  rubyforge_project:
102
- rubygems_version: 2.2.2
94
+ rubygems_version: 2.4.8
103
95
  signing_key:
104
96
  specification_version: 4
105
97
  summary: Read events over a TCP socket from a Log4j SocketAppender
data/.gitignore DELETED
@@ -1,3 +0,0 @@
1
- *.gem
2
- Gemfile.lock
3
- .bundle
data/Rakefile DELETED
@@ -1,7 +0,0 @@
1
- @files=[]
2
-
3
- task :default do
4
- system("rake -T")
5
- end
6
-
7
- require "logstash/devutils/rake"