elastic-apm 3.0.0 → 3.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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.ci/Jenkinsfile +4 -1
  3. data/CHANGELOG.asciidoc +497 -0
  4. data/CHANGELOG.md +1 -359
  5. data/Rakefile +2 -2
  6. data/docs/advanced.asciidoc +0 -2
  7. data/docs/api.asciidoc +12 -1
  8. data/docs/configuration.asciidoc +15 -4
  9. data/docs/custom-instrumentation.asciidoc +2 -2
  10. data/docs/debugging.asciidoc +1 -1
  11. data/docs/getting-started-rack.asciidoc +4 -1
  12. data/docs/getting-started-rails.asciidoc +2 -2
  13. data/docs/index.asciidoc +8 -9
  14. data/docs/introduction.asciidoc +17 -15
  15. data/docs/opentracing.asciidoc +13 -13
  16. data/docs/release-notes.asciidoc +11 -1
  17. data/docs/set-up.asciidoc +16 -0
  18. data/docs/supported-technologies.asciidoc +2 -4
  19. data/lib/elastic_apm.rb +2 -2
  20. data/lib/elastic_apm/agent.rb +4 -4
  21. data/lib/elastic_apm/central_config.rb +7 -3
  22. data/lib/elastic_apm/config.rb +2 -2
  23. data/lib/elastic_apm/config/options.rb +6 -0
  24. data/lib/elastic_apm/context.rb +15 -1
  25. data/lib/elastic_apm/instrumenter.rb +8 -7
  26. data/lib/elastic_apm/normalizers.rb +0 -9
  27. data/lib/elastic_apm/normalizers/rails.rb +10 -0
  28. data/lib/elastic_apm/normalizers/{action_controller.rb → rails/action_controller.rb} +0 -0
  29. data/lib/elastic_apm/normalizers/{action_mailer.rb → rails/action_mailer.rb} +0 -0
  30. data/lib/elastic_apm/normalizers/{action_view.rb → rails/action_view.rb} +0 -0
  31. data/lib/elastic_apm/normalizers/{active_record.rb → rails/active_record.rb} +0 -0
  32. data/lib/elastic_apm/rails.rb +1 -0
  33. data/lib/elastic_apm/sinatra.rb +36 -0
  34. data/lib/elastic_apm/transaction.rb +13 -6
  35. data/lib/elastic_apm/transport/serializers/context_serializer.rb +13 -1
  36. data/lib/elastic_apm/version.rb +1 -1
  37. metadata +10 -6
@@ -1,12 +1,12 @@
1
1
  [[custom-instrumentation]]
2
2
  === Custom instrumentation
3
3
 
4
- When <<introduction,installed>> and <<configuration,properly configured>>
4
+ When installed and properly configured,
5
5
  ElasticAPM will automatically wrap your app's request/responses in transactions
6
6
  and report its errors.
7
7
  It also wraps each background job if you use Sidekiq or DelayedJob.
8
8
 
9
- But it is possible to create your own transactions as well as provide spans for
9
+ But it is also possible to create your own transactions as well as provide spans for
10
10
  any automatic or custom transaction.
11
11
 
12
12
  See <<api-agent-start_transaction,`ElasticAPM.start_transaction`>> and
@@ -1,5 +1,5 @@
1
1
  [[debugging]]
2
- == Debugging the agent itself
2
+ == Troubleshooting
3
3
 
4
4
  Hopefully the agent Just Works™, but depending on your situation the agent might need some tuning.
5
5
 
@@ -5,7 +5,7 @@ https://www.elastic.co/guide/en/apm/agent/ruby/current/introduction.html[elastic
5
5
  endif::[]
6
6
 
7
7
  [[getting-started-rack]]
8
- == Getting started with Rack
8
+ === Getting started with Rack
9
9
 
10
10
  Add the gem to your `Gemfile`:
11
11
 
@@ -64,6 +64,9 @@ end
64
64
  # Takes optional ElasticAPM::Config values
65
65
  ElasticAPM.start(app: MySinatraApp, ...)
66
66
 
67
+ # You can also do the following, which is equivalent to the above:
68
+ # ElasticAPM::Sinatra.start(MySinatraApp, ...)
69
+
67
70
  run MySinatraApp
68
71
 
69
72
  at_exit { ElasticAPM.stop }
@@ -5,10 +5,10 @@ https://www.elastic.co/guide/en/apm/agent/ruby/current/introduction.html[elastic
5
5
  endif::[]
