greenhat 0.3.3 → 0.4.0

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/bin/greenhat +1 -4
  3. data/lib/greenhat/accessors/disk.rb +42 -3
  4. data/lib/greenhat/accessors/gitlab.rb +30 -1
  5. data/lib/greenhat/accessors/memory.rb +1 -1
  6. data/lib/greenhat/archive.rb +19 -8
  7. data/lib/greenhat/cli.rb +24 -126
  8. data/lib/greenhat/entrypoint.rb +170 -0
  9. data/lib/greenhat/host.rb +25 -37
  10. data/lib/greenhat/settings.rb +6 -0
  11. data/lib/greenhat/shell/args.rb +22 -9
  12. data/lib/greenhat/shell/faststats.rb +23 -3
  13. data/lib/greenhat/shell/field_helper.rb +1 -1
  14. data/lib/greenhat/shell/filter_help.rb +232 -9
  15. data/lib/greenhat/shell/log.rb +153 -9
  16. data/lib/greenhat/shell/markdown.rb +352 -0
  17. data/lib/greenhat/shell/old_search_helper.rb +54 -0
  18. data/lib/greenhat/shell/page.rb +1 -1
  19. data/lib/greenhat/shell/pipe.rb +31 -0
  20. data/lib/greenhat/shell/platform.rb +28 -0
  21. data/lib/greenhat/shell/report.rb +106 -25
  22. data/lib/greenhat/shell/shell_helper.rb +115 -106
  23. data/lib/greenhat/shell.rb +10 -3
  24. data/lib/greenhat/thing/file_types.rb +136 -8
  25. data/lib/greenhat/thing/formatters/json.rb +4 -0
  26. data/lib/greenhat/thing/formatters/kube_json.rb +36 -0
  27. data/lib/greenhat/thing/formatters/kube_nginx.rb +48 -0
  28. data/lib/greenhat/thing/formatters/kube_webservice.rb +51 -0
  29. data/lib/greenhat/thing/formatters/nginx.rb +6 -2
  30. data/lib/greenhat/thing/formatters/registry.rb +47 -0
  31. data/lib/greenhat/thing/formatters/time_space.rb +0 -16
  32. data/lib/greenhat/thing/helpers.rb +12 -0
  33. data/lib/greenhat/thing/kind.rb +5 -0
  34. data/lib/greenhat/thing.rb +11 -0
  35. data/lib/greenhat/version.rb +1 -1
  36. data/lib/greenhat/views/api.slim +55 -0
  37. data/lib/greenhat/views/chart.slim +42 -0
  38. data/lib/greenhat/views/chart_template.slim +31 -0
  39. data/lib/greenhat/views/chartkick.js +21 -0
  40. data/lib/greenhat/views/css.slim +47 -0
  41. data/lib/greenhat/views/gitaly.slim +53 -0
  42. data/lib/greenhat/views/headers.slim +16 -0
  43. data/lib/greenhat/views/index-old.slim +51 -0
  44. data/lib/greenhat/views/index.slim +14 -14
  45. data/lib/greenhat/views/info.slim +17 -18
  46. data/lib/greenhat/views/production.slim +55 -0
  47. data/lib/greenhat/views/sidekiq.slim +55 -0
  48. data/lib/greenhat/views/time.slim +63 -0
  49. data/lib/greenhat/views/workhorse.slim +16 -0
  50. data/lib/greenhat/web/api.rb +94 -0
  51. data/lib/greenhat/web/chartkick_shim.rb +14 -0
  52. data/lib/greenhat/web/faststats.rb +44 -0
  53. data/lib/greenhat/web/gitaly.rb +65 -0
  54. data/lib/greenhat/web/helpers.rb +198 -0
  55. data/lib/greenhat/web/production.rb +104 -0
  56. data/lib/greenhat/web/sidekiq.rb +73 -0
  57. data/lib/greenhat/web/stats_helpers.rb +74 -0
  58. data/lib/greenhat/web/time.rb +36 -0
  59. data/lib/greenhat/web/workhorse.rb +43 -0
  60. data/lib/greenhat/web.rb +63 -19
  61. data/lib/greenhat.rb +2 -0
  62. metadata +78 -5
