greenhat 0.6.1 → 0.6.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 +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
|