6
6
 
7
7
  [[getting-started-rails]]
8
- == Getting started with Rails
8
+ === Getting started with Rails
9
9
 
10
10
  [float]
11
- === Setup
11
+ ==== Setup
12
12
 
13
13
  Add the gem to your `Gemfile`:
14
14
 
@@ -1,5 +1,4 @@
1
- :branch: current
2
- :server-branch: 6.5
1
+ include::{asciidoc-dir}/../../shared/versions/stack/current.asciidoc[]
3
2
  include::{asciidoc-dir}/../../shared/attributes.asciidoc[]
4
3
 
5
4
  ifdef::env-github[]
@@ -12,21 +11,21 @@ endif::[]
12
11
 
13
12
  include::./introduction.asciidoc[]
14
13
 
15
- include::./getting-started-rails.asciidoc[]
14
+ include::./set-up.asciidoc[]
16
15
 
17
- include::./getting-started-rack.asciidoc[]
16
+ include::./supported-technologies.asciidoc[]
18
17
 
19
18
  include::./configuration.asciidoc[]
20
19
 
21
- include::./log-correlation.asciidoc[]
20
+ include::./advanced.asciidoc[]
22
21
 
23
- include::./metrics.asciidoc[]
22
+ include::./api.asciidoc[]
24
23
 
25
- include::./advanced.asciidoc[]
24
+ include::./metrics.asciidoc[]
26
25
 
27
- include::./supported-technologies.asciidoc[]
26
+ include::./opentracing.asciidoc[]
28
27
 
29
- include::./api.asciidoc[]
28
+ include::./log-correlation.asciidoc[]
30
29
 
31
30
  include::./debugging.asciidoc[]
32
31
 
@@ -5,15 +5,27 @@ https://www.elastic.co/guide/en/apm/agent/ruby/current/introduction.html[elastic
5
5
  endif::[]
6
6
 
7
7
  [[introduction]]
8
-
9
8
  == Introduction
10
9
 
11
- Welcome to the APM Ruby Agent documentation.
12
-
13
- The Elastic APM Ruby Agent sends performance metrics and error logs to an
14
- Elastic APM Server.
10
+ The Elastic APM Ruby Agent sends performance metrics and error logs to the APM Server.
15
11
  It has built-in support for <<getting-started-rails,Ruby on Rails>> and other
16
12
  <<getting-started-rack,Rack-compatible>> applications.
13
+ It also offers an API which allows you to instrument any application.
14
+
15
+ [float]
16
+ [[how-it-works]]
17
+ === How does the Agent work?
18
+
19
+ The agent auto-instruments <<supported-technologies,supported technologies>> and records interesting events,
20
+ like HTTP requests and database queries. To do this, it uses relevant public APIs when they are provided by the libraries. Otherwise, it carefully wraps the necessary internal methods.
21
+ This means that for the supported technologies, there are no code changes required.
22
+
23
+ The Agent automatically keeps track of queries to your data stores to measure their duration and metadata (like the DB statement),
24
+ as well as HTTP related information (like the URL, parameters, and headers).
25
+
26
+ These events, called Transactions and Spans, are sent to the APM Server.
27
+ The APM Server converts them to a format suitable for Elasticsearch, and sends them to an Elasticsearch cluster.
28
+ You can then use the APM app in Kibana to gain insight into latency issues and error culprits within your application.
17
29
 
18
30
  [float]
19
31
  [[additional-components]]
@@ -21,13 +33,3 @@ It has built-in support for <<getting-started-rails,Ruby on Rails>> and other
21
33
 
22
34
  APM Agents work in conjunction with the {apm-server-ref-v}/index.html[APM Server], {ref}/index.html[Elasticsearch], and {kibana-ref}/index.html[Kibana].
23
35
  Please view the {apm-overview-ref-v}/index.html[APM Overview] for details on how these components work together.
24
-
25
- [float]
26
- [[framework-support]]
27
- === Framework Support
28
-
29
- The Elastic APM Ruby Agent officially supports Ruby on Rails versions 4.x on
30
- onwards, see <<getting-started-rails,Getting started with Ruby on Rails>>.
31
-
32
- For Sinatra and other Rack compatible frameworks, see
33
- <<getting-started-rack,Getting started with Rack>>.
@@ -4,7 +4,7 @@ please view this documentation at https://www.elastic.co/guide/en/apm/agent/ruby
4
4
  endif::[]
