uptrace 0.1.0 → 0.2.4

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: 525b8e2ad45dd955af7095839bfdf024e29b11309e8a0103b36bddb7980f3c41
4
+ data.tar.gz: 0766a2822dad2acb536aeccba788ac898ce7474ae4d74de355577de544772a4b
5
5
  SHA512:
6
- metadata.gz: d6f4ae143df5432535606e745907a7dd8ac9e22d9ac08280826b457ad6fd15d9c16fc368baab5616ec655fa0d9a9596edb7dfd0c7802563fe70e1b4cad2aa70d
7
- data.tar.gz: 29156234fe786b7ceefa118511153fea5afbc2e4fe7890cdc32eac0cb6d6274a40e6630a3c4fee95aa94203c876438434c17e87f8a443260f480c2b6d437b85a
6
+ metadata.gz: 36c69755595e07ffee78a62f3f1633fdd62def2d910b50876e8ffc4e2791800869d98f61b338bb2e30a01280610cc5fbeabe58a0f17214b5f2377031c2801f07
7
+ data.tar.gz: f33956036979a79d2f39e05f8a30f3008ffd967a828a048d88b187867e562bd013cecf9b0958584dc885142341633848739c3fc05dded624c8c16dc7ee8d7848
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.
data/RELEASE.md ADDED
@@ -0,0 +1,7 @@
1
+ Bump version and then run:
2
+
3
+ ```shell
4
+ gem build uptrace.gemspec
5
+ bundle install
6
+ gem push uptrace-0.2.0.gem
7
+ ```
data/lib/uptrace.rb CHANGED
@@ -7,9 +7,31 @@ module Uptrace
7
7
  extend self
8
8
 
9
9
  attr_accessor :logger
10
+ attr_writer :client
10
11
 
11
- self.logger = Logger.new(STDOUT)
12
+ self.logger = Logger.new($stdout)
13
+
14
+ # @return [Object, Client] registered client or a default no-op implementation of the client.
15
+ def client
16
+ @client ||= Client.new
17
+ end
18
+
19
+ def trace_url(span)
20
+ client.trace_url(span)
21
+ end
22
+
23
+ def configure_tracing(c, dsn: '')
24
+ upclient = if dsn.empty?
25
+ client
26
+ else
27
+ Client.new(dsn: dsn)
28
+ end
29
+
30
+ c.add_span_processor(upclient.span_processor) unless upclient.disabled?
31
+ end
12
32
  end
13
33
 
14
34
  require 'uptrace/version'
35
+ require 'uptrace/dsn'
36
+ require 'uptrace/client'
15
37
  require 'uptrace/trace'
