tinymonrb 0.2.0 → 0.3.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: 2fb61a62ef1e259893c449ab46dbbbe6ba67f300a45551cb093e4598adeac193
4
- data.tar.gz: 12f762661bba46acbbce593f7558e5dbc38ed1a2b181c9ed14e334bacc47a3de
3
+ metadata.gz: 8df6c08b32ccae44e241b41fbd2a98f2033043c37ce6292a2f529869838cb8aa
4
+ data.tar.gz: 8e924831169fbbbbd9c409c49c10a71428eef4dbd48e9b01345f606230e75eb5
5
5
  SHA512:
6
- metadata.gz: 53ef44902a951ef0f01c463f94d8ebe841b35718b9a40ffe071e8ed559e34c939a6012e05e7a7b78aab0fcda7704a35aed814ffd982283a22a61633335ff97e4
7
- data.tar.gz: cf09570386509420ff6952856d6366aa15d304699fc6b8d4692a877acb74f59d49933ca4d5d5154a7db24632c857f09272828324ad8dae40c8fb893b2f2ed9e7
6
+ metadata.gz: 27265f4b71e845ffba1f87f3679f6979e7ec5a0175cdbc3399130a2140a8896178554ce72504159f1469674e288ef6a959f0dc84c293ff20a8a4f6b89cf55345
7
+ data.tar.gz: 0ff34d5f4fa892fb1dc00076ba17746836fd5d2205a4b804ca3cf16ec333e81fb307cdcabbbf0a1b778e1ae8cd8a8ff8392e1affaae381def405c72953af09d1
@@ -53,17 +53,31 @@ module Tinymon
53
53
  nil
54
54
  end
55
55
 
56
+ # Per-event context capture. Use from Rack middleware; do NOT use
57
+ # Tinymon.set_user/set_tag for per-request data — they race under
58
+ # concurrency.
59
+ def capture_exception_with_context(exception, request: nil, user: nil, tags: nil)
60
+ return if rand > @sample_rate
61
+ event = _prepare(exception, ctx: { request: request, user: user, tags: tags })
62
+ return if event.nil?
63
+ @transport.enqueue(event)
64
+ rescue StandardError
65
+ nil
66
+ end
67
+
56
68
  private
57
69
 
58
- def _prepare(exception)
70
+ def _prepare(exception, ctx: nil)
59
71
  snap = SCOPE.snapshot
72
+ ctx ||= {}
60
73
  event = EventBuilder.build(
61
74
  exception,
62
75
  release: @release,
63
76
  environment: @environment,
64
- user: snap[:user],
65
- tags: snap[:tags],
77
+ user: ctx[:user] || snap[:user],
78
+ tags: ctx[:tags] || snap[:tags],
66
79
  breadcrumbs: snap[:breadcrumbs],
80
+ request: ctx[:request],
67
81
  )
68
82
  # Default scrub BEFORE before_send.
69
83
  Scrub.scrub_event(event, scrub_url_query: @scrub_url_query, scrub_patterns: @scrub_patterns)
@@ -12,7 +12,7 @@ module Tinymon
12
12
 
13
13
  SENSITIVE = /password|token|secret|auth|card|cvv|ssn/i.freeze
14
14
 
15
- def build(exception, release: nil, environment: nil, user: nil, tags: nil, breadcrumbs: nil, url: nil)
15
+ def build(exception, release: nil, environment: nil, user: nil, tags: nil, breadcrumbs: nil, url: nil, request: nil)
16
16
  event = {
17
17
  "event_id" => SecureRandom.uuid,
18
18
  "timestamp" => Time.now.to_f,
@@ -30,7 +30,16 @@ module Tinymon
30
30
  }
31
31
  event["release"] = release if release
32
32
  event["environment"] = environment if environment
33
- event["request"] = { "url" => url } if url
33
+ if request && (request[:method] || request["method"] || request[:url] || request["url"])
34
+ req = {}
35
+ m = request[:method] || request["method"]
36
+ u = request[:url] || request["url"]
37
+ req["method"] = m if m
38
+ req["url"] = u if u
39
+ event["request"] = req
40
+ elsif url
41
+ event["request"] = { "url" => url }
42
+ end
34
43
  event
35
44
  end