5
5
 
6
6
  [[opentracing]]
7
- === OpenTracing bridge
7
+ == OpenTracing API
8
8
 
9
9
  The Elastic APM OpenTracing bridge allows to create Elastic APM `Transactions` and `Spans`,
10
10
  using the OpenTracing API.
@@ -16,7 +16,7 @@ subsequent spans are mapped to Elastic APM `Span`.
16
16
 
17
17
  [float]
18
18
  [[operation-modes]]
19
- === Operation Modes
19
+ == Operation Modes
20
20
 
21
21
  This bridge allows for different operation modes in combination with the Elastic APM Agent.
22
22
 
@@ -34,12 +34,12 @@ This bridge allows for different operation modes in combination with the Elastic
34
34
 
35
35
  [float]
36
36
  [[getting-started]]
37
- === Getting started
37
+ == Getting started
38
38
  Either `require 'elastic_apm/opentracing'` during the boot of your app or specify the `require:` argument to your `Gemfile`, eg. `gem 'elastic_apm', require: 'elastic_apm/opentracing'`.
39
39
 
40
40
  [float]
41
41
  [[init-tracer]]
42
- === Set Elastic APM as the global tracer
42
+ == Set Elastic APM as the global tracer
43
43
 
44
44
  [source,ruby]
45
45
  ----
@@ -48,47 +48,47 @@ Either `require 'elastic_apm/opentracing'` during the boot of your app or specif
48
48
 
49
49
  [float]
50
50
  [[elastic-apm-tags]]
51
- === Elastic APM specific tags
51
+ == Elastic APM specific tags
52
52
 
53
53
  Elastic APM defines some tags which are not included in the OpenTracing API but are relevant in the context of Elastic APM.
54
54
 
55
55
  - `type` - sets the type of the transaction,
56
56
  for example `request`, `ext` or `db`
57
57
  - `user.id` - sets the user id,
58
- appears in the "User" tab in the transaction details in the Elastic APM UI
58
+ appears in the "User" tab in the transaction details in the Elastic APM app
59
59
  - `user.email` - sets the user email,
60
- appears in the "User" tab in the transaction details in the Elastic APM UI
60
+ appears in the "User" tab in the transaction details in the Elastic APM app
61
61
  - `user.username` - sets the user name,
62
- appears in the "User" tab in the transaction details in the Elastic APM UI
62
+ appears in the "User" tab in the transaction details in the Elastic APM app
63
63
  - `result` - sets the result of the transaction. Overrides the default value of `success`.
64
64
  If the `error` tag is set to `true`, the default value is `error`.
65
65
 
66
66
  [float]
67
67
  [[unsupported]]
68
- === Caveats
68
+ == Caveats
69
69
  Not all features of the OpenTracing API are supported.
70
70
 
71
71
  [float]
72
72
  [[propagation]]
73
- ==== Context propagation
73
+ === Context propagation
74
74
  This bridge only supports the format `OpenTracing::FORMAT_RACK`, using HTTP headers with capitalized names, prefixed with `HTTP_` as Rack does it.
75
75
 
76
76
  `OpenTracing::FORMAT_BINARY` is currently not supported.
77
77
 
78
78
  [float]
79
79
  [[references]]
80
- ==== Span References
80
+ === Span References
81
81
  Currently, this bridge only supports `child_of` references.
82
82
  Other references,
83
83
  like `follows_from` are not supported yet.
84
84
 
85
85
  [float]
86
86
  [[baggage]]
87
- ==== Baggage
87
+ === Baggage
88
88
  The `Span.set_baggage` method is not supported.
89
89
  Baggage items are dropped with a warning log message.
90
90
 
91
91
  [float]
92
92
  [[logs]]
93
- ==== Logs
93
+ === Logs
94
94
  Logs are currently not supported.
@@ -1,4 +1,14 @@
1
+ :pull: https://github.com/elastic/apm-server/pull/
2
+
1
3
  [[release-notes]]
2
4
  == Release notes
3
5
 
