leafy-health 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +34 -4
  3. data/.travis.yml +19 -0
  4. data/CHANGELOG.md +7 -0
  5. data/Gemfile +1 -5
  6. data/README.md +10 -116
  7. data/examples/datadog/.gitignore +2 -0
  8. data/examples/datadog/Gemfile +12 -0
  9. data/examples/datadog/Mavenfile +22 -0
  10. data/examples/datadog/README.md +16 -0
  11. data/examples/datadog/lib/java_gauge.rb +20 -0
  12. data/examples/datadog/lib/metrics.rb +18 -0
  13. data/examples/datadog/lib/ruby_gauge.rb +19 -0
  14. data/examples/hellowarld/.gitignore +3 -0
  15. data/examples/hellowarld/Gemfile +15 -0
  16. data/examples/hellowarld/Mavenfile +162 -0
  17. data/examples/hellowarld/README.md +44 -0
  18. data/examples/hellowarld/Rakefile +13 -0
  19. data/examples/hellowarld/WEB-INF/web.xml +31 -0
  20. data/examples/hellowarld/app/hellowarld.rb +55 -0
  21. data/examples/hellowarld/app/views/person.erb +52 -0
  22. data/examples/hellowarld/config.ru +12 -0
  23. data/leafy-complete.gemspec +22 -0
  24. data/leafy-health/.gitignore +4 -0
  25. data/leafy-health/Gemfile +7 -0
  26. data/leafy-health/LICENSE +22 -0
  27. data/leafy-health/README.md +123 -0
  28. data/{Rakefile → leafy-health/Rakefile} +0 -0
  29. data/{leafy-health.gemspec → leafy-health/leafy-health.gemspec} +0 -0
  30. data/{lib → leafy-health/lib}/leafy-health.rb +0 -0
  31. data/{lib → leafy-health/lib}/leafy-health_jars.rb +0 -0
  32. data/{lib → leafy-health/lib}/leafy/health.rb +0 -0
  33. data/{lib → leafy-health/lib}/leafy/health/health_check.rb +0 -0
  34. data/{lib → leafy-health/lib}/leafy/health/registry.rb +0 -0
  35. data/{lib → leafy-health/lib}/leafy/health/version.rb +1 -1
  36. data/{spec → leafy-health/spec}/registry_spec.rb +0 -0
  37. data/{spec → leafy-health/spec}/setup.rb +0 -0
  38. data/leafy-logger/.gitignore +5 -0
  39. data/leafy-logger/Gemfile +9 -0
  40. data/leafy-logger/LICENSE +22 -0
  41. data/leafy-logger/README.md +174 -0
  42. data/leafy-logger/Rakefile +14 -0
  43. data/leafy-logger/leafy-logger.gemspec +32 -0
  44. data/leafy-logger/lib/leafy-logger.rb +1 -0
  45. data/leafy-logger/lib/leafy-logger_jars.rb +33 -0
  46. data/leafy-logger/lib/leafy/logger.rb +1 -0
  47. data/leafy-logger/lib/leafy/logger/appender_factories.rb +89 -0
  48. data/leafy-logger/lib/leafy/logger/factory.rb +141 -0
  49. data/leafy-logger/lib/leafy/logger/version.rb +6 -0
  50. data/leafy-logger/spec/appender_factories_spec.rb +147 -0
  51. data/leafy-logger/spec/factory_spec.rb +176 -0
  52. data/leafy-logger/spec/logging.yml +16 -0
  53. data/leafy-logger/spec/setup.rb +2 -0
  54. data/leafy-metrics/.gitignore +5 -0
  55. data/leafy-metrics/Gemfile +7 -0
  56. data/leafy-metrics/LICENSE +22 -0
  57. data/leafy-metrics/README.md +221 -0
  58. data/leafy-metrics/Rakefile +14 -0
  59. data/leafy-metrics/leafy-metrics.gemspec +29 -0
  60. data/leafy-metrics/lib/leafy-metrics.rb +2 -0
  61. data/leafy-metrics/lib/leafy-metrics_jars.rb +5 -0
  62. data/leafy-metrics/lib/leafy/metrics.rb +2 -0
  63. data/leafy-metrics/lib/leafy/metrics/console_reporter.rb +32 -0
  64. data/leafy-metrics/lib/leafy/metrics/csv_reporter.rb +26 -0
  65. data/leafy-metrics/lib/leafy/metrics/graphite/graphite.rb +28 -0
  66. data/leafy-metrics/lib/leafy/metrics/graphite/graphite_reporter.rb +43 -0
  67. data/leafy-metrics/lib/leafy/metrics/registry.rb +108 -0
  68. data/leafy-metrics/lib/leafy/metrics/reporter.rb +51 -0
  69. data/leafy-metrics/lib/leafy/metrics/version.rb +6 -0
  70. data/leafy-metrics/spec/console_reporter_spec.rb +72 -0
  71. data/leafy-metrics/spec/csv_reporter_spec.rb +75 -0
  72. data/leafy-metrics/spec/graphite_reporter_spec.rb +72 -0
  73. data/leafy-metrics/spec/graphite_spec.rb +23 -0
  74. data/leafy-metrics/spec/registry_spec.rb +106 -0
  75. data/leafy-metrics/spec/setup.rb +10 -0
  76. data/leafy-rack/.gitignore +4 -0
  77. data/leafy-rack/Gemfile +10 -0
  78. data/leafy-rack/LICENSE +22 -0
  79. data/leafy-rack/README.md +155 -0
  80. data/leafy-rack/Rakefile +14 -0
  81. data/leafy-rack/leafy-rack.gemspec +29 -0
  82. data/leafy-rack/lib/leafy-rack.rb +1 -0
  83. data/leafy-rack/lib/leafy-rack_jars.rb +10 -0
  84. data/leafy-rack/lib/leafy/instrumented/basic_instrumented.rb +38 -0
  85. data/leafy-rack/lib/leafy/instrumented/instrumented.rb +27 -0
  86. data/leafy-rack/lib/leafy/json/health_writer.rb +15 -0
  87. data/leafy-rack/lib/leafy/json/json_writer.rb +33 -0
  88. data/leafy-rack/lib/leafy/json/metrics_writer.rb +22 -0
  89. data/leafy-rack/lib/leafy/rack.rb +1 -0
  90. data/leafy-rack/lib/leafy/rack/admin.rb +73 -0
  91. data/leafy-rack/lib/leafy/rack/health.rb +43 -0
  92. data/leafy-rack/lib/leafy/rack/instrumented.rb +20 -0
  93. data/leafy-rack/lib/leafy/rack/metrics.rb +35 -0
  94. data/leafy-rack/lib/leafy/rack/ping.rb +29 -0
  95. data/leafy-rack/lib/leafy/rack/thread_dump.rb +56 -0
  96. data/leafy-rack/lib/leafy/rack/version.rb +6 -0
  97. data/leafy-rack/spec/admin_rack_spec.rb +141 -0
  98. data/leafy-rack/spec/basic_instrumented_spec.rb +31 -0
  99. data/leafy-rack/spec/health_rack_spec.rb +136 -0
  100. data/leafy-rack/spec/health_writer_spec.rb +47 -0
  101. data/leafy-rack/spec/instrumented_rack_spec.rb +37 -0
  102. data/leafy-rack/spec/instrumented_spec.rb +36 -0
  103. data/leafy-rack/spec/metrics_rack_spec.rb +110 -0
  104. data/leafy-rack/spec/metrics_writer_spec.rb +55 -0
  105. data/leafy-rack/spec/ping_rack_spec.rb +63 -0
  106. data/leafy-rack/spec/setup.rb +3 -0
  107. data/leafy-rack/spec/thread_dump_spec.rb +59 -0
  108. metadata +106 -12