@@ -43,6 +43,13 @@ module GreenHat
43
43
  /dmesg/
44
44
  ]
45
45
  },
46
+ 'lets-encrypt/renewal' => {
47
+ format: :bracket_log,
48
+ log: true,
49
+ pattern: [
50
+ %r{lets-encrypt/renewal}
51
+ ]
52
+ },
46
53
  'repmgrd/current' => {
47
54
  format: :bracket_log,
48
55
  log: true,
@@ -60,7 +67,8 @@ module GreenHat
60
67
  'etc/fstab' => {
61
68
  format: :clean_raw,
62
69
  pattern: [
63
- %r{etc/fstab}
70
+ %r{etc/fstab},
71
+ /fstab/
64
72
  ]
65
73
  },
66
74
  'etc/os-release' => {
@@ -87,6 +95,12 @@ module GreenHat
87
95
  /getenforce/
88
96
  ]
89
97
  },
98
+ 'geo-logcursor/current' => {
99
+ format: :raw,
100
+ pattern: [
101
+ %r{geo-logcursor/current}
102
+ ]
103
+ },
90
104
  'gitaly/current' => {
91
105
  format: :json_shell,
92
106
  log: true,
@@ -95,6 +109,13 @@ module GreenHat
95
109
  %r{gitaly/@.*}
96
110
  ]
97
111
  },
112
+ 'gitaly/gitaly_hooks.log' => {
113
+ format: :shellwords,
114
+ log: true,
115
+ pattern: [
116
+ %r{gitaly/gitaly_hooks\.log}
117
+ ]
118
+ },
98
119
  'consul/current' => {
99
120
  format: :time_space,
100
121
  log: true,
@@ -225,7 +246,8 @@ module GreenHat
225
246
  format: :json,
226
247
  log: true,
227
248
  pattern: [
228
- %r{gitlab-rails/audit_json.log}
249
+ %r{gitlab-rails/audit_json.log},
250
+ %r{webservice.log/audit_json.log}
229
251
  ]
230
252
  },
231
253
  'gitlab-rails/auth.log' => {
@@ -336,6 +358,20 @@ module GreenHat
336
358
  %r{nginx/current}
337
359
  ]
338
360
  },
361
+ 'nginx-ingress.log' => {
362
+ format: :kube_nginx,
363
+ log: true,
364
+ pattern: [
365
+ /nginx-ingress.log/
366
+ ]
367
+ },
368
+ 'nginx/access.log' => {
369
+ format: :nginx,
370
+ log: true,
371
+ pattern: [
372
+ %r{nginx/access.log}
373
+ ]
374
+ },
339
375
  'nginx/gitlab_pages_access.log' => {
340
376
  format: :nginx,
341
377
  log: true,
@@ -422,7 +458,7 @@ module GreenHat
422
458
  ]
423
459
  },
424
460
  'registry/current' => {
425
- format: :time_shellwords,
461
+ format: :time_registry,
426
462
  log: true,
427
463
  pattern: [
428
464
  %r{registry/current},
@@ -444,16 +480,18 @@ module GreenHat
444
480
  },
445
481
  'puma/puma_stderr.log' => {
446
482
  format: :raw,
447
- log: true,
483
+ log: false,
448
484
  pattern: [
449
- %r{puma/puma_stderr.log}
485
+ %r{puma/puma_stderr.log},
486
+ %r{webservice.log/puma.stderr.log}
450
487
  ]
451
488
  },
452
489
  'puma/puma_stdout.log' => {
453
490
  format: :json,
454
491
  log: true,
455
492
  pattern: [
456
- %r{puma/puma_stdout.log}
493
+ %r{puma/puma_stdout.log},
494
+ %r{webservice.log/puma.stdout.log}
457
495
  ]
458
496
  },
459
497
  'gitlab-pages/current' => {
@@ -529,6 +567,20 @@ module GreenHat
529
567
  %r{unicorn/current}
530
568
  ]
531
569
  },
