elasticsearch-rails 0.1.0.rc1 → 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.
- data/Gemfile +4 -0
- data/README.md +55 -4
- data/elasticsearch-rails.gemspec +7 -1
- data/lib/elasticsearch/rails/instrumentation.rb +36 -0
- data/lib/elasticsearch/rails/instrumentation/controller_runtime.rb +41 -0
- data/lib/elasticsearch/rails/instrumentation/log_subscriber.rb +41 -0
- data/lib/elasticsearch/rails/instrumentation/publishers.rb +32 -0
- data/lib/elasticsearch/rails/instrumentation/railtie.rb +27 -0
- data/lib/elasticsearch/rails/lograge.rb +40 -0
- data/lib/elasticsearch/rails/tasks/import.rb +105 -0
- data/lib/elasticsearch/rails/version.rb +1 -1
- data/lib/rails/templates/01-basic.rb +3 -3
- data/test/test_helper.rb +57 -0
- data/test/unit/instrumentation/instrumentation_test.rb +61 -0
- data/test/unit/instrumentation/lograge_test.rb +20 -0
- metadata +78 -17
data/Gemfile
CHANGED
@@ -2,3 +2,7 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in elasticsearch-rails.gemspec
|
4
4
|
gemspec
|
5
|
+
|
6
|
+
if File.exists? File.expand_path("../../elasticsearch-model", __FILE__)
|
7
|
+
gem 'elasticsearch-model', :path => File.expand_path("../../elasticsearch-model", __FILE__), :require => true
|
8
|
+
end
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@ The library is compatible with Ruby 1.9.3 and higher.
|
|
10
10
|
|
11
11
|
Install the package from [Rubygems](https://rubygems.org):
|
12
12
|
|
13
|
-
gem install elasticsearch-rails
|
13
|
+
gem install elasticsearch-rails
|
14
14
|
|
15
15
|
To use an unreleased version, either add it to your `Gemfile` for [Bundler](http://bundler.io):
|
16
16
|
|
@@ -23,7 +23,58 @@ or install it from a source code checkout:
|
|
23
23
|
bundle install
|
24
24
|
rake install
|
25
25
|
|
26
|
-
##
|
26
|
+
## Features
|
27
|
+
|
28
|
+
### Rake Tasks
|
29
|
+
|
30
|
+
To facilitate importing data from your models into Elasticsearch, require the task definition in your application,
|
31
|
+
eg. in the `lib/tasks/elasticsearch.rake` file:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
require 'elasticsearch/rails/tasks/import'
|
35
|
+
```
|
36
|
+
|
37
|
+
To import the records from your `Article` model, run:
|
38
|
+
|
39
|
+
```bash
|
40
|
+
$ bundle exec rake environment elasticsearch:import:model CLASS='Article'
|
41
|
+
```
|
42
|
+
|
43
|
+
Run this command to display usage instructions:
|
44
|
+
|
45
|
+
```bash
|
46
|
+
$ bundle exec rake -D elasticsearch
|
47
|
+
```
|
48
|
+
|
49
|
+
### ActiveSupport Instrumentation
|
50
|
+
|
51
|
+
To display information about the search request (duration, search definition) during development,
|
52
|
+
and to include the information in the Rails log file, require the component in your `application.rb` file:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
require 'elasticsearch/rails/instrumentation'
|
56
|
+
```
|
57
|
+
|
58
|
+
You should see an output like this in your application log in development environment:
|
59
|
+
|
60
|
+
Article Search (321.3ms) { index: "articles", type: "article", body: { query: ... } }
|
61
|
+
|
62
|
+
Also, the total duration of the request to Elasticsearch is displayed in the Rails request breakdown:
|
63
|
+
|
64
|
+
Completed 200 OK in 615ms (Views: 230.9ms | ActiveRecord: 0.0ms | Elasticsearch: 321.3ms)
|
65
|
+
|
66
|
+
There's a special component for the [Lograge](https://github.com/roidrage/lograge) logger.
|
67
|
+
Require the component in your `application.rb` file (and set `config.lograge.enabled`):
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
require 'elasticsearch/rails/lograge'
|
71
|
+
```
|
72
|
+
|
73
|
+
You should see the duration of the request to Elasticsearch as part of each log event:
|
74
|
+
|
75
|
+
method=GET path=/search ... status=200 duration=380.89 view=99.64 db=0.00 es=279.37
|
76
|
+
|
77
|
+
### Rails Application Templates
|
27
78
|
|
28
79
|
You can generate a fully working example Ruby on Rails application, with an `Article` model and a search form,
|
29
80
|
to play with (it even downloads _Elasticsearch_ itself, generates the application skeleton and leaves you with
|
@@ -33,8 +84,8 @@ a _Git_ repository to explore the steps and the code):
|
|
33
84
|
rails new searchapp --skip --skip-bundle --template https://raw.github.com/elasticsearch/elasticsearch-rails/master/elasticsearch-rails/lib/rails/templates/01-basic.rb
|
34
85
|
```
|
35
86
|
|
36
|
-
Run the same command with the `02-pretty` template to add features such as
|
37
|
-
result highlighting and [_Bootstrap_](http://getbootstrap.com) integration:
|
87
|
+
Run the same command again, in the same folder, with the `02-pretty` template to add features such as
|
88
|
+
a custom `Article.search` method, result highlighting and [_Bootstrap_](http://getbootstrap.com) integration:
|
38
89
|
|
39
90
|
```bash
|
40
91
|
rails new searchapp --skip --skip-bundle --template https://raw.github.com/elasticsearch/elasticsearch-rails/master/elasticsearch-rails/lib/rails/templates/02-pretty.rb
|
data/elasticsearch-rails.gemspec
CHANGED
@@ -24,6 +24,13 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.add_development_dependency "bundler", "~> 1.3"
|
25
25
|
s.add_development_dependency "rake"
|
26
26
|
|
27
|
+
s.add_development_dependency "elasticsearch-extensions"
|
28
|
+
|
29
|
+
s.add_development_dependency "oj"
|
30
|
+
s.add_development_dependency "rails", "> 3.0"
|
31
|
+
|
32
|
+
s.add_development_dependency "lograge"
|
33
|
+
|
27
34
|
s.add_development_dependency "shoulda-context"
|
28
35
|
s.add_development_dependency "mocha"
|
29
36
|
s.add_development_dependency "turn"
|
@@ -36,6 +43,5 @@ Gem::Specification.new do |s|
|
|
36
43
|
s.add_development_dependency "simplecov"
|
37
44
|
s.add_development_dependency "cane"
|
38
45
|
s.add_development_dependency "require-prof"
|
39
|
-
s.add_development_dependency "coveralls"
|
40
46
|
end
|
41
47
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'elasticsearch/rails/instrumentation/railtie'
|
2
|
+
require 'elasticsearch/rails/instrumentation/publishers'
|
3
|
+
|
4
|
+
module Elasticsearch
|
5
|
+
module Rails
|
6
|
+
|
7
|
+
# This module adds support for displaying statistics about search duration in the Rails application log
|
8
|
+
# by integrating with the `ActiveSupport::Notifications` framework and `ActionController` logger.
|
9
|
+
#
|
10
|
+
# == Usage
|
11
|
+
#
|
12
|
+
# Require the component in your `application.rb` file:
|
13
|
+
#
|
14
|
+
# require 'elasticsearch/rails/instrumentation'
|
15
|
+
#
|
16
|
+
# You should see an output like this in your application log in development environment:
|
17
|
+
#
|
18
|
+
# Article Search (321.3ms) { index: "articles", type: "article", body: { query: ... } }
|
19
|
+
#
|
20
|
+
# Also, the total duration of the request to Elasticsearch is displayed in the Rails request breakdown:
|
21
|
+
#
|
22
|
+
# Completed 200 OK in 615ms (Views: 230.9ms | ActiveRecord: 0.0ms | Elasticsearch: 321.3ms)
|
23
|
+
#
|
24
|
+
# @note The displayed duration includes the HTTP transfer -- the time it took Elasticsearch
|
25
|
+
# to process your request is available in the `response.took` property.
|
26
|
+
#
|
27
|
+
# @see Elasticsearch::Rails::Instrumentation::Publishers
|
28
|
+
# @see Elasticsearch::Rails::Instrumentation::Railtie
|
29
|
+
#
|
30
|
+
# @see http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html
|
31
|
+
#
|
32
|
+
#
|
33
|
+
module Instrumentation
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'active_support/core_ext/module/attr_internal'
|
2
|
+
|
3
|
+
module Elasticsearch
|
4
|
+
module Rails
|
5
|
+
module Instrumentation
|
6
|
+
|
7
|
+
# Hooks into ActionController to display Elasticsearch runtime
|
8
|
+
#
|
9
|
+
# @see https://github.com/rails/rails/blob/master/activerecord/lib/active_record/railties/controller_runtime.rb
|
10
|
+
#
|
11
|
+
module ControllerRuntime
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
attr_internal :elasticsearch_runtime
|
17
|
+
|
18
|
+
def cleanup_view_runtime
|
19
|
+
elasticsearch_rt_before_render = Elasticsearch::Rails::Instrumentation::LogSubscriber.reset_runtime
|
20
|
+
runtime = super
|
21
|
+
elasticsearch_rt_after_render = Elasticsearch::Rails::Instrumentation::LogSubscriber.reset_runtime
|
22
|
+
self.elasticsearch_runtime = elasticsearch_rt_before_render + elasticsearch_rt_after_render
|
23
|
+
runtime - elasticsearch_rt_after_render
|
24
|
+
end
|
25
|
+
|
26
|
+
def append_info_to_payload(payload)
|
27
|
+
super
|
28
|
+
payload[:elasticsearch_runtime] = (elasticsearch_runtime || 0) + Elasticsearch::Rails::Instrumentation::LogSubscriber.reset_runtime
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
def log_process_action(payload)
|
33
|
+
messages, elasticsearch_runtime = super, payload[:elasticsearch_runtime]
|
34
|
+
messages << ("Elasticsearch: %.1fms" % elasticsearch_runtime.to_f) if elasticsearch_runtime
|
35
|
+
messages
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Elasticsearch
|
2
|
+
module Rails
|
3
|
+
module Instrumentation
|
4
|
+
|
5
|
+
# A log subscriber to attach to Elasticsearch related events
|
6
|
+
#
|
7
|
+
# @see https://github.com/rails/rails/blob/master/activerecord/lib/active_record/log_subscriber.rb
|
8
|
+
#
|
9
|
+
class LogSubscriber < ActiveSupport::LogSubscriber
|
10
|
+
def self.runtime=(value)
|
11
|
+
Thread.current["elasticsearch_runtime"] = value
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.runtime
|
15
|
+
Thread.current["elasticsearch_runtime"] ||= 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.reset_runtime
|
19
|
+
rt, self.runtime = runtime, 0
|
20
|
+
rt
|
21
|
+
end
|
22
|
+
|
23
|
+
# Intercept `search.elasticsearch` events, and display them in the Rails log
|
24
|
+
#
|
25
|
+
def search(event)
|
26
|
+
self.class.runtime += event.duration
|
27
|
+
return unless logger.debug?
|
28
|
+
|
29
|
+
payload = event.payload
|
30
|
+
name = "#{payload[:klass]} #{payload[:name]} (#{event.duration.round(1)}ms)"
|
31
|
+
search = payload[:search].inspect.gsub(/:(\w+)=>/, '\1: ')
|
32
|
+
|
33
|
+
debug %Q| #{color(name, GREEN, true)} #{colorize_logging ? "\e[2m#{search}\e[0m" : search}|
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
Elasticsearch::Rails::Instrumentation::LogSubscriber.attach_to :elasticsearch
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Elasticsearch
|
2
|
+
module Rails
|
3
|
+
module Instrumentation
|
4
|
+
module Publishers
|
5
|
+
|
6
|
+
# Wraps the `SearchRequest` methods to perform the instrumentation
|
7
|
+
#
|
8
|
+
# @see SearchRequest#execute_with_instrumentation!
|
9
|
+
# @see http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html
|
10
|
+
#
|
11
|
+
module SearchRequest
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
included do
|
15
|
+
alias_method_chain :execute!, :instrumentation
|
16
|
+
end
|
17
|
+
|
18
|
+
# Wrap `Search#execute!` and perform instrumentation
|
19
|
+
#
|
20
|
+
def execute_with_instrumentation!
|
21
|
+
ActiveSupport::Notifications.instrument "search.elasticsearch",
|
22
|
+
name: 'Search',
|
23
|
+
klass: (self.klass.is_a?(Elasticsearch::Model::Proxy::ClassMethodsProxy) ? self.klass.target.to_s : self.klass.to_s),
|
24
|
+
search: self.definition do
|
25
|
+
execute_without_instrumentation!
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Elasticsearch
|
2
|
+
module Rails
|
3
|
+
module Instrumentation
|
4
|
+
|
5
|
+
# Rails initializer class to require Elasticsearch::Rails::Instrumentation files,
|
6
|
+
# set up Elasticsearch::Model and hook into ActionController to display Elasticsearch-related duration
|
7
|
+
#
|
8
|
+
# @see http://edgeguides.rubyonrails.org/active_support_instrumentation.html
|
9
|
+
#
|
10
|
+
class Railtie < ::Rails::Railtie
|
11
|
+
initializer "elasticsearch.instrumentation" do |app|
|
12
|
+
require 'elasticsearch/rails/instrumentation/log_subscriber'
|
13
|
+
require 'elasticsearch/rails/instrumentation/controller_runtime'
|
14
|
+
|
15
|
+
Elasticsearch::Model::Searching::SearchRequest.class_eval do
|
16
|
+
include Elasticsearch::Rails::Instrumentation::Publishers::SearchRequest
|
17
|
+
end
|
18
|
+
|
19
|
+
ActiveSupport.on_load(:action_controller) do
|
20
|
+
include Elasticsearch::Rails::Instrumentation::ControllerRuntime
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Elasticsearch
|
2
|
+
module Rails
|
3
|
+
module Lograge
|
4
|
+
|
5
|
+
# Rails initializer class to require Elasticsearch::Rails::Instrumentation files,
|
6
|
+
# set up Elasticsearch::Model and add Lograge configuration to display Elasticsearch-related duration
|
7
|
+
#
|
8
|
+
# Require the component in your `application.rb` file and enable Lograge:
|
9
|
+
#
|
10
|
+
# require 'elasticsearch/rails/lograge'
|
11
|
+
#
|
12
|
+
# You should see the full duration of the request to Elasticsearch as part of each log event:
|
13
|
+
#
|
14
|
+
# method=GET path=/search ... status=200 duration=380.89 view=99.64 db=0.00 es=279.37
|
15
|
+
#
|
16
|
+
# @see https://github.com/roidrage/lograge
|
17
|
+
#
|
18
|
+
class Railtie < ::Rails::Railtie
|
19
|
+
initializer "elasticsearch.lograge" do |app|
|
20
|
+
require 'elasticsearch/rails/instrumentation/publishers'
|
21
|
+
require 'elasticsearch/rails/instrumentation/log_subscriber'
|
22
|
+
require 'elasticsearch/rails/instrumentation/controller_runtime'
|
23
|
+
|
24
|
+
config.lograge.custom_options = lambda do |event|
|
25
|
+
{ es: event.payload[:elasticsearch_runtime].to_f.round(2) }
|
26
|
+
end
|
27
|
+
|
28
|
+
Elasticsearch::Model::Searching::SearchRequest.class_eval do
|
29
|
+
include Elasticsearch::Rails::Instrumentation::Publishers::SearchRequest
|
30
|
+
end
|
31
|
+
|
32
|
+
ActiveSupport.on_load(:action_controller) do
|
33
|
+
include Elasticsearch::Rails::Instrumentation::ControllerRuntime
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# A collection of Rake tasks to facilitate importing data from yout models into Elasticsearch.
|
2
|
+
#
|
3
|
+
# Add this e.g. into the `lib/tasks/elasticsearch.rake` file in your Rails application:
|
4
|
+
#
|
5
|
+
# require 'elasticsearch/rails/tasks/import'
|
6
|
+
#
|
7
|
+
# To import the records from your `Article` model, run:
|
8
|
+
#
|
9
|
+
# $ bundle exec rake environment elasticsearch:import:model CLASS='MyModel'
|
10
|
+
#
|
11
|
+
# Run this command to display usage instructions:
|
12
|
+
#
|
13
|
+
# $ bundle exec rake -D elasticsearch
|
14
|
+
#
|
15
|
+
STDOUT.sync = true
|
16
|
+
STDERR.sync = true
|
17
|
+
|
18
|
+
begin; require 'ansi/progressbar'; rescue LoadError; end
|
19
|
+
|
20
|
+
namespace :elasticsearch do
|
21
|
+
|
22
|
+
task :import => 'import:model'
|
23
|
+
|
24
|
+
namespace :import do
|
25
|
+
desc <<-DESC.gsub(/ /, '')
|
26
|
+
Import data from your model (pass name as CLASS environment variable).
|
27
|
+
|
28
|
+
$ rake environment elasticsearch:import:model CLASS='MyModel'
|
29
|
+
|
30
|
+
Force rebuilding the index (delete and create):
|
31
|
+
$ rake environment elasticsearch:import:model CLASS='Article' FORCE=y
|
32
|
+
|
33
|
+
Customize the batch size:
|
34
|
+
$ rake environment elasticsearch:import:model CLASS='Article' BATCH=100
|
35
|
+
|
36
|
+
Set target index name:
|
37
|
+
$ rake environment elasticsearch:import:model CLASS='Article' INDEX='articles-new'
|
38
|
+
DESC
|
39
|
+
task :model do
|
40
|
+
if ENV['CLASS'].to_s == ''
|
41
|
+
puts '='*90, 'USAGE', '='*90, import_model_desc, ""
|
42
|
+
exit(1)
|
43
|
+
end
|
44
|
+
|
45
|
+
klass = eval(ENV['CLASS'].to_s)
|
46
|
+
total = klass.count rescue nil
|
47
|
+
pbar = ANSI::Progressbar.new(klass.to_s, total) rescue nil
|
48
|
+
pbar.__send__ :show if pbar
|
49
|
+
|
50
|
+
unless ENV['DEBUG']
|
51
|
+
begin
|
52
|
+
klass.__elasticsearch__.client.transport.logger.level = Logger::WARN
|
53
|
+
rescue NoMethodError; end
|
54
|
+
begin
|
55
|
+
klass.__elasticsearch__.client.transport.tracer.level = Logger::WARN
|
56
|
+
rescue NoMethodError; end
|
57
|
+
end
|
58
|
+
|
59
|
+
klass.import force: ENV.fetch('FORCE', false),
|
60
|
+
batch_size: ENV.fetch('BATCH', 1000).to_i,
|
61
|
+
index: ENV.fetch('INDEX', nil),
|
62
|
+
type: ENV.fetch('TYPE', nil) do |response|
|
63
|
+
pbar.inc response['items'].size if pbar
|
64
|
+
STDERR.flush
|
65
|
+
STDOUT.flush
|
66
|
+
end
|
67
|
+
pbar.finish if pbar
|
68
|
+
|
69
|
+
puts '[IMPORT] Done'
|
70
|
+
end
|
71
|
+
|
72
|
+
desc <<-DESC.gsub(/ /, '')
|
73
|
+
Import all indices from `app/models` (or use DIR environment variable).
|
74
|
+
|
75
|
+
$ rake environment elasticsearch:import:all DIR=app/models
|
76
|
+
DESC
|
77
|
+
task :all do
|
78
|
+
dir = ENV['DIR'].to_s != '' ? ENV['DIR'] : Rails.root.join("app/models")
|
79
|
+
|
80
|
+
puts "[IMPORT] Loading models from: #{dir}"
|
81
|
+
Dir.glob(File.join("#{dir}/**/*.rb")).each do |path|
|
82
|
+
model_filename = path[/#{Regexp.escape(dir.to_s)}\/([^\.]+).rb/, 1]
|
83
|
+
|
84
|
+
next if model_filename.match(/^concerns\//i) # Skip concerns/ folder
|
85
|
+
|
86
|
+
begin
|
87
|
+
klass = model_filename.camelize.constantize
|
88
|
+
rescue NameError
|
89
|
+
require(path) ? retry : raise(RuntimeError, "Cannot load class '#{klass}'")
|
90
|
+
end
|
91
|
+
|
92
|
+
# Skip if the class doesn't have Elasticsearch integration
|
93
|
+
next unless klass.respond_to?(:__elasticsearch__)
|
94
|
+
|
95
|
+
puts "[IMPORT] Processing model: #{klass}..."
|
96
|
+
|
97
|
+
ENV['CLASS'] = klass.to_s
|
98
|
+
Rake::Task["elasticsearch:import:model"].invoke
|
99
|
+
puts
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -130,9 +130,9 @@ puts
|
|
130
130
|
say_status "Rubygems", "Adding Elasticsearch libraries into Gemfile...\n", :yellow
|
131
131
|
puts '-'*80, ''; sleep 0.75
|
132
132
|
|
133
|
-
gem 'elasticsearch', git: 'git
|
134
|
-
gem 'elasticsearch-model', git: 'git
|
135
|
-
gem 'elasticsearch-rails', git: 'git
|
133
|
+
gem 'elasticsearch', git: 'git://github.com/elasticsearch/elasticsearch-ruby.git'
|
134
|
+
gem 'elasticsearch-model', git: 'git://github.com/elasticsearch/elasticsearch-rails.git'
|
135
|
+
gem 'elasticsearch-rails', git: 'git://github.com/elasticsearch/elasticsearch-rails.git'
|
136
136
|
|
137
137
|
# ----- Install gems ------------------------------------------------------------------------------
|
138
138
|
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
RUBY_1_8 = defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
|
2
|
+
|
3
|
+
exit(0) if RUBY_1_8
|
4
|
+
|
5
|
+
require 'simplecov' and SimpleCov.start { add_filter "/test|test_/" } if ENV["COVERAGE"]
|
6
|
+
|
7
|
+
# Register `at_exit` handler for integration tests shutdown.
|
8
|
+
# MUST be called before requiring `test/unit`.
|
9
|
+
at_exit { Elasticsearch::Test::IntegrationTestCase.__run_at_exit_hooks }
|
10
|
+
|
11
|
+
puts '-'*80
|
12
|
+
|
13
|
+
require 'test/unit'
|
14
|
+
require 'shoulda-context'
|
15
|
+
require 'mocha/setup'
|
16
|
+
require 'turn' unless ENV["TM_FILEPATH"] || ENV["NOTURN"] || RUBY_1_8
|
17
|
+
|
18
|
+
require 'ansi'
|
19
|
+
require 'oj'
|
20
|
+
|
21
|
+
require 'rails/version'
|
22
|
+
require 'active_record'
|
23
|
+
require 'active_model'
|
24
|
+
|
25
|
+
require 'elasticsearch/model'
|
26
|
+
require 'elasticsearch/rails'
|
27
|
+
|
28
|
+
require 'elasticsearch/extensions/test/cluster'
|
29
|
+
require 'elasticsearch/extensions/test/startup_shutdown'
|
30
|
+
|
31
|
+
module Elasticsearch
|
32
|
+
module Test
|
33
|
+
class IntegrationTestCase < ::Test::Unit::TestCase
|
34
|
+
extend Elasticsearch::Extensions::Test::StartupShutdown
|
35
|
+
|
36
|
+
startup { Elasticsearch::Extensions::Test::Cluster.start(nodes: 1) if ENV['SERVER'] and not Elasticsearch::Extensions::Test::Cluster.running? }
|
37
|
+
shutdown { Elasticsearch::Extensions::Test::Cluster.stop if ENV['SERVER'] && started? }
|
38
|
+
context "IntegrationTest" do; should "noop on Ruby 1.8" do; end; end if RUBY_1_8
|
39
|
+
|
40
|
+
def setup
|
41
|
+
ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :database => ":memory:" )
|
42
|
+
logger = ::Logger.new(STDERR)
|
43
|
+
logger.formatter = lambda { |s, d, p, m| "#{m.ansi(:faint, :cyan)}\n" }
|
44
|
+
ActiveRecord::Base.logger = logger unless ENV['QUIET']
|
45
|
+
|
46
|
+
ActiveRecord::LogSubscriber.colorize_logging = false
|
47
|
+
ActiveRecord::Migration.verbose = false
|
48
|
+
|
49
|
+
tracer = ::Logger.new(STDERR)
|
50
|
+
tracer.formatter = lambda { |s, d, p, m| "#{m.gsub(/^.*$/) { |n| ' ' + n }.ansi(:faint)}\n" }
|
51
|
+
|
52
|
+
Elasticsearch::Model.client = Elasticsearch::Client.new host: "localhost:#{(ENV['TEST_CLUSTER_PORT'] || 9250)}",
|
53
|
+
tracer: (ENV['QUIET'] ? nil : tracer)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'rails/railtie'
|
4
|
+
require 'active_support/log_subscriber/test_helper'
|
5
|
+
|
6
|
+
require 'elasticsearch/rails/instrumentation'
|
7
|
+
|
8
|
+
class Elasticsearch::Rails::InstrumentationTest < Test::Unit::TestCase
|
9
|
+
include ActiveSupport::LogSubscriber::TestHelper
|
10
|
+
|
11
|
+
context "ActiveSupport::Instrumentation integration" do
|
12
|
+
class ::DummyInstrumentationModel
|
13
|
+
extend Elasticsearch::Model::Searching::ClassMethods
|
14
|
+
|
15
|
+
def self.index_name; 'foo'; end
|
16
|
+
def self.document_type; 'bar'; end
|
17
|
+
end
|
18
|
+
|
19
|
+
RESPONSE = { 'took' => '5ms', 'hits' => { 'total' => 123, 'max_score' => 456, 'hits' => [] } }
|
20
|
+
|
21
|
+
setup do
|
22
|
+
@search = Elasticsearch::Model::Searching::SearchRequest.new ::DummyInstrumentationModel, '*'
|
23
|
+
@response = Elasticsearch::Model::Response::Response.new ::DummyInstrumentationModel, @search
|
24
|
+
|
25
|
+
@client = stub('client', search: @response)
|
26
|
+
DummyInstrumentationModel.stubs(:client).returns(@client)
|
27
|
+
|
28
|
+
Elasticsearch::Rails::Instrumentation::Railtie.run_initializers
|
29
|
+
end
|
30
|
+
|
31
|
+
should "wrap SearchRequest#execute! with instrumentation" do
|
32
|
+
s = Elasticsearch::Model::Searching::SearchRequest.new ::DummyInstrumentationModel, 'foo'
|
33
|
+
assert_respond_to s, :execute_without_instrumentation!
|
34
|
+
assert_respond_to s, :execute_with_instrumentation!
|
35
|
+
end
|
36
|
+
|
37
|
+
should "publish the notification" do
|
38
|
+
@query = { query: { match: { foo: 'bar' } } }
|
39
|
+
|
40
|
+
ActiveSupport::Notifications.expects(:instrument).with do |name, payload|
|
41
|
+
assert_equal "search.elasticsearch", name
|
42
|
+
assert_equal 'DummyInstrumentationModel', payload[:klass]
|
43
|
+
assert_equal @query, payload[:search][:body]
|
44
|
+
end
|
45
|
+
|
46
|
+
s = ::DummyInstrumentationModel.search @query
|
47
|
+
s.response
|
48
|
+
end
|
49
|
+
|
50
|
+
should "print the debug information to the Rails log" do
|
51
|
+
s = ::DummyInstrumentationModel.search query: { match: { moo: 'bam' } }
|
52
|
+
s.response
|
53
|
+
|
54
|
+
logged = @logger.logged(:debug).first
|
55
|
+
|
56
|
+
assert_not_nil logged
|
57
|
+
assert_match /DummyInstrumentationModel Search \(\d+\.\d+ms\)/, logged
|
58
|
+
assert_match /body\: \{query\: \{match\: \{moo\: "bam"\}\}\}\}/, logged
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'rails/railtie'
|
4
|
+
require 'lograge'
|
5
|
+
|
6
|
+
require 'elasticsearch/rails/lograge'
|
7
|
+
|
8
|
+
class Elasticsearch::Rails::LogrageTest < Test::Unit::TestCase
|
9
|
+
context "Lograge integration" do
|
10
|
+
setup do
|
11
|
+
Elasticsearch::Rails::Lograge::Railtie.run_initializers
|
12
|
+
end
|
13
|
+
|
14
|
+
should "customize the Lograge configuration" do
|
15
|
+
assert_not_nil Elasticsearch::Rails::Lograge::Railtie.initializers
|
16
|
+
.select { |i| i.name == 'elasticsearch.lograge' }
|
17
|
+
.first
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elasticsearch-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Karel Minarik
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-03-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -44,7 +44,7 @@ dependencies:
|
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
47
|
+
name: elasticsearch-extensions
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
49
49
|
none: false
|
50
50
|
requirements:
|
@@ -60,7 +60,7 @@ dependencies:
|
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
63
|
+
name: oj
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
65
65
|
none: false
|
66
66
|
requirements:
|
@@ -76,7 +76,23 @@ dependencies:
|
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
|
-
name:
|
79
|
+
name: rails
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>'
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '3.0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>'
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '3.0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: lograge
|
80
96
|
requirement: !ruby/object:Gem::Requirement
|
81
97
|
none: false
|
82
98
|
requirements:
|
@@ -92,7 +108,7 @@ dependencies:
|
|
92
108
|
- !ruby/object:Gem::Version
|
93
109
|
version: '0'
|
94
110
|
- !ruby/object:Gem::Dependency
|
95
|
-
name:
|
111
|
+
name: shoulda-context
|
96
112
|
requirement: !ruby/object:Gem::Requirement
|
97
113
|
none: false
|
98
114
|
requirements:
|
@@ -108,7 +124,7 @@ dependencies:
|
|
108
124
|
- !ruby/object:Gem::Version
|
109
125
|
version: '0'
|
110
126
|
- !ruby/object:Gem::Dependency
|
111
|
-
name:
|
127
|
+
name: mocha
|
112
128
|
requirement: !ruby/object:Gem::Requirement
|
113
129
|
none: false
|
114
130
|
requirements:
|
@@ -124,7 +140,7 @@ dependencies:
|
|
124
140
|
- !ruby/object:Gem::Version
|
125
141
|
version: '0'
|
126
142
|
- !ruby/object:Gem::Dependency
|
127
|
-
name:
|
143
|
+
name: turn
|
128
144
|
requirement: !ruby/object:Gem::Requirement
|
129
145
|
none: false
|
130
146
|
requirements:
|
@@ -140,7 +156,7 @@ dependencies:
|
|
140
156
|
- !ruby/object:Gem::Version
|
141
157
|
version: '0'
|
142
158
|
- !ruby/object:Gem::Dependency
|
143
|
-
name:
|
159
|
+
name: yard
|
144
160
|
requirement: !ruby/object:Gem::Requirement
|
145
161
|
none: false
|
146
162
|
requirements:
|
@@ -156,7 +172,7 @@ dependencies:
|
|
156
172
|
- !ruby/object:Gem::Version
|
157
173
|
version: '0'
|
158
174
|
- !ruby/object:Gem::Dependency
|
159
|
-
name:
|
175
|
+
name: ruby-prof
|
160
176
|
requirement: !ruby/object:Gem::Requirement
|
161
177
|
none: false
|
162
178
|
requirements:
|
@@ -172,7 +188,7 @@ dependencies:
|
|
172
188
|
- !ruby/object:Gem::Version
|
173
189
|
version: '0'
|
174
190
|
- !ruby/object:Gem::Dependency
|
175
|
-
name:
|
191
|
+
name: pry
|
176
192
|
requirement: !ruby/object:Gem::Requirement
|
177
193
|
none: false
|
178
194
|
requirements:
|
@@ -188,7 +204,7 @@ dependencies:
|
|
188
204
|
- !ruby/object:Gem::Version
|
189
205
|
version: '0'
|
190
206
|
- !ruby/object:Gem::Dependency
|
191
|
-
name:
|
207
|
+
name: ci_reporter
|
192
208
|
requirement: !ruby/object:Gem::Requirement
|
193
209
|
none: false
|
194
210
|
requirements:
|
@@ -204,7 +220,39 @@ dependencies:
|
|
204
220
|
- !ruby/object:Gem::Version
|
205
221
|
version: '0'
|
206
222
|
- !ruby/object:Gem::Dependency
|
207
|
-
name:
|
223
|
+
name: simplecov
|
224
|
+
requirement: !ruby/object:Gem::Requirement
|
225
|
+
none: false
|
226
|
+
requirements:
|
227
|
+
- - ! '>='
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
none: false
|
234
|
+
requirements:
|
235
|
+
- - ! '>='
|
236
|
+
- !ruby/object:Gem::Version
|
237
|
+
version: '0'
|
238
|
+
- !ruby/object:Gem::Dependency
|
239
|
+
name: cane
|
240
|
+
requirement: !ruby/object:Gem::Requirement
|
241
|
+
none: false
|
242
|
+
requirements:
|
243
|
+
- - ! '>='
|
244
|
+
- !ruby/object:Gem::Version
|
245
|
+
version: '0'
|
246
|
+
type: :development
|
247
|
+
prerelease: false
|
248
|
+
version_requirements: !ruby/object:Gem::Requirement
|
249
|
+
none: false
|
250
|
+
requirements:
|
251
|
+
- - ! '>='
|
252
|
+
- !ruby/object:Gem::Version
|
253
|
+
version: '0'
|
254
|
+
- !ruby/object:Gem::Dependency
|
255
|
+
name: require-prof
|
208
256
|
requirement: !ruby/object:Gem::Requirement
|
209
257
|
none: false
|
210
258
|
requirements:
|
@@ -235,10 +283,20 @@ files:
|
|
235
283
|
- Rakefile
|
236
284
|
- elasticsearch-rails.gemspec
|
237
285
|
- lib/elasticsearch/rails.rb
|
286
|
+
- lib/elasticsearch/rails/instrumentation.rb
|
287
|
+
- lib/elasticsearch/rails/instrumentation/controller_runtime.rb
|
288
|
+
- lib/elasticsearch/rails/instrumentation/log_subscriber.rb
|
289
|
+
- lib/elasticsearch/rails/instrumentation/publishers.rb
|
290
|
+
- lib/elasticsearch/rails/instrumentation/railtie.rb
|
291
|
+
- lib/elasticsearch/rails/lograge.rb
|
292
|
+
- lib/elasticsearch/rails/tasks/import.rb
|
238
293
|
- lib/elasticsearch/rails/version.rb
|
239
294
|
- lib/rails/templates/01-basic.rb
|
240
295
|
- lib/rails/templates/02-pretty.rb
|
241
296
|
- lib/rails/templates/03-expert.rb
|
297
|
+
- test/test_helper.rb
|
298
|
+
- test/unit/instrumentation/instrumentation_test.rb
|
299
|
+
- test/unit/instrumentation/lograge_test.rb
|
242
300
|
homepage: https://github.com/elasticsearch/elasticsearch-rails/
|
243
301
|
licenses:
|
244
302
|
- Apache 2
|
@@ -256,14 +314,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
256
314
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
257
315
|
none: false
|
258
316
|
requirements:
|
259
|
-
- - ! '
|
317
|
+
- - ! '>='
|
260
318
|
- !ruby/object:Gem::Version
|
261
|
-
version:
|
319
|
+
version: '0'
|
262
320
|
requirements: []
|
263
321
|
rubyforge_project:
|
264
322
|
rubygems_version: 1.8.23
|
265
323
|
signing_key:
|
266
324
|
specification_version: 3
|
267
325
|
summary: Ruby on Rails integrations for Elasticsearch.
|
268
|
-
test_files:
|
326
|
+
test_files:
|
327
|
+
- test/test_helper.rb
|
328
|
+
- test/unit/instrumentation/instrumentation_test.rb
|
329
|
+
- test/unit/instrumentation/lograge_test.rb
|
269
330
|
has_rdoc:
|