blipit 0.1.1 → 0.2.1

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: 725f1f7935b92f07ead1f9c8dc944077671d90708857ad933b56f3f99898803e
4
- data.tar.gz: 30cc8ca3193055b99770d4ec0120baa128b3b10ee30c4a379cec1a6ab8cc176f
3
+ metadata.gz: e3b3f5df2c1e54476b7900840749686a2fb0d3428f41722ccfe507431d52bbf7
4
+ data.tar.gz: 509a9d7e0673ea9a82600a798e6f4f71e8d5341633b46754b1e6292a2e4d94b2
5
5
  SHA512:
6
- metadata.gz: e6808a51c08d76b523c739fdba9b5ed1539ea4a2638daa18a9e4f35c4142ca454d4f8140f5dabeab73f084247107465eaac95b48fb31f7db2b409927aede1533
7
- data.tar.gz: 316d73b300b658fb392e2af61049fadc48acc6f593dbbed58490019c03d5d48d4ec83358d766bb5a07337a96d2f3100f6ea1c7251e745a2b951b1df3613aa5a9
6
+ metadata.gz: 8039c976e246061ceb6144765687e628708c7b317d414fc0e5cc6aa33231f4f857fe8d0b284457ace8abdaf11c8ab9eb974216ceabcbadfc1da4b7ac4513719b
7
+ data.tar.gz: 554c68f653f4c30640355ffc67353e386d81a0271a62aa699780d9af6446543305a381d188c6d8f2c0ae72f3344cc5aee9557dfe79cd33c8872b919e1b7b1bdb
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ ## 0.2.1
2
+
3
+ - Events carry the `gem:blipit` package and version, so the dashboard can show when this project runs an old Blipit SDK. A `before_send` you set still runs after it.
4
+ - In development (`environment: "development"` or `debug: true`) the SDK warns once per process when a newer version is out: `[blipit] 0.2.2 is available (you have 0.2.1) — <why> — bundle update blipit`. It reads a header on the responses to events it already sends (no extra request); a custom `transport_class` is left alone. Nothing is printed in production.
5
+
6
+ ## 0.2.0
7
+
8
+ - `Blipit.init` with an empty key or project id prints a warning, returns false and leaves Blipit off instead of raising ArgumentError.
9
+ - Rails: `sentry-rails` is loaded automatically when it is in the Gemfile, so controller and job errors are reported; without it `Blipit.init` warns that controller errors will not be sent.
10
+ - `capture_security` takes `kind` and `actor` positionally or as keywords; a missing actor prints a warning instead of raising.
data/README.md CHANGED
@@ -20,11 +20,24 @@ require "blipit"
20
20
  Blipit.init(key: "<public key>", project: <project id>, environment: "production", release: "myapp@1.4.2")
21
21
  ```
22
22
 
23
- Both values are on the project's Keys page at app.blipit.io. Unhandled exceptions are reported on their own.
23
+ Both values are on the project's Keys page at app.blipit.io. Unhandled exceptions are reported on their own. If the key or project id is empty (for example an unset environment variable), `init` prints a warning, returns `false` and Blipit stays off; it never raises, so a missing key cannot stop the app from booting.
24
24
 
25
25
  ## Rails
26
26
 
27
- Put the `Blipit.init` call in `config/initializers/blipit.rb`. If you want the Rails integration (controller and job context, ActiveRecord breadcrumbs), add `gem "sentry-rails"` instead and set `config.dsn = "https://<public key>@in.blipit.io/<project id>"` in its initializer.
27
+ Rails rescues controller and job errors before they reach Ruby, so Rails apps need `sentry-rails` next to `blipit`:
28
+
29
+ ```ruby
30
+ gem "blipit"
31
+ gem "sentry-rails"
32
+ ```
33
+
34
+ Then put the `Blipit.init` call in `config/initializers/blipit.rb`:
35
+
36
+ ```ruby
37
+ Blipit.init(key: ENV["BLIPIT_KEY"], project: ENV["BLIPIT_PROJECT"], environment: Rails.env, release: ENV["GIT_SHA"])
38
+ ```
39
+
40
+ `blipit` loads `sentry-rails` on its own when Rails is running, and `Blipit.init` configures it, so controller errors, job errors and request context are reported. Without `sentry-rails` in the Gemfile, `Blipit.init` prints a warning saying controller errors will not be sent.
28
41
 
29
42
  ## Manual capture
30
43
 
@@ -40,8 +53,11 @@ Blipit.add_breadcrumb("cache cleared", category: "cache")
40
53
 
41
54
  ```ruby