@@ -0,0 +1 @@
1
+ require 'leafy/rack'
@@ -0,0 +1,10 @@
1
+ # this is a generated file, to avoid over-writing it just delete this comment
2
+ require 'jar_dependencies'
3
+
4
+ require_jar( 'com.fasterxml.jackson.core', 'jackson-annotations', '2.4.0' )
5
+ require_jar( 'com.fasterxml.jackson.core', 'jackson-core', '2.4.2' )
6
+ require_jar( 'org.slf4j', 'slf4j-api', '1.7.7' )
7
+ require_jar( 'io.dropwizard.metrics', 'metrics-jvm', '3.1.0' )
8
+ require_jar( 'io.dropwizard.metrics', 'metrics-core', '3.1.0' )
9
+ require_jar( 'com.fasterxml.jackson.core', 'jackson-databind', '2.4.2' )
10
+ require_jar( 'io.dropwizard.metrics', 'metrics-json', '3.1.0' )
@@ -0,0 +1,38 @@
1
+ module Leafy
2
+ module Instrumented
3
+ class BasicInstrumented
4
+
5
+ NAME_PREFIX = "responseCodes"
6
+
7
+ def initialize( registry, name, meter_names_by_status_code = {} )
8
+ @meters_by_status_code = java.util.concurrent.ConcurrentHashMap.new
9
+ meter_names_by_status_code.each do |k,v|
10
+ @meters_by_status_code[ k ] = registry.register_meter( "#{name}.#{v}" )
11
+ end
12
+ @other = registry.register_meter( "#{name}.#{NAME_PREFIX}.other" )
13
+ @active = registry.register_counter( "#{name}.active_requests" )
14
+ @timer = registry.register_timer( "#{name}.requests" )
15
+ end
16
+
17
+ def call( &block )
18
+ raise "block needed" unless block_given?
19
+ @active.inc
20
+
21
+ @timer.time do
22
+
23
+ result = block.call
24
+ mark_meter_for_status_code result[0]
25
+ result
26
+
27
+ end
28
+ ensure
29
+ @active.dec
30
+ end
31
+
32
+ def mark_meter_for_status_code( status )
33
+ metric = @meters_by_status_code[ status ] || @other
34
+ metric.mark
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,27 @@
1
+ require 'leafy/instrumented/basic_instrumented'
2
+
3
+ module Leafy
4
+ module Instrumented
5
+ class Instrumented < BasicInstrumented
6
+
7
+ OK = 200;
8
+ CREATED = 201;
9
+ NO_CONTENT = 204;
10
+ RESET_CONTENT = 205;
11
+ BAD_REQUEST = 400;
12
+ NOT_FOUND = 404;
13
+ SERVER_ERROR = 500;
14
+
15
+ def initialize( registry, name )
16
+ super( registry, name,
17
+ { OK => "#{NAME_PREFIX}.ok",
18
+ CREATED => "#{NAME_PREFIX}.created",
19
+ NO_CONTENT => "#{NAME_PREFIX}.noContent",
20
+ RESET_CONTENT => "#{NAME_PREFIX}.resetContent",
21
+ BAD_REQUEST => "#{NAME_PREFIX}.badRequest",
22
+ NOT_FOUND => "#{NAME_PREFIX}.notFound",
23
+ SERVER_ERROR => "#{NAME_PREFIX}.serverError" } )
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ require 'leafy/health'
2
+ require 'leafy/json/json_writer'
3
+
4
+ java_import com.codahale.metrics.json.HealthCheckModule
5
+
6
+ module Leafy
7
+ module Json
8
+ class HealthWriter < JsonWriter
9
+
10
+ def initialize
11
+ super( HealthCheckModule.new )
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,33 @@
1
+ java_import com.fasterxml.jackson.databind.ObjectMapper
2
+
3
+ module Leafy
4
+ module Json
5
+ class JsonWriter
6
+
7
+ def initialize( jacksonModule )
8
+ @mapper = ObjectMapper.new.registerModule( jacksonModule )
9
+ end
10
+
11
+ def data
12
+ raise 'need implementation'
13
+ end
14
+
15
+ def to_json( data, pretty = false )
16
+ # TODO make this stream
17
+ output = java.io.ByteArrayOutputStream.new
18
+ writer( pretty ).writeValue(output, data);
19
+ output.to_s
20
+ end
21
+
22
+ private
23
+
24
+ def writer( pretty )
25
+ if pretty
26
+ @mapper.writerWithDefaultPrettyPrinter
27
+ else
28
+ @mapper.writer
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ require 'leafy/metrics'
2
+ require 'leafy/json/json_writer'
3
+
4
+ java_import com.codahale.metrics.MetricFilter
5
+ java_import com.codahale.metrics.json.MetricsModule
6
+
7
+ java_import java.util.concurrent.TimeUnit
8
+
9
+ module Leafy
10
+ module Json
11
+ class MetricsWriter < JsonWriter
12
+
13
+ def initialize
14
+ super( # make this configurable
15
+ MetricsModule.new(TimeUnit::SECONDS,
16
+ TimeUnit::SECONDS,
17
+ true,
18
+ MetricFilter::ALL) )
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1 @@
1
+ require 'leafy-rack_jars'
@@ -0,0 +1,73 @@
1
+ require 'leafy/rack/metrics'
2
+ require 'leafy/rack/health'
3
+ require 'leafy/rack/ping'
4
+ require 'leafy/rack/thread_dump'
5
+
6
+ module Leafy
7
+ module Rack
8
+ class Admin
9
+
10
+ def self.response( path )
11
+ path = path.sub( /^\//, '' )
12
+ [
13
+ 200,
14
+ { 'Content-Type' => 'text/html' },
15
+ [ <<EOF
16
+ <DOCTYPE html>
17
+ <html>
18
+ <head>
19
+ <title>metrics</title>
20
+ </head>
21
+ <body>
22
+ <h1>menu</h1>
23
+ <ul>
24
+ <li><a href='#{path}/metrics'>metrics</a> (<a href='#{path}/metrics?pretty'>pretty</a>)</li>
25
+ <li><a href='#{path}/health'>health</a> (<a href='#{path}/health?pretty'>pretty</a>)</li>
26
+ <li><a href='#{path}/ping'>ping</a></li>
27
+ <li><a href='#{path}/threads'>thread-dump</a></li>
28
+ </ul>
29
+ </body>
30
+ </html>
31
+ EOF
32
+ ]
33
+ ]
34
+ end
35
+
36
+ def initialize(app, metrics_registry, health_registry, path = '/admin')
37
+ @app = app
38
+ @path = path
39
+ @metrics = metrics_registry
40
+ @health = health_registry
41
+ end
42
+
43
+ def call(env)
44
+ if ( path = env['PATH_INFO'] ).start_with? @path
45
+ dispatch( path.sub( /#{@path}/, ''), env )
46
+ else
47
+ @app.call( env )
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def dispatch( path, env )
54
+ case path
55
+ when '/metrics'
56
+ Metrics.response( @metrics.metrics, env )
57
+ when '/health'
58
+ Health.response( @health.health, env )
59
+ when '/ping'
60
+ Ping.response
61
+ when '/threads'
62
+ ThreadDump.response
63
+ when '/'
64
+ Admin.response( @path )
65
+ when ''
66
+ Admin.response( @path )
67
+ else # let the app deal with "not found"
68
+ @app.call( env )
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,43 @@
1
+ require 'leafy/rack'
2
+ require 'leafy/json/health_writer'
3
+ require 'json' unless defined? :JSON
4
+
5
+ module Leafy
6
+ module Rack
7
+ class Health
8
+
9
+ def self.response( health, env )
10
+ data = health.run_health_checks
11
+ is_healthy = data.values.all? { |r| r.healthy? }
12
+ json = if env[ 'QUERY_STRING' ] == 'pretty'
13
+ JSON.pretty_generate( data.to_hash )
14
+ else
15
+ # to use data.to_hash.to_json did produce
16
+ # a different json structure on some
17
+ # rack setup
18
+ JSON.generate( data.to_hash )
19
+ end
20
+ [
21
+ is_healthy ? 200 : 503,
22
+ { 'Content-Type' => 'application/json',
23
+ 'Cache-Control' => 'must-revalidate,no-cache,no-store' },
24
+ [ json ]
25
+ ]
26
+ end
27
+
28
+ def initialize(app, registry, path = '/health')
29
+ @app = app
30
+ @path = path
31
+ @registry = registry
32
+ end
33
+
34
+ def call(env)
35
+ if env['PATH_INFO'] == @path
36
+ Health.response( @registry.health, env )
37
+ else
38
+ @app.call( env )
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,20 @@
1
+ require 'leafy/rack'
2
+ require 'leafy/instrumented/instrumented'
3
+
4
+ module Leafy
5
+ module Rack
6
+ class Instrumented
7
+
8
+ def initialize( app, instrumented )
9
+ @app = app
10
+ @instrumented = instrumented
11
+ end
12
+
13
+ def call( env )
14
+ @instrumented.call do
15
+ @app.call env
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ require 'leafy/rack'
2
+ require 'leafy/metrics'
3
+ require 'leafy/json/metrics_writer'
4
+ module Leafy
5
+ module Rack
6
+
7
+ class Metrics
8
+
9
+ WRITER = ::Leafy::Json::MetricsWriter.new
10
+
11
+ def self.response( metrics, env )
12
+ [
13
+ 200,
14
+ { 'Content-Type' => 'application/json',
15
+ 'Cache-Control' => 'must-revalidate,no-cache,no-store' },
16
+ [ WRITER.to_json( metrics, env[ 'QUERY_STRING' ] == 'pretty' ) ]
17
+ ]
18
+ end
19
+
20
+ def initialize(app, registry, path = '/metrics')
21
+ @app = app
22
+ @path = path
23
+ @registry = registry
24
+ end
25
+
26
+ def call(env)
27
+ if env['PATH_INFO'] == @path
28
+ Metrics.response( @registry.metrics, env )
29
+ else
30
+ @app.call( env )
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ require 'leafy/rack'
2
+ module Leafy
3
+ module Rack
4
+ class Ping
5
+
6
+ def self.response
7
+ [
8
+ 200,
9
+ { 'Content-Type' => 'text/plain',
10
+ 'Cache-Control' => 'must-revalidate,no-cache,no-store' },
11
+ [ 'pong' ]
12
+ ]
13
+ end
14
+
15
+ def initialize(app, path = '/ping')
16
+ @app = app
17
+ @path = path
18
+ end
19
+
20
+ def call(env)
21
+ if env['PATH_INFO'] == @path
22
+ Ping.response
23
+ else
24
+ @app.call( env )
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,56 @@
1
+ require 'leafy/rack'
2
+
3
+ java_import java.lang.management.ManagementFactory
4
+
5
+ module Leafy
6
+ module Rack
7
+ class ThreadDumpWriter
8
+
9
+ def initialize
10
+ begin
11
+ # Some PaaS like Google App Engine blacklist java.lang.managament
12
+ @threads = com.codahale.metrics.jvm.ThreadDump.new(ManagementFactory.getThreadMXBean());
13
+ rescue LoadError
14
+ # we won't be able to provide thread dump
15
+ end
16
+ end
17
+
18
+ def to_text
19
+ if @threads
20
+ # TODO make this stream
21
+ output = java.io.ByteArrayOutputStream.new
22
+ @threads.dump(output)
23
+ output.to_s
24
+ end
25
+ end
26
+ end
27
+
28
+ class ThreadDump
29
+
30
+ WRITER = ThreadDumpWriter.new
31
+
32
+ def self.response
33
+ dump = WRITER.to_text
34
+ [
35
+ 200,
36
+ { 'Content-Type' => 'text/plain',
37
+ 'Cache-Control' => 'must-revalidate,no-cache,no-store' },
38
+ [ dump ? dump : 'Sorry your runtime environment does not allow to dump threads.' ]
39
+ ]
40
+ end
41
+
42
+ def initialize(app, path = '/threads')
43
+ @app = app
44
+ @path = path
45
+ end
46
+
47
+ def call(env)
48
+ if env['PATH_INFO'] == @path
49
+ ThreadDump.response
50
+ else
51
+ @app.call( env )
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,6 @@
1
+ module Leafy
2
+ module Rack
3
+ VERSION = '0.3.1'.freeze
4
+ end
5
+ end
6
+
@@ -0,0 +1,141 @@
1
+ require_relative 'setup'
2
+
3
+ require 'leafy/rack/admin'
4
+ require 'yaml'
5
+ require 'json'
6
+
7
+ describe Leafy::Rack::Admin do
8
+
9
+ subject { Leafy::Rack::Admin }
10
+
11
+ let( :expected_headers ) do
12
+ { 'Content-Type' => 'text/html' }
13
+ end
14
+
15
+ let( :metrics ) { Leafy::Metrics::Registry.new }
16
+
17
+ let( :health ) { Leafy::Health::Registry.new }
18
+
19
+ let( :health_report ) do
20
+ { 'version' => '3.0.0',
21
+ 'gauges' => {},
22
+ 'counters' => {},
23
+ 'histograms' => {},
24
+ 'meters' => {},
25
+ 'timers' => {}
26
+ }
27
+ end
28
+
29
+ let( :result ){ [ 200, nil, [] ] }
30
+ let( :app ) do
31
+ Proc.new() { result }
32
+ end
33
+
34
+ it 'has response' do
35
+ status, headers, body = subject.response( "/path" )
36
+ expect( status ).to eq 200
37
+ expect( headers.to_yaml).to eq expected_headers.to_yaml
38
+ expect( body.join.count("\n" ) ).to eq 15
39
+ expect( body.join.gsub( 'path/' ).collect { |f| f }.size ).to eq 6
40
+ end
41
+
42
+ describe 'default path' do
43
+ subject { Leafy::Rack::Admin.new( app, metrics, health ) }
44
+
45
+ it 'passes request if not matches the given path' do
46
+ env = { 'PATH_INFO'=> '/something' }
47
+ expect( subject.call( env ) ).to eq result
48
+ end
49
+
50
+ it 'shows menu page on admin path' do
51
+ env = { 'PATH_INFO'=> '/admin' }
52
+ status, headers, body = subject.call( env )
53
+ expect( status ).to eq 200
54
+ expect( headers.to_yaml).to eq expected_headers.to_yaml
55
+ expect( body.join.count("\n" ) ).to eq 15
56
+ end
57
+
58
+ it 'pongs on ping path' do
59
+ env = { 'PATH_INFO'=> '/admin/ping' }
60
+ status, _, body = subject.call( env )
61
+ expect( status ).to eq 200
62
+ expect( body.join ).to eq 'pong'
63
+ end
64
+
65
+ it 'thread dump on threads path' do
66
+ env = { 'PATH_INFO'=> '/admin/threads' }
67
+ status, _, body = subject.call( env )
68
+ expect( status ).to eq 200
69
+ expect( body.join.count( "\n" ) ).to be > 100
70
+ end
71
+
72
+ it 'reports metrics on metrics path' do
73
+ env = { 'PATH_INFO'=> '/admin/metrics' }
74
+ status, _, body = subject.call( env )
75
+ expect( status ).to eq 200
76
+ expect( body.join.count( "\n" ) ).to eq 0
77
+ body = JSON.parse(body.join)
78
+ expect( body.to_yaml ).to eq health_report.to_yaml
79
+ end
80
+
81
+ it 'reports health-checks on health path' do
82
+ env = { 'PATH_INFO'=> '/admin/health' }
83
+ status, _, body = subject.call( env )
84
+ expect( status ).to eq 200
85
+ expect( body.join.count( "\n" ) ).to eq 0
86
+ body = JSON.parse(body.join)
87
+ expect( body.to_yaml ).to eq "--- {}\n"
88
+ end
89
+ end
90
+
91
+ describe 'custom path' do
92
+ subject { Leafy::Rack::Admin.new( app, metrics, health, '/custom' ) }
93
+
94
+ it 'passes request if not matches the given path' do
95
+ env = { 'PATH_INFO'=> '/something' }
96
+ expect( subject.call( env ) ).to eq result
97
+ env = { 'PATH_INFO'=> '/ping' }
98
+ expect( subject.call( env ) ).to eq result
99
+ end
100
+
101
+ it 'shows menu page on admin path' do
102
+ env = { 'PATH_INFO'=> '/custom' }
103
+ status, headers, body = subject.call( env )
104
+ expect( status ).to eq 200
105
+ expect( headers.to_yaml).to eq expected_headers.to_yaml
106
+ expect( body.join.count("\n" ) ).to eq 15
107
+ end
108
+
109
+ it 'pongs on ping path' do
110
+ env = { 'PATH_INFO'=> '/custom/ping' }
111
+ status, _, body = subject.call( env )
112
+ expect( status ).to eq 200
113
+ expect( body.join ).to eq 'pong'
114
+ end
115
+
116
+ it 'thread dump on threads path' do
117
+ env = { 'PATH_INFO'=> '/custom/threads' }
118
+ status, _, body = subject.call( env )
119
+ expect( status ).to eq 200
120
+ expect( body.join.count( "\n" ) ).to be > 100
121
+ end
122
+
123
+ it 'reports metrics on metrics path' do
124
+ env = { 'PATH_INFO'=> '/custom/metrics' }
125
+ status, _, body = subject.call( env )
126
+ expect( status ).to eq 200
127
+ expect( body.join.count( "\n" ) ).to eq 0
128
+ body = JSON.parse(body.join)
129
+ expect( body.to_yaml ).to eq health_report.to_yaml
130
+ end
131
+
132
+ it 'reports health-checks on health path' do
133
+ env = { 'PATH_INFO'=> '/custom/health' }
134
+ status, _, body = subject.call( env )
135
+ expect( status ).to eq 200
136
+ expect( body.join.count( "\n" ) ).to eq 0
137
+ body = JSON.parse(body.join)
138
+ expect( body.to_yaml ).to eq "--- {}\n"
139
+ end
140
+ end
141
+ end