opencensus 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.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rubocop.yml +48 -0
  4. data/.travis.yml +16 -0
  5. data/AUTHORS +1 -0
  6. data/CODE_OF_CONDUCT.md +43 -0
  7. data/CONTRIBUTING.md +34 -0
  8. data/Gemfile +4 -0
  9. data/LICENSE +201 -0
  10. data/README.md +180 -0
  11. data/Rakefile +20 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/docs/.gitignore +3 -0
  15. data/docs/404.html +24 -0
  16. data/docs/Gemfile +31 -0
  17. data/docs/_config.yml +39 -0
  18. data/docs/_layouts/default.html +65 -0
  19. data/docs/index.md +151 -0
  20. data/lib/opencensus.rb +21 -0
  21. data/lib/opencensus/common.rb +24 -0
  22. data/lib/opencensus/common/config.rb +521 -0
  23. data/lib/opencensus/config.rb +54 -0
  24. data/lib/opencensus/context.rb +72 -0
  25. data/lib/opencensus/stats.rb +26 -0
  26. data/lib/opencensus/tags.rb +25 -0
  27. data/lib/opencensus/trace.rb +181 -0
  28. data/lib/opencensus/trace/annotation.rb +60 -0
  29. data/lib/opencensus/trace/config.rb +119 -0
  30. data/lib/opencensus/trace/exporters.rb +26 -0
  31. data/lib/opencensus/trace/exporters/logger.rb +149 -0
  32. data/lib/opencensus/trace/formatters.rb +29 -0
  33. data/lib/opencensus/trace/formatters/binary.rb +66 -0
  34. data/lib/opencensus/trace/formatters/cloud_trace.rb +102 -0
  35. data/lib/opencensus/trace/formatters/trace_context.rb +124 -0
  36. data/lib/opencensus/trace/integrations.rb +24 -0
  37. data/lib/opencensus/trace/integrations/faraday_middleware.rb +176 -0
  38. data/lib/opencensus/trace/integrations/rack_middleware.rb +127 -0
  39. data/lib/opencensus/trace/integrations/rails.rb +121 -0
  40. data/lib/opencensus/trace/link.rb +90 -0
  41. data/lib/opencensus/trace/message_event.rb +80 -0
  42. data/lib/opencensus/trace/samplers.rb +50 -0
  43. data/lib/opencensus/trace/samplers/always_sample.rb +34 -0
  44. data/lib/opencensus/trace/samplers/max_qps.rb +55 -0
  45. data/lib/opencensus/trace/samplers/never_sample.rb +34 -0
  46. data/lib/opencensus/trace/samplers/probability.rb +69 -0
  47. data/lib/opencensus/trace/span.rb +196 -0
  48. data/lib/opencensus/trace/span_builder.rb +560 -0
  49. data/lib/opencensus/trace/span_context.rb +308 -0
  50. data/lib/opencensus/trace/status.rb +49 -0
  51. data/lib/opencensus/trace/time_event.rb +38 -0
  52. data/lib/opencensus/trace/trace_context_data.rb +22 -0
  53. data/lib/opencensus/trace/truncatable_string.rb +61 -0
  54. data/lib/opencensus/version.rb +18 -0
  55. data/opencensus.gemspec +32 -0
  56. metadata +210 -0
