greenhat 0.7.2 → 0.7.4
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/README.md +9 -1
- data/lib/greenhat/accessors/gitlab.rb +1 -1
- data/lib/greenhat/accessors/grep.rb +1 -1
- data/lib/greenhat/archive.rb +3 -3
- data/lib/greenhat/cli.rb +2 -2
- data/lib/greenhat/entrypoint.rb +1 -1
- data/lib/greenhat/host.rb +2 -2
- data/lib/greenhat/paper/paper_helper.rb +1 -1
- data/lib/greenhat/reports/internal_methods.rb +2 -2
- data/lib/greenhat/reports/reports/errors.rb +3 -1
- data/lib/greenhat/reports/reports/full.rb +10 -0
- data/lib/greenhat/reports/reports/production_log_duration.rb +1 -0
- data/lib/greenhat/reports/shell_helper.rb +17 -6
- data/lib/greenhat/reports.rb +3 -3
- data/lib/greenhat/shell/args.rb +3 -3
- data/lib/greenhat/shell/field_helper.rb +1 -1
- data/lib/greenhat/shell/filter_help.rb +2 -1
- data/lib/greenhat/shell/log.rb +1 -1
- data/lib/greenhat/shell/query.rb +10 -4
- data/lib/greenhat/shell/reports.rb +10 -1
- data/lib/greenhat/shell/shell_helper.rb +20 -39
- data/lib/greenhat/shell.rb +2 -2
- data/lib/greenhat/thing/file_types.rb +23 -0
- data/lib/greenhat/thing/formatters/api_json.rb +11 -4
- data/lib/greenhat/thing/formatters/exporters.rb +1 -1
- data/lib/greenhat/thing/formatters/gitlab_status.rb +1 -1
- data/lib/greenhat/thing/formatters/identify_db.rb +2 -2
- data/lib/greenhat/thing/formatters/json.rb +6 -0
- data/lib/greenhat/thing/formatters/json_shellwords.rb +12 -5
- data/lib/greenhat/thing/formatters/kube_nginx.rb +10 -10
- data/lib/greenhat/thing/formatters/nginx.rb +10 -10
- data/lib/greenhat/thing/formatters/runner_log.rb +5 -5
- data/lib/greenhat/thing/formatters/syslog.rb +4 -4
- data/lib/greenhat/thing/formatters/time_json.rb +1 -1
- data/lib/greenhat/thing/formatters/time_space.rb +1 -1
- data/lib/greenhat/thing/history.rb +1 -1
- data/lib/greenhat/thing/info_format.rb +2 -2
- data/lib/greenhat/thing/kind.rb +5 -1
- data/lib/greenhat/thing/spinner.rb +1 -1
- data/lib/greenhat/version.rb +1 -1
- data/lib/greenhat/web/faststats.rb +1 -1
- data/lib/greenhat/web/helpers.rb +1 -1
- metadata +11 -81
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a519d68faaec2994665e8c6e442923578d6a0f165a2213f3a5ef0e7e45b65903
|
4
|
+
data.tar.gz: 1a9f905cf1d9f8738a1658f932b5d14d8ef9964a0bb2360a5438460330e868d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e9f31443fdb9917069831fc89e39b97f198c3b298bb06b2331dc0788d2f7ca31e4ce65b1f69e0a89e82d6788e810fe0d344a5cb2c74b30aa53d3b7577442f96
|
7
|
+
data.tar.gz: 3534f35919122f6b01aaa1570429faf852dc4c91c3e170a55e693cc84207fa391cfb7ad2c85af4cca46a0d83adcbbfaa24ecf1db52bcfa76d08bf38d8c42ad83
|
data/README.md
CHANGED
@@ -12,6 +12,8 @@ Experimental SOS and Log Parser for GitLab
|
|
12
12
|
|
13
13
|
`apt-get install libarchive-tools`
|
14
14
|
|
15
|
+
Ruby 3.0 or later, including the headers (such as package `ruby-dev`)
|
16
|
+
|
15
17
|
## Installation
|
16
18
|
|
17
19
|
```
|
@@ -38,7 +40,7 @@ bundle exec rake
|
|
38
40
|
- Update CHANGELOG
|
39
41
|
- Increment `version.rb`
|
40
42
|
- Create MR
|
41
|
-
- Merge to
|
43
|
+
- Merge to `main`
|
42
44
|
|
43
45
|
```
|
44
46
|
# Build and Push
|
@@ -46,6 +48,12 @@ bundle exec rake build
|
|
46
48
|
gem push pkg/greenhat-1.x.x.gem
|
47
49
|
```
|
48
50
|
|
51
|
+
## Dev Troubleshooting
|
52
|
+
|
53
|
+
```
|
54
|
+
docker run -it -v ${PWD}:/app ruby:3.1.4 bash
|
55
|
+
```
|
56
|
+
|
49
57
|
## Contributing
|
50
58
|
|
51
59
|
Bug reports and merge requests are welcome on GitLab at https://gitlab.com/gitlab-com/support/toolbox/greenhat. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
data/lib/greenhat/archive.rb
CHANGED
@@ -24,9 +24,9 @@ module GreenHat
|
|
24
24
|
list = Find.find(path).reject { |x| File.directory?(x) || File.symlink?(x) }
|
25
25
|
|
26
26
|
# Ignore Empty Files
|
27
|
-
list.reject! { |x| File.
|
27
|
+
list.reject! { |x| File.empty?(x) }
|
28
28
|
|
29
|
-
archive = Archive.new(name: archive_path, path:
|
29
|
+
archive = Archive.new(name: archive_path, path:)
|
30
30
|
archive.save
|
31
31
|
|
32
32
|
list.each do |file|
|
@@ -34,7 +34,7 @@ module GreenHat
|
|
34
34
|
next if missing_command(file)
|
35
35
|
|
36
36
|
# Thread.new do
|
37
|
-
thing = archive.things_create(file:
|
37
|
+
thing = archive.things_create(file:)
|
38
38
|
thing.setup
|
39
39
|
# end
|
40
40
|
end
|
data/lib/greenhat/cli.rb
CHANGED
@@ -8,7 +8,7 @@ module GreenHat
|
|
8
8
|
value ||= '' # Empty Start
|
9
9
|
|
10
10
|
loop do
|
11
|
-
line = reader.read_line(readline_notch, value:
|
11
|
+
line = reader.read_line(readline_notch, value:)
|
12
12
|
value = '' # Remove Afterwards
|
13
13
|
|
14
14
|
if reader.breaker
|
@@ -169,7 +169,7 @@ module GreenHat
|
|
169
169
|
def self.did_you_mean
|
170
170
|
dictionary = current_methods + current_submodules + cmd_list
|
171
171
|
|
172
|
-
all = DidYouMean::SpellChecker.new(dictionary:
|
172
|
+
all = DidYouMean::SpellChecker.new(dictionary:).correct(cmd)
|
173
173
|
|
174
174
|
if all.empty?
|
175
175
|
puts [
|
data/lib/greenhat/entrypoint.rb
CHANGED
@@ -12,7 +12,7 @@ module GreenHat
|
|
12
12
|
load_files files
|
13
13
|
Cli.run_command(args) if args.any? { |arg| Cli.run_command?(arg) }
|
14
14
|
|
15
|
-
report_runner(args
|
15
|
+
report_runner(args:, files:, raw:, flags:)
|
16
16
|
post_args(flags)
|
17
17
|
post_setup(flags)
|
18
18
|
|
data/lib/greenhat/host.rb
CHANGED
@@ -152,7 +152,7 @@ class Host < Teron
|
|
152
152
|
obj[headers[i]] = v
|
153
153
|
end
|
154
154
|
end
|
155
|
-
{ headers
|
155
|
+
{ headers:, list: }
|
156
156
|
end
|
157
157
|
|
158
158
|
def systemctl_unit_files
|
@@ -161,7 +161,7 @@ class Host < Teron
|
|
161
161
|
|
162
162
|
all = file.raw[1..-2].map do |x|
|
163
163
|
unit, status = x.split
|
164
|
-
{ unit
|
164
|
+
{ unit:, status: }
|
165
165
|
end
|
166
166
|
|
167
167
|
all.reject! { |x| x[:unit].nil? }
|
@@ -105,7 +105,7 @@ module GreenHat
|
|
105
105
|
# --------------------------------------------------------------------------
|
106
106
|
def render_array_table(entry)
|
107
107
|
header, rows = entry
|
108
|
-
table = TTY::Table.new(header
|
108
|
+
table = TTY::Table.new(header:, rows:)
|
109
109
|
|
110
110
|
LogBot.debug('Rendering Entries') if ENV['DEBUG']
|
111
111
|
self.output = table.render(table_style, padding: [0, 1, 0, 1], multiline: true) do |renderer|
|
@@ -125,10 +125,10 @@ module GreenHat
|
|
125
125
|
def show(value)
|
126
126
|
if value.instance_of?(Array)
|
127
127
|
value.each do |x|
|
128
|
-
output.push GreenHat::Paper.new(data: x, flags:
|
128
|
+
output.push GreenHat::Paper.new(data: x, flags:).render
|
129
129
|
end
|
130
130
|
else
|
131
|
-
output.push GreenHat::Paper.new(data: value, flags:
|
131
|
+
output.push GreenHat::Paper.new(data: value, flags:).render
|
132
132
|
end
|
133
133
|
end
|
134
134
|
|
@@ -26,7 +26,9 @@ entries = [
|
|
26
26
|
stats: 'exception.class,exception.message,status' },
|
27
27
|
{ header: 'Gitaly', base: 'gitaly/current --level=error --truncate=99', stats: 'error' },
|
28
28
|
{ header: 'Praefect', base: 'praefect/current --level=error --truncate=99', stats: 'error' },
|
29
|
-
{ header: 'Pages', base: 'gitlab-pages/current --level=error', stats: 'error' }
|
29
|
+
{ header: 'Pages', base: 'gitlab-pages/current --level=error', stats: 'error' },
|
30
|
+
{ header: 'Geo', base: 'gitlab-rails/geo.log --severity=error', stats: 'message' },
|
31
|
+
{ header: 'Elasticsearch', base: 'gitlab-rails/elasticsearch.log --severity=error', stats: 'message' }
|
30
32
|
]
|
31
33
|
|
32
34
|
# Filter Logic
|
@@ -159,3 +159,13 @@ query_if_exists('gitlab-pages/current --level=error') do |data|
|
|
159
159
|
color = data.count.zero? ? :green : :red
|
160
160
|
indent("#{ljust('Pages:', 14, :magenta)} #{data.count.to_s.pastel(color)}", 4)
|
161
161
|
end
|
162
|
+
|
163
|
+
query_if_exists 'gitlab-rails/geo.log --severity=error' do |data|
|
164
|
+
color = data.count.zero? ? :green : :red
|
165
|
+
indent("#{ljust('Geo:', 14, :magenta)} #{data.count.to_s.pastel(color)}", 4)
|
166
|
+
end
|
167
|
+
|
168
|
+
query_if_exists 'gitlab-rails/elasticsearch.log --severity=error' do |data|
|
169
|
+
color = data.count.zero? ? :green : :red
|
170
|
+
indent("#{ljust('Elasticsearch:', 14, :magenta)} #{data.count.to_s.pastel(color)}", 4)
|
171
|
+
end
|
@@ -4,14 +4,25 @@ module GreenHat
|
|
4
4
|
module Reports
|
5
5
|
# Make Running more consistent
|
6
6
|
def self.run(file:, args:, flags:, raw_args:)
|
7
|
-
report = GreenHat::Reports::Builder.new(file
|
8
|
-
|
7
|
+
report = GreenHat::Reports::Builder.new(file:, args:, flags:, raw_args:)
|
8
|
+
|
9
|
+
# Fuzzy Match Archive Names
|
10
|
+
archives = Archive.all
|
11
|
+
if flags[:archive] && !flags[:archive].empty?
|
12
|
+
archives.select! do |a|
|
13
|
+
flags[:archive].any? do |x|
|
14
|
+
a.name.include? x.to_s
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
output = archives.map do |archive|
|
9
20
|
runner = GreenHat::Reports::Runner.new(
|
10
|
-
archive
|
21
|
+
archive:,
|
11
22
|
store: report.store.clone,
|
12
|
-
flags
|
13
|
-
args
|
14
|
-
raw_args:
|
23
|
+
flags:,
|
24
|
+
args:,
|
25
|
+
raw_args:
|
15
26
|
)
|
16
27
|
|
17
28
|
runner.run!
|
data/lib/greenhat/reports.rb
CHANGED
data/lib/greenhat/shell/args.rb
CHANGED
@@ -201,7 +201,8 @@ module GreenHat
|
|
201
201
|
table_style: [
|
202
202
|
'--table_style'.pastel(:green),
|
203
203
|
' Renderer used for formatted output. basic, ascii, or unicode(default)',
|
204
|
-
'
|
204
|
+
' Without any params this will result in basic',
|
205
|
+
' Ex: log filter --table_style=basic'
|
205
206
|
],
|
206
207
|
|
207
208
|
truncate: [
|
data/lib/greenhat/shell/log.rb
CHANGED
data/lib/greenhat/shell/query.rb
CHANGED
@@ -25,10 +25,13 @@ module GreenHat
|
|
25
25
|
files.reject(&:blank?).map do |file|
|
26
26
|
src = file.archive&.friendly_name || file&.name
|
27
27
|
file.data.map do |entry|
|
28
|
+
# Some entries are nil?
|
29
|
+
next if entry.nil?
|
30
|
+
|
28
31
|
bit = entry.clone
|
29
32
|
bit[:src] = src
|
30
33
|
bit
|
31
|
-
end
|
34
|
+
end.compact
|
32
35
|
end
|
33
36
|
end
|
34
37
|
|
@@ -164,6 +167,9 @@ module GreenHat
|
|
164
167
|
process_transform(flags[:transform], results) if flags.key? :transform
|
165
168
|
|
166
169
|
results.select! do |row|
|
170
|
+
# Skip Integers?
|
171
|
+
# next if row.is_a? Integer
|
172
|
+
|
167
173
|
args.send(flags.logic || :all?) do |arg|
|
168
174
|
filter_row_key(row, arg, flags)
|
169
175
|
end
|
@@ -185,7 +191,7 @@ module GreenHat
|
|
185
191
|
results = filter_except(results, flags[:except]) if flags.key?(:except)
|
186
192
|
|
187
193
|
# Remove Blank from either slice or except
|
188
|
-
results.reject!(&:
|
194
|
+
results.reject!(&:blank?)
|
189
195
|
|
190
196
|
# Sort / Reverse by default
|
191
197
|
if flags.key?(:sort)
|
@@ -372,7 +378,7 @@ module GreenHat
|
|
372
378
|
l95 = l95.round(flags.round) if flags.round
|
373
379
|
|
374
380
|
{
|
375
|
-
key
|
381
|
+
key:,
|
376
382
|
'99' => l99,
|
377
383
|
'95' => l95,
|
378
384
|
mean: flags.round ? values.mean.round(flags.round) : values.mean,
|
@@ -494,7 +500,7 @@ module GreenHat
|
|
494
500
|
match
|
495
501
|
end
|
496
502
|
rescue StandardError => e
|
497
|
-
LogBot.fatal('[Query] Filter Row Failure', message: e.message, backtrace: e.backtrace.first, row:
|
503
|
+
LogBot.fatal('[Query] Filter Row Failure', message: e.message, backtrace: e.backtrace.first, row:)
|
498
504
|
false
|
499
505
|
end
|
500
506
|
|
@@ -8,6 +8,15 @@ require 'greenhat/reports/shell_helper'
|
|
8
8
|
module GreenHat
|
9
9
|
# CLI Helper
|
10
10
|
module Shell
|
11
|
+
# Make `report` a default top layer command
|
12
|
+
def self.report(_raw = ['default'])
|
13
|
+
# Move
|
14
|
+
Cli.move_shell Shell::Reports
|
15
|
+
|
16
|
+
# Run
|
17
|
+
Reports.default ['full']
|
18
|
+
end
|
19
|
+
|
11
20
|
# Logs
|
12
21
|
module Reports
|
13
22
|
def self.auto_complete(_list, word)
|
@@ -48,7 +57,7 @@ module GreenHat
|
|
48
57
|
|
49
58
|
run_list.each do |file|
|
50
59
|
raw_args = list.reject { |x| file.include? x }
|
51
|
-
GreenHat::ShellHelper::Reports.run(file
|
60
|
+
GreenHat::ShellHelper::Reports.run(file:, args:, flags:, raw_args:)
|
52
61
|
end
|
53
62
|
end
|
54
63
|
end
|
@@ -85,7 +85,7 @@ module GreenHat
|
|
85
85
|
# Collect Class Objects for output
|
86
86
|
def self.create_ledger(data, flags)
|
87
87
|
data.map do |x|
|
88
|
-
Paper.new(data: x, flags:
|
88
|
+
Paper.new(data: x, flags:)
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
@@ -244,50 +244,31 @@ module GreenHat
|
|
244
244
|
[output]
|
245
245
|
end
|
246
246
|
|
247
|
-
#
|
248
|
-
|
249
|
-
|
250
|
-
# results.flat_map do |k, values|
|
251
|
-
# [k, total_count_array(values, flags)]
|
252
|
-
# end
|
253
|
-
# end
|
247
|
+
# Table Printer Helper
|
248
|
+
def self.fields_print(files)
|
249
|
+
fields = ShellHelper.find_things(files).map(&:fields).flatten.uniq
|
254
250
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
# return results.count if flags[:total] == 'simple'
|
251
|
+
# truncate = (TTY::Screen.width - columns) / columns
|
252
|
+
# fields.map! { |f| f[0..truncate] }
|
253
|
+
puts ShellHelper.field_table(fields)
|
259
254
|
|
260
|
-
|
261
|
-
|
262
|
-
# output[:duration] = Query.calculate_duration(results)
|
255
|
+
# ShellHelper.fields_print(files)
|
256
|
+
end
|
263
257
|
|
264
|
-
#
|
265
|
-
|
266
|
-
|
267
|
-
# output[:start] = list.first
|
268
|
-
# output[:end] = list.last
|
269
|
-
# end
|
258
|
+
# 5 Columns cause issues with resizing
|
259
|
+
def self.field_table(list, columns: 4)
|
260
|
+
return nil if list.empty?
|
270
261
|
|
271
|
-
|
272
|
-
|
262
|
+
# Split list into groups based on columns
|
263
|
+
groups = list.each_slice((list.size / columns.to_f).ceil).to_a
|
273
264
|
|
274
|
-
|
275
|
-
|
265
|
+
# Max Width for Table
|
266
|
+
truncate = (TTY::Screen.width - groups.count) / groups.count
|
276
267
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
puts k
|
281
|
-
puts field_table(v.map(&:keys).flatten.uniq.sort)
|
282
|
-
puts
|
268
|
+
# Process Truncation
|
269
|
+
groups.each do |group|
|
270
|
+
group.map! { |f| f[0..truncate]&.to_sym }
|
283
271
|
end
|
284
|
-
end
|
285
|
-
|
286
|
-
def self.field_table(list, columns = 4)
|
287
|
-
return nil if list.empty?
|
288
|
-
|
289
|
-
# Keep Alphabetical Sort
|
290
|
-
groups = list.each_slice((list.size / columns.to_f).round).to_a
|
291
272
|
|
292
273
|
table = TTY::Table.new do |t|
|
293
274
|
loop do
|
@@ -297,7 +278,7 @@ module GreenHat
|
|
297
278
|
end
|
298
279
|
end
|
299
280
|
|
300
|
-
table.render(:unicode, padding: [0, 1, 0, 1])
|
281
|
+
table.render(:unicode, padding: [0, 1, 0, 1], resize: false)
|
301
282
|
end
|
302
283
|
|
303
284
|
# Unified Files Interface
|
data/lib/greenhat/shell.rb
CHANGED
@@ -59,11 +59,11 @@ module GreenHat
|
|
59
59
|
file_list = Dir['/var/log/gitlab/*/current'] + Dir['/var/log/gitlab/*/*.log']
|
60
60
|
|
61
61
|
file_list.each do |file|
|
62
|
-
next if File.
|
62
|
+
next if File.empty?(file)
|
63
63
|
|
64
64
|
puts "- Loading #{file.pastel(:green)}"
|
65
65
|
|
66
|
-
archive.things_create(file:
|
66
|
+
archive.things_create(file:).setup
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
@@ -920,6 +920,12 @@ module GreenHat
|
|
920
920
|
/vmstat/
|
921
921
|
]
|
922
922
|
},
|
923
|
+
'date' => {
|
924
|
+
format: :raw,
|
925
|
+
pattern: [
|
926
|
+
/date/
|
927
|
+
]
|
928
|
+
},
|
923
929
|
'gitlab-kas/config' => {
|
924
930
|
format: :raw,
|
925
931
|
pattern: [
|
@@ -962,6 +968,12 @@ module GreenHat
|
|
962
968
|
/rpm_verify/
|
963
969
|
]
|
964
970
|
},
|
971
|
+
'gitlab_system_status' => {
|
972
|
+
format: :raw,
|
973
|
+
pattern: [
|
974
|
+
/gitlab_system_status/
|
975
|
+
]
|
976
|
+
},
|
965
977
|
'gitlab-rails/application.log' => {
|
966
978
|
format: :raw,
|
967
979
|
pattern: [
|
@@ -989,6 +1001,13 @@ module GreenHat
|
|
989
1001
|
%r{sidekiq/perf.data}
|
990
1002
|
]
|
991
1003
|
},
|
1004
|
+
'gitlab-rails/geo.log' => {
|
1005
|
+
format: :json,
|
1006
|
+
log: true,
|
1007
|
+
pattern: [
|
1008
|
+
%r{gitlab-rails/geo.log}
|
1009
|
+
]
|
1010
|
+
},
|
992
1011
|
|
993
1012
|
# ======================================================================
|
994
1013
|
# KubeSoS TODO Section
|
@@ -1014,6 +1033,10 @@ module GreenHat
|
|
1014
1033
|
'kubesos' => {
|
1015
1034
|
format: :raw,
|
1016
1035
|
pattern: [
|
1036
|
+
/license_info/,
|
1037
|
+
%r{etc/sshd_config},
|
1038
|
+
/btmp_size/,
|
1039
|
+
/user_uid/,
|
1017
1040
|
/all_values.yaml/,
|
1018
1041
|
%r{webservice.log/sidekiq_client.log},
|
1019
1042
|
/chart-version/,
|
@@ -8,19 +8,26 @@ module GreenHat
|
|
8
8
|
# Primarily for gitlab-rails/api_json.log
|
9
9
|
def format_api_json
|
10
10
|
self.result = raw.map do |row|
|
11
|
+
# Seeing regular edge cases where there is random new non-json
|
12
|
+
# at the beginning of a log / Attempt to save first entry
|
13
|
+
if row[0] != '{'
|
14
|
+
# Nothing to Escape Parse
|
15
|
+
next unless row.include?('{')
|
16
|
+
|
17
|
+
row = "{#{row.split('{', 2).last}"
|
18
|
+
end
|
19
|
+
|
11
20
|
result = Oj.load row
|
12
21
|
|
13
22
|
# Parsing Time
|
14
23
|
format_time(result)
|
15
24
|
|
16
|
-
# flatten_hash(result).sort.to_h
|
17
25
|
result
|
18
26
|
rescue StandardError => e
|
19
27
|
# TODO: Background Logger?
|
20
|
-
e.message
|
21
|
-
LogBot.warn('JSON Parse', e.message)
|
28
|
+
LogBot.warn('[API JSON] JSON Parse', "#{e.message}: #{row.inspect}")
|
22
29
|
next
|
23
|
-
end
|
30
|
+
end.compact
|
24
31
|
|
25
32
|
:ok
|
26
33
|
end
|
@@ -31,7 +31,7 @@ module GreenHat
|
|
31
31
|
# Breakout
|
32
32
|
method, path, protocol, status, bytes = request.gsub('"', '').split(' ', 5)
|
33
33
|
|
34
|
-
result.merge!(method
|
34
|
+
result.merge!(method:, path:, protocol:, status:, bytes:)
|
35
35
|
|
36
36
|
else
|
37
37
|
result[:msg] = msg
|
@@ -14,6 +14,9 @@ module GreenHat
|
|
14
14
|
{ message: row }
|
15
15
|
end
|
16
16
|
|
17
|
+
# Skip bad results
|
18
|
+
next if result.nil?
|
19
|
+
|
17
20
|
# Parsing Time / Recusrive is really slow
|
18
21
|
format_time(result)
|
19
22
|
|
@@ -47,6 +50,9 @@ module GreenHat
|
|
47
50
|
|
48
51
|
# Loop through potential fields and parse as needed
|
49
52
|
def format_time(result)
|
53
|
+
# Don't format integers
|
54
|
+
# return if result.is_a? Integer
|
55
|
+
|
50
56
|
format_time_fields.each do |field|
|
51
57
|
result[field] = format_time_parse(result[field]) if result.key?(field)
|
52
58
|
rescue StandardError => e
|
@@ -7,11 +7,7 @@ module GreenHat
|
|
7
7
|
# ==========================================================================
|
8
8
|
def format_json_shell
|
9
9
|
self.result = raw.map do |row|
|
10
|
-
result =
|
11
|
-
Oj.load row
|
12
|
-
rescue EncodingError
|
13
|
-
json_shellwords_fallback row
|
14
|
-
end
|
10
|
+
result = format_json_row(row)
|
15
11
|
|
16
12
|
# Parsing Time
|
17
13
|
format_time(result)
|
@@ -25,6 +21,17 @@ module GreenHat
|
|
25
21
|
:ok
|
26
22
|
end
|
27
23
|
|
24
|
+
# Simplify Map Loop / Short Circuit for weird entries
|
25
|
+
def format_json_row(row)
|
26
|
+
return { message: row } if row[0] != '{' && !row.include?('{')
|
27
|
+
|
28
|
+
begin
|
29
|
+
Oj.load row
|
30
|
+
rescue EncodingError
|
31
|
+
json_shellwords_fallback row
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
28
35
|
def json_shellwords_fallback(row)
|
29
36
|
result = Shellwords.split(row).each_with_object({}) do |x, h|
|
30
37
|
key, value = x.split('=')
|
@@ -18,16 +18,16 @@ module GreenHat
|
|
18
18
|
|
19
19
|
{
|
20
20
|
remote_addr: ip,
|
21
|
-
remote_user
|
22
|
-
method
|
23
|
-
path
|
24
|
-
status
|
25
|
-
bytes
|
26
|
-
http_version
|
27
|
-
http_referer
|
28
|
-
http_user_agent
|
29
|
-
gzip_ratio
|
30
|
-
time:
|
21
|
+
remote_user:,
|
22
|
+
method:,
|
23
|
+
path:,
|
24
|
+
status:,
|
25
|
+
bytes:,
|
26
|
+
http_version:,
|
27
|
+
http_referer:,
|
28
|
+
http_user_agent:,
|
29
|
+
gzip_ratio:,
|
30
|
+
time:
|
31
31
|
}
|
32
32
|
|
33
33
|
# Fall back for malformed logs
|
@@ -21,16 +21,16 @@ module GreenHat
|
|
21
21
|
|
22
22
|
{
|
23
23
|
remote_addr: ip,
|
24
|
-
remote_user
|
25
|
-
method
|
26
|
-
path
|
27
|
-
status
|
28
|
-
bytes
|
29
|
-
http_version
|
30
|
-
http_referer
|
31
|
-
http_user_agent
|
32
|
-
gzip_ratio
|
33
|
-
time:
|
24
|
+
remote_user:,
|
25
|
+
method:,
|
26
|
+
path:,
|
27
|
+
status:,
|
28
|
+
bytes:,
|
29
|
+
http_version:,
|
30
|
+
http_referer:,
|
31
|
+
http_user_agent:,
|
32
|
+
gzip_ratio:,
|
33
|
+
time:
|
34
34
|
}
|
35
35
|
rescue StandardError => e
|
36
36
|
LogBot.warn('NGINX Parse', e.message)
|
@@ -23,11 +23,11 @@ module GreenHat
|
|
23
23
|
|
24
24
|
entry = {
|
25
25
|
time: format_time_parse("#{month} #{day} #{time}"),
|
26
|
-
device
|
27
|
-
service
|
28
|
-
message
|
29
|
-
pid
|
30
|
-
row:
|
26
|
+
device:,
|
27
|
+
service:,
|
28
|
+
message:,
|
29
|
+
pid:,
|
30
|
+
row: # Insert full row for different timestamp formats
|
31
31
|
}
|
32
32
|
|
33
33
|
# Remove Empty Keys
|
@@ -103,7 +103,7 @@ module GreenHat
|
|
103
103
|
obj[headers[i]] = v
|
104
104
|
end
|
105
105
|
end
|
106
|
-
{ headers
|
106
|
+
{ headers:, list: }
|
107
107
|
end
|
108
108
|
|
109
109
|
def manifest_json_format
|
@@ -150,7 +150,7 @@ module GreenHat
|
|
150
150
|
|
151
151
|
all = info.systemctl_unit_files[1..-2].map do |x|
|
152
152
|
unit, status = x.split
|
153
|
-
{ unit
|
153
|
+
{ unit:, status: }
|
154
154
|
end
|
155
155
|
all.reject! { |x| x[:unit].nil? }
|
156
156
|
all.sort_by(&:unit)
|
data/lib/greenhat/thing/kind.rb
CHANGED
@@ -44,7 +44,11 @@ module GreenHat
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def check_oj_parse?(first_line)
|
47
|
-
Oj.load(first_line)
|
47
|
+
result = Oj.load(first_line)
|
48
|
+
|
49
|
+
# Extra Validation (Oj is being more generous than we want)
|
50
|
+
return false if result.is_a? Integer
|
51
|
+
|
48
52
|
true
|
49
53
|
rescue StandardError
|
50
54
|
false
|
@@ -9,7 +9,7 @@ module GreenHat
|
|
9
9
|
@spinner = TTY::Spinner.new(
|
10
10
|
"#{time.pastel(:bright_black)} - [:spinner] :title", hide_cursor: true, success_mark: '✔'.pastel(:green)
|
11
11
|
)
|
12
|
-
@spinner.update(title:
|
12
|
+
@spinner.update(title:)
|
13
13
|
|
14
14
|
# Don't Auto spin when debug output is happening
|
15
15
|
@spinner.auto_spin unless ENV['DEBUG']
|
data/lib/greenhat/version.rb
CHANGED
@@ -29,7 +29,7 @@ module WebHelpers
|
|
29
29
|
|
30
30
|
# Handle Short Results
|
31
31
|
top = results.dig(kind, :stats).sort_by { |_k, v| v[:duration] }
|
32
|
-
top = top
|
32
|
+
top = top[-10..] if top.size >= 10
|
33
33
|
|
34
34
|
top.to_h.map do |k, v|
|
35
35
|
count_perc = percent(v[:count], count)
|
data/lib/greenhat/web/helpers.rb
CHANGED
metadata
CHANGED
@@ -1,101 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: greenhat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Davin Walker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: actionview
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1
|
19
|
+
version: '6.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: bundler
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :development
|
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: minitest
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '5.14'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '5.14'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: minitest-reporters
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '1.4'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '1.4'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: rake
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '13.0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '13.0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rubocop
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '1.0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '1.0'
|
26
|
+
version: '6.1'
|
97
27
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
28
|
+
name: activesupport
|
99
29
|
requirement: !ruby/object:Gem::Requirement
|
100
30
|
requirements:
|
101
31
|
- - "~>"
|
@@ -109,19 +39,19 @@ dependencies:
|
|
109
39
|
- !ruby/object:Gem::Version
|
110
40
|
version: '6.1'
|
111
41
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
42
|
+
name: amazing_print
|
113
43
|
requirement: !ruby/object:Gem::Requirement
|
114
44
|
requirements:
|
115
45
|
- - "~>"
|
116
46
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
47
|
+
version: '1.3'
|
118
48
|
type: :runtime
|
119
49
|
prerelease: false
|
120
50
|
version_requirements: !ruby/object:Gem::Requirement
|
121
51
|
requirements:
|
122
52
|
- - "~>"
|
123
53
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
54
|
+
version: '1.3'
|
125
55
|
- !ruby/object:Gem::Dependency
|
126
56
|
name: chartkick
|
127
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -609,14 +539,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
609
539
|
requirements:
|
610
540
|
- - ">="
|
611
541
|
- !ruby/object:Gem::Version
|
612
|
-
version:
|
542
|
+
version: '3'
|
613
543
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
614
544
|
requirements:
|
615
545
|
- - ">="
|
616
546
|
- !ruby/object:Gem::Version
|
617
547
|
version: '0'
|
618
548
|
requirements: []
|
619
|
-
rubygems_version: 3.
|
549
|
+
rubygems_version: 3.3.26
|
620
550
|
signing_key:
|
621
551
|
specification_version: 4
|
622
552
|
summary: GitLab SOS Tool
|