4
- Release notes are published in the https://github.com/elastic/apm-agent-ruby/blob/master/CHANGELOG.md[changelog].
6
+ All notable changes to this project will be documented here.
7
+ This project adheres to http://semver.org/spec/v2.0.0.html[Semantic Versioning].
8
+
9
+ * <<release-notes-3.x>>
10
+ * <<release-notes-2.x>>
11
+ * <<release-notes-1.x>>
12
+ * <<release-notes-0.x>>
13
+
14
+ include::../CHANGELOG.asciidoc[]
@@ -0,0 +1,16 @@
1
+ ifdef::env-github[]
2
+ NOTE: For the best reading experience,
3
+ please view this documentation at
4
+ https://www.elastic.co/guide/en/apm/agent/ruby/current/set-up.html[elastic.co]
5
+ endif::[]
6
+
7
+ [[set-up]]
8
+ == Set up the Agent
9
+
10
+ To get you off the ground, we’ve prepared guides for setting up the Agent with different frameworks:
11
+
12
+ include::./getting-started-rails.asciidoc[]
13
+
14
+ include::./getting-started-rack.asciidoc[]
15
+
16
+ For custom instrumentation, see the <<api>>.
@@ -7,10 +7,8 @@ endif::[]
7
7
  == Supported technologies
8
8
 
9
9
  The Elastic APM Ruby Agent has built-in support for many frameworks and
10
- libraries.
11
-
12
- Generally we want to support all the most popular libraries, so if your favorite
13
- is missing feel free so request it in an issue or better yet supply a pull
10
+ libraries. Generally, we want to support all of the most popular libraries. If your favorite
11
+ is missing, feel free to request it in an issue, or better yet, create a pull
14
12
  request.
15
13
 
16
14
  [float]
@@ -14,6 +14,7 @@ require 'elastic_apm/util'
14
14
  require 'elastic_apm/middleware'
15
15
 
16
16
  require 'elastic_apm/railtie' if defined?(::Rails::Railtie)
17
+ require 'elastic_apm/sinatra' if defined?(::Sinatra)
17
18
 
18
19
  # ElasticAPM
19
20
  module ElasticAPM # rubocop:disable Metrics/ModuleLength
@@ -80,7 +81,6 @@ module ElasticAPM # rubocop:disable Metrics/ModuleLength
80
81
  end
81
82
  # rubocop:enable Metrics/AbcSize
82
83
 
83
- # rubocop:disable Metrics/MethodLength
84
84
  # Start a new transaction
85
85
  #
86
86
  # @param name [String] A description of the transaction, eg
@@ -102,7 +102,6 @@ module ElasticAPM # rubocop:disable Metrics/ModuleLength
102
102
  trace_context: trace_context
103
103
  )
104
104
  end
105
- # rubocop:enable Metrics/MethodLength
106
105
 
107
106
  # Ends the current transaction with `result`
108
107
  #
@@ -150,6 +149,7 @@ module ElasticAPM # rubocop:disable Metrics/ModuleLength
150
149
  end
151
150
  # rubocop:enable Metrics/MethodLength
152
151
 
152
+ # rubocop:disable Metrics/MethodLength, Metrics/ParameterLists
153
153
  # Start a new span
154
154
  #
155
155
  # @param name [String] A description of the span, eq `SELECT FROM "users"`
@@ -17,6 +17,7 @@ module ElasticAPM
17
17
  # @api private
18
18
  class Agent
19
19
  include Logging
20
+ extend Forwardable
20
21
 
21
22
  LOCK = Mutex.new
22
23
 
@@ -61,10 +62,7 @@ module ElasticAPM
61
62
  !!@instance
62
63
  end
63
64
 
64
- # rubocop:disable Metrics/MethodLength
65
65
  def initialize(config)
66
- @config = config
67
-
68
66
  @stacktrace_builder = StacktraceBuilder.new(config)
69
67
  @context_builder = ContextBuilder.new(config)
70
68
  @error_builder = ErrorBuilder.new(self)
@@ -77,7 +75,6 @@ module ElasticAPM
77
75
  ) { |event| enqueue event }
78
76
  @metrics = Metrics.new(config) { |event| enqueue event }
79
77
  end
80
- # rubocop:enable Metrics/MethodLength
81
78
 
82
79
  attr_reader(
83
80
  :central_config,
@@ -90,6 +87,8 @@ module ElasticAPM
90
87
  :transport
91
88
  )
92
89
 
90
+ def_delegator :@central_config, :config
91
+
93
92
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
94
93
  def start
95
94
  unless config.disable_start_message
@@ -150,6 +149,7 @@ module ElasticAPM
150
149
  instrumenter.start_transaction(
151
150
  name,
152
151
  type,
152
+ config: config,
153
153
  context: context,
154
154
  trace_context: trace_context
155
155
  )
