tracemap 1.0.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.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +0 -0
  3. data/tracemap.gemspec +43 -0
  4. data/tracemap.rb +112 -0
  5. metadata +247 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5498684def68c4dcc6a2875f7bcc53167a0951b6661c06817d5486ce945873eb
4
+ data.tar.gz: 71a0e26cf4c83752ef531bbcc0fedc39e2f20d39aaecc46608d65db1cd38c32d
5
+ SHA512:
6
+ metadata.gz: fe5537d10b4697cf0d80d273ce0d72e12951dddf13fedf5d447bc8ea7e6c0f478dffbd30b5fcf456ba6021745b2261ae04cdc75ffb602531ef6ae3b49131c04b
7
+ data.tar.gz: 1817e3fb3964c979c441092d4d3adc87577eca9234f925974eee8adf8c3ccd91502ee4cbff1a078797fbd9b4f9c47f62d8630d99841769469a61d64d2a1630fc
data/README.md ADDED
File without changes
data/tracemap.gemspec ADDED
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "tracemap"
5
+ spec.version = "1.0.0"
6
+ spec.authors = ["TraceMap"]
7
+ spec.email = ["sdk@tracemap.io"]
8
+
9
+ spec.summary = "Thin OpenTelemetry wrapper for Ruby/Rails apps — connects to TraceMap in 5 lines"
10
+ spec.description = "Rack middleware + OTel SDK config that sends traces, metrics, and logs to TraceMap via OTLP/HTTP. Auto-instruments Rails, Sinatra, Sidekiq, ActiveRecord, Redis, and Faraday."
11
+ spec.homepage = "https://tracemap.io"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = ">= 2.7"
14
+
15
+ spec.metadata = {
16
+ "homepage_uri" => spec.homepage,
17
+ "source_code_uri" => "https://github.com/tracemap/tracemap-ruby",
18
+ "changelog_uri" => "https://github.com/tracemap/tracemap-ruby/blob/main/CHANGELOG.md",
19
+ "documentation_uri" => "https://docs.tracemap.io/sdks/ruby",
20
+ }
21
+
22
+ spec.files = %w[tracemap.rb README.md tracemap.gemspec]
23
+ spec.require_paths = ["."]
24
+
25
+ # OpenTelemetry Ruby SDK
26
+ spec.add_dependency "opentelemetry-sdk", "~> 1.4"
27
+ spec.add_dependency "opentelemetry-exporter-otlp", "~> 0.26"
28
+
29
+ # Auto-instrumentations (optional — pulled in when using tracemap/auto)
30
+ spec.add_dependency "opentelemetry-instrumentation-rack", "~> 0.24", ">= 0.24.0"
31
+ spec.add_dependency "opentelemetry-instrumentation-rails", "~> 0.31", ">= 0.31.0"
32
+ spec.add_dependency "opentelemetry-instrumentation-active_record","~> 0.7"
33
+ spec.add_dependency "opentelemetry-instrumentation-redis", "~> 0.25"
34
+ spec.add_dependency "opentelemetry-instrumentation-sidekiq", "~> 0.24"
35
+ spec.add_dependency "opentelemetry-instrumentation-faraday", "~> 0.24"
36
+ spec.add_dependency "opentelemetry-instrumentation-net_http", "~> 0.22"
37
+
38
+ spec.add_development_dependency "bundler", "~> 2.5"
39
+ spec.add_development_dependency "rake", "~> 13.0"
40
+ spec.add_development_dependency "rspec", "~> 3.13"
41
+ spec.add_development_dependency "rack-test","~> 2.1"
42
+ end
43
+
data/tracemap.rb ADDED
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TraceMap Rack middleware — drop-in for any Ruby/Rails app
4
+ #
5
+ # Zero gem dependencies. Uses only stdlib net/http.
6
+ #
7
+ # ── Install (Rails) ───────────────────────────────────────────────────────────
8
+ # # config/application.rb
9
+ # require_relative '../../sdk/ruby/tracemap'
10
+ # config.middleware.insert_before 0, TraceMap::Middleware
11
+ #
12
+ # ── Install (Rack/Sinatra) ────────────────────────────────────────────────────
13
+ # require './sdk/ruby/tracemap'
14
+ # use TraceMap::Middleware
15
+ #
16
+ # ── Env vars ──────────────────────────────────────────────────────────────────
17
+ # TRACEMAP_ENDPOINT default: http://127.0.0.1:4318
18
+ # TRACEMAP_SERVICE_NAME default: my-service
19
+ # TRACEMAP_API_KEY optional
20
+ # TRACEMAP_ENABLED default: true
21
+
22
+ require 'net/http'
23
+ require 'json'
24
+ require 'securerandom'
25
+ require 'uri'
26
+ require 'time'
27
+
28
+ module TraceMap
29
+ class Client
30
+ attr_reader :endpoint, :service_name
31
+
32
+ def initialize(endpoint: nil, service_name: nil, api_key: nil, timeout: 2)
33
+ @endpoint = (endpoint || ENV.fetch('TRACEMAP_ENDPOINT', nil) || ENV.fetch('TRACEMAP_COLLECTOR_URL', 'http://127.0.0.1:4318')).chomp('/')
34
+ @service_name = service_name || ENV.fetch('TRACEMAP_SERVICE_NAME', 'my-service')
35
+ @api_key = api_key || ENV.fetch('TRACEMAP_API_KEY', '')
36
+ @timeout = timeout
37
+ cloud_mode = @endpoint.include?('/api/ingest')
38
+ @span_path = cloud_mode ? '' : '/collect/spans'
39
+ @log_path = cloud_mode ? '/logs' : '/collect/logs'
40
+ end
41
+
42
+ def send_span(span)
43
+ span['service_name'] ||= @service_name
44
+ post(@span_path, { spans: [span] })
45
+ end
46
+
47
+ def send_log(log)
48
+ log['service_name'] ||= @service_name
49
+ post(@log_path, { logs: [log] })
50
+ end
51
+
52
+ private
53
+
54
+ def post(path, body)
55
+ uri = URI("#{@endpoint}#{path}")
56
+ req = Net::HTTP::Post.new(uri)
57
+ req['Content-Type'] = 'application/json'
58
+ req['X-TraceMap-Key'] = @api_key unless @api_key.empty?
59
+ req.body = JSON.generate(body)
60
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https', open_timeout: @timeout, read_timeout: @timeout) do |http|
61
+ http.request(req)
62
+ end
63
+ rescue StandardError
64
+ # Never break app traffic because telemetry emit failed.
65
+ nil
66
+ end
67
+ end
68
+
69
+ class Middleware
70
+ def initialize(app, client: nil)
71
+ @app = app
72
+ @enabled = ENV.fetch('TRACEMAP_ENABLED', 'true').downcase != 'false'
73
+ @client = client || Client.new
74
+ end
75
+
76
+ def call(env)
77
+ return @app.call(env) unless @enabled
78
+
79
+ trace_id = SecureRandom.hex(16)
80
+ span_id = SecureRandom.hex(16)
81
+ method = env['REQUEST_METHOD'] || 'GET'
82
+ endpoint = env['PATH_INFO'] || '/'
83
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
84
+
85
+ status, headers, body = @app.call(env)
86
+
87
+ latency_ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).round(2)
88
+ headers['X-Trace-Id'] = trace_id
89
+ now = Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
90
+ level = status >= 500 ? 'ERROR' : status >= 400 ? 'WARN' : 'INFO'
91
+
92
+ Thread.new do
93
+ @client.send_span({
94
+ 'trace_id' => trace_id, 'span_id' => span_id,
95
+ 'endpoint' => endpoint, 'method' => method,
96
+ 'latency_ms' => latency_ms, 'status' => status,
97
+ 'timestamp' => now
98
+ })
99
+ @client.send_log({
100
+ 'trace_id' => trace_id, 'span_id' => span_id,
101
+ 'level' => level, 'message' => "#{method} #{endpoint} -> #{status}",
102
+ 'timestamp' => now, 'attributes' => { 'latency_ms' => latency_ms }
103
+ })
104
+ end
105
+
106
+ [status, headers, body]
107
+ rescue StandardError => e
108
+ raise e
109
+ end
110
+ end
111
+ end
112
+
metadata ADDED
@@ -0,0 +1,247 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tracemap
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - TraceMap
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-07-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: opentelemetry-sdk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: opentelemetry-exporter-otlp
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.26'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.26'
41
+ - !ruby/object:Gem::Dependency
42
+ name: opentelemetry-instrumentation-rack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.24'
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 0.24.0
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '0.24'
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 0.24.0
61
+ - !ruby/object:Gem::Dependency
62
+ name: opentelemetry-instrumentation-rails
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '0.31'
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 0.31.0
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '0.31'
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 0.31.0
81
+ - !ruby/object:Gem::Dependency
82
+ name: opentelemetry-instrumentation-active_record
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '0.7'
88
+ type: :runtime
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '0.7'
95
+ - !ruby/object:Gem::Dependency
96
+ name: opentelemetry-instrumentation-redis
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: '0.25'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: '0.25'
109
+ - !ruby/object:Gem::Dependency
110
+ name: opentelemetry-instrumentation-sidekiq
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '0.24'
116
+ type: :runtime
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '0.24'
123
+ - !ruby/object:Gem::Dependency
124
+ name: opentelemetry-instrumentation-faraday
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '0.24'
130
+ type: :runtime
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '0.24'
137
+ - !ruby/object:Gem::Dependency
138
+ name: opentelemetry-instrumentation-net_http
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: '0.22'
144
+ type: :runtime
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: '0.22'
151
+ - !ruby/object:Gem::Dependency
152
+ name: bundler
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: '2.5'
158
+ type: :development
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: '2.5'
165
+ - !ruby/object:Gem::Dependency
166
+ name: rake
167
+ requirement: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - "~>"
170
+ - !ruby/object:Gem::Version
171
+ version: '13.0'
172
+ type: :development
173
+ prerelease: false
174
+ version_requirements: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - "~>"
177
+ - !ruby/object:Gem::Version
178
+ version: '13.0'
179
+ - !ruby/object:Gem::Dependency
180
+ name: rspec
181
+ requirement: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - "~>"
184
+ - !ruby/object:Gem::Version
185
+ version: '3.13'
186
+ type: :development
187
+ prerelease: false
188
+ version_requirements: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - "~>"
191
+ - !ruby/object:Gem::Version
192
+ version: '3.13'
193
+ - !ruby/object:Gem::Dependency
194
+ name: rack-test
195
+ requirement: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - "~>"
198
+ - !ruby/object:Gem::Version
199
+ version: '2.1'
200
+ type: :development
201
+ prerelease: false
202
+ version_requirements: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - "~>"
205
+ - !ruby/object:Gem::Version
206
+ version: '2.1'
207
+ description: Rack middleware + OTel SDK config that sends traces, metrics, and logs
208
+ to TraceMap via OTLP/HTTP. Auto-instruments Rails, Sinatra, Sidekiq, ActiveRecord,
209
+ Redis, and Faraday.
210
+ email:
211
+ - sdk@tracemap.io
212
+ executables: []
213
+ extensions: []
214
+ extra_rdoc_files: []
215
+ files:
216
+ - README.md
217
+ - tracemap.gemspec
218
+ - tracemap.rb
219
+ homepage: https://tracemap.io
220
+ licenses:
221
+ - MIT
222
+ metadata:
223
+ homepage_uri: https://tracemap.io
224
+ source_code_uri: https://github.com/tracemap/tracemap-ruby
225
+ changelog_uri: https://github.com/tracemap/tracemap-ruby/blob/main/CHANGELOG.md
226
+ documentation_uri: https://docs.tracemap.io/sdks/ruby
227
+ post_install_message:
228
+ rdoc_options: []
229
+ require_paths:
230
+ - "."
231
+ required_ruby_version: !ruby/object:Gem::Requirement
232
+ requirements:
233
+ - - ">="
234
+ - !ruby/object:Gem::Version
235
+ version: '2.7'
236
+ required_rubygems_version: !ruby/object:Gem::Requirement
237
+ requirements:
238
+ - - ">="
239
+ - !ruby/object:Gem::Version
240
+ version: '0'
241
+ requirements: []
242
+ rubygems_version: 3.5.22
243
+ signing_key:
244
+ specification_version: 4
245
+ summary: Thin OpenTelemetry wrapper for Ruby/Rails apps — connects to TraceMap in
246
+ 5 lines
247
+ test_files: []