logstash-codec-mtrraw 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d88e82a64b32f90104a3e416cec993d4a72335b4
4
+ data.tar.gz: 99542d614c33bedbe63b114c1163f7bdd2ae1d1f
5
+ SHA512:
6
+ metadata.gz: 21b9f69b4dcc2dc982b2ea9b4fa30a684992776294210c5ed5bbb7f82a6484507dc05342db5e50cb960ab5db2c0347ab9c59973106e559e7959cb46e5f8b3cfc
7
+ data.tar.gz: cb1badb8fc189389e7a68552de80e970477107cbad5a3bec6635738b31a60f98cf52552ba356479dbccf0882ce563caada82b07305896a4b5efe0b6f9a0ef7f3
data/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+ ## 0.1.0
2
+ - Plugin created with the logstash plugin generator
data/CONTRIBUTORS ADDED
@@ -0,0 +1,10 @@
1
+ The following is a list of people who have contributed ideas, code, bug
2
+ reports, or in general have helped logstash along its way.
3
+
4
+ Contributors:
5
+ * svdasein - daveparker01@gmail.com
6
+
7
+ Note: If you've sent us patches, bug reports, or otherwise contributed to
8
+ Logstash, and you aren't on the list above and want to be, please let us know
9
+ and we'll make sure you're here. Contributions from folks like you are what make
10
+ open source awesome.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
data/LICENSE ADDED
@@ -0,0 +1,11 @@
1
+ Licensed under the Apache License, Version 2.0 (the "License");
2
+ you may not use this file except in compliance with the License.
3
+ You may obtain a copy of the License at
4
+
5
+ http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software
8
+ distributed under the License is distributed on an "AS IS" BASIS,
9
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ See the License for the specific language governing permissions and
11
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # Logstash Plugin
2
+
3
+ This is a plugin for [Logstash](https://github.com/elastic/logstash).
4
+
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
+
7
+ ## Documentation
8
+
9
+ The logstash mtrraw codec wraps together a bunch of logic that makes it easy to use mtr --raw output in your ELK infrastructure.
10
+
11
+ ### Installation
12
+
13
+ ```
14
+ bin/logstash-plugin install logstash-codec-mtrraw
15
+ ```
16
+ ### Configuration
17
+
18
+ ```
19
+ input {
20
+ tcp {
21
+ port => 4327
22
+ codec => "mtrraw"
23
+ }
24
+ }
25
+ ```
26
+
27
+ ### Sending MTR trace data
28
+ Feed it with something that's functionally equivalent to this:
29
+
30
+ ```
31
+ while true ; do (echo "s 0 GOOGDNS 1";mtr --raw --no-dns -c 1 8.8.8.8 ) | awk '{printf $0";"}' | nc localhost 4327 ; done
32
+ ```
33
+
34
+ Put the above in a script, make the script executable, and run it in the background. It'll continuously feed mtr trace data to
35
+ the codec.
36
+
37
+ Explanation:
38
+
39
+ There's an infinite loop around the traces without a pause. A pause isn't really needed to keep load down as the trace is i/o bound
40
+ on the network all the time anyway.
41
+
42
+ The `(echo ...;mtr)` construct allows us to overload the frontend of the trace a little bit and have the whole thing treated as a single
43
+ stream. The front of the trace has a line that looks like this:
44
+
45
+ ```
46
+ s 0 <targetname> <pingcount>
47
+
48
+ ```
49
+
50
+ * <targetname> is whatever name you want to give the trace
51
+ * <pingcount> is the number of pings you're going to be doing to each node in the trace. This must match the -c parameter to mtr (see below).
52
+
53
+ Modify the echo statement accordingly.
54
+
55
+ The MTR execution part requires the following:
56
+
57
+ * You must use the `--raw` output format
58
+ * You must specify the `-c` (count) option to state how many pings you want to do. This number must also be in the start line (above)
59
+
60
+ Any other options are optional :)
61
+
62
+ The `| awk '{printf $0";"}` construct takes all the --raw output lines and puts them together in one line delimited by semicolons. This
63
+ in turn is sent to your logstash instance at the port you defined when you configured it using a tcp connection via the netcat (nc) command.
64
+
65
+ ### What you'll get
66
+
67
+ The codec generates two kinds of documents:
68
+
69
+ #### wholepath
70
+
71
+ Whole path documents are identified by the "wholepath" tag. These documents describe the entire path taken and assign a signature to the path you can
72
+ use to identify it among paths taken. This allows you to e.g. do route flap detection, rtt & loss analysis, etc.
73
+
74
+ #### hop
75
+
76
+ Hop documents are identified by the "hop" tag. These documents describe a single hop on a path (where the path is identified by the same identifier
77
+ that the wholepath document contains). You can use these with the excellent [Network visualization plugin](https://github.com/dlumbrer/kbn_network) to visualize routes in kibana.
78
+
79
+
80
+ ## Contributing
81
+
82
+ All contributions are welcome: ideas, patches, documentation, bug reports, complaints, and even something you drew up on a napkin.
83
+
84
+ Programming is not a required skill. Whatever you've seen about open source and maintainers or community members saying "send patches or die" - you will not see that here.
85
+
86
+ It is more important to the community that you are able to contribute.
87
+
88
+ For more information about contributing, see the [CONTRIBUTING](https://github.com/elastic/logstash/blob/master/CONTRIBUTING.md) file.
@@ -0,0 +1,132 @@
1
+ # encoding: utf-8
2
+ require "logstash/codecs/base"
3
+ require "logstash/codecs/line"
4
+ require "logstash/namespace"
5
+ require "securerandom"
6
+ require "digest"
7
+
8
+
9
+ # This codec presumes you've somehow sent in the equivalent of this
10
+ # bash one-liner:
11
+ # (echo "S MYTARGET" ; mtr --raw -c <samplecount> 8.8.8.8) | awk '{printf $1";"}'
12
+ # You can get that into logstash any way you want, e.g. netcat will
13
+ # work if you set up a tcp input:
14
+ # (echo "S MYTARGET" ; mtr --raw -c <samplecount> 8.8.8.8) | awk '{printf $1";"}' | nc <myserver> <myport>
15
+ #
16
+
17
+ class MtrRec
18
+ attr_accessor :type,:id,:data
19
+ def initialize(line)
20
+ parts = line.split(/\s+/,3)
21
+ @type = parts[0]
22
+ @id = parts[1]
23
+ @data = parts[2]
24
+ end
25
+ end
26
+
27
+ class MtrHost
28
+ attr_accessor :hostid,:addr,:pings,:dns,:recs,:totalreplies
29
+ def initialize(rec,pingcount,recs)
30
+ @hostid = rec.id
31
+ @addr = rec.data
32
+ @recs = recs
33
+ @pings = recs.select{|each| each.type == 'p'}.collect {|each|each.data}
34
+ @pingloss = (100.to_f - (100.to_f * (@pings.size.to_f / pingcount.to_f))).to_i if pingcount.to_i > 0
35
+ @avgrtt = (@pings.inject(0.0) {|counter,each| counter += (each.to_f/1000)} / @pings.size).to_i
36
+ @dns = recs.select{|each| each.type =='d'}.collect {|each|each.data}.pop
37
+ end
38
+ def to_event_struct
39
+ {:hostid => @hostid, :addr => @addr , :pings => @pings ,:dns => @dns,:pingloss => @pingloss,:avgrtt => @avgrtt}
40
+ end
41
+ end
42
+
43
+ class LogStash::Codecs::Mtrraw < LogStash::Codecs::Base
44
+
45
+ # The codec name
46
+ config_name "mtrraw"
47
+
48
+ # Append a string to the message
49
+ # config :append, :validate => :string, :default => ', Hello World!'
50
+
51
+ def register
52
+ end # def register
53
+
54
+ def decode(data)
55
+ mtrlines = data.split(';')
56
+ mtrrecs = mtrlines.collect {|each| MtrRec.new(each) }
57
+ if mtrrecs[0].type == 's'
58
+ target = mtrrecs.shift.data
59
+ pingcount = 0
60
+ if target =~ /(\w+) (\d+)/
61
+ target = $1
62
+ pingcount = $2
63
+ end
64
+ end
65
+ id = SecureRandom.uuid
66
+ hops = Array.new
67
+ mtrrecs.each { |rec|
68
+ if rec.type == 'h'
69
+ hop = MtrHost.new(rec,pingcount,mtrrecs.select{|each| each.id == rec.id }).to_event_struct
70
+ if hops.size > 1
71
+ if (hops[hops.size - 1][:addr] != hop[:addr])
72
+ hops.push(hop)
73
+ else
74
+ # It's a duplicate of the last hop - drop it
75
+ end
76
+ else
77
+ hops.push(hop)
78
+ end
79
+ end
80
+ }
81
+ path = hops.collect {|each|each[:addr]}
82
+ pathsig = Digest::MD5.hexdigest(path.join('-'))
83
+ avgloss = hops.inject(0) {|loss,each| loss += each[:pingloss]} / path.size
84
+ avgrtt = hops.inject(0.0) {|rtt,each| rtt += each[:avgrtt]} / path.size
85
+ tracedata = { "id" => id,
86
+ "target" => target,
87
+ "message" => data ,
88
+ "hops" => hops,
89
+ "path" => path ,
90
+ "pathsig" => pathsig,
91
+ "pingcount"=>pingcount,
92
+ "avgloss"=>avgloss,
93
+ "avgrtt" => avgrtt,
94
+ "tags" => ["wholepath"]
95
+ }
96
+ yield LogStash::Event.new(tracedata)
97
+ # Construct a starting point for trace to target
98
+ yield LogStash::Event.new({
99
+ "id" => id,
100
+ "target" => target,
101
+ "tags" => ["hop"],
102
+ "seq" => -1,
103
+ "pathsig" => pathsig,
104
+ "A_node" => "TO:#{target}",
105
+ "Z_node" => hops[0][:addr],
106
+ "dns" => "startingpoint",
107
+ "avgrtt" => 0,
108
+ "avgloss" => 0
109
+ })
110
+ 0.upto(path.size - 2) {
111
+ |index|
112
+ yield LogStash::Event.new({ "id" => id,
113
+ "target" => target,
114
+ "tags" => ["hop"],
115
+ "pathsig" => pathsig,
116
+ "seq" => index,
117
+ "A_node" => hops[index][:addr],
118
+ "Z_node" => hops[index + 1][:addr],
119
+ "dns" => hops[index + 1][:dns],
120
+ "avgrtt" => hops[index + 1][:avgrtt],
121
+ "avgloss" => hops[index + 1][:avgloss]
122
+ })
123
+ }
124
+ end # def decode
125
+
126
+ # Encode a single event, this returns the raw data to be returned as a String
127
+ def encode_sync(event)
128
+ # Nothing to do.
129
+ @on_event.call(event, event)
130
+ end # def encode_sync
131
+
132
+ end # class LogStash::Codecs::Mtrraw
@@ -0,0 +1,24 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'logstash-codec-mtrraw'
3
+ s.version = '0.1.0'
4
+ s.licenses = ['Apache License (2.0)']
5
+ s.summary = 'Converts optionally overloaded mtr --raw data to an event'
6
+ s.description = 'Turn mtr --raw events with optional overloading into logstash events. see docs'
7
+ s.homepage = 'https://github.com/svdasein/logstash-codec-mtrraw'
8
+ s.authors = ['svdasein']
9
+ s.email = 'daveparker01@gmail.com'
10
+ s.require_paths = ['lib']
11
+
12
+ # Files
13
+ s.files = Dir['lib/**/*','spec/**/*','vendor/**/*','*.gemspec','*.md','CONTRIBUTORS','Gemfile','LICENSE','NOTICE.TXT']
14
+ # Tests
15
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
16
+
17
+ # Special flag to let us know this is actually a logstash plugin
18
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "codec" }
19
+
20
+ # Gem dependencies
21
+ s.add_runtime_dependency 'logstash-core-plugin-api', "~> 2.0"
22
+ s.add_runtime_dependency 'logstash-codec-line'
23
+ s.add_development_dependency 'logstash-devutils'
24
+ end
@@ -0,0 +1,3 @@
1
+ # encoding: utf-8
2
+ require_relative '../spec_helper'
3
+ require "logstash/codecs/mtrraw"
@@ -0,0 +1,2 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-codec-mtrraw
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - svdasein
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-11-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: logstash-core-plugin-api
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: logstash-codec-line
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: logstash-devutils
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Turn mtr --raw events with optional overloading into logstash events. see
56
+ docs
57
+ email: daveparker01@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - CHANGELOG.md
63
+ - CONTRIBUTORS
64
+ - Gemfile
65
+ - LICENSE
66
+ - README.md
67
+ - lib/logstash/codecs/mtrraw.rb
68
+ - logstash-codec-mtrraw.gemspec
69
+ - spec/codecs/mtrraw_spec.rb
70
+ - spec/spec_helper.rb
71
+ homepage: https://github.com/svdasein/logstash-codec-mtrraw
72
+ licenses:
73
+ - Apache License (2.0)
74
+ metadata:
75
+ logstash_plugin: 'true'
76
+ logstash_group: codec
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.5.1
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Converts optionally overloaded mtr --raw data to an event
97
+ test_files:
98
+ - spec/codecs/mtrraw_spec.rb
99
+ - spec/spec_helper.rb
100
+ has_rdoc: