ostrich-jruby 2.0.1
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/Gemfile +23 -0
- data/Rakefile +18 -0
- data/lib/ostrich-jruby.rb +12 -0
- data/lib/ostrich-jruby/command_handler.rb +41 -0
- data/lib/ostrich-jruby/ext/hash.rb +9 -0
- data/lib/ostrich-jruby/grape_endpoint.rb +22 -0
- data/lib/ostrich-jruby/scala/functions.rb +21 -0
- data/lib/ostrich-jruby/scala/kernel.rb +7 -0
- data/lib/ostrich-jruby/stats.rb +43 -0
- data/lib/ostrich-jruby/util.rb +3 -0
- data/lib/ostrich-jruby/util/duration.rb +18 -0
- data/lib/ostrich-jruby/version.rb +3 -0
- data/ostrich-jruby.gemspec +22 -0
- data/spec/command_handler_spec.rb +21 -0
- data/spec/ext/hash_spec.rb +19 -0
- data/spec/grape_endpoint_spec.rb +20 -0
- data/spec/spec_helper.rb +49 -0
- data/spec/stats_spec.rb +29 -0
- data/spec/util/duration_spec.rb +14 -0
- metadata +64 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a5501e591147820c321e0b7e44c807f431664f66
|
4
|
+
data.tar.gz: 76fabcc57352345790b7e6b5ac9a265ac08f85fa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5365b0eb50c41dd1e13063191f919a8c2774ad7719ca63a99a82e5dfdd9fadd5e8ecd25ad54d1548cea8d82a8b618c6b7653d543fdcaefee72191fe9b4ec450b
|
7
|
+
data.tar.gz: 3db43bca39f2197d98dd1d3669f56a7b01fcf9c3b644626e5c04e2b3744b6698f57e17619621a15b9189acf90bbd674d566cf78f661d29eeb1ee5b6d4f900f3c
|
data/Gemfile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
source "http://gems.local.twitter.com"
|
2
|
+
|
3
|
+
group :development, :test do
|
4
|
+
gem "rake"
|
5
|
+
gem "jbundler"
|
6
|
+
|
7
|
+
# necessary for development because jbundler
|
8
|
+
# doesn't bootstrap our environment properly
|
9
|
+
load 'ostrich-jruby.gemspec'
|
10
|
+
|
11
|
+
require 'jbundler/classpath_file'
|
12
|
+
JBundler::ClasspathFile.new.require_classpath
|
13
|
+
|
14
|
+
require 'ostrich-jruby'
|
15
|
+
end
|
16
|
+
|
17
|
+
group :test do
|
18
|
+
gem 'rspec', '~> 2.11.0'
|
19
|
+
gem 'rr', '~> 1.0.4'
|
20
|
+
gem 'grape', '~> 0.11.0'
|
21
|
+
gem 'json'
|
22
|
+
gem 'rack-test'
|
23
|
+
end
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
4
|
+
|
5
|
+
require 'bundler'
|
6
|
+
require 'digest'
|
7
|
+
|
8
|
+
require 'rubygems/package_task'
|
9
|
+
require 'rspec/core/rake_task'
|
10
|
+
|
11
|
+
Bundler::GemHelper.install_tasks
|
12
|
+
|
13
|
+
task :default => :spec
|
14
|
+
|
15
|
+
desc 'Run specs'
|
16
|
+
RSpec::Core::RakeTask.new do |t|
|
17
|
+
t.pattern = './spec/**/*_spec.rb'
|
18
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Ostrich
|
2
|
+
autoload :Stats, "ostrich-jruby/stats"
|
3
|
+
autoload :CommandHandler, "ostrich-jruby/command_handler"
|
4
|
+
autoload :GrapeEndpoint, "ostrich-jruby/grape_endpoint"
|
5
|
+
end
|
6
|
+
|
7
|
+
require "java"
|
8
|
+
require "ostrich-jruby/util"
|
9
|
+
|
10
|
+
require "ostrich-jruby/ext/hash"
|
11
|
+
require "ostrich-jruby/scala/functions"
|
12
|
+
require "ostrich-jruby/scala/kernel"
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# https://github.com/twitter/ostrich/blob/master/src/main/scala/com/twitter/ostrich/admin/CommandHandler.scala
|
2
|
+
module Ostrich
|
3
|
+
class CommandHandler
|
4
|
+
|
5
|
+
attr_reader :handler
|
6
|
+
|
7
|
+
DEFAULT_MIN_DURATION = Util::Duration.from_seconds(60)
|
8
|
+
|
9
|
+
def initialize(stats_collection, min_period = DEFAULT_MIN_DURATION)
|
10
|
+
@handler = handler_class.new(nil, stats_collection, min_period)
|
11
|
+
end
|
12
|
+
|
13
|
+
%w(ping stats).each do |command|
|
14
|
+
define_method(command.to_sym) do |parameters = {}, format = :json|
|
15
|
+
execute(command.to_s, parameters, format)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def execute(command, parameters, format)
|
22
|
+
handler.apply(command, parameters.to_scala, format_obj_for(format))
|
23
|
+
end
|
24
|
+
|
25
|
+
def handler_class
|
26
|
+
com.twitter.ostrich.admin.CommandHandler
|
27
|
+
end
|
28
|
+
|
29
|
+
def format_obj_for(symbol)
|
30
|
+
java_sym = case symbol
|
31
|
+
when :txt then :PlainText
|
32
|
+
when :json then :Json
|
33
|
+
else
|
34
|
+
raise "Invalid format"
|
35
|
+
end
|
36
|
+
|
37
|
+
companion(com.twitter.ostrich.admin, :Format, java_sym)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'grape'
|
2
|
+
|
3
|
+
module Ostrich
|
4
|
+
class GrapeEndpoint < Grape::API
|
5
|
+
|
6
|
+
# let Ostrich handle the formatting for json (just return the string)
|
7
|
+
content_type :json, "application/json"
|
8
|
+
formatter :json, lambda { |object, env| object }
|
9
|
+
|
10
|
+
default_format :json
|
11
|
+
|
12
|
+
desc "Get stats from ostrich." do
|
13
|
+
named: 'stats'
|
14
|
+
end
|
15
|
+
|
16
|
+
get :stats do
|
17
|
+
handler = Ostrich::CommandHandler.new(Ostrich::Stats.collection)
|
18
|
+
handler.stats(params, params[:format].to_sym)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Scala
|
2
|
+
class Function
|
3
|
+
attr_reader :proc
|
4
|
+
|
5
|
+
def initialize(proc)
|
6
|
+
@proc = proc
|
7
|
+
end
|
8
|
+
|
9
|
+
def method_missing(method, *args, &block)
|
10
|
+
# This is necessary for Scala's "specialization" feature,
|
11
|
+
# which will call `apply$mcD$sp` if it wants a double, for example.
|
12
|
+
if method.to_s =~ /\Aapply/
|
13
|
+
proc.call(*args, &block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Function0 < Function
|
19
|
+
include Java::Scala.Function0
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# https://github.com/twitter/ostrich/blob/master/src/main/scala/com/twitter/ostrich/stats/Stats.scala
|
2
|
+
# https://github.com/twitter/ostrich/blob/master/src/main/scala/com/twitter/ostrich/stats/StatsCollection.scala
|
3
|
+
# https://github.com/twitter/ostrich/blob/master/src/main/scala/com/twitter/ostrich/stats/StatsProvider.scala
|
4
|
+
module Ostrich
|
5
|
+
class Stats
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def incr(name, amount = 1)
|
9
|
+
collection.incr(name, amount)
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_counter(name)
|
13
|
+
collection.getCounter(name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_gauge(name, &block)
|
17
|
+
proc = Scala::Function0.new(block)
|
18
|
+
collection.addGauge(name, proc)
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_gauge(name)
|
22
|
+
collection.getGauge(name)
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_metric(name, value)
|
26
|
+
collection.addMetric(name, value)
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_metric(name)
|
30
|
+
collection.getMetric(name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def clear_all
|
34
|
+
collection.clearAll
|
35
|
+
end
|
36
|
+
|
37
|
+
def collection
|
38
|
+
companion(com.twitter.ostrich.stats, :Stats)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# https://github.com/twitter/util/blob/master/util-core/src/main/scala/com/twitter/util/Duration.scala
|
2
|
+
module Util
|
3
|
+
class Duration
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def from_seconds(seconds)
|
7
|
+
duration.fromSeconds(seconds)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def duration
|
13
|
+
companion(com.twitter.util, :Duration)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
4
|
+
require 'ostrich-jruby/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "ostrich-jruby"
|
8
|
+
s.version = '2.0.1'
|
9
|
+
s.authors = ["Cameron Dutro"]
|
10
|
+
s.email = ["cdutro@twitter.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
|
13
|
+
s.description = s.summary = "Ruby wrapper around the stats collector & reporter for Scala servers"
|
14
|
+
|
15
|
+
s.platform = Gem::Platform::RUBY
|
16
|
+
s.has_rdoc = true
|
17
|
+
|
18
|
+
s.requirements << "jar 'com.twitter:ostrich', '9.2.0'"
|
19
|
+
s.require_path = 'lib'
|
20
|
+
|
21
|
+
s.files = Dir["{lib,spec}/**/*", "Gemfile", "History.txt", "LICENSE", "README.md", "Rakefile", "ostrich-jruby.gemspec"]
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Ostrich::CommandHandler do
|
6
|
+
let(:handler) { Ostrich::CommandHandler.new(Ostrich::Stats.collection) }
|
7
|
+
|
8
|
+
describe "#ping" do
|
9
|
+
it "should return 'pong'" do
|
10
|
+
JSON.parse(handler.ping).should == { "response" => "pong" }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#stats" do
|
15
|
+
def get_stats(params)
|
16
|
+
handler.stats({}, params[:format])
|
17
|
+
end
|
18
|
+
|
19
|
+
it_behaves_like "a stats reporter"
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Hash do
|
6
|
+
describe "#to_scala" do
|
7
|
+
let(:hash) do
|
8
|
+
{ "a" => "b", "c" => "d" }
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should convert the ruby hash into a mutable scala hashmap" do
|
12
|
+
hash.to_scala.tap do |hash_map|
|
13
|
+
hash_map.should be_a(Java::Scala.collection.mutable::HashMap)
|
14
|
+
hash_map.get("a").get.should == "b"
|
15
|
+
hash_map.get("c").get.should == "d"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Ostrich::GrapeEndpoint do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
|
8
|
+
def app
|
9
|
+
Ostrich::GrapeEndpoint
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#stats" do
|
13
|
+
def get_stats(params)
|
14
|
+
get "stats.#{params[:format]}"
|
15
|
+
last_response.body
|
16
|
+
end
|
17
|
+
|
18
|
+
it_behaves_like "a stats reporter"
|
19
|
+
end
|
20
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require "rspec"
|
4
|
+
require "ostrich-jruby"
|
5
|
+
require 'rack/test'
|
6
|
+
require 'json'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.mock_with(:rr)
|
11
|
+
|
12
|
+
config.before(:each) do
|
13
|
+
Ostrich::Stats.clear_all
|
14
|
+
end
|
15
|
+
|
16
|
+
shared_examples "a stats reporter" do
|
17
|
+
it "should report basic JVM stats in json format" do
|
18
|
+
results = JSON.parse(get_stats(format: :json))
|
19
|
+
results["gauges"].should include("jvm_heap_committed")
|
20
|
+
results["counters"].should include("jvm_gc_msec")
|
21
|
+
end
|
22
|
+
|
23
|
+
# NOTE: the txt format just so happens to be yaml
|
24
|
+
it "should report basic JVM stats in txt format" do
|
25
|
+
results = YAML.load(get_stats(format: :txt))
|
26
|
+
results["gauges"].should include("jvm_heap_committed")
|
27
|
+
results["counters"].should include("jvm_gc_msec")
|
28
|
+
end
|
29
|
+
|
30
|
+
context "with some statsy things" do
|
31
|
+
before(:each) do
|
32
|
+
Ostrich::Stats.incr("foo", 2)
|
33
|
+
Ostrich::Stats.add_gauge("bar") { 4 + 1 }
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should report custom counters and gauges in json format" do
|
37
|
+
results = JSON.parse(get_stats(format: :json))
|
38
|
+
results["counters"]["foo"].should == 2
|
39
|
+
results["gauges"]["bar"].should == 5
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should report custom counters and gauges in txt format" do
|
43
|
+
results = YAML.load(get_stats(format: :txt))
|
44
|
+
results["counters"]["foo"].should == 2
|
45
|
+
results["gauges"]["bar"].should == 5
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/spec/stats_spec.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Ostrich::Stats do
|
6
|
+
let(:stats) { Ostrich::Stats }
|
7
|
+
|
8
|
+
describe "#incr" do
|
9
|
+
it "should increment the stat" do
|
10
|
+
stats.incr("blarg").should == 1
|
11
|
+
stats.incr("blarg", 2).should == 3
|
12
|
+
stats.get_counter("blarg").apply.should == 3
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#add_gauge" do
|
17
|
+
it "should add a gauge with a block" do
|
18
|
+
stats.add_gauge("foobar") { 10.2 }
|
19
|
+
stats.get_gauge("foobar").get.should == 10.2
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#add_metric" do
|
24
|
+
it "should add a metric" do
|
25
|
+
stats.add_metric("teapot", 14.1)
|
26
|
+
stats.get_metric("teapot").should be_a(com.twitter.ostrich.stats.Metric)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Util::Duration do
|
6
|
+
describe "#from_seconds" do
|
7
|
+
it "should return a Duration object with the correct length of time" do
|
8
|
+
Util::Duration.from_seconds(60).tap do |duration|
|
9
|
+
duration.should be_a(com.twitter.util.Duration)
|
10
|
+
duration.inNanoseconds.should == 60_000_000_000
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ostrich-jruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cameron Dutro
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-14 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Ruby wrapper around the stats collector & reporter for Scala servers
|
14
|
+
email:
|
15
|
+
- cdutro@twitter.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- Gemfile
|
21
|
+
- Rakefile
|
22
|
+
- lib/ostrich-jruby.rb
|
23
|
+
- lib/ostrich-jruby/command_handler.rb
|
24
|
+
- lib/ostrich-jruby/ext/hash.rb
|
25
|
+
- lib/ostrich-jruby/grape_endpoint.rb
|
26
|
+
- lib/ostrich-jruby/scala/functions.rb
|
27
|
+
- lib/ostrich-jruby/scala/kernel.rb
|
28
|
+
- lib/ostrich-jruby/stats.rb
|
29
|
+
- lib/ostrich-jruby/util.rb
|
30
|
+
- lib/ostrich-jruby/util/duration.rb
|
31
|
+
- lib/ostrich-jruby/version.rb
|
32
|
+
- ostrich-jruby.gemspec
|
33
|
+
- spec/command_handler_spec.rb
|
34
|
+
- spec/ext/hash_spec.rb
|
35
|
+
- spec/grape_endpoint_spec.rb
|
36
|
+
- spec/spec_helper.rb
|
37
|
+
- spec/stats_spec.rb
|
38
|
+
- spec/util/duration_spec.rb
|
39
|
+
homepage: ''
|
40
|
+
licenses: []
|
41
|
+
metadata: {}
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements:
|
57
|
+
- jar 'com.twitter:ostrich', '9.2.0'
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 2.4.3
|
60
|
+
signing_key:
|
61
|
+
specification_version: 4
|
62
|
+
summary: Ruby wrapper around the stats collector & reporter for Scala servers
|
63
|
+
test_files: []
|
64
|
+
has_rdoc: true
|