sawmill-sawyer 13.0.2

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: 55137b531ea6620f6a0f27a0fe51569e8240118f
4
+ data.tar.gz: 1bc7ceaf34cd708a76dc75974d0e77a4e0df3443
5
+ SHA512:
6
+ metadata.gz: bd78951fbe1e60bacf54c7ef8a4419a587bdcb9aca0b0e57ef9366f40b3eaf3104f44bf81ef38bf8fdb5064555fa72bb8a2fe5bd13b2a962a8739c939b93223e
7
+ data.tar.gz: 4234a4d8e3c6a1f26b346f28e161de5cc9801fe9ea6e23071eb4c9fb9bcb652e405dc26c6fde05b0d747dc9b94e812b9cbfef41546e33fb2f47547b5b331ce31
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ *~
2
+ *.log
3
+ *.gem
4
+ *.out
5
+ *.pid
6
+ *.swp
7
+ *.lock
8
+ tmp
9
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'pry'
7
+ gem 'rake'
8
+ gem 'yard'
9
+ gem 'version'
10
+ gem 'rubygems-tasks'
11
+ end
12
+
13
+ group :test do
14
+ gem 'minitest'
15
+ gem 'simplecov'
16
+ gem 'rubocop'
17
+ end
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2014 Sean Clemmer and Blue Jeans Network
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any
4
+ purpose with or without fee is hereby granted, provided that the above
5
+ copyright notice and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13
+ PERFORMANCE OF THIS SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ require 'rake'
4
+
5
+ require 'rake/testtask'
6
+ Rake::TestTask.new(:test) do |test|
7
+ test.libs << 'lib' << 'test'
8
+ test.test_files = FileList['test/test*.rb']
9
+ test.verbose = true
10
+ end
11
+
12
+ task default: :test
13
+
14
+
15
+ require 'yard'
16
+ YARD::Rake::YardocTask.new do |t|
17
+ t.files = %w[ --readme Readme.md lib/**/*.rb - VERSION ]
18
+ end
19
+
20
+
21
+ require 'rubygems/tasks'
22
+ Gem::Tasks.new push: true, sign: {} do |tasks|
23
+ tasks.console.command = 'pry'
24
+ end
25
+ Gem::Tasks::Sign::Checksum.new sha2: true
26
+
27
+
28
+ require 'rake/version_task'
29
+ Rake::VersionTask.new
data/Readme.md ADDED
@@ -0,0 +1,3 @@
1
+ # Sawyer
2
+
3
+ See [the Sawyer page](http://wiki.bluejeansnet.com/operations/sawmill/sawyer) on the Blue Jeans Wiki for documentation.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 13.0.2
data/bin/sawyer ADDED
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../lib/sawyer'
3
+
4
+ BIN_DIR = File.dirname(File.expand_path(__FILE__))
5
+ VERSION = File.read(File.join(BIN_DIR, '..', 'VERSION')).strip
6
+ ABOUT = "sawyer v#{VERSION} - Sean Clemmer (sclemmer@bluejeans.com) / Blue Jeans Network"
7
+ ACTIONS = [
8
+ "logs QUERY_STRING -- Find all logs matching the query string within an interval",
9
+ "events QUERY_STRING [LOGS] -- Find all events matching the query string within the given logs and interval"
10
+ ]
11
+
12
+ argv = ARGV.empty? ? %w[ --help ] : ARGV
13
+
14
+ opts = Trollop::options(argv) do
15
+ version ABOUT
16
+
17
+ ART = <<-'EOART' % VERSION
18
+ .---. __ ,-.
19
+ .--.--. /. ./| ,' ,'/ /|
20
+ / / ' ,--.--. .-'-. ' | .--, ,---. ' | |' |
21
+ | : /`./ / \ /___/ \: | /_ ./| / \ | | ,'
22
+ | : ;_ .--. .-. | .-'.. ' ' . , ' , ' : / / |' : /
23
+ \ \ `. \__\/: . ./___/ \: '/___/ \: |. ' / || | '
24
+ `----. \ ," .--.; |. \ ' .\ . \ ' |' ; /|; : |
25
+ / /`--' // / ,. | \ \ ' \ | \ ; :' | / || , ;
26
+ '--'. /; : .' \ \ \ |--" \ \ ;| : | ---'
27
+ `--'---' | , .-./ \ \ | : \ \\ \ /
28
+ `--`---' '---" \ ' ; `----'
29
+ `--` v%s
30
+ EOART
31
+
32
+ USAGE = <<-EOS.gsub(/^ /, '')
33
+ Usage: sawyer [OPTIONS] ACTION [ARGS]
34
+
35
+ Actions:
36
+ \t#{ACTIONS.join("\n\t")}
37
+
38
+ Options:
39
+ EOS
40
+
41
+ banner "\n\n" + ART + "\n" + USAGE
42
+ opt :from, 'Match events after this', default: '15 minutes ago'
43
+ opt :to, 'Match events before this', default: 'now'
44
+ opt :environment, 'Match events in this environment', default: 'prod'
45
+ opt :prefix, 'Match events with this index prefix', default: 'logs'
46
+ opt :limit, 'Limit search result size', default: 25
47
+ opt :debug, 'Enable debug output', default: false
48
+ end
49
+
50
+ level = ::Logger::INFO
51
+ level = ::Logger::DEBUG if opts[:debug]
52
+ logger = Sawyer::Logger.new STDERR, level
53
+ action = argv.shift.to_sym rescue nil
54
+
55
+ Trollop::die 'No action provided' if action.nil?
56
+ exit Sawyer::Actions.new(opts, action, argv, logger).status
data/lib/sawyer.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'json'
2
+ require 'date'
3
+ require 'time'
4
+ require 'logger'
5
+ require 'pathname'
6
+ require 'fileutils'
7
+
8
+ require 'curb'
9
+ require 'chronic'
10
+ require 'trollop'
11
+
12
+ require_relative 'sawyer/logger'
13
+ require_relative 'sawyer/actions'
@@ -0,0 +1,99 @@
1
+ require_relative 'actions_raw'
2
+
3
+ class Fixnum
4
+ def hours
5
+ self * 60 * 60 # [hr] * [min/hr] * [s/min] => [s]
6
+ end
7
+ end
8
+
9
+
10
+ module Sawyer
11
+ ENVIRONMENTS = {
12
+ prod: 'http://10.100.0.146:8080/es',
13
+ stage: 'http://10.100.200.12:8080/es'
14
+ }
15
+
16
+ class Actions
17
+ include RawActions
18
+
19
+ attr_reader :logger, :status
20
+
21
+ def initialize opts, action, args, logger
22
+ environment = opts[:environment].to_sym
23
+ from = Chronic.parse(opts[:from])
24
+ to = Chronic.parse(opts[:to])
25
+
26
+ @prefix = opts[:prefix]
27
+ @limit = opts[:limit]
28
+ @action = action
29
+ @args = args
30
+ @logger = logger
31
+ @status = 0
32
+
33
+ @elasticsearch = ENVIRONMENTS[environment.to_sym]
34
+
35
+ @status = send action, from, to, args
36
+ end
37
+
38
+ private
39
+ def search from, to, request
40
+ indexes = []
41
+
42
+ # INF-4114: Limit searches to 24h max
43
+ max = 24
44
+ limit = from + max.hours
45
+ if to > limit
46
+ @logger.warn "Truncating search to first #{max} hours"
47
+ to = limit
48
+ end
49
+
50
+ date_from = from.getutc.to_date
51
+ date_to = to.getutc.to_date
52
+
53
+ until date_from > date_to
54
+ indexes << date_from.strftime("#{@prefix}-%Y.%m.%d")
55
+ date_from += 1 # day
56
+ end
57
+
58
+ unless request.has_key?(:size) and request[:size] == 0
59
+ request[:size] = @limit
60
+ end
61
+
62
+ if request.has_key? :aggregations
63
+ request[:aggregations].each do |name, agg|
64
+ agg.keys.each do |k|
65
+ request[:aggregations][name][k].merge!({ size: @limit })
66
+ end
67
+ end
68
+ end
69
+
70
+ request[:query] = {
71
+ filtered: {
72
+ query: request[:query],
73
+ filter: {
74
+ bool: {
75
+ must: {
76
+ range: {
77
+ '@timestamp' => {
78
+ gte: from.iso8601,
79
+ lte: to.iso8601
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
87
+
88
+ url = "#{@elasticsearch}/#{indexes * ','}/_search?ignore_unavailable=true&timeout=10000"
89
+ @logger.debug url
90
+ @logger.debug request.to_json
91
+ curl_request = Curl::Easy.http_post(url, request.to_json) do |curl|
92
+ curl.headers['Accept'] = 'application/json'
93
+ curl.headers['Content-Type'] = 'application/json'
94
+ curl.verbose = @logger.debug?
95
+ end
96
+ JSON::parse curl_request.body_str
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,69 @@
1
+ module RawActions
2
+ def logs from, to, args
3
+ qs = args.shift
4
+ request = {
5
+ size: 0,
6
+ query: {
7
+ query_string: {
8
+ query: qs
9
+ }
10
+ },
11
+ aggregations: {
12
+ logs: {
13
+ terms: {
14
+ script: "_source.host + _source.path"
15
+ }
16
+ }
17
+ }
18
+ }
19
+
20
+ response = search from, to, request
21
+ buckets = []
22
+ if response.has_key? 'aggregations'
23
+ buckets = response['aggregations']['logs']['buckets']
24
+ end
25
+ logs = buckets.map { |log| "%d\t%s" % [ log['doc_count'], log['key'] ] }
26
+ puts logs.reverse
27
+ return 0
28
+ end
29
+
30
+
31
+
32
+ def events from, to, args
33
+ qs = args.shift
34
+ logs = args
35
+
36
+ $stdin.read.split("\n").each do |l|
37
+ logs << l.split(' ', 2).last
38
+ end unless $stdin.tty?
39
+
40
+ unless logs.empty?
41
+ logs = logs.map do |log|
42
+ host, path = log.split('/', 2)
43
+ if path.nil? || path.empty?
44
+ 'host:"%s"' % host
45
+ else
46
+ '(host:"%s" AND path:"/%s")' % [ host, path ]
47
+ end
48
+ end.join(' OR ')
49
+ logs = " AND (#{logs})"
50
+ else
51
+ logs = ''
52
+ end
53
+
54
+ request = {
55
+ query: {
56
+ query_string: {
57
+ query: qs + logs
58
+ }
59
+ }
60
+ }
61
+
62
+ response = search from, to, request
63
+ if response.has_key?('hits')
64
+ puts JSON::pretty_generate(response['hits']['hits'].map { |e| e['_source'] })
65
+ return 0
66
+ end
67
+ return 1
68
+ end
69
+ end
@@ -0,0 +1,12 @@
1
+ module Sawyer
2
+ module Logger
3
+ def self.new file=STDOUT, level=::Logger::INFO
4
+ logger = ::Logger.new file
5
+ logger.level = level
6
+ logger.formatter = proc { |severity, datetime, _, msg|
7
+ "#{severity} [#{datetime.iso8601(6)}] #{File::basename caller[4]} -- #{msg}\n"
8
+ }
9
+ return logger
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'sawmill-sawyer'
3
+ s.version = File.read('VERSION').strip
4
+ s.platform = Gem::Platform::RUBY
5
+ s.author = 'Sean Clemmer'
6
+ s.email = 'sclemmer@bluejeans.com'
7
+ s.homepage = 'http://wiki.bluejeansnet.com/operations/sawyer'
8
+ s.summary = 'Sawyer is a command-line companion to Sawmill'
9
+ s.description = 'Sawyer is a command-line companion to Sawmill.'
10
+ s.license = 'ISC'
11
+
12
+ s.add_runtime_dependency 'curb', '~> 0'
13
+ s.add_runtime_dependency 'chronic', '~> 0'
14
+ s.add_runtime_dependency 'trollop', '~> 2'
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ['lib']
20
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sawmill-sawyer
3
+ version: !ruby/object:Gem::Version
4
+ version: 13.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Sean Clemmer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: curb
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: chronic
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: trollop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2'
55
+ description: Sawyer is a command-line companion to Sawmill.
56
+ email: sclemmer@bluejeans.com
57
+ executables:
58
+ - sawyer
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - Gemfile
64
+ - LICENSE
65
+ - Rakefile
66
+ - Readme.md
67
+ - VERSION
68
+ - bin/sawyer
69
+ - lib/sawyer.rb
70
+ - lib/sawyer/actions.rb
71
+ - lib/sawyer/actions_raw.rb
72
+ - lib/sawyer/logger.rb
73
+ - sawmill-sawyer.gemspec
74
+ homepage: http://wiki.bluejeansnet.com/operations/sawyer
75
+ licenses:
76
+ - ISC
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.2.2
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: Sawyer is a command-line companion to Sawmill
98
+ test_files: []