@@ -0,0 +1,24 @@
1
+ # Copyright 2017 OpenCensus Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module OpenCensus
16
+ module Trace
17
+ ##
18
+ # The Integrations module contains implementations of integrations with
19
+ # popular gems such as Rails and Faraday.
20
+ #
21
+ module Integrations
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,176 @@
1
+ # Copyright 2017 OpenCensus Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "faraday"
16
+
17
+ module OpenCensus
18
+ module Trace
19
+ module Integrations
20
+ ##
21
+ # # Faraday integration
22
+ #
23
+ # This is a middleware for the Faraday HTTP client:
24
+ #
25
+ # * It wraps all outgoing requests in spans
26
+ # * It adds the trace context to outgoing requests.
27
+ #
28
+ # Example:
29
+ #
30
+ # conn = Faraday.new(url: "http://www.example.com") do |c|
31
+ # c.use OpenCensus::Trace::Integrations::FaradayMiddleware,
32
+ # span_name: "http request"
33
+ # c.adapter Faraday.default_adapter
34
+ # end
35
+ # conn.get "/"
36
+ #
37
+ # ## Configuring spans
38
+ #
39
+ # By default, spans are added to the thread-local span context, as if
40
+ # by calling `OpenCensus::Trace.start_span`. If there is no span context,
41
+ # then no span is added and this middleware effectively disables itself.
42
+ #
43
+ # You may also provide a span context, by passing it in the middleware
44
+ # options hash. For example:
45
+ #
46
+ # conn = Faraday.new(url: "http://www.example.com") do |c|
47
+ # c.use OpenCensus::Trace::Integrations::FaradayMiddleware,
48
+ # span_context: my_span_context
49
+ # c.adapter Faraday.default_adapter
50
+ # end
51
+ #
52
+ # You may also override the span context for a particular request by
53
+ # including it in the options:
54
+ #
55
+ # conn.get do |req|
56
+ # req.url "/"
57
+ # req.options.context = { span_context: my_span_context }
58
+ # end
59
+ #
60
+ # By default, all spans are given a default name. You may also override
61
+ # this by passing a `:span_name` in the middleware options hash and/or
62
+ # the request options.
63
+ #
64
+ # ## Trace context
65
+ #
66
+ # This currently adds a header to each outgoing request, propagating the
67
+ # trace context for distributed tracing. By default, this uses the
68
+ # formatter in the current config.
69
+ #
70
+ # You may provide your own implementation of the formatter by configuring
71
+ # it in the middleware options hash. For example:
72
+ #
73
+ # conn = Faraday.new(url: "http://www.example.com") do |c|
74
+ # c.use OpenCensus::Trace::Integrations::FaradayMiddleware,
75
+ # formatter: OpenCensus::Trace::Formatters::CloudTrace.new
76
+ # c.adapter Faraday.default_adapter
77
+ # end
78
+ #
79
+ # You many also override the formatter for a particular request by
80
+ # including it in the options:
81
+ #
82
+ # conn.get do |req|
83
+ # req.url "/"
84
+ # req.options.context = {
85
+ # formatter: OpenCensus::Trace::Formatters::CloudTrace.new
86
+ # }
87
+ # end
88
+ #
89
+ class FaradayMiddleware < Faraday::Middleware
90
+ ## The default name for Faraday spans
91
+ DEFAULT_SPAN_NAME = "faraday_request".freeze
92
+
93
+ ##
94
+ # Create a FaradayMiddleware.
95
+ #
96
+ # @param [#call] app Next item on the middleware stack.
97
+ # @param [SpanContext] span_context The span context within which
98
+ # to create spans. Optional: If omitted, spans are created in the
99
+ # current thread-local span context.
100
+ # @param [String, #call] span_name The name of the span to create.
101
+ # Can be a string or a callable that takes a faraday request env
102
+ # and returns a string. Optional: If omitted, uses
103
+ # `DEFAULT_SPAN_NAME`
104
+ # @param [#call] sampler The sampler to use when creating spans.
105
+ # Optional: If omitted, uses the sampler in the current config.
106
+ # @param [#serialize,#header_name] formatter The formatter to use when
107
+ # propagating span context. Optional: If omitted, use the formatter
108
+ # in the current config.
109
+ #
110
+ def initialize app, span_context: nil, span_name: nil, sampler: nil,
111
+ formatter: nil
112
+ @app = app
113
+ @span_context = span_context || OpenCensus::Trace
114
+ @span_name = span_name || DEFAULT_SPAN_NAME
115
+ @sampler = sampler
116
+ @formatter = formatter || OpenCensus::Trace.config.http_formatter
117
+ end
118
+
119
+ ##
120
+ # Wraps an HTTP call with a span with the request/response info.
121
+ # @private
122
+ #
123
+ def call request_env
124
+ span_context = request_env[:span_context] || @span_context
125
+ if span_context == OpenCensus::Trace && !span_context.span_context
126
+ return @app.call request_env
127
+ end
128
+
129
+ span_name = request_env[:span_name] || @span_name
130
+ span_name = span_name.call request_env if span_name.respond_to? :call
131
+
132
+ span = span_context.start_span span_name, sampler: @sampler
133
+ start_request span, request_env
134
+ @app.call(request_env).on_complete do |response_env|
135
+ finish_request span, response_env
136
+ span_context.end_span span
137
+ end
138
+ end
139
+
140
+ protected
141
+
142
+ ##
143
+ # @private Set span attributes from request object
144
+ #
145
+ def start_request span, env
146
+ req_method = env[:method]
147
+ span.put_attribute "/http/method", req_method if req_method
148
+ url = env[:url]
149
+ span.put_attribute "/http/url", url if url
150
+ body = env[:body]
151
+ body_size = body.bytesize if body.respond_to? :bytesize
152
+ span.put_attribute "/rpc/request/size", body_size if body_size
153
+
154
+ formatter = env[:formatter] || @formatter
155
+ trace_context = formatter.serialize span.context.trace_context
156
+ headers = env[:request_headers] ||= {}
157
+ headers[formatter.header_name] = trace_context
158
+ end
159
+
160
+ ##
161
+ # @private Set span attributes from response
162
+ #
163
+ def finish_request span, env
164
+ status = env[:status].to_i
165
+ if status > 0
166
+ span.set_status status
167
+ span.put_attribute "/rpc/status_code", status
168
+ end
169
+ body = env[:body]
170
+ body_size = body.bytesize if body.respond_to? :bytesize
171
+ span.put_attribute "/rpc/response/size", body_size if body_size
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,127 @@
1
+ # Copyright 2017 OpenCensus Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module OpenCensus
16
+ module Trace
17
+ module Integrations
18
+ ##
19
+ # # Rack integration
20
+ #
21
+ # This is a middleware for Rack applications:
22
+ #
23
+ # * It wraps all incoming requests in a root span
24
+ # * It exports the captured spans at the end of the request.
25
+ #
26
+ # Example:
27
+ #
28
+ # require "opencensus/trace/integrations/rack_middleware"
29
+ #
30
+ # use OpenCensus::Trace::Integrations::RackMiddleware
31
+ #
32
+ class RackMiddleware
33
+ ##
34
+ # List of trace context formatters we use to parse the parent span
35
+ # context.
36
+ #
37
+ # @private
38
+ #
39
+ AUTODETECTABLE_FORMATTERS = [
40
+ Formatters::CloudTrace.new,
41
+ Formatters::TraceContext.new
42
+ ].freeze
43
+
44
+ ##
45
+ # Create the Rack middleware.
46
+ #
47
+ # @param [#call] app Next item on the middleware stack
48
+ # @param [#export] exporter The exported used to export captured spans
49
+ # at the end of the request. Optional: If omitted, uses the exporter
50
+ # in the current config.
51
+ #
52
+ def initialize app, exporter: nil
53
+ @app = app
54
+ @exporter = exporter || OpenCensus::Trace.config.exporter
55
+ end
56
+
57
+ ##
58
+ # Run the Rack middleware.
59
+ #
60
+ # @param [Hash] env The rack environment
61
+ # @return [Array] The rack response. An array with 3 elements: the HTTP
62
+ # response code, a Hash of the response headers, and the response
63
+ # body which must respond to `each`.
64
+ #
65
+ def call env
66
+ formatter = AUTODETECTABLE_FORMATTERS.detect do |f|
67
+ env.key? f.rack_header_name
68
+ end
69
+ if formatter
70
+ context = formatter.deserialize env[formatter.rack_header_name]
71
+ end
72
+
73
+ Trace.start_request_trace trace_context: context do |span_context|
74
+ begin
75
+ span_context.in_span get_path(env) do |span|
76
+ start_request span, env
77
+ @app.call(env).tap do |response|
78
+ finish_request span, response
79
+ end
80
+ end
81
+ ensure
82
+ @exporter.export span_context.build_contained_spans
83
+ end
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ def get_path env
90
+ path = "#{env['SCRIPT_NAME']}#{env['PATH_INFO']}"
91
+ path = "/#{path}" unless path.start_with? "/"
92
+ path
93
+ end
94
+
95
+ def get_host env
96
+ env["HTTP_HOST"] || env["SERVER_NAME"]
97
+ end
98
+
99
+ def get_url env
100
+ path = get_path env
101
+ host = get_host env
102
+ scheme = env["SERVER_PROTOCOL"]
103
+ query_string = env["QUERY_STRING"].to_s
104
+ url = "#{scheme}://#{host}#{path}"
105
+ url = "#{url}?#{query_string}" unless query_string.empty?
106
+ url
107
+ end
108
+
109
+ def start_request span, env
110
+ span.put_attribute "/http/host", get_host(env)
111
+ span.put_attribute "/http/url", get_url(env)
112
+ span.put_attribute "/http/method", env["REQUEST_METHOD"]
113
+ span.put_attribute "/http/client_protocol", env["SERVER_PROTOCOL"]
114
+ span.put_attribute "/http/user_agent", env["HTTP_USER_AGENT"]
115
+ span.put_attribute "/pid", ::Process.pid.to_s
116
+ span.put_attribute "/tid", ::Thread.current.object_id.to_s
117
+ end
118
+
119
+ def finish_request span, response
120
+ if response.is_a?(::Array) && response.size == 3
121
+ span.set_status response[0]
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,121 @@
1
+ # Copyright 2017 OpenCensus Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "active_support"
16
+ require "rails/railtie"
17
+ require "opencensus/trace/integrations/rack_middleware"
18
+
19
+ module OpenCensus
20
+ module Trace
21
+ module Integrations
22
+ ##
23
+ # # Rails Integration
24
+ #
25
+ # This Railtie automatically sets up OpenCensus for a Rails server:
26
+ #
27
+ # * It wraps all requests in spans, using the `RackMiddleware`
28
+ # integration.
29
+ # * It wraps common events (ActiveRecord database calls, ActionView
30
+ # renders, etc) in subspans.
31
+ #
32
+ # ## Configuration
33
+ #
34
+ # This Railtie exposes the OpenCensus configuration on the `opencensus`
35
+ # key of the Rails configuration. So you can, for example, set:
36
+ #
37
+ # config.opencensus.trace.default_max_attributes = 64
38
+ #
39
+ # This Railtie also provides a `notifications` configuration that
40
+ # supports the following fields:
41
+ #
42
+ # * `events` An array of strings indicating the events that will
43
+ # trigger the creation of spans. The default value is
44
+ # {OpenCensus::Trace::Integrations::Rails::DEFAULT_NOTIFICATION_EVENTS}.
45
+ # * `attribute_namespace` A string that will be prepended to all
46
+ # attributes copied from the event payload. Defaults to "`rails/`"
47
+ #
48
+ # You can access these in the `notifications` subconfiguration under
49
+ # the trace configuration. For example:
50
+ #
51
+ # OpenCensus::Trace.config do |config|
52
+ # config.notifications.attribute_namespace = "myapp/"
53
+ # end
54
+ #
55
+ # Or, using Rails:
56
+ #
57
+ # config.opencensus.trace.notifications.attribute_namespace = "myapp/"
58
+ #
59
+ class Rails < ::Rails::Railtie
60
+ ##
61
+ # The ActiveSupport notifications that will be reported as spans by
62
+ # default. To change this list, update the value of the
63
+ # `trace.notifications.events` configuration.
64
+ #
65
+ DEFAULT_NOTIFICATION_EVENTS = [
66
+ "sql.active_record",
67
+ "render_template.action_view",
68
+ "send_file.action_controller",
69
+ "send_data.action_controller",
70
+ "deliver.action_mailer"
71
+ ].freeze
72
+
73
+ OpenCensus::Trace.configure do |c|
74
+ c.add_config! :notifications do |rc|
75
+ rc.add_option! :events, DEFAULT_NOTIFICATION_EVENTS.dup
76
+ rc.add_option! :attribute_namespace, "rails/"
77
+ end
78
+ end
79
+
80
+ unless config.respond_to? :opencensus
81
+ config.opencensus = OpenCensus.configure
82
+ end
83
+
84
+ initializer "opencensus.trace" do |app|
85
+ app.middleware.insert_before ::Rack::Runtime, RackMiddleware
86
+ setup_notifications
87
+ end
88
+
89
+ ##
90
+ # Initialize notifications
91
+ # @private
92
+ #
93
+ def setup_notifications
94
+ OpenCensus::Trace.configure.notifications.events.each do |type|
95
+ ActiveSupport::Notifications.subscribe(type) do |*args|
96
+ event = ActiveSupport::Notifications::Event.new(*args)
97
+ handle_notification_event event
98
+ end
99
+ end
100
+ end
101
+
102
+ ##
103
+ # Add a span based on a notification event.
104
+ # @private
105
+ #
106
+ def handle_notification_event event
107
+ span_context = OpenCensus::Trace.span_context
108
+ if span_context
109
+ ns = OpenCensus::Trace.configure.notifications.attribute_namespace
110
+ span = span_context.start_span event.name, skip_frames: 2
111
+ span.start_time = event.time
112
+ span.end_time = event.end
113
+ event.payload.each do |k, v|
114
+ span.put_attribute "#{ns}#{k}", v.to_s
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end