logstash-cli 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ Gemfile.lock
data/.rvmrc ADDED
@@ -0,0 +1,6 @@
1
+ #this uses rvm
2
+ rvm use 1.8.7
3
+ rvm_gemset_create_on_use_flag=1
4
+ rvm gemset use logstash-cli
5
+ alias rake="bundle exec rake"
6
+ alias logstash-cli="bundle exec bin/logstash-cli"
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "logstash-cli", :path => "."
4
+
5
+ group :test do
6
+ gem "rake"
7
+ end
8
+
9
+ gemspec
data/README.md ADDED
@@ -0,0 +1,55 @@
1
+ ** Work in progress **
2
+
3
+ ## Description
4
+
5
+ A cli tool to query an elasticsearch host for logstash information.
6
+ Because let's face it, we're CLI junkies :)
7
+
8
+ Mucho inspired by a gist of the eminent @lusis - <https://gist.github.com/1388077>
9
+
10
+ ## Installation
11
+ Installation using the usual steps
12
+
13
+ Install rvm , (no gem yet)
14
+
15
+ $ git clone thisrepo
16
+ $ cd thisrepo
17
+ $ gem install bundler
18
+ $ bundle install
19
+
20
+ ## Usage
21
+
22
+ Usage:
23
+ logstash-cli grep PATTERN
24
+
25
+ Options:
26
+ [--index-prefix=INDEX_PREFIX] # Logstash index prefix
27
+ # Default: logstash-
28
+ [--fields=FIELDS] # Logstash Fields to show
29
+ # Default: message,program
30
+ [--meta=META] # Meta Logstash fields to show
31
+ # Default: type,message
32
+ [--to=TO] # End date
33
+ # Default: 2012-05-11
34
+ [--delim=DELIM] # csv delimiter
35
+ # Default: |
36
+ [--format=FORMAT] # Format to use for exporting
37
+ # Default: csv
38
+ [--from=FROM] # Begin date
39
+ # Default: 2012-05-11
40
+ [--size=SIZE] # Number of results to return
41
+ # Default: 500
42
+ [--esurl=ESURL] # URL to connect to elasticsearch
43
+ # Default: http://localhost:9200
44
+ [--last=LAST] # Specify period since now f.i. 1d
45
+
46
+ Search logstash for a pattern
47
+
48
+ ## Examples
49
+
50
+ $ logstash-cli grep --esurl="http://logger-1.jedi.be:9200" '@message:jedi4ever AND program:sshd' --last 5d --format csv --delim ':'
51
+ ## TODO
52
+
53
+ - find a way to query existing instances
54
+ - specify last 15m
55
+ - find a way to get the results by streaming instead of loading all in memory (maybe pagination will help here)
data/bin/logstash-cli ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ require 'logstash-cli'
3
+
4
+ # Disable color if the proper argument was passed
5
+ shell = ARGV.include?("--no-color") ? Thor::Shell::Basic.new : Thor::Base.shell.new
6
+
7
+ # Start the CLI
8
+ ::LogstashCli::CLI.start(ARGV)
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rack'
4
+ require 'tire'
5
+ require 'time'
6
+ require 'fastercsv'
7
+ require 'logstash-cli/command/grep'
8
+
9
+ module LogstashCli
10
+ class CLI < Thor
11
+
12
+ include LogstashCli::Command
13
+
14
+ desc "grep PATTERN", "Search logstash for a pattern"
15
+ method_option :esurl , :default => 'http://localhost:9200', :desc => "URL to connect to elasticsearch"
16
+ method_option :index_prefix , :default => "logstash-", :desc => "Logstash index prefix"
17
+ method_option :from , :default => "#{Time.now.strftime('%Y-%m-%d')}", :desc => "Begin date"
18
+ method_option :to, :default => "#{Time.now.strftime('%Y-%m-%d')}", :desc => "End date"
19
+ method_option :format , :default => 'csv', :desc => "Format to use for exporting"
20
+ method_option :size , :default => 500, :desc => "Number of results to return"
21
+ method_option :last , :default => nil, :desc => "Specify period since now f.i. 1d"
22
+ method_option :meta , :default => "type,message", :desc => "Meta Logstash fields to show"
23
+ method_option :fields , :default => "message,program", :desc => "Logstash Fields to show"
24
+ method_option :delim , :default => "|", :desc => "csv delimiter"
25
+ def grep(pattern)
26
+ _grep(pattern,options)
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,82 @@
1
+ require 'date'
2
+
3
+ require 'yajl/json_gem'
4
+
5
+ module LogstashCli::Command
6
+
7
+ def _grep(pattern,options)
8
+ es_url = options[:esurl]
9
+ index_prefix = options[:index_prefix]
10
+
11
+ from = options[:from]
12
+ to = options[:to]
13
+ metafields = options[:meta].split(',')
14
+ fields = options[:fields].split(',')
15
+
16
+ begin
17
+ unless options[:last].nil?
18
+ days = options[:last].match(/(\d*)d/)[1].to_i
19
+ to_date = Date.today
20
+ from_date = to_date - days
21
+ from = from_date.to_s
22
+ to = to_date.to_s
23
+ end
24
+
25
+ from_date = Date.parse(from)
26
+ to_date = Date.parse(to)
27
+ rescue Exception => ex
28
+ $stderr.puts "Something went wrong while parsing the dates: currently only dates are supported with last. Be sure to add the suffix 'd' "+ex
29
+ exit -1
30
+ end
31
+
32
+ $stderr.puts "Searching #{es_url}[#{index_prefix}#{from_date}..#{index_prefix}#{to_date}] - #{pattern}"
33
+
34
+ (from_date..to_date).to_a.each do |date|
35
+ es_index = index_prefix+date.to_s.gsub('-','.')
36
+
37
+ result_size = options[:size]
38
+
39
+ begin
40
+ Tire.configure {url es_url}
41
+ search = Tire.search(es_index) do
42
+ query do
43
+ string "#{pattern}"
44
+ end
45
+ sort do
46
+ by :@timestamp, 'desc'
47
+ end
48
+ size result_size
49
+ end
50
+ rescue Exception => e
51
+ $stderr.puts e
52
+ $stderr.puts "\nSomething went wrong with the search. This is usually due to lucene query parsing of the 'grep' option"
53
+ exit
54
+ end
55
+
56
+ begin
57
+ result = Array.new
58
+ search.results.sort {|a,b| a[:@timestamp] <=> b[:@timestamp] }.each do |res|
59
+
60
+ metafields.each do |metafield|
61
+ result << res["@#{metafield}".to_sym]
62
+ end
63
+
64
+ fields.each do |field|
65
+ result << res[:@fields][field.to_sym]
66
+ end
67
+
68
+ output = case options[:format]
69
+ when 'csv' then result.to_csv({:col_sep => options[:delim]})
70
+ when 'json' then result.to_json
71
+ end
72
+ #tstamp = Time.iso8601(res[:@timestamp]).localtime.iso8601
73
+
74
+ puts output
75
+ result = []
76
+ end
77
+ rescue ::Tire::Search::SearchRequestFailed => e
78
+ $stderr.puts e.message
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env ruby
2
+ # vim:filetype=ruby
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ begin
6
+ require 'tire'
7
+ require 'slop'
8
+ require 'time'
9
+ rescue LoadError
10
+ puts "You seem to be missing some key libraries"
11
+ puts "please run `gem install bundler --no-ri --no-rdoc; bundle install`"
12
+ end
13
+
14
+ begin
15
+ require 'yajl/json_gem'
16
+ rescue LoadError
17
+ puts "`gem install yajl-ruby for better performance"
18
+ end
19
+
20
+ opts = Slop.parse do
21
+ banner "Usage: search.rb -i <index> -f <facility>"
22
+ on :i, :index=, "index to search (default: logstash-#{Time.now.strftime('%Y.%m.%d')})", :default => "logstash-#{Time.now.strftime('%Y.%m.%d')}"
23
+ on :f, :facility=, "REQUIRED: Facility(application name) to use", nil
24
+ on :s, :size=, "number of results to return (default: 500)", true, :default => 500
25
+ on :c, :class_name=, "optional class name to narrow results by", nil
26
+ on :g, :grep=, "optional search on message content. Warning!!! This is slow", true
27
+ on :exceptions, "toggle exception search. Warning!!! This is slow", :default => false
28
+ on :live, "runs in live logging mode. This is A LOT of output. Please use non-wildcard facilities", :default => false
29
+ on :fields=, Array, "optional comma-separated list of fields to display (tstamp, msg, file, class_name, service) in order (default: tstamp,service,msg)"
30
+ on :h, :help, 'Print this help message', :tail => true do
31
+ #puts help
32
+ puts <<-EOF
33
+
34
+ --------
35
+ Examples
36
+ --------
37
+ - last 10 results log entries from curation including timestamp, classname and message:
38
+
39
+ search.rb -f curation* -s 10 --fields tstamp,class_name,msg
40
+
41
+ - last 5 entries for class name com.va (note the quote around * in the -f option):
42
+
43
+ search.rb -f "*" -s 5 -c com.va.*
44
+
45
+ - last 20 entries everywhere with timestamp, service name and message
46
+
47
+ search.rb -f "*" -s 20 --fields tstamp,service,msg
48
+
49
+ - last 5 exceptions everywhere
50
+
51
+ search.rb -f "*" -s 5 --exceptions
52
+
53
+ - live tail tracker_web
54
+
55
+ search.rb -f tracker_web --live
56
+
57
+ - live tail foo with custom display
58
+
59
+ search.rb -f foo --live --fields tstamp,service,class_name,msg
60
+
61
+ EOF
62
+ exit
63
+ end
64
+ end
65
+
66
+ if opts[:live]
67
+ require 'amqp'
68
+ require 'yajl/json_gem'
69
+ #https://github.com/ruby-amqp/amqp/pull/74
70
+ #URL naming scheme
71
+ AMQP.start("amqp://logstash:bar@localhost:7777") do |connection, open_ok|
72
+ channel = AMQP::Channel.new(connection, :auto_recovery => true)
73
+ exchange_name = "rawlogs"
74
+
75
+ channel.queue("", :auto_delete => true, :durable => false) do |queue, declare_ok|
76
+ queue.bind(exchange_name, :routing_key => opts[:facility])
77
+ queue.subscribe do |payload|
78
+ parsed_message = JSON.parse(payload)
79
+ require 'pp'
80
+ pp parsed_message
81
+ service = parsed_message["@fields"]["facility"]
82
+ class_name = parsed_message["@fields"]["_logger"]
83
+ file = parsed_message["@fields"]["file"]
84
+ msg = parsed_message["@message"]
85
+ #msg = parsed_message["@fields"]["full_message"]
86
+ tstamp = Time.iso8601(parsed_message["@timestamp"]).localtime.iso8601
87
+ fields = opts[:fields] || ["tstamp", "service", "msg"]
88
+ vals = fields.map {|x| x == fields[0] ? "\e[1m[#{eval(x)}]\e[0m" : eval(x)}
89
+ display = vals.join(" - ")
90
+ puts display
91
+ end
92
+ end
93
+
94
+ trap("INT") { puts "Shutting down..."; connection.close { EM.stop };exit }
95
+ end
96
+ end
97
+
98
+ if opts[:facility].nil?
99
+ puts "Facility (matches name of service) CANNOT be empty!"
100
+ require 'pp'
101
+ pp opts
102
+ exit
103
+ end
104
+
105
+ begin
106
+ Tire.configure {url "http://localhost:9200"}
107
+ puts opts[:index]
108
+ search = Tire.search(opts[:index]) do
109
+ query do
110
+ boolean do
111
+ must { string 'HOSTNAME:shipper'}
112
+ #must { string "facility:#{opts[:facility]}" } unless opts[:facility].nil?
113
+ #must { string "_logger:#{opts[:class_name]}" } unless opts[:class_name].nil?
114
+ #must { string "full_message:Exception*" } if opts[:exceptions]
115
+ must { string "message:#{opts[:grep]}*" } if opts[:grep]
116
+ end
117
+ end
118
+ sort do
119
+ by :@timestamp, 'desc'
120
+ end
121
+ size opts[:size]
122
+ end
123
+ rescue Exception => e
124
+ puts "\nSomething went wrong with the search. This is usually do to lucene query parsing of the 'grep' option"
125
+ exit
126
+ end
127
+
128
+ search.results.sort {|a,b| a[:@timestamp] <=> b[:@timestamp] }.each do |res|
129
+ service = res[:@fields][:facility]
130
+ class_name = res[:@fields][:_logger]
131
+ file = res[:@fields][:file]
132
+ #msg = res[:@fields][:full_message]
133
+ msg = res[:@fields][:message]
134
+ tstamp = Time.iso8601(res[:@timestamp]).localtime.iso8601
135
+ fields = opts[:fields] || ["tstamp", "service", "msg"]
136
+ vals = fields.map {|x| x == fields[0] ? "\e[1m[#{eval(x)}]\e[0m" : eval(x)}
137
+ display = vals.join(" - ")
138
+ puts display
139
+ end
@@ -0,0 +1,3 @@
1
+ module LogstashCli
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,3 @@
1
+ require 'thor'
2
+
3
+ require 'logstash-cli/cli'
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/logstash-cli/version", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "logstash-cli"
6
+ s.version = LogstashCli::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Patrick Debois"]
9
+ s.email = ["patrick.debois@jedi.be"]
10
+ s.homepage = "http://github.com/jedi4ever/logstash-cli/"
11
+ s.summary = %q{CLI interface to logstash}
12
+ s.description = %q{CLI inteface to logstash}
13
+
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+ s.rubyforge_project = "logstash-cli"
16
+
17
+ s.add_dependency "tire"
18
+ s.add_dependency "thor"
19
+ # s.add_dependency "amqp"
20
+ s.add_dependency "rack"
21
+ s.add_dependency "yajl-ruby"
22
+ s.add_dependency "fastercsv"
23
+ s.add_dependency "json"
24
+ #s.add_dependency "amqp-utils"
25
+
26
+ s.add_development_dependency "bundler", ">= 1.0.0"
27
+
28
+ s.files = `git ls-files`.split("\n")
29
+ s.executables = `git ls-files`.split("\n").map{ |f| f =~ /^bin\/(.*)/ ? $1 : nil }.compact
30
+ s.require_path = 'lib'
31
+ end
32
+
metadata ADDED
@@ -0,0 +1,177 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-cli
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Patrick Debois
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-05-11 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ requirement: &id001 !ruby/object:Gem::Requirement
22
+ none: false
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ hash: 3
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ name: tire
32
+ version_requirements: *id001
33
+ prerelease: false
34
+ - !ruby/object:Gem::Dependency
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ hash: 3
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :runtime
45
+ name: thor
46
+ version_requirements: *id002
47
+ prerelease: false
48
+ - !ruby/object:Gem::Dependency
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ hash: 3
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ type: :runtime
59
+ name: rack
60
+ version_requirements: *id003
61
+ prerelease: false
62
+ - !ruby/object:Gem::Dependency
63
+ requirement: &id004 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ type: :runtime
73
+ name: yajl-ruby
74
+ version_requirements: *id004
75
+ prerelease: false
76
+ - !ruby/object:Gem::Dependency
77
+ requirement: &id005 !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ hash: 3
83
+ segments:
84
+ - 0
85
+ version: "0"
86
+ type: :runtime
87
+ name: fastercsv
88
+ version_requirements: *id005
89
+ prerelease: false
90
+ - !ruby/object:Gem::Dependency
91
+ requirement: &id006 !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ hash: 3
97
+ segments:
98
+ - 0
99
+ version: "0"
100
+ type: :runtime
101
+ name: json
102
+ version_requirements: *id006
103
+ prerelease: false
104
+ - !ruby/object:Gem::Dependency
105
+ requirement: &id007 !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ hash: 23
111
+ segments:
112
+ - 1
113
+ - 0
114
+ - 0
115
+ version: 1.0.0
116
+ type: :development
117
+ name: bundler
118
+ version_requirements: *id007
119
+ prerelease: false
120
+ description: CLI inteface to logstash
121
+ email:
122
+ - patrick.debois@jedi.be
123
+ executables:
124
+ - logstash-cli
125
+ extensions: []
126
+
127
+ extra_rdoc_files: []
128
+
129
+ files:
130
+ - .gitignore
131
+ - .rvmrc
132
+ - Gemfile
133
+ - README.md
134
+ - bin/logstash-cli
135
+ - lib/logstash-cli.rb
136
+ - lib/logstash-cli/cli.rb
137
+ - lib/logstash-cli/command/grep.rb
138
+ - lib/logstash-cli/command/live.rb
139
+ - lib/logstash-cli/version.rb
140
+ - logstashcli.gemspec
141
+ homepage: http://github.com/jedi4ever/logstash-cli/
142
+ licenses: []
143
+
144
+ post_install_message:
145
+ rdoc_options: []
146
+
147
+ require_paths:
148
+ - lib
149
+ required_ruby_version: !ruby/object:Gem::Requirement
150
+ none: false
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ hash: 3
155
+ segments:
156
+ - 0
157
+ version: "0"
158
+ required_rubygems_version: !ruby/object:Gem::Requirement
159
+ none: false
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ hash: 23
164
+ segments:
165
+ - 1
166
+ - 3
167
+ - 6
168
+ version: 1.3.6
169
+ requirements: []
170
+
171
+ rubyforge_project: logstash-cli
172
+ rubygems_version: 1.8.12
173
+ signing_key:
174
+ specification_version: 3
175
+ summary: CLI interface to logstash
176
+ test_files: []
177
+