uptrace 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6fed520ea5aa64b60260f976f155c618852f95c36e0eacfca80dd3b0654cf00f
4
- data.tar.gz: b93d8bb971d72e571b9f87c098779c0aede9157d698ea522ea360801d9f133e3
3
+ metadata.gz: a05b7c62ea6f2a2fb078f3b8272951c1d114f8062ff833c14c3b5a9183524cb1
4
+ data.tar.gz: 2876c7b4803b791d5955665a5fb8e97754355f9929c2a6b5ea39b511a839f54c
5
5
  SHA512:
6
- metadata.gz: d6f4ae143df5432535606e745907a7dd8ac9e22d9ac08280826b457ad6fd15d9c16fc368baab5616ec655fa0d9a9596edb7dfd0c7802563fe70e1b4cad2aa70d
7
- data.tar.gz: 29156234fe786b7ceefa118511153fea5afbc2e4fe7890cdc32eac0cb6d6274a40e6630a3c4fee95aa94203c876438434c17e87f8a443260f480c2b6d437b85a
6
+ metadata.gz: 9ce7612b3d87b3a32605996de564ce4f44821590bca24af38c6ef267d0a5c7c3d141a8241042bb36f86e532e4e38d971d3f82c9a096f69a1a58af5262efbd0af
7
+ data.tar.gz: b9b4d42c52cdfac6ae3444a3d782c83c7d410941a8b4a63aaf05d318863fa229d30e588484746df86a60358d57c5eefc718611bc94987987c5082bd8017887a1
data/README.md CHANGED
@@ -1,89 +1,21 @@
1
1
  # Uptrace Ruby exporter for OpenTelemetry
2
2
 