@@ -0,0 +1,45 @@
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
+ # @param [string] dsn
9
+ def initialize(dsn: '')
10
+ dsn = ENV.fetch('UPTRACE_DSN', '') if dsn.empty?
11
+
12
+ begin
13
+ @dsn = DSN.new(dsn)
14
+ rescue ArgumentError => e
15
+ Uptrace.logger.error("Uptrace is disabled: #{e.message}")
16
+ @disabled = true
17
+
18
+ @dsn = DSN.new('https://TOKEN@api.uptrace.dev/PROJECT_ID')
19
+ end
20
+ end
21
+
22
+ def disabled?
23
+ @disabled
24
+ end
25
+
26
+ # @param [OpenTelemetry::Trace::Span] span
27
+ # @return [String]
28
+ def trace_url(span)
29
+ host = @dsn.host.delete_prefix('api.')
30
+ trace_id = span.context.hex_trace_id
31
+ "#{@dsn.scheme}://#{host}/search/#{@dsn.project_id}?q=#{trace_id}"
32
+ end
33
+
34
+ # @return [OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor]
35
+ def span_processor
36
+ exp = Uptrace::Trace::Exporter.new(@dsn)
37
+ OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
38
+ exp,
39
+ max_queue_size: 1000,
40
+ max_export_batch_size: 1000,
41
+ schedule_delay: 5_000
42
+ )
43
+ end
44
+ end
45
+ 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, "DSN can't be empty" if dsn.empty?
12
+
13
+ begin
14
+ uri = URI.parse(dsn)
15
+ rescue URI::InvalidURIError => e
16
+ raise ArgumentError, %(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, %(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,104 +1,125 @@
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
- def initialize(cfg)
32
- @cfg = cfg
33
-
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
23
+ def initialize(dsn)
24
+ @dsn = dsn
25
+ @endpoint = "/api/v1/tracing/#{@dsn.project_id}/spans"
26
+
27
+ @http = Net::HTTP.new(@dsn.host, 443)
28
+ @http.use_ssl = true
29
+ @http.open_timeout = 5
30
+ @http.read_timeout = 5
31
+ @http.keep_alive_timeout = 30
42
32
  end
43
33
 
44
- def export(spans)
45
- return if @disabled
34
+ # Called to export sampled {OpenTelemetry::SDK::Trace::SpanData} structs.
35
+ #
36
+ # @param [Enumerable<OpenTelemetry::SDK::Trace::SpanData>] spans the
37
+ # list of recorded {OpenTelemetry::SDK::Trace::SpanData} structs to be
38
+ # exported.
39
+ # @param [optional Numeric] timeout An optional timeout in seconds.
40
+ # @return [Integer] the result of the export.
41
+ def export(spans, timeout: nil)
42
+ return SUCCESS if @disabled
43
+ return FAILURE if @shutdown
46
44
 
47
- traces = {}
45
+ out = []
48
46
 
49
47
  spans.each do |span|
50
- trace = traces[span.trace_id]
48
+ out.push(uptrace_span(span))
49
+ end
51
50
 
52
- if trace.nil?
53
- trace = []
54
- traces[span.trace_id] = trace
55
- end
51
+ send({ spans: out }, timeout: timeout)
52
+ end
56
53
 
57
- expose = expo_span(span)
58
- trace.push(expose)
59
- end
54
+ # Called when {OpenTelemetry::SDK::Trace::Tracer#shutdown} is called, if
55
+ # this exporter is registered to a {OpenTelemetry::SDK::Trace::Tracer}
56
+ # object.
57
+ #
58
+ # @param [optional Numeric] timeout An optional timeout in seconds.
59
+ def shutdown(timeout: nil) # rubocop:disable Lint/UnusedMethodArgument
60
+ @shutdown = true
61
+ @http.finish if @http.started?
60
62
  end
61
63
 
62
64
  private
63
65
 
64
- def send(traces)
65
- req = build_request(traces: traces)
66
- connection.request(req)
67
- end
68
-
69
66
  ##
70
- # @return [ExpoSpan]
67
+ # @return [hash]
71
68
  #
72
- def expo_span(span)
73
- expose = ExpoSpan.new
69
+ def uptrace_span(span)
70
+ out = {
71
+ id: span.span_id.unpack1('Q'),
72
+ traceId: span.trace_id,
73
+
74
+ name: span.name,
75
+ kind: kind_as_str(span.kind),
76
+ startTime: as_unix_nano(span.start_timestamp),
77
+ endTime: as_unix_nano(span.end_timestamp),
78
+
79
+ resource: uptrace_resource(span.resource),
80
+ attrs: span.attributes
81
+ }
74
82
 
75
- expose.id = span.id
76
- expose.parentId = span.parent_span_id
83
+ out[:parentId] = span.parent_span_id.unpack1('Q') if span.parent_span_id
77
84
 
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
85
+ out[:events] = uptrace_events(span.events) unless span.events.nil?
86
+ out[:links] = uptrace_links(span.links) unless span.links.nil?
85
87
 
86
- expose
88
+ status = span.status
89
+ out[:statusCode] = status_code_as_str(status.code)
90
+ out[:statusMessage] = status.description unless status.description.empty?
91
+
92
+ il = span.instrumentation_library
93
+ out[:tracerName] = il.name
94
+ out[:tracerVersion] = il.name unless il.version.empty?
95
+
96
+ out
87
97
  end
88
98
 
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
99
+ def send(data, timeout: nil) # rubocop:disable Lint/UnusedMethodArgument
100
+ req = build_request(data)
101
+
102
+ begin
103
+ resp = @http.request(req)
104
+ rescue Net::OpenTimeout, Net::ReadTimeout
105
+ return FAILURE
99
106
  end
100
107
 
101
- @conn
108
+ case resp
109
+ when Net::HTTPOK
110
+ resp.body # Read and discard body
111
+ SUCCESS
112
+ when Net::HTTPBadRequest
113
+ data = JSON.parse(resp.body)
114
+ Uptrace.logger.error("status=#{data['status']}: #{data['message']}")
115
+ FAILURE
116
+ when Net::HTTPInternalServerError
117
+ resp.body
118
+ FAILURE
119
+ else
120
+ @http.finish
121
+ FAILURE
122
+ end
102
123
  end
103
124
 
104
125
  ##
@@ -106,18 +127,96 @@ module Uptrace
106
127
  # @return [Net::HTTP::Post]
107
128
  #
108
129
  def build_request(data)
109
- data = data.to_msgpack
110
- data = LZ4.compress data
130
+ data = MessagePack.pack(data)
131
+ data = Zstd.compress(data, 3)
111
132
 
112
133
  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'
134
+ req.add_field('Authorization', "Bearer #{@dsn.token}")
135
+ req.add_field('Content-Type', 'application/msgpack')
136
+ req.add_field('Content-Encoding', 'zstd')
137
+ req.add_field('Connection', 'keep-alive')
117
138
  req.body = data
118
139
 
119
140
  req
120
141
  end
142
+
143
+ # @param [SpanKind] kind
144
+ # @return [String]
145
+ def kind_as_str(kind)
146
+ case kind
147
+ when OpenTelemetry::Trace::SpanKind::SERVER
148
+ 'server'
149
+ when OpenTelemetry::Trace::SpanKind::CLIENT
150
+ 'client'
151
+ when OpenTelemetry::Trace::SpanKind::PRODUCER
152
+ 'producer'
153
+ when OpenTelemetry::Trace::SpanKind::CONSUMER
154
+ 'consumer'
155
+ else
156
+ 'internal'
157
+ end
158
+ end
159
+
160
+ ##
161
+ # @param [Integer] timestamp
162
+ # @return [Integer]
163
+ #
164
+ def as_unix_nano(timestamp)
165
+ (timestamp.to_r * 1_000_000_000).to_i
166
+ end
167
+
168
+ ##
169
+ # @param [Integer] code
170
+ # @return [String]
171
+ #
172
+ def status_code_as_str(code)
173
+ case code
174
+ when OpenTelemetry::Trace::Status::OK
175
+ 'ok'
176
+ when OpenTelemetry::Trace::Status::ERROR
177
+ 'error'
178
+ else
179
+ 'unset'
180
+ end
181
+ end
182
+
183
+ ##
184
+ # @param [OpenTelemetry::SDK::Resources::Resource] resource
185
+ # @return [Hash]
186
+ #
187
+ def uptrace_resource(resource)
188
+ out = {}
189
+ resource.attribute_enumerator.map { |key, value| out[key] = value }
190
+ out
191
+ end
192
+
193
+ def uptrace_events(events)
194
+ out = []
195
+ events.each do |event|
196
+ out.push(
197
+ {
198
+ name: event.name,
199
+ attrs: event.attributes,
200
+ time: as_unix_nano(event.timestamp)
201
+ }
202
+ )
203
+ end
204
+ out
205
+ end
206
+
207
+ def uptrace_links(links)
208
+ out = []
209
+ links.each do |link|
210
+ out.push(
211
+ {
212
+ trace_id => link.span_context.trace_id,
213
+ span_id => link.span_context.span_id.unpack1('Q'),
214
+ attrs => link.attributes
215
+ }
216
+ )
217
+ end
218
+ out
219
+ end
121
220
  end
122
221
  end
123
222
  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.4'
5
5
  end
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.4
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-03-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.15.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.15.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
@@ -132,10 +174,12 @@ files:
132
174
  - ".yardopts"
133
175
  - LICENSE
134
176
  - README.md
177
+ - RELEASE.md
135
178
  - lib/uptrace.rb
179
+ - lib/uptrace/client.rb
180
+ - lib/uptrace/dsn.rb
136
181
  - lib/uptrace/metric.rb
137
182
  - lib/uptrace/trace.rb
138
- - lib/uptrace/trace/config.rb
139
183
  - lib/uptrace/trace/exporter.rb
140
184
  - lib/uptrace/version.rb
141
185
  homepage: https://github.com/uptrace/uptrace-ruby
@@ -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
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Uptrace
4
- module Trace
5
- # Config is a configuration for Uptrace span exporter.
6
- class Config
7
- # @return [String] a data source name to connect to uptrace.dev.
8
- # @api public
9
- attr_accessor :dsn
10
- end
11
- end
12
- end