opencensus 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|