36
45
 
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Rack middleware. Insert into ANY Rack app (Rails, Sinatra, Hanami,
4
+ # plain Rack) to capture in-request exceptions. Captures with per-event
5
+ # request context (method + URL) and RE-RAISES so the framework's own
6
+ # error handling still fires.
7
+ #
8
+ # Manual insert:
9
+ # require "tinymonrb"
10
+ # use Tinymon::Rack # Sinatra / plain Rack
11
+ # # Rails:
12
+ # config.middleware.use Tinymon::Rack
13
+ #
14
+ # Or use the Railtie for auto-insert in Rails apps (loaded automatically
15
+ # when Rails is detected at runtime).
16
+
17
+ module Tinymon
18
+ class Rack
19
+ def initialize(app)
20
+ @app = app
21
+ end
22
+
23
+ def call(env)
24
+ @app.call(env)
25
+ rescue StandardError, ScriptError => e
26
+ capture(e, env)
27
+ raise
28
+ end
29
+
30
+ private
31
+
32
+ def capture(exc, env)
33
+ mod = ::Tinymon
34
+ client = mod.instance_variable_get(:@client)
35
+ return unless client
36
+
37
+ url = build_url(env)
38
+ method = env["REQUEST_METHOD"]
39
+ client.capture_exception_with_context(
40
+ exc,
41
+ request: { method: method, url: url }
42
+ )
43
+ rescue StandardError
44
+ # never let the SDK break the request
45
+ nil
46
+ end
47
+
48
+ def build_url(env)
49
+ scheme = env["rack.url_scheme"] || "http"
50
+ host = env["HTTP_HOST"] || env["SERVER_NAME"] || ""
51
+ path = env["REQUEST_URI"] ||
52
+ "#{env['SCRIPT_NAME']}#{env['PATH_INFO']}#{env['QUERY_STRING'] && !env['QUERY_STRING'].empty? ? "?#{env['QUERY_STRING']}" : ''}"
53
+ host.empty? ? path : "#{scheme}://#{host}#{path}"
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Auto-insert Tinymon::Rack into the Rails middleware stack. Loaded only
4
+ # when Rails is present at require time — no hard Rails dependency.
5
+ require_relative "rack"
6
+
7
+ module Tinymon
8
+ class Railtie < ::Rails::Railtie
9
+ initializer "tinymon.middleware" do |app|
10
+ app.middleware.use Tinymon::Rack
11
+ end
12
+ end
13
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tinymon
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  SDK_NAME = "tinymon.ruby"
6
6
  end
data/lib/tinymonrb.rb CHANGED
@@ -7,6 +7,9 @@ require_relative "tinymon/scope"
7
7
  require_relative "tinymon/transport"
8
8
  require_relative "tinymon/client"
9
9
  require_relative "tinymon/integrations"
10
+ require_relative "tinymon/rack"
11
+ # Rails auto-insert — only loaded when Rails is present at require time.
12
+ require_relative "tinymon/railtie" if defined?(::Rails::Railtie)
10
13
 
11
14
  # Public API:
12
15
  #
@@ -53,6 +56,12 @@ module Tinymon
53
56
  @client&.capture_exception(exception)
54
57
  end
55
58
 
59
+ # Per-event context capture. Use from Rack middleware; do NOT use
60
+ # set_user/set_tag for per-request data (they race under concurrency).
61
+ def capture_exception_with_context(exception, request: nil, user: nil, tags: nil)
62
+ @client&.capture_exception_with_context(exception, request: request, user: user, tags: tags)
63
+ end
64
+
56
65
  def capture_message(message, level: "info")
57
66
  @client&.capture_message(message, level: level)
58
67
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tinymonrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tinymon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-06-09 00:00:00.000000000 Z
11
+ date: 2026-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json_schemer
@@ -48,6 +48,8 @@ files:
48
48
  - lib/tinymon/client.rb
49
49
  - lib/tinymon/event_builder.rb
50
50
  - lib/tinymon/integrations.rb
51
+ - lib/tinymon/rack.rb
52
+ - lib/tinymon/railtie.rb
51
53
  - lib/tinymon/scope.rb
52
54
  - lib/tinymon/scrub.rb
53
55
  - lib/tinymon/stacktrace.rb