3
3
  [![Build Status](https://travis-ci.org/uptrace/uptrace-ruby.svg?branch=master)](https://travis-ci.org/uptrace/uptrace-ruby)
4
+ [![Documentation](https://img.shields.io/badge/uptrace-documentation-informational)](https://docs.uptrace.dev/ruby/)
4
5
 
5
- ## Introduction
6
-
7
- uptrace-ruby is an exporter for [OpenTelemetry](https://opentelemetry.io/) that
8
- sends your traces/spans and metrics to [Uptrace.dev](https://uptrace.dev).
9
- Briefly the process is the following:
10
-
11
- - OpenTelemetry API is used to instrument your application with spans and
12
- metrics.
13
- - OpenTelemetry SDK and this exporter send collected information to Uptrace.dev.
14
- - Uptrace.dev uses that information to help you pinpoint failures and find
15
- performance bottlenecks.
16
-
17
- ## Instrumenting code
18
-
19
- You instrument your application by wrapping potentially interesting operations
20
- with spans. Each span has:
21
-
22
- - an operation name;
23
- - a start time and end time;
24
- - a set of key/value attributes containing data about the operation;
25
- - a set of timed events representing events, errors, logs, etc.
26
-
27
- You create spans using a tracer:
6
+ <a href="https://docs.uptrace.dev/ruby/">
7
+ <img src="https://docs.uptrace.dev/devicons/ruby-original.svg" height="200px" />
8
+ </a>
28
9
 
29
- ```ruby
30
- require 'opentelemetry'
10
+ ## Installation
31
11
 
32
- // Create a named tracer using your repo as an identifier.
33
- tracer = OpenTelemetry.tracer_provider.tracer('github.com/username/app-name', 'semver:1.0')
12
+ ```bash
13
+ gem install uptrace
34
14
  ```
35
15
 
36
- To create a span:
37
-
38
- ```ruby
39
- tracer.in_span('operation-name') do |span|
40
- do_some_work
41
- end
42
- ```
43
-
44
- Internally that does roughly the following:
45
-
46
- ```ruby
47
- // Create a span.
48
- span = tracer.start_span('operation-name')
49
-
50
- // Activate the span within the current context.
51
- tracer.with_span(span) do |span|
52
- do_some_work
53
- end
54
-
55
- // Finish the span when operation is completed.
56
- span.finish
57
- ```
58
-
59
- To get the active span from the context:
60
-
61
- ```ruby
62
- span = tracer.current_span
63
- ```
64
-
65
- Once you have a span you can start adding attributes:
66
-
67
- ```ruby
68
- span.set_attribute('enduser.id', '123')
69
- span.set_attribute('enduser.role', 'admin')
70
- ```
71
-
72
- or events:
73
-
74
- ```ruby
75
- span.add_event(name: 'log', attributes: {
76
- 'log.severity': 'error',
77
- 'log.message': 'User not found',
78
- 'enduser.id': '123',
79
- })
80
- ```
16
+ ## Introduction
81
17
 
82
- To record an error use `record_error` which internally uses `add_event`. Note
83
- that `tracer.in_span` already records resqued exceptions.
18
+ uptrace-ruby is the official Uptrace client for Ruby that sends your traces/spans and metrics to
19
+ [Uptrace.dev](https://uptrace.dev).
84
20
 
85
- ```ruby
86
- rescue Exception => e
87
- span.record_error(e)
88
- end
89
- ```
21
+ See [uptrace-ruby documentation](https://docs.uptrace.dev/ruby/) for details.
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'opentelemetry/sdk'
4
+
5
+ module Uptrace
6
+ # Uptrace client that configures OpenTelemetry SDK to use Uptrace exporter.
7
+ class Client
8
+ ##
9
+ # @yieldparam config [Uptrace::Config]
10
+ # @return [void]
11
+ #
12
+ def initialize
13
+ @cfg = Uptrace::Trace::Config.new
14
+ yield @cfg if block_given?
15
+
16
+ begin
17
+ @cfg.dsno
18
+ rescue ArgumentError => e
19
+ Uptrace.logger.error(e.message)
20
+ @cfg.disabled = true
21
+
22
+ @cfg.dsn = 'https://TOKEN@api.uptrace.dev/PROJECT_ID'
23
+ end
24
+
25
+ setup_tracing unless @cfg.disabled
26
+ end
27
+
28
+ # @param [optional Numeric] timeout An optional timeout in seconds.
29
+ def shutdown(timeout: nil)
30
+ return if @cfg.disabled
31
+
32
+ OpenTelemetry.tracer_provider.shutdown(timeout: timeout)
33
+ end
34
+
35
+ # @return [OpenTelemetry::Trace::Span]
36
+ def trace_url(span)
37
+ dsn = @cfg.dsno
38
+ host = dsn.host.delete_prefix('api.')
39
+ trace_id = span.context.hex_trace_id
40
+ "#{dsn.scheme}://#{host}/#{dsn.project_id}/search?q=#{trace_id}"
41
+ end
42
+
43
+ private
44
+
45
+ def setup_tracing
46
+ exp = Uptrace::Trace::Exporter.new(@cfg)
47
+
48
+ OpenTelemetry::SDK.configure do |c|
49
+ bsp = OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(exporter: exp, max_queue_size: 1000, max_export_batch_size: 1000, schedule_delay: 5_000)
50
+ c.add_span_processor(bsp)
51
+
52
+ c.service_name = @cfg.service_name
53
+ c.service_version = @cfg.service_version
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Uptrace
4
+ # Uptrace DSN
5
+ class DSN
6
+ KEYS = %w[scheme host project_id token].freeze
7
+
8
+ attr_reader :dsn, :port, *KEYS
9
+
10
+ def initialize(dsn)
11
+ raise ArgumentError, "uptrace: DSN can't be empty" if dsn.empty?
12
+
13
+ begin
14
+ uri = URI.parse(dsn)
15
+ rescue URI::InvalidURIError => e
16
+ raise ArgumentError, %(uptrace: can't parse DSN=#{dsn.inspect}: #{e})
17
+ end
18
+
19
+ @dsn = dsn
20
+ @project_id = uri.path.delete_prefix('/')
21
+ @token = uri.user
22
+ @host = uri.host
23
+ @port = uri.port
24
+ @scheme = uri.scheme
25
+
26
+ KEYS.each do |k|
27
+ v = public_send(k)
28
+ raise ArgumentError, %(uptrace: DSN does not have #{k} (DSN=#{dsn.inspect})) if v.nil? || v.empty?
29
+ end
30
+ end
31
+
32
+ def to_s
33
+ @dsn
34
+ end
35
+ end
36
+ end
@@ -1,12 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'uptrace/dsn'
4
+
3
5
  module Uptrace
4
6
  module Trace
5
7
  # Config is a configuration for Uptrace span exporter.
6
8
  class Config
7
- # @return [String] a data source name to connect to uptrace.dev.
8
- # @api public
9
+ # @return [string] a data source name to connect to uptrace.dev.
9
10
  attr_accessor :dsn
11
+
12
+ # @return [string] `service.name` resource attribute.
13
+ attr_accessor :service_name
14
+
15
+ # @return [string] `service.name` resource attribute.
16
+ attr_accessor :service_version
17
+
18
+ # @return [boolean] disables the exporter.
19
+ attr_accessor :disabled
20
+
21
+ def initialize
22
+ @dsn = ENV.fetch('UPTRACE_DSN', '')
23
+ end
24
+
25
+ def dsno
26
+ @dsno ||= DSN.new(@dsn)
27
+ end
10
28
  end
11
29
  end
12
30
  end
@@ -1,104 +1,124 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'uri'
4
+ require 'net/http'
5
+ require 'json'
4
6
 
7
+ require 'opentelemetry/sdk'
5
8
  require 'msgpack'
6
- require 'lz4-ruby'
9
+ require 'zstd-ruby'
7
10
 
8
11
  module Uptrace
9
12
  module Trace
10
- # @!visibility private
11
- ExpoSpan = Struct.new(
12
- :id,
13
- :parentId,
14
- :name,
15
- :kind,
16
- :startTime,
17
- :endTime,
18
- :statusCode,
19
- :statusMessage,
20
- :attrs,
21
- :events,
22
- :links,
23
- :resource
24
- )
25
-
26
13
  # Exporter is a span exporter for OpenTelemetry.
27
14
  class Exporter
15
+ SUCCESS = OpenTelemetry::SDK::Trace::Export::SUCCESS
16
+ FAILURE = OpenTelemetry::SDK::Trace::Export::FAILURE
17
+ TIMEOUT = OpenTelemetry::SDK::Trace::Export::TIMEOUT
18
+ private_constant(:SUCCESS, :FAILURE, :TIMEOUT)
19
+
28
20
  ##
29
21
  # @param [Config] cfg
30
22
  #
31
23
  def initialize(cfg)
32
24
  @cfg = cfg
33
25
 
34
- begin
35
- @uri = URI.parse(cfg.dsn)
36
- rescue URI::InvalidURIError => e
37
- @disabled = true
38
- Uptrace.logger.error("can't parse dsn=#{cfg.dsn}: #{e}")
39
- else
40
- @endpoint = "#{@uri.scheme}://#{@uri.host}/api/v1/tracing#{@uri.path}/spans"
41
- end
26
+ dsn = @cfg.dsno
27
+ @endpoint = "/api/v1/tracing/#{dsn.project_id}/spans"
28
+
29
+ @http = Net::HTTP.new(dsn.host, 443)
30
+ @http.use_ssl = true
31
+ @http.open_timeout = 5
32
+ @http.read_timeout = 5
33
+ @http.keep_alive_timeout = 30
42
34
  end
43
35
 
44
- def export(spans)
45
- return if @disabled
36
+ # Called to export sampled {OpenTelemetry::SDK::Trace::SpanData} structs.
37
+ #
38
+ # @param [Enumerable<OpenTelemetry::SDK::Trace::SpanData>] spans the
39
+ # list of recorded {OpenTelemetry::SDK::Trace::SpanData} structs to be
40
+ # exported.
41
+ # @param [optional Numeric] timeout An optional timeout in seconds.
42
+ # @return [Integer] the result of the export.
43
+ def export(spans, timeout: nil)
44
+ return SUCCESS if @disabled
45
+ return FAILURE if @shutdown
46
46
 
47
- traces = {}
47
+ out = []
48
48
 
49
49
  spans.each do |span|
50
- trace = traces[span.trace_id]
50
+ out.push(uptrace_span(span))
51
+ end
51
52
 
52
- if trace.nil?
53
- trace = []
54
- traces[span.trace_id] = trace
55
- end
53
+ send({ spans: out }, timeout: timeout)
54
+ end
56
55
 
57
- expose = expo_span(span)
58
- trace.push(expose)
59
- end
56
+ # Called when {OpenTelemetry::SDK::Trace::Tracer#shutdown} is called, if
57
+ # this exporter is registered to a {OpenTelemetry::SDK::Trace::Tracer}
58
+ # object.
59
+ #
60
+ # @param [optional Numeric] timeout An optional timeout in seconds.
61
+ def shutdown(timeout: nil) # rubocop:disable Lint/UnusedMethodArgument
62
+ @shutdown = true
63
+ @http.finish if @http.started?
60
64
  end
61
65
 
62
66
  private
63
67
 
64
- def send(traces)
65
- req = build_request(traces: traces)
66
- connection.request(req)
67
- end
68
-
69
68
  ##
70
- # @return [ExpoSpan]
69
+ # @return [hash]
71
70
  #
72
- def expo_span(span)
73
- expose = ExpoSpan.new
71
+ def uptrace_span(span)
72
+ out = {
73
+ id: span.span_id.unpack1('Q'),
74
+ traceId: span.trace_id,
74
75
 
75
- expose.id = span.id
76
- expose.parentId = span.parent_span_id
76
+ name: span.name,
77
+ kind: kind_as_str(span.kind),
78
+ startTime: as_unix_nano(span.start_timestamp),
79
+ endTime: as_unix_nano(span.end_timestamp),
77
80
 
78
- expose.name = span.name
79
- expose.kind = span.kind
80
- expose.startTime = span.start_timestamp.to_i
81
- expose.endTime = span.end_timestamp.to_i
82
- expose.statusCode = span.status.canonical_code
83
- expose.statusMessage = span.status.description
84
- expose.attrs = span.attributes
81
+ resource: uptrace_resource(span.resource),
82
+ attrs: span.attributes,
85
83
 
86
- expose
84
+ statusCode: status_code_as_str(span.status.code),
85
+ statusMessage: span.status.description,
86
+
87
+ tracer: uptrace_tracer(span.instrumentation_library)
88
+ }
89
+
90
+ out['parentId'] = span.parent_span_id.unpack1('Q') if span.parent_span_id
91
+
92
+ out['events'] = uptrace_events(span.events) unless span.events.nil?
93
+ out['links'] = uptrace_links(span.links) unless span.links.nil?
94
+
95
+ out
87
96
  end
88
97
 
89
- ##
90
- # @return [Net::HTTP]
91
- #
92
- def connection
93
- unless @conn
94
- @conn = Net::HTTP.new(@uri.host, @uri.port)
95
- @conn.use_ssl = @uri.is_a?(URI::HTTPS)
96
- @conn.open_timeout = 5
97
- @conn.read_timeout = 5
98
- @conn.keep_alive_timeout = 30
98
+ def send(data, timeout: nil) # rubocop:disable Lint/UnusedMethodArgument
99
+ req = build_request(data)
100
+
101
+ begin
102
+ resp = @http.request(req)
103
+ rescue Net::OpenTimeout, Net::ReadTimeout
104
+ return FAILURE
99
105
  end
100
106
 
101
- @conn
107
+ case resp
108
+ when Net::HTTPOK
109
+ resp.body # Read and discard body
110
+ SUCCESS
111
+ when Net::HTTPBadRequest
112
+ data = JSON.parse(resp.body)
113
+ Uptrace.logger.error("status=#{data['status']}: #{data['message']}")
114
+ FAILURE
115
+ when Net::HTTPInternalServerError
116
+ resp.body
117
+ FAILURE
118
+ else
119
+ @http.finish
120
+ FAILURE
121
+ end
102
122
  end
103
123
 
104
124
  ##
@@ -106,18 +126,107 @@ module Uptrace
106
126
  # @return [Net::HTTP::Post]
107
127
  #
108
128
  def build_request(data)
109
- data = data.to_msgpack
110
- data = LZ4.compress data
129
+ data = MessagePack.pack(data)
130
+ data = Zstd.compress(data, 3)
111
131
 
112
132
  req = Net::HTTP::Post.new(@endpoint)
113
- req['Authorization'] = @uri.user
114
- req['Content-Type'] = 'application/msgpack'
115
- req['Content-Encoding'] = 'lz4'
116
- req['Connection'] = 'keep-alive'
133
+ req.add_field('Authorization', "Bearer #{@cfg.dsno.token}")
134
+ req.add_field('Content-Type', 'application/msgpack')
135
+ req.add_field('Content-Encoding', 'zstd')
136
+ req.add_field('Connection', 'keep-alive')
117
137
  req.body = data
118
138
 
119
139
  req
120
140
  end
141
+
142
+ # @param [SpanKind] kind
143
+ # @return [String]
144
+ def kind_as_str(kind)
145
+ case kind
146
+ when OpenTelemetry::Trace::SpanKind::SERVER
147
+ 'server'
148
+ when OpenTelemetry::Trace::SpanKind::CLIENT
149
+ 'client'
150
+ when OpenTelemetry::Trace::SpanKind::PRODUCER
151
+ 'producer'
152
+ when OpenTelemetry::Trace::SpanKind::CONSUMER
153
+ 'consumer'
154
+ else
155
+ 'internal'
156
+ end
157
+ end
158
+
159
+ ##
160
+ # @param [Integer] timestamp
161
+ # @return [Integer]
162
+ #
163
+ def as_unix_nano(timestamp)
164
+ (timestamp.to_r * 1_000_000_000).to_i
165
+ end
166
+
167
+ ##
168
+ # @param [Integer] code
169
+ # @return [String]
170
+ #
171
+ def status_code_as_str(code)
172
+ case code
173
+ when OpenTelemetry::Trace::Status::OK
174
+ 'ok'
175
+ when OpenTelemetry::Trace::Status::ERROR
176
+ 'error'
177
+ else
178
+ 'unset'
179
+ end
180
+ end
181
+
182
+ ##
183
+ # @param [OpenTelemetry::SDK::Resources::Resource] resource
184
+ # @return [Hash]
185
+ #
186
+ def uptrace_resource(resource)
187
+ out = {}
188
+ resource.attribute_enumerator.map { |key, value| out[key] = value }
189
+ out
190
+ end
191
+
192
+ def uptrace_events(events)
193
+ out = []
194
+ events.each do |event|
195
+ out.push(
196
+ {
197
+ name: event.name,
198
+ attrs: event.attributes,
199
+ time: as_unix_nano(event.timestamp)
200
+ }
201
+ )
202
+ end
203
+ out
204
+ end
205
+
206
+ def uptrace_links(links)
207
+ out = []
208
+ links.each do |link|
209
+ out.push(
210
+ {
211
+ trace_id => link.span_context.trace_id,
212
+ span_id => link.span_context.span_id.unpack1('Q'),
213
+ attrs => link.attributes
214
+ }
215
+ )
216
+ end
217
+ out
218
+ end
219
+
220
+ ##
221
+ # @param [OpenTelemetry::SDK::InstrumentationLibrary] il
222
+ # @return [Hash]
223
+ #
224
+ def uptrace_tracer(il)
225
+ {
226
+ name: il.name,
227
+ version: il.version
228
+ }
229
+ end
121
230
  end
122
231
  end
123
232
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Uptrace
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/uptrace.rb CHANGED
@@ -8,8 +8,10 @@ module Uptrace
8
8
 
9
9
  attr_accessor :logger
10
10
 
11
- self.logger = Logger.new(STDOUT)
11
+ self.logger = Logger.new($stdout)
12
12
  end
13
13
 
14
14
  require 'uptrace/version'
15
+ require 'uptrace/dsn'
16
+ require 'uptrace/client'
15
17
  require 'uptrace/trace'
metadata CHANGED
@@ -1,43 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uptrace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Uptrace Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-04 00:00:00.000000000 Z
11
+ date: 2021-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: lz4-ruby
14
+ name: msgpack
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.3.3
19
+ version: '1.3'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.3.3
26
+ version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
- name: msgpack
28
+ name: opentelemetry-sdk
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.3'
33
+ version: 0.14.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.3'
40
+ version: 0.14.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: zstd-ruby
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.4.5.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.4.5.0
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +100,42 @@ dependencies:
86
100
  requirements:
87
101
  - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: 0.73.0
103
+ version: 1.10.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 1.10.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-minitest
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.10.2
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.10.2
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-rake
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.5.1
90
132
  type: :development
91
133
  prerelease: false
92
134
  version_requirements: !ruby/object:Gem::Requirement
93
135
  requirements:
94
136
  - - "~>"
95
137
  - !ruby/object:Gem::Version
96
- version: 0.73.0
138
+ version: 0.5.1
97
139
  - !ruby/object:Gem::Dependency
98
140
  name: yard
99
141
  requirement: !ruby/object:Gem::Requirement
@@ -133,6 +175,8 @@ files:
133
175
  - LICENSE
134
176
  - README.md
135
177
  - lib/uptrace.rb
178
+ - lib/uptrace/client.rb
179
+ - lib/uptrace/dsn.rb
136
180
  - lib/uptrace/metric.rb
137
181
  - lib/uptrace/trace.rb
138
182
  - lib/uptrace/trace/config.rb
@@ -157,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
201
  - !ruby/object:Gem::Version
158
202
  version: '0'
159
203
  requirements: []
160
- rubygems_version: 3.1.2
204
+ rubygems_version: 3.1.4
161
205
  signing_key:
162
206
  specification_version: 4
163
207
  summary: Uptrace Ruby exporter for OpenTelemetry