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.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rubocop.yml +48 -0
- data/.travis.yml +16 -0
- data/AUTHORS +1 -0
- data/CODE_OF_CONDUCT.md +43 -0
- data/CONTRIBUTING.md +34 -0
- data/Gemfile +4 -0
- data/LICENSE +201 -0
- data/README.md +180 -0
- data/Rakefile +20 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/docs/.gitignore +3 -0
- data/docs/404.html +24 -0
- data/docs/Gemfile +31 -0
- data/docs/_config.yml +39 -0
- data/docs/_layouts/default.html +65 -0
- data/docs/index.md +151 -0
- data/lib/opencensus.rb +21 -0
- data/lib/opencensus/common.rb +24 -0
- data/lib/opencensus/common/config.rb +521 -0
- data/lib/opencensus/config.rb +54 -0
- data/lib/opencensus/context.rb +72 -0
- data/lib/opencensus/stats.rb +26 -0
- data/lib/opencensus/tags.rb +25 -0
- data/lib/opencensus/trace.rb +181 -0
- data/lib/opencensus/trace/annotation.rb +60 -0
- data/lib/opencensus/trace/config.rb +119 -0
- data/lib/opencensus/trace/exporters.rb +26 -0
- data/lib/opencensus/trace/exporters/logger.rb +149 -0
- data/lib/opencensus/trace/formatters.rb +29 -0
- data/lib/opencensus/trace/formatters/binary.rb +66 -0
- data/lib/opencensus/trace/formatters/cloud_trace.rb +102 -0
- data/lib/opencensus/trace/formatters/trace_context.rb +124 -0
- data/lib/opencensus/trace/integrations.rb +24 -0
- data/lib/opencensus/trace/integrations/faraday_middleware.rb +176 -0
- data/lib/opencensus/trace/integrations/rack_middleware.rb +127 -0
- data/lib/opencensus/trace/integrations/rails.rb +121 -0
- data/lib/opencensus/trace/link.rb +90 -0
- data/lib/opencensus/trace/message_event.rb +80 -0
- data/lib/opencensus/trace/samplers.rb +50 -0
- data/lib/opencensus/trace/samplers/always_sample.rb +34 -0
- data/lib/opencensus/trace/samplers/max_qps.rb +55 -0
- data/lib/opencensus/trace/samplers/never_sample.rb +34 -0
- data/lib/opencensus/trace/samplers/probability.rb +69 -0
- data/lib/opencensus/trace/span.rb +196 -0
- data/lib/opencensus/trace/span_builder.rb +560 -0
- data/lib/opencensus/trace/span_context.rb +308 -0
- data/lib/opencensus/trace/status.rb +49 -0
- data/lib/opencensus/trace/time_event.rb +38 -0
- data/lib/opencensus/trace/trace_context_data.rb +22 -0
- data/lib/opencensus/trace/truncatable_string.rb +61 -0
- data/lib/opencensus/version.rb +18 -0
- data/opencensus.gemspec +32 -0
- 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
|