greenhat 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/greenhat/reports/reports/errors.rb +5 -3
- data/lib/greenhat/shell/log.rb +10 -2
- data/lib/greenhat/shell/shell_helper.rb +101 -104
- data/lib/greenhat/thing/file_types.rb +15 -1
- data/lib/greenhat/thing/formatters/exporters.rb +48 -0
- data/lib/greenhat/thing/formatters/identify_db.rb +32 -0
- data/lib/greenhat/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 585d6d2f1488ca970ca64230991151e3417c28f14662dfdb6f02fec7c617d54a
|
4
|
+
data.tar.gz: 2999efd11049fc2d20ad1f5f1e8967b7b0d5caccce2f819530de9f0982349ed6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 21f480e7eda0513557b373283119317bd2e13ffcb6d8f97924fed30b03b4913ea7f86fee4b007e068384d3615cf18fd9eed405ce89df7c7bcb54eb6d36282a25
|
7
|
+
data.tar.gz: 3028f8003fdee07c04a0e327b2eca2138147203854bc8fbadd3784d2af80ea3660bb402d096632f25033f70cea456204aec5f0508eec2233c91f4099138a9d87
|
@@ -23,7 +23,8 @@ entries = [
|
|
23
23
|
{ header: 'Workhorse', base: 'gitlab-workhorse/current --level=error', stats: 'error' },
|
24
24
|
{ header: 'Sidekiq', base: 'sidekiq/current --severity=error', stats: 'message' },
|
25
25
|
{ header: 'API', base: 'gitlab-rails/api_json.log --severity=error',
|
26
|
-
stats: 'exception.class,exception.message,status' }
|
26
|
+
stats: 'exception.class,exception.message,status' },
|
27
|
+
{ header: 'Gitaly', base: 'gitaly/current --level=error --truncate=99', stats: 'error' }
|
27
28
|
]
|
28
29
|
|
29
30
|
# Filter Logic
|
@@ -38,9 +39,10 @@ end
|
|
38
39
|
|
39
40
|
# Return output
|
40
41
|
entries.each do |entry|
|
41
|
-
query_string = flags
|
42
|
+
query_string = flags[:verbose] ? entry.base : entry.base + " --stats=#{entry.stats}"
|
42
43
|
query(query_string, false) do |results|
|
43
|
-
next if results.
|
44
|
+
next if results.empty?
|
45
|
+
next if !flags[:verbose] && results.map(&:values).map(&:first).sum.zero?
|
44
46
|
|
45
47
|
header entry.header
|
46
48
|
|
data/lib/greenhat/shell/log.rb
CHANGED
@@ -125,10 +125,18 @@ module GreenHat
|
|
125
125
|
return false
|
126
126
|
end
|
127
127
|
|
128
|
-
Thing.new.query_save(results, name)
|
128
|
+
Thing.new.query_save(save_greenhat_query_info + results, name)
|
129
129
|
puts "#{name.pastel(:green)} Saved!"
|
130
130
|
end
|
131
131
|
|
132
|
+
def self.save_greenhat_query_info
|
133
|
+
[{
|
134
|
+
time: Time.now,
|
135
|
+
query: ShellHelper::Log.last,
|
136
|
+
msg: 'GreenHat Save/Write'
|
137
|
+
}]
|
138
|
+
end
|
139
|
+
|
132
140
|
def self.write(raw = [])
|
133
141
|
if ShellHelper::Log.last.nil?
|
134
142
|
puts 'No previous query found'.pastel(:red)
|
@@ -158,7 +166,7 @@ module GreenHat
|
|
158
166
|
return false
|
159
167
|
end
|
160
168
|
|
161
|
-
all = results.map { |row| Oj.dump(row) }
|
169
|
+
all = (save_greenhat_query_info + results).map { |row| Oj.dump(row) }
|
162
170
|
File.write(name, all.join("\n"))
|
163
171
|
puts "#{name.pastel(:green)} File Written!"
|
164
172
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module GreenHat
|
2
2
|
# Common Helpers
|
3
|
-
# rubocop:disable Metrics/ModuleLength
|
4
3
|
module ShellHelper
|
5
4
|
# Use File Process for Output
|
6
5
|
def self.file_output(files, flags = {})
|
@@ -95,109 +94,109 @@ module GreenHat
|
|
95
94
|
end
|
96
95
|
|
97
96
|
# Entry Shower / Top Level
|
98
|
-
def self.entry_show(flags, entry, key = nil)
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
end
|
97
|
+
# def self.entry_show(flags, entry, key = nil)
|
98
|
+
# LogBot.debug('Entry Show', entry.class) if ENV['DEBUG']
|
99
|
+
# case entry
|
100
|
+
# when Hash then render_table(entry, flags)
|
101
|
+
# when Float, Integer
|
102
|
+
# format_table_entry(flags, entry, key)
|
103
|
+
# # Ignore Special Formatting for Strings / Usually already formatted
|
104
|
+
# when String
|
105
|
+
# entry
|
106
|
+
# when Array
|
107
|
+
# render_array_table(entry, flags)
|
108
|
+
# else
|
109
|
+
# LogBot.warn('Shell Show', "Unknown #{entry.class}")
|
110
|
+
# nil
|
111
|
+
# end
|
112
|
+
# end
|
114
113
|
|
115
114
|
# Format Table Entries
|
116
|
-
def self.format_table_entry(flags, entry, key = nil)
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
rescue StandardError => e
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
end
|
148
|
-
|
149
|
-
def self.render_array_table(entry, flags)
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
end
|
164
|
-
|
165
|
-
# Print the Table in a Nice way
|
166
|
-
def self.render_table(entry, flags)
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
rescue StandardError => e
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
end
|
195
|
-
|
196
|
-
def self.render_table_entry(val, col_index, flags)
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
end
|
115
|
+
# def self.format_table_entry(flags, entry, key = nil)
|
116
|
+
# formatted_entry = case entry
|
117
|
+
# # Rounding
|
118
|
+
# when Float, Integer || entry.numeric?
|
119
|
+
# flags.key?(:round) ? entry.to_f.round(flags.round).ai : entry.ai
|
120
|
+
|
121
|
+
# # General Inspecting
|
122
|
+
# when Hash then entry.ai(ruby19_syntax: true)
|
123
|
+
|
124
|
+
# # Arrays often contain Hashes. Dangerous Recursive?
|
125
|
+
# when Array
|
126
|
+
# entry.map { |x| format_table_entry(flags, x) }.join("\n")
|
127
|
+
# when Time
|
128
|
+
# entry.to_s.pastel(:bright_white)
|
129
|
+
|
130
|
+
# # Default String Formatting
|
131
|
+
# else
|
132
|
+
# StringColor.do(key, entry)
|
133
|
+
# end
|
134
|
+
|
135
|
+
# # Stats truncation handled separately
|
136
|
+
# if flags[:truncate] && !flags[:stats]
|
137
|
+
# entry_truncate(formatted_entry, flags[:truncate])
|
138
|
+
# else
|
139
|
+
# formatted_entry
|
140
|
+
# end
|
141
|
+
# rescue StandardError => e
|
142
|
+
# if ENV['DEBUG']
|
143
|
+
# LogBot.warn('Table Format Entry', message: e.message)
|
144
|
+
# ap e.backtrace
|
145
|
+
# end
|
146
|
+
# end
|
147
|
+
|
148
|
+
# def self.render_array_table(entry, flags)
|
149
|
+
# table_style = flags[:table_style]&.to_sym || :unicode
|
150
|
+
# header, rows = entry
|
151
|
+
# table = TTY::Table.new(header: header, rows: rows)
|
152
|
+
|
153
|
+
# LogBot.debug('Rendering Entries') if ENV['DEBUG']
|
154
|
+
# output = table.render(table_style, padding: [0, 1, 0, 1], multiline: true) do |renderer|
|
155
|
+
# renderer.border.style = :cyan
|
156
|
+
# end
|
157
|
+
|
158
|
+
# # Line breaks for basic tables
|
159
|
+
# output += "\n" if flags[:table_style] == 'basic'
|
160
|
+
|
161
|
+
# output
|
162
|
+
# end
|
163
|
+
|
164
|
+
# # Print the Table in a Nice way
|
165
|
+
# def self.render_table(entry, flags)
|
166
|
+
# entry = entry.to_h { |k, v| [k, format_table_entry(flags, v, k)] }
|
167
|
+
# # Pre-format Entry
|
168
|
+
|
169
|
+
# table_style = flags[:table_style]&.to_sym || :unicode
|
170
|
+
|
171
|
+
# table = TTY::Table.new(header: entry.keys, rows: [entry], orientation: :vertical)
|
172
|
+
|
173
|
+
# LogBot.debug('Rendering Entries') if ENV['DEBUG']
|
174
|
+
# output = table.render(table_style, padding: [0, 1, 0, 1], multiline: true) do |renderer|
|
175
|
+
# renderer.border.style = :cyan
|
176
|
+
# end
|
177
|
+
|
178
|
+
# # Line breaks for basic tables
|
179
|
+
# output += "\n" if flags[:table_style] == 'basic'
|
180
|
+
|
181
|
+
# output
|
182
|
+
# rescue StandardError => e
|
183
|
+
# if ENV['DEBUG']
|
184
|
+
# LogBot.warn('Table', message: e.message)
|
185
|
+
# ap e.backtrace
|
186
|
+
# end
|
187
|
+
|
188
|
+
# [
|
189
|
+
# entry.ai,
|
190
|
+
# ('_' * (TTY::Screen.width / 3)).pastel(:cyan),
|
191
|
+
# "\n"
|
192
|
+
# ].join("\n")
|
193
|
+
# end
|
194
|
+
|
195
|
+
# def self.render_table_entry(val, col_index, flags)
|
196
|
+
# return val.to_s unless col_index == 1
|
197
|
+
|
198
|
+
# format_table_entry(flags, val)
|
199
|
+
# end
|
201
200
|
|
202
201
|
# Internal Query Helper
|
203
202
|
# query = 'gitlab-rails/application_json.log --message!="Cannot obtain an exclusive lease" --severity=error'
|
@@ -373,6 +372,4 @@ module GreenHat
|
|
373
372
|
puts
|
374
373
|
end
|
375
374
|
end
|
376
|
-
|
377
|
-
# rubocop:enable Metrics/ModuleLength
|
378
375
|
end
|
@@ -131,6 +131,13 @@ module GreenHat
|
|
131
131
|
%r{consul/current}
|
132
132
|
]
|
133
133
|
},
|
134
|
+
'consul/identify_primary_db_node.log' => {
|
135
|
+
format: :identify_db,
|
136
|
+
log: true,
|
137
|
+
pattern: [
|
138
|
+
%r{consul/identify_primary_db_node.log}
|
139
|
+
]
|
140
|
+
},
|
134
141
|
'gitlab-kas/current' => {
|
135
142
|
format: :time_space,
|
136
143
|
log: true,
|
@@ -223,12 +230,19 @@ module GreenHat
|
|
223
230
|
]
|
224
231
|
},
|
225
232
|
'gitlab-exporter/current' => {
|
226
|
-
format: :
|
233
|
+
format: :exporters,
|
227
234
|
log: true,
|
228
235
|
pattern: [
|
229
236
|
%r{gitlab-exporter/current}
|
230
237
|
]
|
231
238
|
},
|
239
|
+
'gitlab-rails/web_exporter' => {
|
240
|
+
format: :exporters,
|
241
|
+
log: true,
|
242
|
+
pattern: [
|
243
|
+
%r{gitlab-rails/web_exporter}
|
244
|
+
]
|
245
|
+
},
|
232
246
|
'gitlab-monitor/current' => {
|
233
247
|
format: :time_space,
|
234
248
|
log: true,
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# ==========================================================================
|
6
|
+
# General Exporter Parser
|
7
|
+
# https://gitlab.com/gitlab-com/support/toolbox/greenhat/-/issues/30
|
8
|
+
# [YYYY-MM-DDTHH:MM:SS.sss-HHMM] …ip… - - [DD/Mon/YYYY:HH:MM:SS ZON]
|
9
|
+
# "GET /metrics HTTP/1.1" 200 12345 "-" "Prometheus/2.25.0"
|
10
|
+
# ==========================================================================
|
11
|
+
def format_exporters
|
12
|
+
self.result = raw.map do |row|
|
13
|
+
result = {}
|
14
|
+
time, output = row.split(' ', 2)
|
15
|
+
result[:time] = Time.parse(time)
|
16
|
+
|
17
|
+
# Weird Edge Cases for when IP is not included
|
18
|
+
msg = ''
|
19
|
+
if output.include? '- - '
|
20
|
+
ip, msg = output.split('- -', 2)
|
21
|
+
result[:ip] = ip unless ip.empty?
|
22
|
+
else
|
23
|
+
msg = output
|
24
|
+
end
|
25
|
+
|
26
|
+
# Styrip Extra Time / Get Call Details
|
27
|
+
if msg&.include? ']'
|
28
|
+
_time, request = msg.split('] ', 2)
|
29
|
+
result[:msg] = request # Pass full request
|
30
|
+
|
31
|
+
# Breakout
|
32
|
+
method, path, protocol, status, bytes = request.gsub('"', '').split(' ', 5)
|
33
|
+
|
34
|
+
result.merge!(method: method, path: path, protocol: protocol, status: status, bytes: bytes)
|
35
|
+
|
36
|
+
else
|
37
|
+
result[:msg] = msg
|
38
|
+
end
|
39
|
+
|
40
|
+
result
|
41
|
+
rescue StandardError => e
|
42
|
+
# TODO: Background logger
|
43
|
+
LogBot.warn('Exporters', "Unable to Parse, #{row}:#{e.message}")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
# ==========================================================================
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# consul/identify_primary_db_node.log
|
6
|
+
# https://gitlab.com/gitlab-com/support/toolbox/greenhat/-/issues/33
|
7
|
+
# I, [YYYY-MM-DDThh:mm:ss.ssssss #12345] INFO -- : Found master: sub.domain.tld
|
8
|
+
def format_identify_db
|
9
|
+
self.result = raw.map do |row|
|
10
|
+
next if row.empty? || row == "\n"
|
11
|
+
|
12
|
+
level_abrv, row = row.split(', ', 2)
|
13
|
+
|
14
|
+
time, output = row.split('] ', 2)
|
15
|
+
time = Time.parse time.split('[', 2).last.strip
|
16
|
+
|
17
|
+
level, _a, _b, msg = output.split(' ', 4)
|
18
|
+
{
|
19
|
+
time: time,
|
20
|
+
i: level_abrv,
|
21
|
+
level: level,
|
22
|
+
message: msg
|
23
|
+
}
|
24
|
+
rescue StandardError => e
|
25
|
+
# TODO: Background logger
|
26
|
+
LogBot.warn('identify_db', "Unable to Parse, #{row}:#{e.message}")
|
27
|
+
end
|
28
|
+
|
29
|
+
result.compact!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/greenhat/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: greenhat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Davin Walker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-06-
|
11
|
+
date: 2022-06-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: amazing_print
|
@@ -513,10 +513,12 @@ files:
|
|
513
513
|
- lib/greenhat/thing/formatters/clean_raw.rb
|
514
514
|
- lib/greenhat/thing/formatters/colon_split_strip.rb
|
515
515
|
- lib/greenhat/thing/formatters/dotenv.rb
|
516
|
+
- lib/greenhat/thing/formatters/exporters.rb
|
516
517
|
- lib/greenhat/thing/formatters/format.rb
|
517
518
|
- lib/greenhat/thing/formatters/free_m.rb
|
518
519
|
- lib/greenhat/thing/formatters/gitlab_ctl_tail.rb
|
519
520
|
- lib/greenhat/thing/formatters/gitlab_status.rb
|
521
|
+
- lib/greenhat/thing/formatters/identify_db.rb
|
520
522
|
- lib/greenhat/thing/formatters/json.rb
|
521
523
|
- lib/greenhat/thing/formatters/json_shellwords.rb
|
522
524
|
- lib/greenhat/thing/formatters/kube_json.rb
|