42
55
  Blipit.capture_security("login_failed", email, outcome: "wrong password", ip: request.remote_ip, user_agent: request.user_agent)
56
+ Blipit.capture_security(kind: "login_failed", actor: email, ip: request.remote_ip)
43
57
  ```
44
58
 
59
+ Both forms work. Without a kind or an actor it prints a warning and sends nothing instead of raising.
60
+
45
61
  `kind` is one of `login_failed`, `login_blocked`, `login_succeeded`, `password_reset_requested` or `privilege_granted`; any other kind arrives as a plain message. Login attempts need the project's secret key (init with it on the server) and the Scale plan; with the public key ingest refuses them with 403 `security_needs_secret_key`.
46
62
 
47
63
  ## Performance
@@ -49,3 +65,7 @@ Blipit.capture_security("login_failed", email, outcome: "wrong password", ip: re
49
65
  Pass `traces_sample_rate: 0.2` to `init` and requests show up on the Performance page.
50
66
 
51
67
  Docs: https://docs.blipit.io/ruby
68
+
69
+ ## Updates
70
+
71
+ In development Blipit prints one line when a newer version is out, with the reason and the command. Update with `bundle update blipit`. Details: https://docs.blipit.io/updates
@@ -1,3 +1,3 @@
1
1
  module Blipit
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.1"
3
3
  end
data/lib/blipit.rb CHANGED
@@ -1,12 +1,43 @@
1
1
  require "sentry-ruby"
2
+ require "json"
3
+ require "uri"
2
4
  require_relative "blipit/version"
3
5
 
6
+ if defined?(::Rails::Railtie)
7
+ begin
8
+ require "sentry-rails"
9
+ rescue LoadError
10
+ nil
11
+ end
12
+ end
13
+
4
14
  module Blipit
5
15
  DEFAULT_ENDPOINT = "https://in.blipit.io"
6
16
  WARNING_KINDS = %w[login_failed login_blocked].freeze
7
17
  PUBLIC_KEY_WARNING = "[blipit] login attempts need the project's secret key (blipit_sk_...). " \
8
18
  "This SDK was started with the public key, so capture_security sends nothing. " \
9
19
  "Use the secret key on the server."
20
+ MISSING_KEY_WARNING = "[blipit] Blipit.init got no key, so Blipit is off and nothing is sent. " \
21
+ "Pass the project's key (app.blipit.io, Keys), for example from ENV[\"BLIPIT_KEY\"]; " \
22
+ "with Rails config caching, check that the value is set where the app boots."
23
+ MISSING_PROJECT_WARNING = "[blipit] Blipit.init got no project id, so Blipit is off and nothing is sent. " \
24
+ "Pass project: with the id from the project's Keys page at app.blipit.io."
25
+ RAILS_WARNING = "[blipit] Rails is loaded but sentry-rails is not, so errors raised in controllers and jobs are not reported " \
26
+ "(Rails rescues them before they reach Ruby). Add gem \"sentry-rails\" to your Gemfile next to gem \"blipit\" " \
27
+ "and run bundle install."
28
+ MISSING_ACTOR_WARNING = "[blipit] capture_security needs a kind and an actor, so this login attempt was not sent."
29
+ UPDATE_COMMAND = "bundle update blipit"
30
+ PACKAGE = { "name" => "gem:blipit", "version" => VERSION }.freeze
31
+
32
+ if Sentry::HTTPTransport.method_defined?(:do_request)
33
+ class NoticeTransport < Sentry::HTTPTransport
34
+ def do_request(*args)
35
+ response = super
36
+ Blipit.notice(response)
37
+ response
38
+ end
39
+ end
40
+ end
10
41
 
11
42
  class << self
12
43
  def dsn(key, project, endpoint = DEFAULT_ENDPOINT)
@@ -16,9 +47,16 @@ module Blipit
16
47
  end
17
48
 
18
49
  def init(key:, project:, environment: nil, release: nil, traces_sample_rate: 0.0, endpoint: DEFAULT_ENDPOINT, **options)
19
- raise ArgumentError, "Blipit.init needs the project's public key" if key.nil? || key.to_s.empty?
50
+ if key.nil? || key.to_s.strip.empty?
51
+ warn(MISSING_KEY_WARNING)
52
+ return false
53
+ end
54
+ if project.nil? || project.to_s.strip.empty?
55
+ warn(MISSING_PROJECT_WARNING)
56
+ return false
57
+ end
20
58
  @public_key = key.to_s.start_with?("blipit_pk_")
21
- raise ArgumentError, "Blipit.init needs the project id" if project.nil? || project.to_s.empty?
59
+ warn(RAILS_WARNING) if defined?(::Rails::Railtie) && !defined?(::Sentry::Rails)
22
60
 
23
61
  Sentry.init do |config|
24
62
  config.dsn = dsn(key, project, endpoint)
@@ -28,7 +66,51 @@ module Blipit
28
66
  config.send_default_pii = false
29
67
  options.each { |name, value| config.public_send("#{name}=", value) }
30
68
  yield config if block_given?
69
+ user_before_send = config.before_send
70
+ config.before_send = lambda do |event, hint|
71
+ with_identity(event)
72
+ user_before_send ? user_before_send.call(event, hint) : event
73
+ end
74
+ if (config.environment == "development" || config.debug) && config.transport.transport_class.nil? && defined?(NoticeTransport)
75
+ config.transport.transport_class = NoticeTransport
76
+ end
31
77
  end
78
+ true
79
+ end
80
+
81
+ def update_notice(header, current = VERSION)
82
+ latest = JSON.parse(URI.decode_www_form_component(header.to_s.gsub("+", "%2B")))
83
+ version = latest.is_a?(Hash) ? latest["version"] : nil
84
+ return nil unless version.is_a?(String) && !version.empty? && version != current
85
+
86
+ note = latest["note"].is_a?(String) ? latest["note"].strip : ""
87
+ why = note.empty? ? "" : " — #{note}"
88
+ "[blipit] #{version} is available (you have #{current})#{why} — #{UPDATE_COMMAND}"
89
+ rescue StandardError
90
+ nil
91
+ end
92
+
93
+ def notice(response)
94
+ return if @noticed
95
+
96
+ header = response["x-blipit-latest"]
97
+ line = header && update_notice(header)
98
+ return unless line
99
+
100
+ @noticed = true
101
+ warn(line)
102
+ rescue StandardError
103
+ nil
104
+ end
105
+
106
+ def with_identity(event)
107
+ sdk = event.sdk.is_a?(Hash) ? event.sdk : {}
108
+ packages = Array(sdk["packages"] || sdk[:packages])
109
+ return if packages.any? { |p| p.is_a?(Hash) && (p["name"] || p[:name]) == PACKAGE["name"] }
110
+
111
+ event.sdk = sdk.merge("packages" => packages + [PACKAGE.dup])
112
+ rescue StandardError
113
+ nil
32
114
  end
33
115
 
34
116
  def capture_exception(error, **options)
@@ -51,7 +133,13 @@ module Blipit
51
133
  Sentry.add_breadcrumb(Sentry::Breadcrumb.new(message: message, category: category, level: level, data: data))
52
134
  end
53
135
 
54
- def capture_security(kind, actor, outcome: nil, actor_id: nil, ip: nil, user_agent: nil, target: nil)
136
+ def capture_security(kind_arg = nil, actor_arg = nil, kind: nil, actor: nil, outcome: nil, actor_id: nil, ip: nil, user_agent: nil, target: nil)
137
+ kind ||= kind_arg
138
+ actor ||= actor_arg
139
+ if kind.to_s.empty? || actor.to_s.strip.empty?
140
+ warn(MISSING_ACTOR_WARNING)
141
+ return
142
+ end
55
143
  if @public_key
56
144
  warn(PUBLIC_KEY_WARNING) unless @public_key_warned
57
145
  @public_key_warned = true
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blipit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Louward Labs
8
+ autorequire:
8
9
  bindir: bin
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2026-10-12 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: logger
@@ -72,6 +73,7 @@ executables: []
72
73
  extensions: []
73
74
  extra_rdoc_files: []
74
75
  files:
76
+ - CHANGELOG.md
75
77
  - README.md
76
78
  - lib/blipit.rb
77
79
  - lib/blipit/version.rb
@@ -83,6 +85,7 @@ metadata:
83
85
  documentation_uri: https://docs.blipit.io/ruby
84
86
  changelog_uri: https://blipit.io/changelog
85
87
  rubygems_mfa_required: 'true'
88
+ post_install_message:
86
89
  rdoc_options: []
87
90
  require_paths:
88
91
  - lib
@@ -97,7 +100,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
97
100
  - !ruby/object:Gem::Version
98
101
  version: '0'
99
102
  requirements: []
100
- rubygems_version: 4.0.20
103
+ rubygems_version: 3.5.22
104
+ signing_key:
101
105
  specification_version: 4
102
106
  summary: Blipit error monitoring for Ruby and Rails
103
107
  test_files: []