greenhat 0.3.5 → 0.3.6
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/accessors/disk.rb +1 -3
- data/lib/greenhat/accessors/gitlab.rb +5 -2
- data/lib/greenhat/archive.rb +7 -2
- data/lib/greenhat/cli.rb +36 -0
- data/lib/greenhat/host.rb +25 -37
- data/lib/greenhat/shell/args.rb +22 -9
- data/lib/greenhat/shell/faststats.rb +23 -3
- data/lib/greenhat/shell/field_helper.rb +1 -1
- data/lib/greenhat/shell/filter_help.rb +32 -10
- data/lib/greenhat/shell/log.rb +142 -7
- data/lib/greenhat/shell/markdown.rb +16 -8
- data/lib/greenhat/shell/old_search_helper.rb +54 -0
- data/lib/greenhat/shell/page.rb +1 -1
- data/lib/greenhat/shell/pipe.rb +31 -0
- data/lib/greenhat/shell/platform.rb +28 -0
- data/lib/greenhat/shell/report.rb +47 -15
- data/lib/greenhat/shell/shell_helper.rb +92 -101
- data/lib/greenhat/shell.rb +7 -0
- data/lib/greenhat/thing/file_types.rb +28 -0
- data/lib/greenhat/thing/formatters/json.rb +4 -0
- data/lib/greenhat/thing/formatters/nginx.rb +6 -2
- data/lib/greenhat/thing/formatters/time_space.rb +0 -16
- data/lib/greenhat/thing/helpers.rb +12 -0
- data/lib/greenhat/thing.rb +10 -0
- data/lib/greenhat/version.rb +1 -1
- data/lib/greenhat/views/api.slim +55 -0
- data/lib/greenhat/views/chart.slim +42 -0
- data/lib/greenhat/views/chart_template.slim +31 -0
- data/lib/greenhat/views/chartkick.js +21 -0
- data/lib/greenhat/views/css.slim +47 -0
- data/lib/greenhat/views/gitaly.slim +53 -0
- data/lib/greenhat/views/headers.slim +16 -0
- data/lib/greenhat/views/index-old.slim +51 -0
- data/lib/greenhat/views/index.slim +14 -14
- data/lib/greenhat/views/info.slim +17 -18
- data/lib/greenhat/views/production.slim +55 -0
- data/lib/greenhat/views/sidekiq.slim +55 -0
- data/lib/greenhat/views/time.slim +63 -0
- data/lib/greenhat/views/workhorse.slim +16 -0
- data/lib/greenhat/web/api.rb +94 -0
- data/lib/greenhat/web/chartkick_shim.rb +14 -0
- data/lib/greenhat/web/faststats.rb +44 -0
- data/lib/greenhat/web/gitaly.rb +65 -0
- data/lib/greenhat/web/helpers.rb +198 -0
- data/lib/greenhat/web/production.rb +104 -0
- data/lib/greenhat/web/sidekiq.rb +73 -0
- data/lib/greenhat/web/stats_helpers.rb +74 -0
- data/lib/greenhat/web/time.rb +36 -0
- data/lib/greenhat/web/workhorse.rb +43 -0
- data/lib/greenhat/web.rb +63 -19
- data/lib/greenhat.rb +1 -0
- metadata +68 -2
@@ -103,7 +103,8 @@ module GreenHat
|
|
103
103
|
StringColor.do(key, entry)
|
104
104
|
end
|
105
105
|
|
106
|
-
|
106
|
+
# Stats truncation handled separately
|
107
|
+
if flags[:truncate] && !flags[:stats]
|
107
108
|
entry_truncate(formatted_entry, flags[:truncate])
|
108
109
|
else
|
109
110
|
formatted_entry
|
@@ -157,6 +158,9 @@ module GreenHat
|
|
157
158
|
files, flags, args = Args.parse(Shellwords.split(search))
|
158
159
|
flags[:combine] = true
|
159
160
|
|
161
|
+
# Default to everything
|
162
|
+
files = Thing.all.map(&:name) if files.empty?
|
163
|
+
|
160
164
|
ShellHelper.filter_start(files, flags, args)
|
161
165
|
end
|
162
166
|
|
@@ -177,11 +181,17 @@ module GreenHat
|
|
177
181
|
|
178
182
|
# Include Total Count in Name
|
179
183
|
results = ShellHelper.filter(log.data, flags, args)
|
184
|
+
duration = calculate_duration(results)
|
185
|
+
|
180
186
|
title = [
|
181
187
|
log.friendly_name,
|
182
188
|
" #{results.count}".pastel(:bright_black)
|
189
|
+
|
183
190
|
]
|
184
191
|
|
192
|
+
# Append Duration
|
193
|
+
title.push(" #{duration.pastel(:cyan, :dim)}") unless duration.blank?
|
194
|
+
|
185
195
|
# Save unless empty
|
186
196
|
obj[title.join] = results unless results.count.zero?
|
187
197
|
|
@@ -190,6 +200,31 @@ module GreenHat
|
|
190
200
|
end
|
191
201
|
end
|
192
202
|
|
203
|
+
def self.calculate_duration(results)
|
204
|
+
only_with_time = results.select(&:time)
|
205
|
+
|
206
|
+
# If slice is used ignore
|
207
|
+
return nil if only_with_time.empty?
|
208
|
+
|
209
|
+
sorted = only_with_time.map(&:time).sort
|
210
|
+
humanize_time(sorted.first, sorted.last)
|
211
|
+
end
|
212
|
+
|
213
|
+
# Replace TimeDifference with https://stackoverflow.com/a/4136485/1678507
|
214
|
+
def self.humanize_time(time_start, time_end, increments = 2)
|
215
|
+
miliseconds = (time_end - time_start) * 1000
|
216
|
+
|
217
|
+
list = [[1000, :ms], [60, :s], [60, :m], [24, :h]].map do |count, name|
|
218
|
+
next unless miliseconds.positive?
|
219
|
+
|
220
|
+
miliseconds, n = miliseconds.divmod(count)
|
221
|
+
|
222
|
+
"#{n.to_i}#{name}" unless n.to_i.zero?
|
223
|
+
end
|
224
|
+
|
225
|
+
list.compact.reverse[0..increments - 1].join(' ')
|
226
|
+
end
|
227
|
+
|
193
228
|
# Filter Logic
|
194
229
|
# TODO: Simplify
|
195
230
|
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
@@ -265,7 +300,6 @@ module GreenHat
|
|
265
300
|
end
|
266
301
|
|
267
302
|
# Filter Start and End Times
|
268
|
-
# rubocop:disable Metrics/MethodLength
|
269
303
|
# TODO: This is a bit icky, simplify/dry
|
270
304
|
def self.filter_time(results, flags)
|
271
305
|
if flags.key?(:start)
|
@@ -302,7 +336,6 @@ module GreenHat
|
|
302
336
|
|
303
337
|
results
|
304
338
|
end
|
305
|
-
# rubocop:enable Metrics/MethodLength
|
306
339
|
|
307
340
|
def self.filter_except(results, except)
|
308
341
|
# Avoid Empty Results
|
@@ -380,6 +413,9 @@ module GreenHat
|
|
380
413
|
stats.map do |field|
|
381
414
|
occurrences = filter_count_occurrences(results, field, flags)
|
382
415
|
|
416
|
+
# Use Truncate For Long Keys
|
417
|
+
occurrences.transform_keys! { |key| key.to_s[0..flags[:truncate]] } if flags[:truncate]
|
418
|
+
|
383
419
|
# Total Occurences
|
384
420
|
total = occurrences.values.sum
|
385
421
|
|
@@ -397,13 +433,6 @@ module GreenHat
|
|
397
433
|
# Append Header / Total with field name
|
398
434
|
output.unshift([field.to_s.pastel(:bright_black), total])
|
399
435
|
|
400
|
-
# Use Truncate For Long Keys
|
401
|
-
if flags[:truncate]
|
402
|
-
output.map! do |key, value|
|
403
|
-
[key.to_s[0..flags[:truncate]], value]
|
404
|
-
end
|
405
|
-
end
|
406
|
-
|
407
436
|
# Format
|
408
437
|
output.to_h
|
409
438
|
end
|
@@ -443,48 +472,83 @@ module GreenHat
|
|
443
472
|
end
|
444
473
|
|
445
474
|
# Break out filter row logic into separate method
|
446
|
-
|
447
475
|
def self.filter_row_key(row, arg, flags)
|
448
476
|
# Ignore Other Logic if Field isn't even included / Full Text Searching
|
449
477
|
return false unless row.key?(arg[:field]) || arg[:field] == :text
|
450
478
|
|
451
479
|
# Sensitivity Check / Check for Match / Full Text Searching
|
452
|
-
|
453
|
-
|
454
|
-
else
|
455
|
-
filter_row_entry(row[arg.field].to_s, arg, flags)
|
456
|
-
end
|
480
|
+
search_data = arg[:field] == :text ? row : row[arg.field]
|
481
|
+
match = filter_row_entry(search_data.to_s, arg, flags)
|
457
482
|
|
458
483
|
# Pivot of off include vs exclude
|
459
484
|
if arg.bang
|
460
|
-
!
|
485
|
+
!match
|
461
486
|
else
|
462
|
-
|
487
|
+
match
|
463
488
|
end
|
464
489
|
end
|
465
490
|
|
466
491
|
# Field Partial / Case / Exact search
|
467
492
|
def self.filter_row_entry(entry, arg, flags)
|
468
493
|
# Exact Matching / Unless doing full text search
|
469
|
-
return entry
|
494
|
+
return entry == arg.value.to_s if flags.key?(:exact) && arg.field != :text
|
470
495
|
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
496
|
+
# Cast to String/Integer Helper
|
497
|
+
entry, value = filter_entry_cast(entry, arg, flags)
|
498
|
+
|
499
|
+
entry.send(arg.logic, value)
|
500
|
+
end
|
501
|
+
|
502
|
+
# Handle casting to strings or integers
|
503
|
+
def self.filter_entry_cast(entry, arg, flags)
|
504
|
+
# Cast to String
|
505
|
+
value = arg.value.to_s
|
506
|
+
|
507
|
+
case arg.logic
|
508
|
+
when :include?
|
509
|
+
|
510
|
+
# Exact Case argument
|
511
|
+
unless flags.key?(:case)
|
512
|
+
entry.downcase!
|
513
|
+
value.downcase!
|
514
|
+
end
|
515
|
+
when :>=, :<=
|
516
|
+
entry = entry.to_i if entry.numeric?
|
517
|
+
value = value.to_i if value&.numeric?
|
475
518
|
end
|
519
|
+
|
520
|
+
[entry, value]
|
521
|
+
end
|
522
|
+
|
523
|
+
def self.filter_entry_logic(entry, arg)
|
524
|
+
entry.send(arg.logic, arg.value)
|
476
525
|
end
|
477
526
|
|
478
527
|
# Total Count Helper
|
479
|
-
def self.total_count(results)
|
480
|
-
results.
|
528
|
+
def self.total_count(results, flags)
|
529
|
+
results.map do |k, v|
|
481
530
|
puts k
|
482
|
-
puts "Total: #{v.count.to_s.pastel(:blue)}"
|
531
|
+
# puts "Total: #{v.count.to_s.pastel(:blue)}"
|
532
|
+
# puts "Time Covered: #{calculate_duration(v).pastel(:cyan)}"
|
533
|
+
|
534
|
+
output = {}
|
535
|
+
output[:total] = v.count
|
536
|
+
output[:duration] = calculate_duration(v)
|
537
|
+
|
538
|
+
# Sort / Get first and Last
|
539
|
+
list = v.select(&:time).map(&:time)
|
540
|
+
unless list.blank?
|
541
|
+
output[:start] = list.first
|
542
|
+
output[:end] = list.last
|
543
|
+
end
|
544
|
+
|
545
|
+
puts render_table(output, flags)
|
546
|
+
|
483
547
|
puts
|
484
548
|
end
|
485
549
|
end
|
486
550
|
|
487
|
-
#
|
551
|
+
# Table Printer Helper
|
488
552
|
def self.fields_print(results)
|
489
553
|
results.each do |k, v|
|
490
554
|
puts k
|
@@ -548,7 +612,7 @@ module GreenHat
|
|
548
612
|
return file if file.instance_of?(Thing)
|
549
613
|
|
550
614
|
if flags.fuzzy_file_match
|
551
|
-
Thing.all.select { |x| x.name.include? file }
|
615
|
+
Thing.all.select { |x| x.name.include?(file) || x.type.include?(file) }
|
552
616
|
else
|
553
617
|
Thing.where name: file
|
554
618
|
end
|
@@ -560,62 +624,6 @@ module GreenHat
|
|
560
624
|
things
|
561
625
|
end
|
562
626
|
|
563
|
-
# Main Entry Point for Searching
|
564
|
-
# def self.search_start(log_list, filter_type, args, opts)
|
565
|
-
def self.search_start(files, flags, args)
|
566
|
-
# Convert to Things
|
567
|
-
logs = ShellHelper.find_things(files, flags)
|
568
|
-
|
569
|
-
logs.each_with_object({}) do |log, obj|
|
570
|
-
# Ignore Empty Results / No Thing
|
571
|
-
next if log&.data.blank?
|
572
|
-
|
573
|
-
obj[log.friendly_name] = ShellHelper.search(log.data, flags, args)
|
574
|
-
|
575
|
-
obj
|
576
|
-
end
|
577
|
-
end
|
578
|
-
|
579
|
-
# Generic Search Helper / String/Regex
|
580
|
-
def self.search(data, flags = {}, args = {})
|
581
|
-
results = data.clone.flatten.compact
|
582
|
-
results.select! do |row|
|
583
|
-
args.send(flags.logic) do |arg|
|
584
|
-
search_row(row, arg, flags)
|
585
|
-
end
|
586
|
-
end
|
587
|
-
|
588
|
-
# Strip Results if Slice is defined
|
589
|
-
results.map! { |row| row.slice(*flags[:slice]) } if flags[:slice]
|
590
|
-
|
591
|
-
# Strip Results if Except is defined
|
592
|
-
results.map! { |row| row.except(*flags[:except]) } if flags[:except]
|
593
|
-
|
594
|
-
# Remove Blank from either slice or except
|
595
|
-
results.reject!(&:empty?)
|
596
|
-
|
597
|
-
results
|
598
|
-
end
|
599
|
-
|
600
|
-
# Break out filter row logic into separate method
|
601
|
-
def self.search_row(row, arg, flags)
|
602
|
-
# Sensitivity Check / Check for Match
|
603
|
-
included = filter_row_entry(row.to_s, arg, flags)
|
604
|
-
|
605
|
-
# Pivot of off include vs exclude
|
606
|
-
if arg.bang
|
607
|
-
!included
|
608
|
-
else
|
609
|
-
included
|
610
|
-
end
|
611
|
-
end
|
612
|
-
|
613
|
-
# TODO: Remove?
|
614
|
-
# Color Reader Helper
|
615
|
-
# def self.pastel
|
616
|
-
# @pastel ||= Pastel.new
|
617
|
-
# end
|
618
|
-
|
619
627
|
# Number Helper
|
620
628
|
# https://gitlab.com/zedtux/human_size_to_number/-/blob/master/lib/human_size_to_number/helper.rb
|
621
629
|
def self.human_size_to_number(string)
|
@@ -637,23 +645,6 @@ module GreenHat
|
|
637
645
|
number.round
|
638
646
|
end
|
639
647
|
|
640
|
-
# TODO: Needed?
|
641
|
-
def self.filter_and(data, params = {})
|
642
|
-
result = data.clone.flatten.compact
|
643
|
-
params.each do |k, v|
|
644
|
-
result.select! do |row|
|
645
|
-
if row.key? k.to_sym
|
646
|
-
row[k.to_sym].include? v
|
647
|
-
else
|
648
|
-
false
|
649
|
-
end
|
650
|
-
end
|
651
|
-
next
|
652
|
-
end
|
653
|
-
|
654
|
-
result
|
655
|
-
end
|
656
|
-
|
657
648
|
# General Helper for `show`
|
658
649
|
def self.common_opts
|
659
650
|
puts 'Common Options'.pastel(:blue)
|
data/lib/greenhat/shell.rb
CHANGED
@@ -357,6 +357,13 @@ module GreenHat
|
|
357
357
|
/nginx-ingress.log/
|
358
358
|
]
|
359
359
|
},
|
360
|
+
'nginx/access.log' => {
|
361
|
+
format: :nginx,
|
362
|
+
log: true,
|
363
|
+
pattern: [
|
364
|
+
%r{nginx/access.log}
|
365
|
+
]
|
366
|
+
},
|
360
367
|
'nginx/gitlab_pages_access.log' => {
|
361
368
|
format: :nginx,
|
362
369
|
log: true,
|
@@ -552,6 +559,20 @@ module GreenHat
|
|
552
559
|
%r{unicorn/current}
|
553
560
|
]
|
554
561
|
},
|
562
|
+
'unicorn_stats' => {
|
563
|
+
format: :time_space,
|
564
|
+
log: true,
|
565
|
+
pattern: [
|
566
|
+
/unicorn_stats/
|
567
|
+
]
|
568
|
+
},
|
569
|
+
'unicorn/unicorn_stdout.log' => {
|
570
|
+
format: :raw,
|
571
|
+
log: true,
|
572
|
+
pattern: [
|
573
|
+
%r{unicorn/unicorn_stdout.log}
|
574
|
+
]
|
575
|
+
},
|
555
576
|
'running_swappiness' => {
|
556
577
|
format: :raw,
|
557
578
|
pattern: [
|
@@ -589,6 +610,7 @@ module GreenHat
|
|
589
610
|
log: true,
|
590
611
|
pattern: [
|
591
612
|
%r{sidekiq/current},
|
613
|
+
/sidekiq_current/,
|
592
614
|
%r{sidekiq/@.*}
|
593
615
|
]
|
594
616
|
},
|
@@ -652,6 +674,12 @@ module GreenHat
|
|
652
674
|
/uname/
|
653
675
|
]
|
654
676
|
},
|
677
|
+
'gitlab_socket_stats' => {
|
678
|
+
format: :gitlab_socket_stats,
|
679
|
+
pattern: [
|
680
|
+
/gitlab_socket_stats/
|
681
|
+
]
|
682
|
+
},
|
655
683
|
'uptime' => {
|
656
684
|
format: :raw,
|
657
685
|
pattern: [
|
@@ -43,6 +43,10 @@ module GreenHat
|
|
43
43
|
# Check for Common Fields
|
44
44
|
def format_json_time(result)
|
45
45
|
result.time = format_time_parse(result.time) if result.key? :time
|
46
|
+
|
47
|
+
# If timestamp exists but time doesn't, add time
|
48
|
+
result.time = format_time_parse(result.timestamp) if result.key?(:timestamp) && !result.key?(:time)
|
49
|
+
|
46
50
|
result.created_at = format_time_parse(result.created_at) if result.key? :created_at
|
47
51
|
result.enqueued_at = format_time_parse(result.enqueued_at) if result.key? :enqueued_at
|
48
52
|
rescue StandardError => e
|
@@ -7,10 +7,11 @@ module GreenHat
|
|
7
7
|
# ==========================================================================
|
8
8
|
def format_nginx
|
9
9
|
self.result = raw.map do |row|
|
10
|
-
|
10
|
+
conn_data, rest = row.split(' [', 2)
|
11
|
+
ip, _sym, remote_user = conn_data.split(' ', 3)
|
11
12
|
|
12
13
|
time, rest = rest.split(']', 2)
|
13
|
-
time = Time.strptime(time, '
|
14
|
+
time = Time.strptime(time, '%d/%b/%Y:%H:%M:%S %z')
|
14
15
|
|
15
16
|
verb, status, bytes, http_referer, http_user_agent, gzip_ratio = Shellwords.split(rest)
|
16
17
|
|
@@ -29,6 +30,9 @@ module GreenHat
|
|
29
30
|
gzip_ratio: gzip_ratio,
|
30
31
|
time: time
|
31
32
|
}
|
33
|
+
rescue StandardError => e
|
34
|
+
LogBot.warn('NGINX Parse', e.message)
|
35
|
+
{ msg: row }
|
32
36
|
end
|
33
37
|
|
34
38
|
:ok
|
@@ -18,19 +18,3 @@ module GreenHat
|
|
18
18
|
# ==========================================================================
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
22
|
-
# def time_space
|
23
|
-
# IO.foreach(file) do |row|
|
24
|
-
# time, msg = row.split(' ', 2)
|
25
|
-
# result = {
|
26
|
-
# time: parse_datetime(time), msg: msg, host: thing.host,
|
27
|
-
# source: path_format
|
28
|
-
# }
|
29
|
-
|
30
|
-
# result[:time] ||= datetime
|
31
|
-
# post result
|
32
|
-
# rescue StandardError => e
|
33
|
-
# puts "Unable to Parse, #{name}:#{e.message}"
|
34
|
-
# post(time: datetime, msg: row, source: path_format, host: thing.host)
|
35
|
-
# end
|
36
|
-
# end
|
@@ -69,3 +69,15 @@ class FalseClass
|
|
69
69
|
0
|
70
70
|
end
|
71
71
|
end
|
72
|
+
|
73
|
+
# https://stackoverflow.com/a/449322/1678507
|
74
|
+
class Time
|
75
|
+
# Time#round already exists with different meaning in Ruby 1.9
|
76
|
+
def round_off(seconds = 60)
|
77
|
+
Time.at((to_f / seconds).round * seconds).utc
|
78
|
+
end
|
79
|
+
|
80
|
+
def floor(seconds = 60)
|
81
|
+
Time.at((to_f / seconds).floor * seconds).utc
|
82
|
+
end
|
83
|
+
end
|
data/lib/greenhat/thing.rb
CHANGED
@@ -140,4 +140,14 @@ class Thing < Teron
|
|
140
140
|
|
141
141
|
[]
|
142
142
|
end
|
143
|
+
|
144
|
+
def query_save(results, name)
|
145
|
+
self.archive = Archive.first
|
146
|
+
self.result = results
|
147
|
+
self.name = name
|
148
|
+
self.log = true
|
149
|
+
self.parsed = true
|
150
|
+
self.result_fields = field_processing
|
151
|
+
save!
|
152
|
+
end
|
143
153
|
end
|
data/lib/greenhat/version.rb
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
== slim :chart_template
|
2
|
+
.row
|
3
|
+
.chart-menu
|
4
|
+
ul.section.table-of-contents
|
5
|
+
li
|
6
|
+
a href="#top" Top
|
7
|
+
li
|
8
|
+
a href="#path" Path
|
9
|
+
li
|
10
|
+
a href="#time" Time
|
11
|
+
|
12
|
+
h3.white-text.center API
|
13
|
+
|
14
|
+
h4.col.s12.white-text.center id="top" Top
|
15
|
+
.col.s12.card.padding.z-depth-4
|
16
|
+
== bubble_chart(faststats_top('gitlab-rails/api_json.log', :project_stats), xtitle:'Duration', ytitle:'% Count', label: "Total", title: 'by Project')
|
17
|
+
.col.s12.padding
|
18
|
+
.legend X: Duration
|
19
|
+
.legend.red Y: % of total calls
|
20
|
+
.legend.blue Size: Total Calls
|
21
|
+
|
22
|
+
|
23
|
+
.col.s12.card.padding.z-depth-4
|
24
|
+
== bubble_chart(faststats_top('gitlab-rails/api_json.log', :user_stats), xtitle:'Duration', ytitle:'% Count', label: "Total", title: 'by User')
|
25
|
+
.col.s12.padding
|
26
|
+
.legend X: Duration
|
27
|
+
.legend.red Y: % of total calls
|
28
|
+
.legend.blue Size: Total Calls
|
29
|
+
|
30
|
+
.col.s12.card.padding.z-depth-4
|
31
|
+
== pie_chart(api_duration_pie, title: 'Duration Total')
|
32
|
+
|
33
|
+
h4.col.s12.white-text.center id="path" Path
|
34
|
+
.col.s12.card.padding.z-depth-4
|
35
|
+
== pie_chart(faststats_field('gitlab-rails/api_json.log', :count), title: 'Total by Path')
|
36
|
+
|
37
|
+
.col.s12.card.padding.z-depth-4
|
38
|
+
== column_chart(faststats_field('gitlab-rails/api_json.log',:p95), title: 'p95', ytitle: 'ms')
|
39
|
+
|
40
|
+
.col.s12.card.padding.z-depth-4
|
41
|
+
== column_chart(faststats_field('gitlab-rails/api_json.log',:median), title: 'Median', ytitle: 'ms')
|
42
|
+
|
43
|
+
h4.col.s12.white-text.center id="time" Over Time
|
44
|
+
|
45
|
+
.col.s12.card.padding.z-depth-4
|
46
|
+
== area_chart(api_avg_path_duration_series, title: 'Path Duration', ytitle: 'seconds')
|
47
|
+
|
48
|
+
.col.s12.card.padding.z-depth-4
|
49
|
+
== area_chart(api_avg_duration_series, title: 'Avg Duration', ytitle: 'ms')
|
50
|
+
|
51
|
+
.col.s12.card.padding.z-depth-4
|
52
|
+
== column_chart(api_duration_series_stacked, stacked: true, title: 'Duration Breakdown', ytitle: 'seconds')
|
53
|
+
|
54
|
+
.col.s12.card.padding.z-depth-4
|
55
|
+
== area_chart(api_duration_series_stacked, stacked: true, title: 'Duration Breakdown', ytitle: 'seconds')
|
@@ -0,0 +1,42 @@
|
|
1
|
+
doctype html
|
2
|
+
html
|
3
|
+
head
|
4
|
+
== slim :headers
|
5
|
+
body.grey.darken-4
|
6
|
+
== slim :css
|
7
|
+
|
8
|
+
nav.blue-grey.darken-4
|
9
|
+
.nav-wrapper
|
10
|
+
a.brand-logo.center href="/" Charts Home
|
11
|
+
ul.left.white-text
|
12
|
+
li
|
13
|
+
a href ='/'
|
14
|
+
.btn-flat.white-text
|
15
|
+
i.fa.fa-home.left.line-height
|
16
|
+
| Home
|
17
|
+
|
18
|
+
li
|
19
|
+
a href ='/chart'
|
20
|
+
.btn-flat.white-text
|
21
|
+
i.fa.fa-chart-pie.left.line-height
|
22
|
+
| Charts
|
23
|
+
li
|
24
|
+
a href ='/chart/time'
|
25
|
+
.btn-flat.white-text
|
26
|
+
i.fa.fa-chart-line.left.line-height
|
27
|
+
| Time Query
|
28
|
+
|
29
|
+
.container.padding
|
30
|
+
.row
|
31
|
+
h5.white-text.center Dashboards
|
32
|
+
.row
|
33
|
+
.col.s4.padding
|
34
|
+
a.blue.btn-large.chart-btn href="/charts/gitaly" Gitaly
|
35
|
+
.col.s4.padding
|
36
|
+
a.green.btn-large.chart-btn href="/charts/sidekiq" Sidekiq
|
37
|
+
.col.s4.padding
|
38
|
+
a.red.btn-large.chart-btn href="/charts/api" Api
|
39
|
+
.col.s4.padding
|
40
|
+
a.purple.btn-large.chart-btn href="/charts/production" Production
|
41
|
+
.col.s4.padding
|
42
|
+
a.teal.btn-large.chart-btn href="/charts/workhorse" Workhorse
|
@@ -0,0 +1,31 @@
|
|
1
|
+
doctype html
|
2
|
+
html
|
3
|
+
head
|
4
|
+
== slim :headers
|
5
|
+
|
6
|
+
body.grey.darken-4
|
7
|
+
== slim :css
|
8
|
+
|
9
|
+
nav.blue-grey.darken-4
|
10
|
+
.nav-wrapper
|
11
|
+
a.brand-logo.center href="/" Charts Home
|
12
|
+
ul.left.white-text
|
13
|
+
li
|
14
|
+
a href ='/'
|
15
|
+
.btn-flat.white-text
|
16
|
+
i.fa.fa-home.left.line-height
|
17
|
+
| Home
|
18
|
+
|
19
|
+
li
|
20
|
+
a href ='/chart'
|
21
|
+
.btn-flat.white-text
|
22
|
+
i.fa.fa-chart-pie.left.line-height
|
23
|
+
| Charts
|
24
|
+
li
|
25
|
+
a href ='/chart/time'
|
26
|
+
.btn-flat.white-text
|
27
|
+
i.fa.fa-chart-line.left.line-height
|
28
|
+
| Time Query
|
29
|
+
|
30
|
+
.container.padding
|
31
|
+
== yield
|