570
+ 'unicorn_stats' => {
571
+ format: :time_space,
572
+ log: true,
573
+ pattern: [
574
+ /unicorn_stats/
575
+ ]
576
+ },
577
+ 'unicorn/unicorn_stdout.log' => {
578
+ format: :raw,
579
+ log: true,
580
+ pattern: [
581
+ %r{unicorn/unicorn_stdout.log}
582
+ ]
583
+ },
532
584
  'running_swappiness' => {
533
585
  format: :raw,
534
586
  pattern: [
@@ -566,6 +618,7 @@ module GreenHat
566
618
  log: true,
567
619
  pattern: [
568
620
  %r{sidekiq/current},
621
+ /sidekiq_current/,
569
622
  %r{sidekiq/@.*}
570
623
  ]
571
624
  },
@@ -629,6 +682,12 @@ module GreenHat
629
682
  /uname/
630
683
  ]
631
684
  },
685
+ 'gitlab_socket_stats' => {
686
+ format: :gitlab_socket_stats,
687
+ pattern: [
688
+ /gitlab_socket_stats/
689
+ ]
690
+ },
632
691
  'uptime' => {
633
692
  format: :raw,
634
693
  pattern: [
@@ -745,13 +804,16 @@ module GreenHat
745
804
  'gitlab-rails/application.log' => {
746
805
  format: :raw,
747
806
  pattern: [
748
- %r{gitlab-rails/application.log}
807
+ %r{gitlab-rails/application.log},
808
+ %r{webservice.log/application.log}
749
809
  ]
750
810
  },
751
811
  'gitlab-rails/production.log' => {
752
812
  format: :raw,
753
813
  pattern: [
754
- %r{gitlab-rails/production.log}
814
+ /production.log/,
815
+ %r{gitlab-rails/production.log},
816
+ %r{webservice.log/production.log}
755
817
  ]
756
818
  },
757
819
  'gitlab/version-manifest.txt' => {
@@ -765,6 +827,72 @@ module GreenHat
765
827
  pattern: [
766
828
  %r{sidekiq/perf.data}
767
829
  ]
830
+ },
831
+
832
+ # ======================================================================
833
+ # KubeSoS TODO Section
834
+ # Things I am going to shortcut and set to raw for now
835
+ # ======================================================================
836
+ # Attempted Parsing
837
+ 'kubesos_json' => {
838
+ log: true,
839
+ format: :kube_json,
840
+ pattern: [
841
+ /gitaly.log/
842
+ ]
843
+ },
844
+
845
+ 'kube_webservice' => {
846
+ log: false,
847
+ format: :kube_webservice,
848
+ pattern: [
849
+ /^webservice\.log$/
850
+ ]
851
+ },
852
+
853
+ 'kubesos' => {
854
+ format: :raw,
855
+ pattern: [
856
+ /all_values.yaml/,
857
+ %r{webservice.log/sidekiq_client.log},
858
+ /chart-version/,
859
+ /configmaps/,
860
+ /describe_deployments/,
861
+ /describe_ingress/,
862
+ /describe_nodes/,
863
+ /describe_pods/,
864
+ /describe_pv/,
865
+ /describe_pvc/,
866
+ /events/,
867
+ /get_deployments/,
868
+ /get_endpoints/,
869
+ /get_jobs/,
870
+ /get_pods/,
871
+ /get_pv/,
872
+ /get_pvc/,
873
+ /get_services/,
874
+ /gitaly.log/,
875
+ /gitlab-exporter.log/,
876
+ /gitlab-pages.log/,
877
+ /gitlab-shell.log/,
878
+ /grafana.log/,
879
+ /helm-version/,
880
+ /kubectl-check/,
881
+ /migrations.log/,
882
+ /minio.log/,
883
+ /nfs-client-provisioner.log/,
884
+ /operator.log/,
885
+ /postgresql.log/,
886
+ /prometheus.log/,
887
+ /redis.log/,
888
+ /registry.log/,
889
+ /secrets/,
890
+ /sidekiq.log/,
891
+ /task-runner.log/,
892
+ /top_nodes/,
893
+ /top_pods/,
894
+ /user_supplied_values.yaml/
895
+ ]
768
896
  }
769
897
  }
770
898
  end
@@ -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
@@ -0,0 +1,36 @@
1
+ # Top
2
+ module GreenHat
3
+ # Log
4
+ module Formatters
5
+ # ==========================================================================
6
+ # K8s logs seem to have a lot of non-json entries
7
+ # Extract all json, ignore everything else
8
+ # ==========================================================================
9
+ def format_kube_json
10
+ self.result = raw.map do |row|
11
+ # Skip all non-json
12
+ next unless row.first == '{'
13
+
14
+ result = begin
15
+ Oj.load row
16
+ rescue EncodingError
17
+ puts
18
+ next
19
+ end
20
+
21
+ # Parsing Time
22
+ format_json_traverse result
23
+
24
+ result.sort.to_h
25
+ rescue StandardError => e
26
+ # TODO: Background Logger?
27
+ e.message
28
+ LogBot.warn('JSON Parse', e.message)
29
+ next
30
+ end.compact
31
+
32
+ :ok
33
+ end
34
+ # =========================================================================
35
+ end
36
+ end
@@ -0,0 +1,48 @@
1
+ # Top
2
+ module GreenHat
3
+ # Log
4
+ module Formatters
5
+ # ==========================================================================
6
+ # Formatters
7
+ # ==========================================================================
8
+ def format_kube_nginx
9
+ self.result = raw.map do |row|
10
+ ip, _sym, remote_user, rest = row.split(' ', 4)
11
+
12
+ time, rest = rest.split(']', 2)
13
+ time = Time.strptime(time, '[%d/%b/%Y:%H:%M:%S %z')
14
+
15
+ verb, status, bytes, http_referer, http_user_agent, gzip_ratio = Shellwords.split(rest)
16
+
17
+ method, path, http_version = verb.split
18
+
19
+ {
20
+ remote_addr: ip,
21
+ remote_user: remote_user,
22
+ method: method,
23
+ path: path,
24
+ status: status,
25
+ bytes: bytes,
26
+ http_version: http_version,
27
+ http_referer: http_referer,
28
+ http_user_agent: http_user_agent,
29
+ gzip_ratio: gzip_ratio,
30
+ time: time
31
+ }
32
+
33
+ # Fall back for malformed logs
34
+ rescue StandardError
35
+ { message: row }
36
+ end
37
+
38
+ :ok
39
+ end
40
+
41
+ # rubocop:disable Layout/LineLength
42
+ # NGINX Conf: /var/opt/gitlab/nginx/conf/nginx.conf
43
+ # log_format gitlab_access '$remote_addr - $remote_user [$time_local] "$request_method $filtered_request_uri $server_protocol" $status $body_bytes_sent "$filtered_http_referer" "$http_user_agent" $gzip_ratio';
44
+ # rubocop:enable Layout/LineLength
45
+
46
+ # ==========================================================================
47
+ end
48
+ end
@@ -0,0 +1,51 @@
1
+ # Top
2
+ module GreenHat
3
+ # Log
4
+ module Formatters
5
+ # ==========================================================================
6
+ # Gitlab Tail Formatter
7
+ # ==========================================================================
8
+ def format_kube_webservice
9
+ # Revert to raw for cats
10
+ self.kind = :raw
11
+
12
+ output = {}
13
+ current_log = nil
14
+
15
+ raw.each do |line|
16
+ next if line.blank?
17
+
18
+ if line.include? '*** '
19
+ current_log = /\*\*\* (.+?) \*\*\*/.match(line).captures.first
20
+ else
21
+ output[current_log] ||= [] unless current_log.nil?
22
+ output[current_log].push line unless current_log.nil?
23
+ end
24
+ end
25
+
26
+ # Remove Empty Entries
27
+ output.reject { |_k, v| v.empty? }
28
+
29
+ # Root Dir
30
+ root_dir = "#{$TMP}/#{name}"
31
+ Dir.mkdir(root_dir)
32
+
33
+ # Write Files / Create Things
34
+ output.each do |k, v|
35
+ file_name = k.gsub('/var/log/gitlab/', '')
36
+
37
+ dir = "#{root_dir}/gitlab-rails"
38
+ Dir.mkdir(dir) unless File.exist?(dir)
39
+
40
+ File.write("#{root_dir}/#{file_name}", v.join("\n"))
41
+
42
+ # Thing Setup
43
+ archive.things_create(file: "#{root_dir}/#{file_name}").setup
44
+ end
45
+
46
+ # Link
47
+ self.result = raw
48
+ end
49
+ # ==========================================================================
50
+ end
51
+ end
@@ -7,10 +7,11 @@ module GreenHat
7
7
  # ==========================================================================
8
8
  def format_nginx
9
9
  self.result = raw.map do |row|
10
- ip, _sym, remote_user, rest = row.split(' ', 4)
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, '[%d/%b/%Y:%H:%M:%S %z')
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
@@ -0,0 +1,47 @@
1
+ # Top
2
+ module GreenHat
3
+ # Log
4
+ module Formatters
5
+ # ==========================================================================
6
+ # Registry Split
7
+ # ==========================================================================
8
+ # https://docs.docker.com/registry/configuration/#log
9
+ # Formatters text, json
10
+ # registry['log_formatter'] = "json"
11
+ # TODO: Logstash (Not working in 14.3)
12
+
13
+ def format_time_registry
14
+ self.result = raw.map do |row|
15
+ result = row[0] == '{' ? registry_json(row) : registry_shell_words(row)
16
+
17
+ # Timestamp Parsing
18
+ result.ts = Time.parse result.ts if result.key? 'ts'
19
+ result.time = Time.parse(result.time)
20
+
21
+ result
22
+ end
23
+ end
24
+
25
+ def registry_shell_words(row)
26
+ time, msg = row.split(' ', 2)
27
+
28
+ output = Shellwords.split(msg).each_with_object({}) do |x, h|
29
+ key, value = x.split('=')
30
+ next if value.nil?
31
+
32
+ h[key.to_sym] = value.numeric? ? value.to_f : value
33
+ end
34
+
35
+ output[:time] = time
36
+
37
+ output
38
+ end
39
+
40
+ def registry_json(msg)
41
+ Oj.load(msg)
42
+ rescue EncodingError
43
+ { message: msg }
44
+ end
45
+ # ==========================================================================
46
+ end
47
+ end
@@ -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
@@ -73,6 +73,11 @@ module GreenHat
73
73
  end
74
74
  end
75
75
 
76
+ if Settings.assume_raw?
77
+ self.type = 'raw'
78
+ return true
79
+ end
80
+
76
81
  puts "Unable to determine file type for #{name.pastel(:yellow)}"
77
82
  puts "Use '#{'json'.pastel(:cyan)}' or '#{'raw'.pastel(:cyan)}' if there are no matches (see file_types.rb)"
78
83
 
@@ -140,4 +140,15 @@ 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.type = 'json'
151
+ self.result_fields = field_processing
152
+ save!
153
+ end
143
154
  end
@@ -1,3 +1,3 @@
1
1
  module GreenHat
2
- VERSION = '0.3.3'.freeze
2
+ VERSION = '0.4.0'.freeze
3
3
  end
@@ -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