@@ -81,11 +81,15 @@ module ElasticAPM
81
81
  update[key] = @modified_options.delete(key)
82
82
  end
83
83
 
84
- config.assign(update)
84
+ update_config(update)
85
85
  end
86
86
 
87
87
  private
88
88
 
89
+ def update_config(new_options)
90
+ @config = config.dup.tap { |new_config| new_config.assign(new_options) }
91
+ end
92
+
89
93
  # rubocop:disable Metrics/MethodLength
90
94
  def handle_success(resp)
91
95
  if resp.status == 304
@@ -107,7 +111,7 @@ module ElasticAPM
107
111
  # rubocop:enable Metrics/MethodLength
108
112
 
109
113
  def handle_error(error)
110
- error(
114
+ debug(
111
115
  'Failed fetching config: %s, trying again in %d seconds',
112
116
  error.response.body, DEFAULT_MAX_AGE
113
117
  )
@@ -119,7 +123,7 @@ module ElasticAPM
119
123
 
120
124
  def perform_request
121
125
  Http.post(
122
- config.server_url + '/agent/v1/config/',
126
+ config.server_url + '/config/v1/agents',
123
127
  body: @service_info,
124
128
  headers: { etag: 1, content_type: 'application/json' }
125
129
  )
@@ -21,7 +21,7 @@ module ElasticAPM
21
21
 
22
22
  # rubocop:disable Metrics/LineLength, Layout/ExtraSpacing
23
23
  option :config_file, type: :string, default: 'config/elastic_apm.yml'
24
- option :server_url, type: :string, default: 'http://localhost:8200'
24
+ option :server_url, type: :url, default: 'http://localhost:8200'
25
25
  option :secret_token, type: :string
26
26
 
27
27
  option :active, type: :bool, default: true
@@ -215,7 +215,7 @@ module ElasticAPM
215
215
  def set_sinatra(app)
216
216
  self.service_name = format_name(service_name || app.to_s)
217
217
  self.framework_name = framework_name || 'Sinatra'
218
- self.framework_version = framework_version || Sinatra::VERSION
218
+ self.framework_version = framework_version || ::Sinatra::VERSION
219
219
  self.__root_path = Dir.pwd
220
220
  end
221
221
 
@@ -48,6 +48,7 @@ module ElasticAPM
48
48
  when :bool then normalize_bool(val)
49
49
  when :list then normalize_list(val)
50
50
  when :dict then normalize_dict(val)
51
+ when :url then normalize_url(val)
51
52
  else
52
53
  # raise "Unknown options type '#{type.inspect}'"
53
54
  val
@@ -69,6 +70,11 @@ module ElasticAPM
69
70
  return val unless val.is_a?(String)
70
71
  Hash[val.split(/[&,]/).map { |kv| kv.split('=') }]
71
72
  end
73
+
74
+ def normalize_url(val)
75
+ val = val.to_s
76
+ val.end_with?('/') ? val.chomp('/') : val
77
+ end
72
78
  end
73
79
 
74
80
  # @api private
@@ -9,25 +9,39 @@ require 'elastic_apm/context/user'
9
9
  module ElasticAPM
10
10
  # @api private
11
11
  class Context
12
- def initialize(custom: {}, labels: {}, user: nil)
12
+ def initialize(custom: {}, labels: {}, user: nil, service: nil)
13
13
  @custom = custom
14
14
  @labels = labels
15
15
  @user = user || User.new
16
+ @service = service
16
17
  end
17
18
 
19
+ Service = Struct.new(:framework)
20
+ Framework = Struct.new(:name, :version)
21
+
18
22
  attr_accessor :request
19
23
  attr_accessor :response
20
24
  attr_accessor :user
21
25
  attr_reader :custom
22
26
  attr_reader :labels
27
+ attr_reader :service
23
28
 
29
+ # rubocop:disable Metrics/CyclomaticComplexity
24
30
  def empty?
25
31
  return false if labels.any?
26
32
  return false if custom.any?
27
33
  return false if user.any?
34
+ return false if service
28
35
  return false if request || response
29
36
 
30
37
  true
31
38
  end
39
+ # rubocop:enable Metrics/CyclomaticComplexity
40
+
41
+ def set_service(framework_name: nil, framework_version: nil)
42
+ @service = Service.new(
43
+ Framework.new(framework_name, framework_version)
44
+ )
45
+ end
32
46
  end
33
47
  end