elastic-apm 2.8.0 → 2.8.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of elastic-apm might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2395fecd3ead993ac77f072d0b552e0814d2eb09ae985ba3d0b22e7168a9f005
4
- data.tar.gz: 20e07d3f8444b83bc424de8b7772547c41eba90ac8561d406599cfb36854ebd9
3
+ metadata.gz: 11b66b86db45e066da0c6055bd5cb58894a5ba0eca8fb9d891b5b918fcd8d7c0
4
+ data.tar.gz: 87bfdbcc9b57f128f032d8e617dfe4540fcf8afeea91f80621d5e1a6b476d47e
5
5
  SHA512:
6
- metadata.gz: 341eff39abd1c021aaa61967a56482ada41ac9d94f6dda54a2b480cbaff2844768ffaea7c54c8e2781211cf8209a2b8309631a3360b63bad15c7554fa9705ca6
7
- data.tar.gz: 4158a60e93bd55f6cd28274e734943e1f5984c4ce963be7ad65be8fa508419f92227e18e12cc46c6813793f4b8baf490bdd52eb240e1a6c6f567057fe254a7ee
6
+ metadata.gz: a514f4463ee2294d1e825fd9ba0b42a764d8380e9ea4ba90254acf92ebd7ffec8d4f2a329a77307732e7206a22009c3cb91218650e499235d8ca2cae3cf1d8ae
7
+ data.tar.gz: 93e558bab35f323f77116031333ce065fa00b101871ea80e913b082612552857dadc9074c6c4219bf97010eddc6b9abc996fa2dac68454aed1dcb91048c9bd6c
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## 2.8.1 (2019-05-29)
8
+
9
+ ### Fixed
10
+
11
+ - Database statements are properly truncated ([#431](https://github.com/elastic/apm-agent-ruby/pull/431))
12
+
7
13
  ## 2.8.0 (2019-05-20)
8
14
 
9
15
  ### Added
data/Gemfile CHANGED
@@ -6,7 +6,6 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
6
 
7
7
  gemspec
8
8
 
9
- gem 'pry'
10
9
  gem 'rack-test'
11
10
  gem 'rspec'
12
11
  gem 'rspec-its'
@@ -16,6 +15,7 @@ gem 'webmock'
16
15
 
17
16
  gem 'elasticsearch', require: nil
18
17
  gem 'fakeredis', require: nil
18
+ gem 'faraday', require: nil
19
19
  gem 'json-schema', require: nil
20
20
  gem 'mongo', require: nil
21
21
  gem 'opentracing', require: nil
@@ -45,6 +45,8 @@ else
45
45
  gem framework
46
46
  end
47
47
 
48
+ gem 'activerecord-jdbcsqlite3-adapter', platform: :jruby
49
+
48
50
  unless version =~ /^(master|6)/
49
51
  gem 'delayed_job', require: nil
50
52
  end
@@ -32,7 +32,7 @@ pipeline {
32
32
  quietPeriod(10)
33
33
  }
34
34
  triggers {
35
- issueCommentTrigger('.*(?:jenkins\\W+)?run\\W+(?:the\\W+)?tests(?:\\W+please)?.*')
35
+ issueCommentTrigger('(?i).*(?:jenkins\\W+)?run\\W+(?:the\\W+)?tests(?:\\W+please)?.*')
36
36
  }
37
37
  parameters {
38
38
  booleanParam(name: 'Run_As_Master_Branch', defaultValue: false, description: 'Allow to run any steps on a PR, some steps normally only run on master branch.')
@@ -266,6 +266,10 @@ def runBenchmark(version){
266
266
  } catch(e){
267
267
  throw e
268
268
  } finally {
269
+ archiveArtifacts(
270
+ allowEmptyArchive: true,
271
+ artifacts: "**/benchmark-${transformedVersion}.raw,**/benchmark-${transformedVersion}.error",
272
+ onlyIfSuccessful: false)
269
273
  sendBenchmarks(file: "benchmark-${transformedVersion}.bulk",
270
274
  index: "benchmark-ruby", archive: true)
271
275
  }
@@ -1,39 +1,53 @@
1
+ #!/usr/bin/env ruby
1
2
  # frozen_string_literal: true
2
3
 
3
4
  $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
5
+ require 'active_record'
6
+ require 'action_controller/railtie'
4
7
  require 'elastic-apm'
8
+ require 'elastic_apm/railtie'
5
9
 
6
- class App
7
- module Helpers
8
- def with_app(config = {})
9
- app = App.new(config)
10
- app.start
11
- result = yield app
12
- app.stop
10
+ $log = Logger.new('/tmp/bench.log')
13
11
 
14
- result
15
- end
12
+ ActiveRecord::Base.logger = $log
16
13
 
17
- end
14
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: '/tmp/bench.sqlite3')
18
15
 
19
- def initialize(config = {})
20
- @config = ElasticAPM::Config.new(
21
- {
22
- environment: 'bench',
23
- disable_send: true
24
- }.merge(config)
25
- )
26
- # @serializer = ElasticAPM::Serializers::Transactions.new(@config)
27
- @mock_env = Rack::MockRequest.env_for('/')
16
+ ActiveRecord::Schema.define do
17
+ create_table :posts, force: true do |t|
18
+ t.string :title
19
+ t.timestamps
28
20
  end
21
+ end
29
22
 
30
- attr_reader :mock_env, :serializer
23
+ class Post < ActiveRecord::Base
24
+ end
31
25
 
32
- def start
33
- @agent = ElasticAPM.start(@config)
26
+ 10.times { |i| Post.create! title: "Post #{i}" }
27
+
28
+ class ApplicationController < ActionController::Base
29
+ def index
30
+ render inline: '<%= Post.pluck(:title).join(", ") %>'
34
31
  end
35
32
 
36
- def stop
37
- ElasticAPM.stop
33
+ def favicon
34
+ render nothing: true
38
35
  end
39
36
  end
37
+
38
+ class App < Rails::Application
39
+ config.secret_key_base = '__secret'
40
+ config.logger = $log
41
+ config.eager_load = false
42
+
43
+ config.elastic_apm.disable_send = true
44
+ config.elastic_apm.logger = $log
45
+ config.elastic_apm.log_level = Logger::DEBUG
46
+ end
47
+
48
+ App.initialize!
49
+
50
+ App.routes.draw do
51
+ get '/favicon.ico', to: 'application#favicon'
52
+ root to: 'application#index'
53
+ end
@@ -1,64 +1,36 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ ENV['RAILS_ENV'] = 'production'
5
+
6
+ require 'bundler'
4
7
  require 'bundler/setup'
5
8
 
6
9
  require 'benchmark'
7
10
  include Benchmark
8
-
9
11
  require 'rack/test'
10
12
 
11
13
  require './bench/app'
12
- include App::Helpers
13
-
14
- def perform(app, count: 1000)
15
- app.start
16
-
17
- transactions = count.times.map do |i|
18
- ElasticAPM.transaction "Transaction##{i}",
19
- context: ElasticAPM.build_context(app.mock_env) do
20
- ElasticAPM.span('Number one') { 'ok 1' }
21
- ElasticAPM.span('Number two') { 'ok 2' }
22
- ElasticAPM.span('Number three') { 'ok 3' }
23
- end
24
- end
25
-
26
- # app.serializer.build_all(transactions)
27
14
 
28
- app.stop
15
+ def app
16
+ App
29
17
  end
30
18
 
31
- def avg(benchmarks)
32
- [benchmarks.reduce(Tms.new(0), &:+) / benchmarks.length]
33
- end
19
+ include Rack::Test::Methods
34
20
 
35
- def banner(text)
36
- puts "=== #{text}"
21
+ def perform
22
+ 10_000.times do
23
+ get '/'
24
+ end
37
25
  end
38
26
 
39
- def do_bench(transaction_count: 10, **config)
40
- puts "Count: #{transaction_count} transactions... \n \n"
27
+ bench = Benchmark.benchmark(CAPTION, 15, FORMAT) do |b|
28
+ perform # warm up
41
29
 
42
- bench = Benchmark.benchmark(CAPTION, 7, FORMAT, 'avg:') do |x|
43
- benchmarks =
44
- with_app(config) do |app|
45
- # warm-up
46
- puts "1 run of warm-up"
47
- perform(app, count: transaction_count)
30
+ b.report('with agent:') { perform }
48
31
 
49
- 5.times.map do |i|
50
- x.report("run[#{i}]") { perform(app, count: transaction_count) }
51
- end
52
- end
32
+ ElasticAPM.stop
33
+ perform # warm up
53
34
 
54
- avg(benchmarks)
55
- end
35
+ b.report('without agent:') { perform }
56
36
  end
57
-
58
- transaction_count = Integer(ARGV.shift || 100_000)
59
-
60
- banner 'Default settings'
61
- do_bench transaction_count: transaction_count
62
-
63
- banner 'With transaction_sample_rate = 0'
64
- do_bench(transaction_count: transaction_count, transaction_sample_rate: 0)
@@ -1,46 +1,55 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- Encoding.default_external = 'utf-8'
5
-
6
4
  require 'time'
7
- require 'bundler/setup'
8
5
  require 'json'
9
6
 
10
7
  input = STDIN.read.split("\n")
11
- STDERR.puts input
12
-
13
- titles = input.grep(/^===/).map { |t| t.gsub(/^=== /, '') }
14
- counts = input.grep(/^Count: /).map { |a| a.gsub(/^Count: /, '').to_i }
15
- averages = input.grep(/^avg/).map { |a| a.match(/\((.+)\)/)[1].to_f }
16
8
 
17
9
  git_sha, git_msg = `git log -n 1 --pretty="format:%H|||%s"`.split('|||')
18
10
  git_date = `git log -n 1 --pretty="format:%ai"`
19
11
  platform = Gem::Platform.local
20
12
 
21
- payloads = titles.zip(averages, counts).map do |(title, avg, count)|
22
- return nil unless avg
23
-
24
- {
25
- title: title,
26
- avg: avg,
27
- transaction_count: count,
28
- executed_at: Time.new.iso8601,
29
- 'git.commit' => git_sha,
30
- 'git.date' => String(git_date).strip != '' && Time.parse(git_date).iso8601,
31
- 'git.subject' => git_msg,
32
- hostname: `hostname`.chomp,
33
- engine: RUBY_ENGINE,
34
- arch: platform.cpu,
35
- os: platform.os,
36
- ruby_version: "#{RUBY_ENGINE == 'jruby' ? 'j' : ''}#{RUBY_VERSION}"
37
- }
38
- end.compact
39
-
40
- STDERR.puts '=== Reporting to ES'
41
- STDERR.puts payloads.inspect
42
-
43
- payloads.each do |payload|
44
- puts '{ "index" : { "_index" : "benchmark-ruby", "_type" : "_doc" } }'
45
- puts payload.to_json
13
+ def doc(payload)
14
+ puts({ index: { _index: "benchmark-ruby", _type: "_doc" } }.to_json)
15
+ puts(payload.to_json)
46
16
  end
17
+
18
+ meta = {
19
+ executed_at: Time.new.iso8601,
20
+ 'git.commit' => git_sha,
21
+ 'git.date' => String(git_date).strip != '' && Time.parse(git_date).iso8601,
22
+ 'git.subject' => git_msg,
23
+ hostname: `hostname`.chomp,
24
+ engine: RUBY_ENGINE,
25
+ arch: platform.cpu,
26
+ os: platform.os,
27
+ ruby_version: "#{RUBY_ENGINE == 'jruby' ? 'j' : ''}#{RUBY_VERSION}"
28
+ }
29
+
30
+ results =
31
+ input
32
+ .grep(/^with/)
33
+ .map do |line|
34
+ title = line.match(/^(.*):/) { |m| m[1] }
35
+ user, system, total, real = line.scan(/[0-9\.]+/).map(&:to_f)
36
+ meta.merge(
37
+ title: title,
38
+ user: user,
39
+ system: system,
40
+ total: total,
41
+ real: real,
42
+ )
43
+ end
44
+
45
+ results.each { |result| doc result }
46
+
47
+ overhead =
48
+ (results[0][:total] - results[1][:total]) *
49
+ 1000 / # milliseconds
50
+ 10_000 # transactions
51
+
52
+ doc meta.merge(
53
+ title: 'overhead',
54
+ overhead: overhead
55
+ )
@@ -1,36 +1,23 @@
1
+ #!/usr/bin/env ruby
1
2
  # frozen_string_literal: true
2
3
 
3
- Dir.chdir('./bench')
4
-
5
- ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
6
-
7
4
  require 'stackprof'
8
5
  require 'rack/test'
9
- require 'elastic-apm'
10
6
 
11
- ElasticAPM.start environment: 'bench'
7
+ require './bench/app'
12
8
 
13
- env = Rack::MockRequest.env_for('/')
9
+ def app
10
+ App
11
+ end
12
+
13
+ include Rack::Test::Methods
14
14
 
15
15
  puts 'Running '
16
16
  profile = StackProf.run(mode: :cpu) do
17
17
  10_000.times do
18
- ElasticAPM.transaction 'Name', 'custom',
19
- context: ElasticAPM.build_context(env) do
20
- ElasticAPM.span 'Number one' do
21
- 'ok'
22
- end
23
- ElasticAPM.span 'Number two' do
24
- 'ok'
25
- end
26
- ElasticAPM.span 'Number three' do
27
- 'ok'
28
- end
29
- end
18
+ get '/'
30
19
  end
31
20
  end
32
21
  puts ''
33
22
 
34
- ElasticAPM.stop
35
-
36
23
  StackProf::Report.new(profile).print_text
@@ -579,6 +579,18 @@ It has to be provided in *<<config-format-duration, duration format>>*.
579
579
 
580
580
  The path to a custom CA certificate for connecting to APM Server.
581
581
 
582
+ [float]
583
+ [[config-stack-trace-limit]]
584
+ ==== `stack_trace_limit`
585
+
586
+ [options="header"]
587
+ |============
588
+ | Environment | `Config` key | Default
589
+ | `ELASTIC_APM_STACK_TRACE_LIMIT` | `stack_trace_limit` | `999999`
590
+ |============
591
+
592
+ The maximum number of stack trace lines per span/error.
593
+
582
594
  [float]
583
595
  [[config-transaction-max-spans]]
584
596
  ==== `transaction_max_spans`
@@ -0,0 +1,30 @@
1
+ [[debugging]]
2
+ == Debugging the agent itself
3
+
4
+ Hopefully the agent Just Works™, but depending on your situation the agent might need some tuning.
5
+
6
+ First, to learn more about what's going on inside the agent, you can increase the amount of log messages it writes. To do this, set the log level with the option `log_level = 0` -- `0` being the level of most messages, `DEBUG`.
7
+
8
+ In your `config/elastic_apm.yml`:
9
+
10
+ [source,yaml]
11
+ ----
12
+ log_level: <%= Logger::DEBUG %>
13
+ ----
14
+
15
+ [float]
16
+ [[debugging-log-messages]]
17
+ === Log messages
18
+
19
+ [float]
20
+ [[debugging-errors-queue-full]]
21
+ ==== `Queue is full (256 items), skipping…`
22
+
23
+ The agent has an internal queue that holds events after they are done, and before they are safely serialized and sent to APM Server. To avoid using up all of your memory, this queue has a fixed size. Depending on your load and server setup, events may be added to the queue faster than they are consumed, hence the warning.
24
+
25
+ Things to consider:
26
+
27
+ - Is `server_url` misconfigured or APM Server down? If the agent fails to connect you will also see log messages containing `Connection error` or `Couldn't establish connection to APM Server`.
28
+ - Experiencing high load? The agent can spawn multiple instances of its Workers that pick off the queue by changing the option `pool_size` (default is `1`).
29
+ - If you have high load you may also consider setting `transaction_sample_rate` to something smaller than `1.0`. This determines whether to include _spans_ for every _transaction_. If you have enough traffic, skipping some (probably) identical spans won't have a noticeable effect on your data.
30
+
@@ -26,5 +26,7 @@ include::./supported-technologies.asciidoc[]
26
26
 
27
27
  include::./api.asciidoc[]
28
28
 
29
+ include::./debugging.asciidoc[]
30
+
29
31
  include::./release-notes.asciidoc[]
30
32
 
@@ -403,7 +403,7 @@ module ElasticAPM
403
403
  end
404
404
 
405
405
  def set_rails(app) # rubocop:disable Metrics/AbcSize
406
- self.service_name ||= format_name(service_name || app.class.parent_name)
406
+ self.service_name ||= format_name(service_name || rails_app_name(app))
407
407
  self.framework_name ||= 'Ruby on Rails'
408
408
  self.framework_version ||= Rails::VERSION::STRING
409
409
  self.logger ||= Rails.logger
@@ -412,6 +412,14 @@ module ElasticAPM
412
412
  self.view_paths = app.config.paths['app/views'].existent
413
413
  end
414
414
 
415
+ def rails_app_name(app)
416
+ if Rails::VERSION::MAJOR >= 6
417
+ app.class.module_parent_name
418
+ else
419
+ app.class.parent_name
420
+ end
421
+ end
422
+
415
423
  def build_logger
416
424
  logger = Logger.new(log_path == '-' ? STDOUT : log_path)
417
425
  logger.level = log_level
@@ -6,7 +6,7 @@ module ElasticAPM
6
6
  # @api private
7
7
  class SqlSummarizer
8
8
  DEFAULT = 'SQL'
9
- TABLE_REGEX = %{["'`]?([A-Za-z0-9_]+)}
9
+ TABLE_REGEX = %{["'`]?([A-Za-z0-9_]+)["'`]?}
10
10
 
11
11
  REGEXES = {
12
12
  /^BEGIN/i => 'BEGIN',
@@ -26,7 +26,7 @@ module ElasticAPM
26
26
  def summarize(sql)
27
27
  self.class.cache[sql] ||=
28
28
  REGEXES.find do |regex, sig|
29
- if (match = sql.match(regex))
29
+ if (match = sql[0...1000].match(regex))
30
30
  break format(FORMAT, sig, match[1] && match[1].gsub(/["']/, ''))
31
31
  end
32
32
  end || DEFAULT
@@ -50,7 +50,7 @@ module ElasticAPM
50
50
 
51
51
  {
52
52
  instance: db.instance,
53
- statement: db.statement,
53
+ statement: Util.truncate(db.statement, max_length: 10_000),
54
54
  type: db.type,
55
55
  user: db.user
56
56
  }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ElasticAPM
4
- VERSION = '2.8.0'
4
+ VERSION = '2.8.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elastic-apm
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.0
4
+ version: 2.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikkel Malmberg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-20 00:00:00.000000000 Z
11
+ date: 2019-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -73,6 +73,7 @@ files:
73
73
  - docs/configuration.asciidoc
74
74
  - docs/context.asciidoc
75
75
  - docs/custom-instrumentation.asciidoc
76
+ - docs/debugging.asciidoc
76
77
  - docs/getting-started-rack.asciidoc
77
78
  - docs/getting-started-rails.asciidoc
78
79
  - docs/index.asciidoc