epsagon 0.0.0 → 0.0.1
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 +4 -4
- data/lib/epsagon.rb +55 -21
- data/lib/instrumentation/aws_sdk.rb +171 -0
- data/lib/instrumentation/faraday.rb +12 -3
- data/lib/instrumentation/net_http.rb +10 -2
- data/lib/instrumentation/sinatra.rb +11 -2
- data/lib/util.rb +1 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87955008fa3a72eef9788a33b27ea5b1b803f05f5b4576980cbfcde82f418b8f
|
4
|
+
data.tar.gz: 8f55c3de860ad268786aac29fc6d132d60aaf3314858de5b7a396700a8e6b57c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c75902bf40adc989654cafad809e2cfac0a9dbba506981a3f52be29868fad8ba77691580bbae616fe793a3fb47e0ef4070d822cb659ae186ba1af86016ecd0a8
|
7
|
+
data.tar.gz: 7eaf1f961154c97d106bf0ec95d763bbdb049783bbcafb08abe2ff9f685a4ab17f77282b483e42d2a06bf07ef588ab9d346b66a074355141a1f13f5a6f104190
|
data/lib/epsagon.rb
CHANGED
@@ -12,31 +12,65 @@ require_relative 'util'
|
|
12
12
|
|
13
13
|
Bundler.require
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
# Epsagon tracing main entry point
|
16
|
+
module Epsagon
|
17
|
+
module_function
|
18
18
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
19
|
+
def init(**args)
|
20
|
+
defaults = {
|
21
|
+
metadata_only: ENV['EPSAGON_METADATA']&.to_s&.downcase != 'false',
|
22
|
+
debug: ENV['EPSAGON_DEBUG']&.to_s&.downcase == 'true',
|
23
|
+
token: ENV['EPSAGON_TOKEN'],
|
24
|
+
app_name: ENV['EPSAGON_APP_NAME'],
|
25
|
+
backend: ENV['EPSAGON_BACKEND'] || 'localhost:55681/v1/trace'
|
26
|
+
}
|
27
|
+
@@epsagon_config = defaults.merge(args)
|
28
|
+
end
|
29
|
+
|
30
|
+
def metadata_only?
|
31
|
+
ENV['EPSAGON_METADATA']&.to_s&.downcase != 'false'
|
32
|
+
end
|
33
|
+
|
34
|
+
def debug?
|
35
|
+
ENV['EPSAGON_DEBUG']&.to_s&.downcase == 'true'
|
36
|
+
end
|
22
37
|
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
38
|
+
# config opentelemetry with epsaon extensions:
|
39
|
+
|
40
|
+
def epsagon_confs(configurator)
|
41
|
+
configurator.resource = OpenTelemetry::SDK::Resources::Resource.telemetry_sdk.merge(
|
42
|
+
OpenTelemetry::SDK::Resources::Resource.create({ 'application' => ENV['EPSAGON_APP_NAME'] })
|
43
|
+
)
|
44
|
+
configurator.use 'EpsagonSinatraInstrumentation', { epsagon: @@epsagon_config }
|
45
|
+
configurator.use 'EpsagonNetHTTPInstrumentation', { epsagon: @@epsagon_config }
|
46
|
+
configurator.use 'EpsagonFaradayInstrumentation', { epsagon: @@epsagon_config }
|
47
|
+
# if ENV['EPSAGON_BACKEND']
|
48
|
+
configurator.add_span_processor OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
|
49
|
+
exporter: OpenTelemetry::Exporter::OTLP::Exporter.new(headers: {
|
50
|
+
'x-epsagon-token' => @@epsagon_config[:token]
|
51
|
+
},
|
52
|
+
endpoint: @@epsagon_config[:backend],
|
53
|
+
insecure: @@epsagon_config[:insecure] || false)
|
36
54
|
)
|
37
|
-
|
38
|
-
|
55
|
+
return unless debug?
|
56
|
+
|
57
|
+
configurator.add_span_processor OpenTelemetry::SDK::Trace::Export::SimpleSpanProcessor.new(
|
39
58
|
OpenTelemetry::SDK::Trace::Export::ConsoleSpanExporter.new
|
40
59
|
)
|
41
60
|
end
|
61
|
+
|
62
|
+
OpenTelemetry::SDK.configure
|
63
|
+
end
|
64
|
+
|
65
|
+
# monkey patch to include epsagon confs
|
66
|
+
module OpenTelemetry
|
67
|
+
# monkey patch inner SDK module
|
68
|
+
module SDK
|
69
|
+
def self.configure
|
70
|
+
super do |c|
|
71
|
+
yield c if block_given?
|
72
|
+
Epsagon.epsagon_confs c
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
42
76
|
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../util'
|
4
|
+
|
5
|
+
# AWS SDK plugin for epsagon instrumentation
|
6
|
+
class EpsagonAwsPlugin < Seahorse::Client::Plugin
|
7
|
+
def add_handlers(handlers, _)
|
8
|
+
handlers.add(EpsagonAwsHandler, step: :validate)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Generates Spans for all uses of AWS SDK
|
13
|
+
class EpsagonAwsHandler < Seahorse::Client::Handler
|
14
|
+
def call(context)
|
15
|
+
span_name = "AWS #{context[:service_name]}"
|
16
|
+
tracer.in_span(span_name) do |span|
|
17
|
+
@handler.call(context).tap do
|
18
|
+
span.set_attribute('aws.command', context[:command])
|
19
|
+
span.set_attribute('aws.status_code', context[:status_code])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def tracer
|
25
|
+
EpsagonAwsSdkInstrumentation.instance.tracer
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# AWS SDK epsagon instrumentation
|
30
|
+
class EpsagonAwsSdkInstrumentation < OpenTelemetry::Instrumentation::Base
|
31
|
+
VERSION = '0.0.0'
|
32
|
+
SERVICES = %w[
|
33
|
+
ACM
|
34
|
+
APIGateway
|
35
|
+
AppStream
|
36
|
+
ApplicationAutoScaling
|
37
|
+
ApplicationDiscoveryService
|
38
|
+
Athena
|
39
|
+
AutoScaling
|
40
|
+
Batch
|
41
|
+
Budgets
|
42
|
+
CloudDirectory
|
43
|
+
CloudFormation
|
44
|
+
CloudFront
|
45
|
+
CloudHSM
|
46
|
+
CloudHSMV2
|
47
|
+
CloudSearch
|
48
|
+
CloudSearchDomain
|
49
|
+
CloudTrail
|
50
|
+
CloudWatch
|
51
|
+
CloudWatchEvents
|
52
|
+
CloudWatchLogs
|
53
|
+
CodeBuild
|
54
|
+
CodeCommit
|
55
|
+
CodeDeploy
|
56
|
+
CodePipeline
|
57
|
+
CodeStar
|
58
|
+
CognitoIdentity
|
59
|
+
CognitoIdentityProvider
|
60
|
+
CognitoSync
|
61
|
+
ConfigService
|
62
|
+
CostandUsageReportService
|
63
|
+
DAX
|
64
|
+
DataPipeline
|
65
|
+
DatabaseMigrationService
|
66
|
+
DeviceFarm
|
67
|
+
DirectConnect
|
68
|
+
DirectoryService
|
69
|
+
DynamoDB
|
70
|
+
DynamoDBStreams
|
71
|
+
EC2
|
72
|
+
ECR
|
73
|
+
ECS
|
74
|
+
EFS
|
75
|
+
EMR
|
76
|
+
ElastiCache
|
77
|
+
ElasticBeanstalk
|
78
|
+
ElasticLoadBalancing
|
79
|
+
ElasticLoadBalancingV2
|
80
|
+
ElasticTranscoder
|
81
|
+
ElasticsearchService
|
82
|
+
EventBridge
|
83
|
+
Firehose
|
84
|
+
GameLift
|
85
|
+
Glacier
|
86
|
+
Glue
|
87
|
+
Greengrass
|
88
|
+
Health
|
89
|
+
IAM
|
90
|
+
ImportExport
|
91
|
+
Inspector
|
92
|
+
IoT
|
93
|
+
IoTDataPlane
|
94
|
+
KMS
|
95
|
+
Kinesis
|
96
|
+
KinesisAnalytics
|
97
|
+
Lambda
|
98
|
+
LambdaPreview
|
99
|
+
Lex
|
100
|
+
LexModelBuildingService
|
101
|
+
Lightsail
|
102
|
+
MTurk
|
103
|
+
MachineLearning
|
104
|
+
MarketplaceCommerceAnalytics
|
105
|
+
MarketplaceEntitlementService
|
106
|
+
MarketplaceMetering
|
107
|
+
MigrationHub
|
108
|
+
Mobile
|
109
|
+
OpsWorks
|
110
|
+
OpsWorksCM
|
111
|
+
Organizations
|
112
|
+
Pinpoint
|
113
|
+
Polly
|
114
|
+
RDS
|
115
|
+
Redshift
|
116
|
+
Rekognition
|
117
|
+
ResourceGroupsTaggingAPI
|
118
|
+
Route53
|
119
|
+
Route53Domains
|
120
|
+
S3
|
121
|
+
SES
|
122
|
+
SMS
|
123
|
+
SNS
|
124
|
+
SQS
|
125
|
+
SSM
|
126
|
+
STS
|
127
|
+
SWF
|
128
|
+
ServiceCatalog
|
129
|
+
Shield
|
130
|
+
SimpleDB
|
131
|
+
Snowball
|
132
|
+
States
|
133
|
+
StorageGateway
|
134
|
+
Support
|
135
|
+
Textract
|
136
|
+
WAF
|
137
|
+
WAFRegional
|
138
|
+
WorkDocs
|
139
|
+
WorkSpaces
|
140
|
+
XRay
|
141
|
+
].freeze
|
142
|
+
|
143
|
+
install do |_|
|
144
|
+
::Seahorse::Client::Base.add_plugin(EpsagonAwsPlugin)
|
145
|
+
loaded_constants.each { |klass| klass.add_plugin(EpsagonAwsPlugin) }
|
146
|
+
end
|
147
|
+
|
148
|
+
present do
|
149
|
+
defined?(::Seahorse::Client::Base)
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
def loaded_constants
|
155
|
+
# Cross-check services against loaded AWS constants
|
156
|
+
# Module#const_get can return a constant from ancestors when there's a miss.
|
157
|
+
# If this conincidentally matches another constant, it will attempt to patch
|
158
|
+
# the wrong constant, resulting in patch failure.
|
159
|
+
available_services = ::Aws.constants & SERVICES.map(&:to_sym)
|
160
|
+
|
161
|
+
available_services.each_with_object([]) do |service, constants|
|
162
|
+
next if ::Aws.autoload?(service)
|
163
|
+
|
164
|
+
begin
|
165
|
+
constants << ::Aws.const_get(service, false).const_get(:Client, false)
|
166
|
+
rescue StandardError
|
167
|
+
next
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -3,7 +3,12 @@
|
|
3
3
|
require 'faraday'
|
4
4
|
require_relative '../util'
|
5
5
|
|
6
|
+
# Faraday middleware for epsagon instrumentaton
|
6
7
|
class EpsagonFaradayMiddleware < ::Faraday::Middleware
|
8
|
+
def config
|
9
|
+
EpsagonFaradayInstrumentation.instance.config
|
10
|
+
end
|
11
|
+
|
7
12
|
HTTP_METHODS_SYMBOL_TO_STRING = {
|
8
13
|
connect: 'CONNECT',
|
9
14
|
delete: 'DELETE',
|
@@ -27,7 +32,7 @@ class EpsagonFaradayMiddleware < ::Faraday::Middleware
|
|
27
32
|
'http.request.path' => path
|
28
33
|
}
|
29
34
|
|
30
|
-
unless metadata_only
|
35
|
+
unless config[:epsagon][:metadata_only]
|
31
36
|
attributes.merge!(Util.epsagon_query_attributes(env.url.query))
|
32
37
|
attributes.merge!({
|
33
38
|
'http.request.path_params' => path_params,
|
@@ -59,7 +64,7 @@ class EpsagonFaradayMiddleware < ::Faraday::Middleware
|
|
59
64
|
def trace_response(span, response)
|
60
65
|
span.set_attribute('http.status_code', response.status)
|
61
66
|
|
62
|
-
unless metadata_only
|
67
|
+
unless config[:epsagon][:metadata_only]
|
63
68
|
span.set_attribute('http.response.headers', response.headers.to_json)
|
64
69
|
span.set_attribute('http.response.body', response.body)
|
65
70
|
end
|
@@ -69,6 +74,7 @@ class EpsagonFaradayMiddleware < ::Faraday::Middleware
|
|
69
74
|
end
|
70
75
|
end
|
71
76
|
|
77
|
+
# Patch faraday to include middleware
|
72
78
|
module EpsagonFaradayPatch
|
73
79
|
def adapter(*args)
|
74
80
|
use(:epsagon_open_telemetry) unless @handlers.any? do |handler|
|
@@ -79,12 +85,15 @@ module EpsagonFaradayPatch
|
|
79
85
|
end
|
80
86
|
end
|
81
87
|
|
88
|
+
# Faraday epsagon instrumentaton
|
82
89
|
class EpsagonFaradayInstrumentation < OpenTelemetry::Instrumentation::Base
|
90
|
+
VERSION = '0.0.0'
|
91
|
+
|
83
92
|
install do |_config|
|
84
93
|
::Faraday::Middleware.register_middleware(
|
85
94
|
epsagon_open_telemetry: EpsagonFaradayMiddleware
|
86
95
|
)
|
87
|
-
::Faraday::RackBuilder.
|
96
|
+
::Faraday::RackBuilder.include(EpsagonFaradayPatch)
|
88
97
|
end
|
89
98
|
|
90
99
|
present do
|
@@ -4,10 +4,15 @@ require 'opentelemetry'
|
|
4
4
|
|
5
5
|
require_relative '../util'
|
6
6
|
|
7
|
+
# Net::HTTP patch for epsagon instrumentaton
|
7
8
|
module EpsagonNetHTTPExtension
|
8
9
|
HTTP_METHODS_TO_SPAN_NAMES = Hash.new { |h, k| h[k] = "HTTP #{k}" }
|
9
10
|
USE_SSL_TO_SCHEME = { false => 'http', true => 'https' }.freeze
|
10
11
|
|
12
|
+
def config
|
13
|
+
EpsagonNetHTTPInstrumentation.instance.config
|
14
|
+
end
|
15
|
+
|
11
16
|
def request(req, body = nil, &block)
|
12
17
|
# Do not trace recursive call for starting the connection
|
13
18
|
return super(req, body, &block) unless started?
|
@@ -22,7 +27,7 @@ module EpsagonNetHTTPExtension
|
|
22
27
|
'http.request.path' => path
|
23
28
|
})
|
24
29
|
|
25
|
-
unless metadata_only
|
30
|
+
unless config[:epsagon][:metadata_only]
|
26
31
|
headers = Hash[req.each_header.to_a]
|
27
32
|
attributes.merge!({
|
28
33
|
'http.request.path_params' => path_params,
|
@@ -53,7 +58,7 @@ module EpsagonNetHTTPExtension
|
|
53
58
|
status_code = response.code.to_i
|
54
59
|
|
55
60
|
span.set_attribute('http.status_code', status_code)
|
56
|
-
unless metadata_only
|
61
|
+
unless config[:epsagon][:metadata_only]
|
57
62
|
span.set_attribute('http.response.headers', Hash[response.each_header.to_a].to_json)
|
58
63
|
span.set_attribute('http.response.body', response.body)
|
59
64
|
end
|
@@ -67,7 +72,10 @@ module EpsagonNetHTTPExtension
|
|
67
72
|
end
|
68
73
|
end
|
69
74
|
|
75
|
+
# Net::HTTP epsagon instrumentaton
|
70
76
|
class EpsagonNetHTTPInstrumentation < OpenTelemetry::Instrumentation::Base
|
77
|
+
VERSION = '0.0.0'
|
78
|
+
|
71
79
|
install do |_|
|
72
80
|
::Net::HTTP.prepend(EpsagonNetHTTPExtension)
|
73
81
|
end
|
@@ -5,11 +5,16 @@ require 'opentelemetry'
|
|
5
5
|
|
6
6
|
require_relative '../util'
|
7
7
|
|
8
|
+
# Sinatra middleware for epsagon instrumentation
|
8
9
|
class EpsagonTracerMiddleware
|
9
10
|
def initialize(app)
|
10
11
|
@app = app
|
11
12
|
end
|
12
13
|
|
14
|
+
def config
|
15
|
+
EpsagonSinatraInstrumentation.instance.config
|
16
|
+
end
|
17
|
+
|
13
18
|
def call(env)
|
14
19
|
request = Rack::Request.new(env)
|
15
20
|
path, path_params = request.path.split(';')
|
@@ -27,7 +32,7 @@ class EpsagonTracerMiddleware
|
|
27
32
|
'http.request.headers' => request_headers
|
28
33
|
}
|
29
34
|
|
30
|
-
unless metadata_only
|
35
|
+
unless config[:epsagon][:metadata_only]
|
31
36
|
request.body.rewind
|
32
37
|
request_body = request.body.read
|
33
38
|
request.body.rewind
|
@@ -68,7 +73,7 @@ class EpsagonTracerMiddleware
|
|
68
73
|
def trace_response(http_span, framework_span, env, resp)
|
69
74
|
status, headers, response_body = resp
|
70
75
|
|
71
|
-
unless metadata_only
|
76
|
+
unless config[:epsagon][:metadata_only]
|
72
77
|
http_span.set_attribute('http.response.headers', JSON.generate(headers))
|
73
78
|
http_span.set_attribute('http.response.body', response_body.join)
|
74
79
|
end
|
@@ -79,6 +84,7 @@ class EpsagonTracerMiddleware
|
|
79
84
|
end
|
80
85
|
end
|
81
86
|
|
87
|
+
# Sinatra extension for epsagon instrumentation
|
82
88
|
module EpsagonTracerExtension
|
83
89
|
# Sinatra hook after extension is registered
|
84
90
|
def self.registered(app)
|
@@ -100,7 +106,10 @@ module EpsagonTracerExtension
|
|
100
106
|
end
|
101
107
|
end
|
102
108
|
|
109
|
+
# Sinatra epsagon instrumentation
|
103
110
|
class EpsagonSinatraInstrumentation < OpenTelemetry::Instrumentation::Base
|
111
|
+
VERSION = '0.0.0'
|
112
|
+
|
104
113
|
install do |_|
|
105
114
|
::Sinatra::Base.register EpsagonTracerExtension
|
106
115
|
end
|
data/lib/util.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: epsagon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Assaf Paneth
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Epsagon for ruby
|
14
14
|
email: assaf.paneth@gmail.com
|
@@ -18,6 +18,7 @@ extra_rdoc_files: []
|
|
18
18
|
files:
|
19
19
|
- lib/epsagon.rb
|
20
20
|
- lib/epsagon_opentelemetry.rb
|
21
|
+
- lib/instrumentation/aws_sdk.rb
|
21
22
|
- lib/instrumentation/faraday.rb
|
22
23
|
- lib/instrumentation/net_http.rb
|
23
24
|
- lib/instrumentation/sinatra.rb
|
@@ -32,9 +33,9 @@ require_paths:
|
|
32
33
|
- lib
|
33
34
|
required_ruby_version: !ruby/object:Gem::Requirement
|
34
35
|
requirements:
|
35
|
-
- - "
|
36
|
+
- - "~>"
|
36
37
|
- !ruby/object:Gem::Version
|
37
|
-
version: '
|
38
|
+
version: '2.7'
|
38
39
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
39
40
|
requirements:
|
40
41
|
- - ">="
|