thrift_server 0.1.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.
- checksums.yaml +7 -0
- data/.dockerignore +3 -0
- data/.gitignore +24 -0
- data/Dockerfile +12 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/Makefile +43 -0
- data/README.md +108 -0
- data/Rakefile +12 -0
- data/Vagrantfile +14 -0
- data/benchmark/server.rb +44 -0
- data/echo_client.rb +35 -0
- data/echo_server.rb +33 -0
- data/echo_service.thrift +3 -0
- data/lib/thrift_server.rb +110 -0
- data/lib/thrift_server/error_tracking_middleware.rb +12 -0
- data/lib/thrift_server/honeybadger_error_tracker.rb +11 -0
- data/lib/thrift_server/logging_middleware.rb +13 -0
- data/lib/thrift_server/metrics_middleware.rb +14 -0
- data/lib/thrift_server/version.rb +3 -0
- data/script/buildbox/ci +5 -0
- data/script/buildbox/step_failed +5 -0
- data/test/acceptance_test.rb +225 -0
- data/test/error_tracking_middleware_test.rb +25 -0
- data/test/honeybadger_error_tracking_test.rb +12 -0
- data/test/logging_middleware_test.rb +42 -0
- data/test/metrics_middleware_test.rb +51 -0
- data/test/test_helper.rb +60 -0
- data/thrift_server.gemspec +32 -0
- metadata +218 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9558c4785c5f60c3178add28862c2074d0a45ed9
|
4
|
+
data.tar.gz: af9ce55e5055cca900ff4d32f48558bb21d5a158
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3ec3fd8f56101e485a8f03654cbb921f6d1f5f047b1f408e20da258d11231d5b0e77a0124bd614b2af13f224baeb9776abbc4ea18b93d3c8db3f9813a986d05f
|
7
|
+
data.tar.gz: 8696c6d72a71ed0c6307dd88bd722d40109abbcc0761da9033294808f3a0d0c8e9cfc607c818ef29abed3a7c6eb381ea7acaa0b486e2a889dfd27015fcfce38f
|
data/.dockerignore
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
23
|
+
vendor/cache
|
24
|
+
gen-rb/
|
data/Dockerfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
FROM ruby:2.1
|
2
|
+
|
3
|
+
RUN mkdir -p /usr/src/app
|
4
|
+
WORKDIR /usr/src/app
|
5
|
+
|
6
|
+
ADD Gemfile /usr/src/app/Gemfile
|
7
|
+
ADD lib/thrift_server/version.rb /usr/src/app/lib/thrift_server/version.rb
|
8
|
+
ADD thrift_server.gemspec /usr/src/app/thrift_server.gemspec
|
9
|
+
|
10
|
+
RUN bundle install
|
11
|
+
|
12
|
+
CMD [ "bundle", "console" ]
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 ahawkins
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Makefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
APP:=thrift_server
|
2
|
+
|
3
|
+
.DEFAULT_GOAL:=build
|
4
|
+
|
5
|
+
APP_RUN:=docker run --rm -t -v $(CURDIR):/usr/src/app $(APP)
|
6
|
+
|
7
|
+
gen-rb/echo_service.rb: echo_service.thrift
|
8
|
+
docker run --rm -t -v $(CURDIR):/data thrift:0.9.2 \
|
9
|
+
thrift -o /data --gen rb /data/$<
|
10
|
+
|
11
|
+
.PHONY: thrift
|
12
|
+
thrift: gen-rb/echo_service.rb
|
13
|
+
|
14
|
+
tmp/image: Dockerfile Gemfile lib/thrift_server/version.rb thrift_server.gemspec
|
15
|
+
docker build -t $(APP) .
|
16
|
+
mkdir -p $(@D)
|
17
|
+
docker inspect -f '{{.Id}}' $(APP) >> $@
|
18
|
+
|
19
|
+
.PHONY: build
|
20
|
+
build: tmp/image
|
21
|
+
|
22
|
+
.PHONY: test-unit
|
23
|
+
test-unit: tmp/image
|
24
|
+
$(APP_RUN) bundle exec rake
|
25
|
+
|
26
|
+
.PHONY: test-network
|
27
|
+
test-network: tmp/image gen-rb/echo_service.rb
|
28
|
+
-@docker stop server > /dev/null 2>&1
|
29
|
+
-@docker rm -v server > /dev/null 2>&1
|
30
|
+
docker run -d --name server -v $(CURDIR):/usr/src/app $(APP) ruby echo_server.rb
|
31
|
+
docker run --rm -t -v $(CURDIR):/usr/src/app --link server:server $(APP) ruby echo_client.rb server 9090
|
32
|
+
|
33
|
+
.PHONY: test-ci
|
34
|
+
test-ci: test-unit test-network
|
35
|
+
|
36
|
+
.PHONY: clean
|
37
|
+
clean:
|
38
|
+
-docker stop server > /dev/null 2>&1
|
39
|
+
-docker rm -v server > /dev/null 2>&1
|
40
|
+
@mkdir -p tmp
|
41
|
+
@touch tmp/image
|
42
|
+
cat tmp/image | xargs --no-run-if-empty docker rmi
|
43
|
+
rm -rf tmp/image
|
data/README.md
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
# ThriftServer
|
2
|
+
|
3
|
+
Encapsulate bolierplate code and functionality for running Thrift
|
4
|
+
servers in Ruby. Bundled functionality:
|
5
|
+
|
6
|
+
* Error tracking
|
7
|
+
* Metrics on each RPC
|
8
|
+
* Logging on each RPC
|
9
|
+
* Middleware based approaching making it easy to extend
|
10
|
+
* Binary protocol
|
11
|
+
* Framed transport
|
12
|
+
* Thread pool sever
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
gem 'thrift_server'
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install thrift_server
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
The libary is defined to wrapping Thrift's processor classes in useful
|
31
|
+
functionality for production servers. You must provide objects
|
32
|
+
required to implement the behavior. Here's an example from
|
33
|
+
[echo\_server.rb](echo_server.rb).
|
34
|
+
|
35
|
+
server = ThriftServer.build(EchoService::Processor, Handler.new, {
|
36
|
+
logger: Logger.new($stdout),
|
37
|
+
statsd: Statsd.new,
|
38
|
+
error_tracker: ErrorTracker.new
|
39
|
+
})
|
40
|
+
|
41
|
+
# Now call serve to start it
|
42
|
+
server.serve
|
43
|
+
|
44
|
+
The first arument is a generated `Thrift::Processor` subclass. The second
|
45
|
+
is your implementation of the define protocol. The options hash
|
46
|
+
defines all the misc objecs and settings. The following options are
|
47
|
+
available:
|
48
|
+
|
49
|
+
* `logger:` - a `Logger` instance
|
50
|
+
* `statsd:` - a `Statsd` instance from the [statsd-ruby gem](https://github.com/reinh/statsd)
|
51
|
+
* `error_tracker:` object that implement `#track(rpc, error). Use
|
52
|
+
`ThriftServer::HoneybaderErrorTracker` if unsure
|
53
|
+
* `threads:` - number of threads to run. Defaults to `4`
|
54
|
+
* `port:` - port to run server on. Defaults to `9090`
|
55
|
+
|
56
|
+
## Middleware
|
57
|
+
|
58
|
+
The library uses a middleware approach to implement preprocessing of
|
59
|
+
each RPC before handing it off the original handler. You can
|
60
|
+
implement your own middleware easily. The middleware must respond to
|
61
|
+
`call` and accept a `ThriftServer::RPC` object.
|
62
|
+
`ThriftServer::RPC` is a simple struct with two members: `name` and
|
63
|
+
`args`. Here's an example that dumps the `args` to stdout.
|
64
|
+
|
65
|
+
class ExampleMiddleware
|
66
|
+
include Concord.new(:app)
|
67
|
+
|
68
|
+
def call(rpc)
|
69
|
+
puts rpc.args.inspect
|
70
|
+
app.call rpc
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
New middleware can be added at build time or afterwards.
|
75
|
+
|
76
|
+
ThriftServer::build processor, handler, options do |stack|
|
77
|
+
stack.use ExampleMiddlware
|
78
|
+
end
|
79
|
+
|
80
|
+
Middleware can also be added after the server is built
|
81
|
+
|
82
|
+
server = ThriftServer::build processor, handler, options
|
83
|
+
server.use ExampleMiddleware
|
84
|
+
serve.serve # start it!
|
85
|
+
|
86
|
+
## Implementation
|
87
|
+
|
88
|
+
`ThriftServer` used metaprogramming and delegating to implement the
|
89
|
+
funcationality. `build` used the processor class to determine which
|
90
|
+
methods are required by the protocol. A middleware stack is created
|
91
|
+
using the object passed in the `options` hash. A delegate class is
|
92
|
+
created to wrap each method call to pass through the stack before
|
93
|
+
calling the defined handler. A subclass of the processor is defined to
|
94
|
+
wrap the handler provided in `initialize` in the delegate class.
|
95
|
+
|
96
|
+
## Development
|
97
|
+
|
98
|
+
$ vagrant up
|
99
|
+
$ vagrant ssh
|
100
|
+
$ cd /vagrant
|
101
|
+
$ make test-ci
|
102
|
+
|
103
|
+
## Contributing
|
104
|
+
|
105
|
+
1. Create your feature branch (`git checkout -b my-new-feature`)
|
106
|
+
2. Commit your changes (`git commit -am 'Add some feature'`)
|
107
|
+
3. Push to the branch (`git push origin my-new-feature`)
|
108
|
+
4. Create a new Pull Request
|
data/Rakefile
ADDED
data/Vagrantfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
5
|
+
VAGRANTFILE_API_VERSION = "2"
|
6
|
+
|
7
|
+
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
8
|
+
config.vm.box = "ubuntu/trusty64"
|
9
|
+
|
10
|
+
config.vm.provision "docker" do |docker|
|
11
|
+
docker.pull_images "ruby:2.1"
|
12
|
+
docker.pull_images "thrift:0.9.2"
|
13
|
+
end
|
14
|
+
end
|
data/benchmark/server.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'thrift_server'
|
3
|
+
|
4
|
+
require 'benchmark/ips'
|
5
|
+
require 'logger-better'
|
6
|
+
require 'middleware'
|
7
|
+
|
8
|
+
class NullStatsd
|
9
|
+
def time(*) ; yield ; end
|
10
|
+
def increment(*) ; end
|
11
|
+
end
|
12
|
+
|
13
|
+
class NullErrorTracker
|
14
|
+
def track(*) ; end
|
15
|
+
end
|
16
|
+
|
17
|
+
class FakeProcessor
|
18
|
+
include Concord.new(:handler)
|
19
|
+
|
20
|
+
def process_someRPC
|
21
|
+
handler.someRPC
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class FakeHandler
|
26
|
+
def someRPC
|
27
|
+
:response
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Benchmark.ips do |x|
|
32
|
+
x.time = 20
|
33
|
+
x.warmup = 5
|
34
|
+
|
35
|
+
processor = ThriftServer.wrap(FakeProcessor, {
|
36
|
+
logger: NullLogger.new,
|
37
|
+
statsd: NullStatsd.new,
|
38
|
+
error_tracker: NullErrorTracker.new
|
39
|
+
})
|
40
|
+
|
41
|
+
server = processor.new FakeHandler.new
|
42
|
+
|
43
|
+
x.report("server") { server.process_someRPC }
|
44
|
+
end
|
data/echo_client.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
$stdout.sync = true
|
2
|
+
$stderr.sync = true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'thrift_server'
|
6
|
+
|
7
|
+
$LOAD_PATH << "#{__dir__}/gen-rb"
|
8
|
+
|
9
|
+
require 'echo_service'
|
10
|
+
|
11
|
+
host, port = ARGV[0], ARGV[1]
|
12
|
+
|
13
|
+
if !host || !port
|
14
|
+
$stdout.puts "usage: echo_client HOST PORT"
|
15
|
+
abort
|
16
|
+
end
|
17
|
+
|
18
|
+
logger = Logger.new $stdout
|
19
|
+
|
20
|
+
transport = Thrift::FramedTransport.new(Thrift::Socket.new(host, port.to_i))
|
21
|
+
transport.open
|
22
|
+
|
23
|
+
protocol = Thrift::BinaryProtocol.new transport
|
24
|
+
client = EchoService::Client.new protocol
|
25
|
+
|
26
|
+
result = client.echo "testing"
|
27
|
+
|
28
|
+
transport.close
|
29
|
+
|
30
|
+
if result == 'testing'
|
31
|
+
$stdout.puts 'OK'
|
32
|
+
else
|
33
|
+
$stderr.puts 'Message not echoed'
|
34
|
+
abort
|
35
|
+
end
|
data/echo_server.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
$stdout.sync = true
|
2
|
+
$stderr.sync = true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'thrift_server'
|
6
|
+
|
7
|
+
$LOAD_PATH << "#{__dir__}/gen-rb"
|
8
|
+
|
9
|
+
require 'echo_service'
|
10
|
+
|
11
|
+
class Handler
|
12
|
+
def echo(msg)
|
13
|
+
msg
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class ErrorTracker
|
18
|
+
def track(*)
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
logger = Logger.new $stdout
|
24
|
+
|
25
|
+
server = ThriftServer.build(EchoService::Processor, Handler.new, {
|
26
|
+
logger: logger,
|
27
|
+
statsd: Statsd.new,
|
28
|
+
error_tracker: ErrorTracker.new
|
29
|
+
})
|
30
|
+
|
31
|
+
logger.info 'Starting server'
|
32
|
+
|
33
|
+
server.serve
|
data/echo_service.thrift
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
require "thrift_server/version"
|
2
|
+
|
3
|
+
require 'thrift'
|
4
|
+
require 'middleware'
|
5
|
+
require 'concord'
|
6
|
+
require 'forwardable'
|
7
|
+
require 'honeybadger'
|
8
|
+
require 'statsd-ruby'
|
9
|
+
|
10
|
+
require_relative 'thrift_server/logging_middleware'
|
11
|
+
require_relative 'thrift_server/metrics_middleware'
|
12
|
+
require_relative 'thrift_server/error_tracking_middleware'
|
13
|
+
require_relative 'thrift_server/honeybadger_error_tracker'
|
14
|
+
|
15
|
+
class ThriftServer
|
16
|
+
RPC = Struct.new(:name, :args)
|
17
|
+
|
18
|
+
class MiddlewareStack < Middleware::Builder
|
19
|
+
def finalize!
|
20
|
+
stack.freeze
|
21
|
+
to_app
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class StackDelegate
|
26
|
+
class Dispatcher
|
27
|
+
include Concord.new(:app, :handler)
|
28
|
+
|
29
|
+
def call(rpc)
|
30
|
+
handler.send rpc.name, *rpc.args
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
extend Forwardable
|
35
|
+
|
36
|
+
include Concord.new(:stack, :handler)
|
37
|
+
|
38
|
+
def_delegator :stack, :use
|
39
|
+
|
40
|
+
def call(rpc)
|
41
|
+
app.call rpc
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def app
|
46
|
+
@app ||= finalize_stack!
|
47
|
+
end
|
48
|
+
|
49
|
+
def finalize_stack!
|
50
|
+
stack.use Dispatcher, handler
|
51
|
+
stack.finalize!
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class << self
|
56
|
+
def build(processor, handler, options = { }, &block)
|
57
|
+
stack = wrap(processor, options, &block).new handler
|
58
|
+
transport = Thrift::ServerSocket.new options.fetch(:port, 9090)
|
59
|
+
transport_factory = Thrift::FramedTransportFactory.new
|
60
|
+
|
61
|
+
Thrift::ThreadPoolServer.new stack, transport, transport_factory, nil, options.fetch(:threads, 4)
|
62
|
+
end
|
63
|
+
|
64
|
+
def wrap(processor, options = { })
|
65
|
+
rpcs = processor.instance_methods.select { |m| m =~ /^process_(.+)$/ }
|
66
|
+
|
67
|
+
logger = options.fetch :logger do
|
68
|
+
fail ArgumentError, ':logger required'
|
69
|
+
end
|
70
|
+
|
71
|
+
statsd = options.fetch :statsd do
|
72
|
+
fail ArgumentError, ':statsd required'
|
73
|
+
end
|
74
|
+
|
75
|
+
error_tracker = options.fetch :error_tracker do
|
76
|
+
fail ArgumentError, ':error_tracker required'
|
77
|
+
end
|
78
|
+
|
79
|
+
stack = MiddlewareStack.new
|
80
|
+
stack.use ErrorTrackingMiddleware, error_tracker
|
81
|
+
stack.use MetricsMiddleware, statsd
|
82
|
+
stack.use LoggingMiddleware, logger
|
83
|
+
|
84
|
+
yield stack if block_given?
|
85
|
+
|
86
|
+
wrapped = Class.new processor do
|
87
|
+
extend Forwardable
|
88
|
+
|
89
|
+
def_delegator :@handler, :use
|
90
|
+
|
91
|
+
define_method :initialize do |handler|
|
92
|
+
stack_delegator = Class.new StackDelegate
|
93
|
+
stack_delegator.module_eval do
|
94
|
+
rpcs.each do |method|
|
95
|
+
rpc_name = method.to_s.match(/^process_(.+)$/)[1]
|
96
|
+
|
97
|
+
define_method rpc_name.to_sym do |*args|
|
98
|
+
call RPC.new(rpc_name, args)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
super stack_delegator.new(stack, handler)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
wrapped
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
data/script/buildbox/ci
ADDED
@@ -0,0 +1,225 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class AcceptanceTest < MiniTest::Unit::TestCase
|
4
|
+
attr_reader :processor
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@processor = Processor(:getItems)
|
8
|
+
end
|
9
|
+
|
10
|
+
def wrap(klass, &block)
|
11
|
+
ThriftServer.wrap(processor, {
|
12
|
+
logger: NullLogger.new,
|
13
|
+
statsd: FakeStatsd.new,
|
14
|
+
error_tracker: NullErrorTracker.new,
|
15
|
+
}, &block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_wrap_fails_if_no_logger
|
19
|
+
ex = assert_raises ArgumentError do
|
20
|
+
ThriftServer.wrap(processor, {
|
21
|
+
statsd: FakeStatsd.new,
|
22
|
+
error_tracker: NullErrorTracker.new,
|
23
|
+
})
|
24
|
+
end
|
25
|
+
|
26
|
+
assert_match /logger/, ex.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_wrap_fails_if_no_stats
|
30
|
+
ex = assert_raises ArgumentError do
|
31
|
+
ThriftServer.wrap(processor, {
|
32
|
+
logger: NullLogger.new,
|
33
|
+
error_tracker: NullErrorTracker.new,
|
34
|
+
})
|
35
|
+
end
|
36
|
+
|
37
|
+
assert_match /statsd/, ex.to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_wrap_fails_if_no_error_tracker
|
41
|
+
ex = assert_raises ArgumentError do
|
42
|
+
ThriftServer.wrap(processor, {
|
43
|
+
logger: NullLogger.new,
|
44
|
+
statsd: FakeStatsd.new
|
45
|
+
})
|
46
|
+
end
|
47
|
+
|
48
|
+
assert_match /error_tracker/, ex.to_s
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_wraps_methods_defined_by_the_protocol
|
52
|
+
handler = stub
|
53
|
+
handler.expects(:getItems).with(:request).returns(:response)
|
54
|
+
|
55
|
+
stack = wrap(processor).new(handler)
|
56
|
+
|
57
|
+
assert_equal :response, stack.process_getItems(:request)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_can_add_new_middleware_after_wrapping
|
61
|
+
handler = mock
|
62
|
+
handler.expects(:getItems).with(:modified_args)
|
63
|
+
|
64
|
+
stack = wrap(processor).new(handler)
|
65
|
+
|
66
|
+
test_middleware = Class.new do
|
67
|
+
def initialize(app)
|
68
|
+
@app = app
|
69
|
+
end
|
70
|
+
|
71
|
+
def call(env)
|
72
|
+
env.args = :modified_args
|
73
|
+
@app.call env
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
stack.use test_middleware
|
78
|
+
|
79
|
+
stack.process_getItems :request
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_cannot_add_middleware_to_stack_after_first_rpc
|
83
|
+
handler = stub getItems: :response
|
84
|
+
|
85
|
+
stack = wrap(processor).new(handler)
|
86
|
+
|
87
|
+
stack.process_getItems :request
|
88
|
+
|
89
|
+
ex = assert_raises RuntimeError do
|
90
|
+
stack.use ->(rpc) { rpc }
|
91
|
+
end
|
92
|
+
|
93
|
+
assert_match /frozen/, ex.to_s
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_wrap_yields_the_middleware_stack
|
97
|
+
handler = mock
|
98
|
+
handler.expects(:getItems).with(:from_block)
|
99
|
+
|
100
|
+
test_middleware = Class.new do
|
101
|
+
def initialize(app)
|
102
|
+
@app = app
|
103
|
+
end
|
104
|
+
|
105
|
+
def call(env)
|
106
|
+
env.args = :from_block
|
107
|
+
@app.call env
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
stack_processor = wrap processor do |stack|
|
112
|
+
stack.use test_middleware
|
113
|
+
end
|
114
|
+
stack = stack_processor.new(handler)
|
115
|
+
|
116
|
+
stack.process_getItems :request
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_build_returns_thread_pool_server
|
120
|
+
handler = stub getItems: :response
|
121
|
+
server = ThriftServer.build(processor, handler, {
|
122
|
+
logger: NullLogger.new,
|
123
|
+
statsd: FakeStatsd.new,
|
124
|
+
error_tracker: NullErrorTracker.new
|
125
|
+
})
|
126
|
+
|
127
|
+
assert_instance_of Thrift::ThreadPoolServer, server
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_build_defaults_to_port_9090
|
131
|
+
handler = stub getItems: :response
|
132
|
+
server = ThriftServer.build(processor, handler, {
|
133
|
+
logger: NullLogger.new,
|
134
|
+
statsd: FakeStatsd.new,
|
135
|
+
error_tracker: NullErrorTracker.new
|
136
|
+
})
|
137
|
+
|
138
|
+
assert_equal 9090, server.port
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_build_accepts_port_options
|
142
|
+
handler = stub getItems: :response
|
143
|
+
server = ThriftServer.build(processor, handler, {
|
144
|
+
logger: NullLogger.new,
|
145
|
+
statsd: FakeStatsd.new,
|
146
|
+
error_tracker: NullErrorTracker.new,
|
147
|
+
port: 5000
|
148
|
+
})
|
149
|
+
|
150
|
+
assert_equal 5000, server.port
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_build_defaults_to_4_threads
|
154
|
+
handler = stub getItems: :response
|
155
|
+
server = ThriftServer.build(processor, handler, {
|
156
|
+
logger: NullLogger.new,
|
157
|
+
statsd: FakeStatsd.new,
|
158
|
+
error_tracker: NullErrorTracker.new
|
159
|
+
})
|
160
|
+
|
161
|
+
assert_equal 4, server.threads
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_build_accepts_threads_option
|
165
|
+
handler = stub getItems: :response
|
166
|
+
server = ThriftServer.build(processor, handler, {
|
167
|
+
logger: NullLogger.new,
|
168
|
+
statsd: FakeStatsd.new,
|
169
|
+
error_tracker: NullErrorTracker.new,
|
170
|
+
threads: 8
|
171
|
+
})
|
172
|
+
|
173
|
+
assert_equal 8, server.threads
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_builds_creates_server_with_framed_transport
|
177
|
+
handler = stub getItems: :response
|
178
|
+
server = ThriftServer.build(processor, handler, {
|
179
|
+
logger: NullLogger.new,
|
180
|
+
statsd: FakeStatsd.new,
|
181
|
+
error_tracker: NullErrorTracker.new
|
182
|
+
})
|
183
|
+
|
184
|
+
assert_instance_of Thrift::FramedTransportFactory, server.transport_factory
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_build_uses_server_socket_transport
|
188
|
+
handler = stub getItems: :response
|
189
|
+
server = ThriftServer.build(processor, handler, {
|
190
|
+
logger: NullLogger.new,
|
191
|
+
statsd: FakeStatsd.new,
|
192
|
+
error_tracker: NullErrorTracker.new
|
193
|
+
})
|
194
|
+
|
195
|
+
assert_instance_of Thrift::ServerSocket, server.server_transport
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_build_creates_server_with_binary_protocol
|
199
|
+
handler = stub getItems: :response
|
200
|
+
server = ThriftServer.build(processor, handler, {
|
201
|
+
logger: NullLogger.new,
|
202
|
+
statsd: FakeStatsd.new,
|
203
|
+
error_tracker: NullErrorTracker.new
|
204
|
+
})
|
205
|
+
|
206
|
+
assert_instance_of Thrift::BinaryProtocolFactory, server.protocol_factory
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_buil_accepts_a_block_to_customize_the_middleware_stack
|
210
|
+
handler = stub getItems: :response
|
211
|
+
block_yielded = false
|
212
|
+
|
213
|
+
server = ThriftServer.build(processor, handler, {
|
214
|
+
logger: NullLogger.new,
|
215
|
+
statsd: FakeStatsd.new,
|
216
|
+
error_tracker: NullErrorTracker.new
|
217
|
+
}) do |stack|
|
218
|
+
block_yielded = true
|
219
|
+
|
220
|
+
assert_instance_of ThriftServer::MiddlewareStack, stack
|
221
|
+
end
|
222
|
+
|
223
|
+
assert block_yielded, 'Block not used'
|
224
|
+
end
|
225
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class ErrorTrackingMiddlewareTest < MiniTest::Unit::TestCase
|
4
|
+
attr_reader :rpc
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@rpc = ThriftServer::RPC.new :foo, :bar
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_logs_errors
|
11
|
+
error = TestError.new
|
12
|
+
|
13
|
+
logger = mock
|
14
|
+
logger.expects(:track).with(rpc, error)
|
15
|
+
|
16
|
+
app = stub
|
17
|
+
app.stubs(:call).raises(error)
|
18
|
+
|
19
|
+
middleware = ThriftServer::ErrorTrackingMiddleware.new app, logger
|
20
|
+
|
21
|
+
assert_raises TestError do
|
22
|
+
middleware.call rpc
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class HoneybadgerErrorTrackerTest < MiniTest::Unit::TestCase
|
4
|
+
def test_logs_according_to_honeybadger_api
|
5
|
+
client = mock
|
6
|
+
client.expects(:notify_or_ignore).with(:error)
|
7
|
+
|
8
|
+
tracker = ThriftServer::HoneybadgerErrorTracker.new client
|
9
|
+
|
10
|
+
tracker.track :rpc, :error
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class LoggingMiddlewareTest < MiniTest::Unit::TestCase
|
4
|
+
attr_reader :output, :logger, :rpc
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@output = StringIO.new
|
8
|
+
@logger = Logger.new output
|
9
|
+
@rpc = ThriftServer::RPC.new :foo, :bar
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_logs_incoming_rpcs_names
|
13
|
+
app = stub call: :result
|
14
|
+
|
15
|
+
middleware = ThriftServer::LoggingMiddleware.new(app, logger)
|
16
|
+
|
17
|
+
middleware.call rpc
|
18
|
+
|
19
|
+
assert_logged output, 'INFO'
|
20
|
+
assert_logged output, rpc.name
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_logs_errors
|
24
|
+
app = stub
|
25
|
+
app.stubs(:call).raises(TestError)
|
26
|
+
|
27
|
+
middleware = ThriftServer::LoggingMiddleware.new(app, logger)
|
28
|
+
|
29
|
+
assert_raises TestError do
|
30
|
+
middleware.call rpc
|
31
|
+
end
|
32
|
+
|
33
|
+
assert_logged output, 'ERROR'
|
34
|
+
assert_logged output, 'TestError'
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def assert_logged(log, text)
|
39
|
+
log.rewind
|
40
|
+
assert log.read.include?(text.to_s), "#{text} not logged"
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class MetricsMiddlewareTest < MiniTest::Unit::TestCase
|
4
|
+
attr_reader :rpc
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@rpc = ThriftServer::RPC.new :foo, :bar
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_times_the_rpc
|
11
|
+
app = stub call: :result
|
12
|
+
|
13
|
+
statsd = Class.new FakeStatsd do
|
14
|
+
attr_reader :timer
|
15
|
+
|
16
|
+
def time(*args)
|
17
|
+
@timer = args.first
|
18
|
+
yield
|
19
|
+
end
|
20
|
+
end.new
|
21
|
+
|
22
|
+
middleware = ThriftServer::MetricsMiddleware.new(app, statsd)
|
23
|
+
|
24
|
+
middleware.call rpc
|
25
|
+
|
26
|
+
assert statsd.timer, 'Timer not recorded'
|
27
|
+
assert_equal rpc.name, statsd.timer
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_increments_a_counter_on_failed_rpcs
|
31
|
+
app = stub
|
32
|
+
app.stubs(:call).raises(TestError)
|
33
|
+
|
34
|
+
statsd = Class.new FakeStatsd do
|
35
|
+
attr_reader :counter
|
36
|
+
|
37
|
+
def increment(*args)
|
38
|
+
@counter = args.first
|
39
|
+
end
|
40
|
+
end.new
|
41
|
+
|
42
|
+
middleware = ThriftServer::MetricsMiddleware.new(app, statsd)
|
43
|
+
|
44
|
+
assert_raises TestError do
|
45
|
+
middleware.call rpc
|
46
|
+
end
|
47
|
+
|
48
|
+
assert statsd.counter, 'Counter not updated'
|
49
|
+
assert_equal 'errors', statsd.counter
|
50
|
+
end
|
51
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'thrift_server'
|
3
|
+
|
4
|
+
require 'stringio'
|
5
|
+
require 'logger-better'
|
6
|
+
|
7
|
+
require 'minitest/autorun'
|
8
|
+
require 'mocha/mini_test'
|
9
|
+
|
10
|
+
TestError = Class.new StandardError
|
11
|
+
|
12
|
+
class FakeStatsd
|
13
|
+
def time(*)
|
14
|
+
yield
|
15
|
+
end
|
16
|
+
|
17
|
+
def increment(*)
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class NullErrorTracker
|
23
|
+
def track(*)
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def Processor(*rpcs)
|
29
|
+
Class.new do
|
30
|
+
def initialize(handler)
|
31
|
+
@handler = handler
|
32
|
+
end
|
33
|
+
|
34
|
+
rpcs.each do |method_name|
|
35
|
+
define_method "process_#{method_name}" do |*args|
|
36
|
+
# nothing to do, this is just a stub to create objects inline
|
37
|
+
# with the generate thrift processors
|
38
|
+
@handler.send method_name, *args
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Monkey patch attr readers to test various server settings
|
45
|
+
module Thrift
|
46
|
+
class ServerSocket
|
47
|
+
attr_reader :port
|
48
|
+
end
|
49
|
+
|
50
|
+
class ThreadPoolServer
|
51
|
+
attr_reader :server_transport, :transport_factory, :protocol_factory
|
52
|
+
def threads
|
53
|
+
@thread_q.max
|
54
|
+
end
|
55
|
+
|
56
|
+
def port
|
57
|
+
server_transport.port
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'thrift_server/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "thrift_server"
|
8
|
+
spec.version = ThriftServer::VERSION
|
9
|
+
spec.authors = ["ahawkins"]
|
10
|
+
spec.email = ["adam@saltside.se"]
|
11
|
+
spec.summary = %q{Encapsulate error handling, logging, and metrics for thrift servers}
|
12
|
+
spec.description = %q{}
|
13
|
+
spec.homepage = "https://github.com/saltside/thrift_server-ruby"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "statsd-ruby"
|
22
|
+
spec.add_dependency "middleware"
|
23
|
+
spec.add_dependency "concord"
|
24
|
+
spec.add_dependency "honeybadger"
|
25
|
+
spec.add_dependency "thrift"
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
28
|
+
spec.add_development_dependency "rake"
|
29
|
+
spec.add_development_dependency "mocha"
|
30
|
+
spec.add_development_dependency "logger-better"
|
31
|
+
spec.add_development_dependency "benchmark-ips"
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: thrift_server
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- ahawkins
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: statsd-ruby
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: middleware
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
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: concord
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: honeybadger
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: thrift
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.6'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.6'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: mocha
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: logger-better
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: benchmark-ips
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
description: ''
|
154
|
+
email:
|
155
|
+
- adam@saltside.se
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- ".dockerignore"
|
161
|
+
- ".gitignore"
|
162
|
+
- Dockerfile
|
163
|
+
- Gemfile
|
164
|
+
- LICENSE.txt
|
165
|
+
- Makefile
|
166
|
+
- README.md
|
167
|
+
- Rakefile
|
168
|
+
- Vagrantfile
|
169
|
+
- benchmark/server.rb
|
170
|
+
- echo_client.rb
|
171
|
+
- echo_server.rb
|
172
|
+
- echo_service.thrift
|
173
|
+
- lib/thrift_server.rb
|
174
|
+
- lib/thrift_server/error_tracking_middleware.rb
|
175
|
+
- lib/thrift_server/honeybadger_error_tracker.rb
|
176
|
+
- lib/thrift_server/logging_middleware.rb
|
177
|
+
- lib/thrift_server/metrics_middleware.rb
|
178
|
+
- lib/thrift_server/version.rb
|
179
|
+
- script/buildbox/ci
|
180
|
+
- script/buildbox/step_failed
|
181
|
+
- test/acceptance_test.rb
|
182
|
+
- test/error_tracking_middleware_test.rb
|
183
|
+
- test/honeybadger_error_tracking_test.rb
|
184
|
+
- test/logging_middleware_test.rb
|
185
|
+
- test/metrics_middleware_test.rb
|
186
|
+
- test/test_helper.rb
|
187
|
+
- thrift_server.gemspec
|
188
|
+
homepage: https://github.com/saltside/thrift_server-ruby
|
189
|
+
licenses:
|
190
|
+
- MIT
|
191
|
+
metadata: {}
|
192
|
+
post_install_message:
|
193
|
+
rdoc_options: []
|
194
|
+
require_paths:
|
195
|
+
- lib
|
196
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
197
|
+
requirements:
|
198
|
+
- - ">="
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: '0'
|
201
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
202
|
+
requirements:
|
203
|
+
- - ">="
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
206
|
+
requirements: []
|
207
|
+
rubyforge_project:
|
208
|
+
rubygems_version: 2.2.2
|
209
|
+
signing_key:
|
210
|
+
specification_version: 4
|
211
|
+
summary: Encapsulate error handling, logging, and metrics for thrift servers
|
212
|
+
test_files:
|
213
|
+
- test/acceptance_test.rb
|
214
|
+
- test/error_tracking_middleware_test.rb
|
215
|
+
- test/honeybadger_error_tracking_test.rb
|
216
|
+
- test/logging_middleware_test.rb
|
217
|
+
- test/metrics_middleware_test.rb
|
218
|
+
- test/test_helper.rb
|