tinymonrb 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 +4 -4
- data/lib/tinymon/client.rb +40 -21
- data/lib/tinymon/scrub.rb +63 -0
- data/lib/tinymon/version.rb +1 -1
- data/lib/tinymonrb.rb +14 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2fb61a62ef1e259893c449ab46dbbbe6ba67f300a45551cb093e4598adeac193
|
|
4
|
+
data.tar.gz: 12f762661bba46acbbce593f7558e5dbc38ed1a2b181c9ed14e334bacc47a3de
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 53ef44902a951ef0f01c463f94d8ebe841b35718b9a40ffe071e8ed559e34c939a6012e05e7a7b78aab0fcda7704a35aed814ffd982283a22a61633335ff97e4
|
|
7
|
+
data.tar.gz: cf09570386509420ff6952856d6366aa15d304699fc6b8d4692a877acb74f59d49933ca4d5d5154a7db24632c857f09272828324ad8dae40c8fb893b2f2ed9e7
|
data/lib/tinymon/client.rb
CHANGED
|
@@ -2,37 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "event_builder"
|
|
4
4
|
require_relative "scope"
|
|
5
|
+
require_relative "scrub"
|
|
5
6
|
require_relative "transport"
|
|
6
7
|
|
|
7
8
|
module Tinymon
|
|
8
9
|
class Client
|
|
9
10
|
DEFAULT_ENDPOINT = "https://console.tinymon.dev/api/ingest"
|
|
10
11
|
|
|
11
|
-
def initialize(
|
|
12
|
+
def initialize(
|
|
13
|
+
dsn:,
|
|
14
|
+
endpoint: nil,
|
|
15
|
+
environment: nil,
|
|
16
|
+
release: nil,
|
|
17
|
+
sample_rate: 1.0,
|
|
18
|
+
before_send: nil,
|
|
19
|
+
# Privacy controls — defaults are privacy-preserving.
|
|
20
|
+
scrub_url_query: true,
|
|
21
|
+
scrub_patterns: nil,
|
|
22
|
+
send_default_pii: false
|
|
23
|
+
)
|
|
12
24
|
@dsn = dsn
|
|
13
25
|
@endpoint = endpoint || DEFAULT_ENDPOINT
|
|
14
26
|
@environment = environment
|
|
15
27
|
@release = release
|
|
16
28
|
@sample_rate = sample_rate
|
|
17
29
|
@before_send = before_send
|
|
30
|
+
@scrub_url_query = scrub_url_query
|
|
31
|
+
@scrub_patterns = scrub_patterns
|
|
32
|
+
@send_default_pii = send_default_pii
|
|
18
33
|
@transport = Transport.new(@endpoint, dsn)
|
|
19
34
|
end
|
|
20
35
|
|
|
21
36
|
def capture_exception(exception)
|
|
22
37
|
return if rand > @sample_rate
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
exception,
|
|
26
|
-
release: @release,
|
|
27
|
-
environment: @environment,
|
|
28
|
-
user: snap[:user],
|
|
29
|
-
tags: snap[:tags],
|
|
30
|
-
breadcrumbs: snap[:breadcrumbs],
|
|
31
|
-
)
|
|
32
|
-
if @before_send
|
|
33
|
-
event = @before_send.call(event)
|
|
34
|
-
return if event.nil?
|
|
35
|
-
end
|
|
38
|
+
event = _prepare(exception)
|
|
39
|
+
return if event.nil?
|
|
36
40
|
@transport.enqueue(event)
|
|
37
41
|
rescue StandardError
|
|
38
42
|
# SWALLOW. The SDK must never throw into the host app.
|
|
@@ -40,21 +44,36 @@ module Tinymon
|
|
|
40
44
|
end
|
|
41
45
|
|
|
42
46
|
def capture_message(message, level: "info")
|
|
43
|
-
|
|
47
|
+
event = _prepare(StandardError.new(message))
|
|
48
|
+
return if event.nil?
|
|
49
|
+
event["level"] = level
|
|
50
|
+
event["exception"]["type"] = "Message"
|
|
51
|
+
@transport.enqueue(event)
|
|
52
|
+
rescue StandardError
|
|
53
|
+
nil
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def _prepare(exception)
|
|
44
59
|
snap = SCOPE.snapshot
|
|
45
60
|
event = EventBuilder.build(
|
|
46
|
-
|
|
61
|
+
exception,
|
|
47
62
|
release: @release,
|
|
48
63
|
environment: @environment,
|
|
49
64
|
user: snap[:user],
|
|
50
65
|
tags: snap[:tags],
|
|
51
66
|
breadcrumbs: snap[:breadcrumbs],
|
|
52
67
|
)
|
|
53
|
-
|
|
54
|
-
event
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
68
|
+
# Default scrub BEFORE before_send.
|
|
69
|
+
Scrub.scrub_event(event, scrub_url_query: @scrub_url_query, scrub_patterns: @scrub_patterns)
|
|
70
|
+
# PII gate on the wire — server only attaches IP if true.
|
|
71
|
+
event["send_default_pii"] = !!@send_default_pii
|
|
72
|
+
if @before_send
|
|
73
|
+
event = @before_send.call(event)
|
|
74
|
+
return nil if event.nil?
|
|
75
|
+
end
|
|
76
|
+
event
|
|
58
77
|
end
|
|
59
78
|
end
|
|
60
79
|
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Default PII scrub. Identical semantics to the JS SDK and the server.
|
|
4
|
+
# Runs BEFORE before_send so user hooks can both relax and tighten the defaults.
|
|
5
|
+
module Tinymon
|
|
6
|
+
module Scrub
|
|
7
|
+
SENSITIVE_TAG_KEY = /password|token|secret|auth|card|cvv|ssn/i.freeze
|
|
8
|
+
|
|
9
|
+
DEFAULT_PATTERNS = [
|
|
10
|
+
/\b[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}\b/, # email
|
|
11
|
+
/\b(?:\d[ \-]?){12,15}\d\b/, # card-like
|
|
12
|
+
/\b[Bb]earer\s+[A-Za-z0-9._\-]+/, # bearer
|
|
13
|
+
/\bAuthorization\s*:\s*\S+/ # auth header
|
|
14
|
+
].freeze
|
|
15
|
+
|
|
16
|
+
module_function
|
|
17
|
+
|
|
18
|
+
def scrub_string(s, patterns)
|
|
19
|
+
out = s.to_s.dup
|
|
20
|
+
patterns.each { |re| out.gsub!(re, "[redacted]") }
|
|
21
|
+
out
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def strip_url_query(url)
|
|
25
|
+
return url if url.nil? || url.empty?
|
|
26
|
+
i = url.index(/[?#]/)
|
|
27
|
+
i.nil? ? url : url[0...i]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Mutate the event hash in place. Returns it for chaining.
|
|
31
|
+
def scrub_event(event, scrub_url_query: true, scrub_patterns: nil)
|
|
32
|
+
patterns = DEFAULT_PATTERNS + Array(scrub_patterns)
|
|
33
|
+
|
|
34
|
+
if scrub_url_query && (req = event[:request] || event["request"])
|
|
35
|
+
url_key = req.key?(:url) ? :url : "url"
|
|
36
|
+
req[url_key] = strip_url_query(req[url_key]) if req[url_key]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
if (exc = event[:exception] || event["exception"])
|
|
40
|
+
val_key = exc.key?(:value) ? :value : "value"
|
|
41
|
+
exc[val_key] = scrub_string(exc[val_key], patterns) if exc[val_key]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
Array(event[:breadcrumbs] || event["breadcrumbs"]).each do |b|
|
|
45
|
+
msg_key = b.key?(:message) ? :message : "message"
|
|
46
|
+
b[msg_key] = scrub_string(b[msg_key], patterns) if b[msg_key]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
tags = event[:tags] || event["tags"]
|
|
50
|
+
if tags
|
|
51
|
+
cleaned = {}
|
|
52
|
+
tags.each { |k, v| cleaned[k] = SENSITIVE_TAG_KEY.match?(k.to_s) ? "[redacted]" : v }
|
|
53
|
+
if event.key?(:tags)
|
|
54
|
+
event[:tags] = cleaned
|
|
55
|
+
else
|
|
56
|
+
event["tags"] = cleaned
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
event
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
data/lib/tinymon/version.rb
CHANGED
data/lib/tinymonrb.rb
CHANGED
|
@@ -23,7 +23,17 @@ module Tinymon
|
|
|
23
23
|
@client = nil
|
|
24
24
|
|
|
25
25
|
class << self
|
|
26
|
-
def init(
|
|
26
|
+
def init(
|
|
27
|
+
dsn:,
|
|
28
|
+
endpoint: nil,
|
|
29
|
+
environment: nil,
|
|
30
|
+
release: nil,
|
|
31
|
+
sample_rate: 1.0,
|
|
32
|
+
before_send: nil,
|
|
33
|
+
scrub_url_query: true,
|
|
34
|
+
scrub_patterns: nil,
|
|
35
|
+
send_default_pii: false
|
|
36
|
+
)
|
|
27
37
|
@client = Client.new(
|
|
28
38
|
dsn: dsn,
|
|
29
39
|
endpoint: endpoint,
|
|
@@ -31,6 +41,9 @@ module Tinymon
|
|
|
31
41
|
release: release,
|
|
32
42
|
sample_rate: sample_rate,
|
|
33
43
|
before_send: before_send,
|
|
44
|
+
scrub_url_query: scrub_url_query,
|
|
45
|
+
scrub_patterns: scrub_patterns,
|
|
46
|
+
send_default_pii: send_default_pii,
|
|
34
47
|
)
|
|
35
48
|
Integrations.install(@client)
|
|
36
49
|
@client
|
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.
|
|
4
|
+
version: 0.2.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-
|
|
11
|
+
date: 2026-06-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: json_schemer
|
|
@@ -49,6 +49,7 @@ files:
|
|
|
49
49
|
- lib/tinymon/event_builder.rb
|
|
50
50
|
- lib/tinymon/integrations.rb
|
|
51
51
|
- lib/tinymon/scope.rb
|
|
52
|
+
- lib/tinymon/scrub.rb
|
|
52
53
|
- lib/tinymon/stacktrace.rb
|
|
53
54
|
- lib/tinymon/transport.rb
|
|
54
55
|
- lib/tinymon/version.rb
|