logplex 0.0.7 → 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.
@@ -1,118 +1,195 @@
1
- require 'spec_helper'
2
- require 'logplex/publisher'
3
- require 'logplex/message'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "logplex/publisher"
5
+ require "logplex/message"
4
6
 
5
7
  describe Logplex::Publisher do
6
- describe '#publish' do
8
+ describe "#publish" do
7
9
  before do
8
- Excon.defaults[:mock] = true
9
10
  Logplex.configure do |config|
10
11
  config.process = "postgres"
11
12
  config.host = "host"
12
13
  end
13
14
  end
14
15
 
15
- after do
16
- Excon.stubs.clear
17
- end
18
-
19
- context 'with a working logplex' do
16
+ context "with a working logplex" do
20
17
  after do
21
18
  restore_default_config
22
19
  end
23
20
 
24
- it 'encodes a message and publishes it' do
25
- Excon.stub({ method: :post, password: "t.some-token", body: /message for you/ }, status: 204)
26
- message = 'I have a message for you'
27
- publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
21
+ it "encodes a message and publishes it" do
22
+ stub = WebMock.stub_request(:post, "https://logplex.example.com")
23
+ .with(body: /message for you/, basic_auth: ["token", "t.some-token"])
24
+ .to_return(status: 204)
25
+ message = "I have a message for you"
26
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
28
27
  publisher.publish(message)
28
+ expect(stub).to have_been_requested
29
29
  end
30
30
 
31
- it 'sends many messages in one request when passed an array' do
32
- Excon.stub({ method: :post, password: "t.some-token", body: /message for you.+here is another.+some final thoughts/ }, status: 204)
33
- messages = ['I have a message for you', 'here is another', 'some final thoughts']
34
- publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
31
+ it "sends many messages in one request when passed an array" do
32
+ stub = WebMock.stub_request(:post, "https://logplex.example.com")
33
+ .with(body: /message for you.+here is another.+some final thoughts/, basic_auth: ["token", "t.some-token"])
34
+ .to_return(status: 204)
35
+ messages = ["I have a message for you", "here is another", "some final thoughts"]
36
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
35
37
  publisher.publish(messages)
38
+ expect(stub).to have_been_requested
36
39
  end
37
40
 
38
- it 'uses the token if app_name is not given' do
39
- Excon.stub({ method: :post, password: "t.some-token", body: /t.some-token/ }, status: 204)
40
- message = 'I have a message for you'
41
- publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
41
+ it "uses the token if app_name is not given" do
42
+ stub = WebMock.stub_request(:post, "https://logplex.example.com")
43
+ .with(body: /t.some-token/, basic_auth: ["token", "t.some-token"])
44
+ .to_return(status: 204)
45
+ message = "I have a message for you"
46
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
42
47
  publisher.publish(message)
48
+ expect(stub).to have_been_requested
43
49
  end
44
50
 
45
- it 'uses the given app_name' do
46
- Excon.stub({ method: :post, password: "t.some-token", body: /foo/ }, status: 204)
47
- message = 'I have a message for you'
48
- publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
49
- publisher.publish(message, app_name: 'foo')
51
+ it "uses the given app_name" do
52
+ stub = WebMock.stub_request(:post, "https://logplex.example.com")
53
+ .with(body: /foo/, basic_auth: ["token", "t.some-token"])
54
+ .to_return(status: 204)
55
+ message = "I have a message for you"
56
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
57
+ publisher.publish(message, app_name: "foo")
58
+ expect(stub).to have_been_requested
50
59
  end
51
60
 
52
- it 'does the thing' do
53
- Excon.stub({ method: :post, password: "t.some-token", body: /hi\="there\"/ }, status: 204)
54
- message = { hi: 'there' }
55
- publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
61
+ it "does the thing" do
62
+ WebMock.stub_request(:post, "https://logplex.example.com")
63
+ .with(body: /hi="there"/, basic_auth: ["token", "t.some-token"])
64
+ .to_return(status: 204)
65
+ message = { hi: "there" }
66
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
56
67
  expect(publisher.publish(message)).to be_truthy
57
68
  end
58
69
 
59
- it 'does the thing with a 202' do
60
- Excon.stub({ method: :post, password: "t.some-token", body: /hi\="there\"/ }, status: 202)
61
- message = { hi: 'there' }
62
- publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
70
+ it "does the thing with a 202" do
71
+ WebMock.stub_request(:post, "https://logplex.example.com")
72
+ .with(body: /hi="there"/, basic_auth: ["token", "t.some-token"])
73
+ .to_return(status: 202)
74
+ message = { hi: "there" }
75
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
63
76
  expect(publisher.publish(message)).to be_truthy
64
77
  end
65
78
 
66
- it 'returns true' do
67
- Excon.stub({ method: :post, password: "t.some-token" }, status: 204)
68
- message = 'I have a message for you'
69
- publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
79
+ it "returns true" do
80
+ WebMock.stub_request(:post, "https://logplex.example.com")
81
+ .with(basic_auth: ["token", "t.some-token"])
82
+ .to_return(status: 204)
83
+ message = "I have a message for you"
84
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
70
85
  expect(publisher.publish(message)).to be_truthy
71
86
  end
72
87
 
73
- it "returns false when there's an auth error" do
74
- Excon.stub({ method: :post, password: "t.some-token" }, status: 401)
75
- message = 'I have a message for you'
76
- publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
77
- expect(publisher.publish(message)).to be_falsey
88
+ it "raises ClientError when there's an auth error" do
89
+ WebMock.stub_request(:post, "https://logplex.example.com")
90
+ .with(basic_auth: ["token", "t.some-token"])
91
+ .to_return(status: 401)
92
+ message = "I have a message for you"
93
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
94
+ expect { publisher.publish(message) }.to raise_error(Logplex::HTTP::ClientError)
78
95
  end
79
96
  end
80
97
 
81
- context 'when the logplex service is acting up' do
82
- it 'returns false' do
83
- Excon.stub({ method: :post, password: "t.some-token" }, status: 500)
84
- publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
85
- expect(publisher.publish('hi')).to be_falsey
98
+ context "when the logplex service is acting up" do
99
+ it "raises ServerError on 500" do
100
+ WebMock.stub_request(:post, "https://logplex.example.com")
101
+ .with(basic_auth: ["token", "t.some-token"])
102
+ .to_return(status: 500)
103
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
104
+ expect { publisher.publish("hi") }.to raise_error(Logplex::HTTP::ServerError)
105
+ end
106
+
107
+ it "raises ServiceUnavailableError on 503" do
108
+ WebMock.stub_request(:post, "https://logplex.example.com")
109
+ .with(basic_auth: ["token", "t.some-token"])
110
+ .to_return(status: 503)
111
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
112
+ expect { publisher.publish("hi") }.to raise_error(Logplex::HTTP::ServiceUnavailableError)
113
+ end
114
+
115
+ it "ServiceUnavailableError is rescuable as ServerError" do
116
+ WebMock.stub_request(:post, "https://logplex.example.com")
117
+ .with(basic_auth: ["token", "t.some-token"])
118
+ .to_return(status: 503)
119
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
120
+ expect { publisher.publish("hi") }.to raise_error(Logplex::HTTP::ServerError)
121
+ end
122
+
123
+ it "raises SeeOtherError on 303" do
124
+ WebMock.stub_request(:post, "https://logplex.example.com")
125
+ .with(basic_auth: ["token", "t.some-token"])
126
+ .to_return(status: 303)
127
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
128
+ expect { publisher.publish("hi") }.to raise_error(Logplex::HTTP::SeeOtherError)
86
129
  end
87
130
  end
88
131
 
89
- it "handles timeouts" do
90
- expect(Excon).to receive(:post).and_raise(Timeout::Error)
91
- publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
92
- expect(publisher.publish('hi')).to be_falsey
132
+ context "when there are client errors" do
133
+ it "raises ClientError on 401" do
134
+ WebMock.stub_request(:post, "https://logplex.example.com")
135
+ .with(basic_auth: ["token", "t.some-token"])
136
+ .to_return(status: 401)
137
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
138
+ expect { publisher.publish("hi") }.to raise_error(Logplex::HTTP::ClientError)
139
+ end
140
+ end
141
+
142
+ context "when there are network errors" do
143
+ it "raises TimeoutError on timeout" do
144
+ WebMock.stub_request(:post, "https://logplex.example.com")
145
+ .to_timeout
146
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
147
+ expect { publisher.publish("hi") }.to raise_error(Logplex::HTTP::TimeoutError)
148
+ end
149
+
150
+ it "raises ConnectionResetError on ECONNRESET" do
151
+ WebMock.stub_request(:post, "https://logplex.example.com")
152
+ .to_raise(Errno::ECONNRESET)
153
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
154
+ expect { publisher.publish("hi") }.to raise_error(Logplex::HTTP::ConnectionResetError)
155
+ end
156
+
157
+ it "raises SocketError on connection refused" do
158
+ WebMock.stub_request(:post, "https://logplex.example.com")
159
+ .to_raise(Errno::ECONNREFUSED)
160
+ publisher = described_class.new("https://token:t.some-token@logplex.example.com")
161
+ expect { publisher.publish("hi") }.to raise_error(Logplex::HTTP::SocketError)
162
+ end
93
163
  end
94
164
 
95
165
  it "includes the correct headers" do
96
- message = 'hello-harold'
97
- headers = {
98
- "Content-Type" => 'application/logplex-1',
99
- "Content-Length" => 79,
100
- "Logplex-Msg-Count" => 1
101
- }
102
- expect(Excon).to receive(:post).with(any_args, hash_including(:headers => headers))
103
- Logplex::Publisher.new('https://token:t.some-token@logplex.example.com').publish(message)
166
+ stub = WebMock.stub_request(:post, "https://logplex.example.com")
167
+ .with(
168
+ basic_auth: ["token", "t.some-token"],
169
+ headers: {
170
+ "Content-Type" => "application/logplex-1",
171
+ "Content-Length" => 79,
172
+ "Logplex-Msg-Count" => 1,
173
+ },
174
+ ).to_return(status: 204)
175
+ message = "hello-harold"
176
+ described_class.new("https://token:t.some-token@logplex.example.com").publish(message)
177
+ expect(stub).to have_been_requested
104
178
  end
105
179
 
106
180
  it "supports bearer authentication" do
107
- message = 'hello-bearer'
108
- headers = {
109
- "Authorization" => 'Bearer test-bearer-token',
110
- "Content-Type" => 'application/logplex-1',
111
- "Content-Length" => 70,
112
- "Logplex-Msg-Count" => 1
113
- }
114
- expect(Excon).to receive(:post).with(any_args, hash_including(:headers => headers))
115
- Logplex::Publisher.new('https://logplex-next.example.com', bearer_token: 'test-bearer-token').publish(message)
181
+ stub = WebMock.stub_request(:post, "https://logplex-next.example.com")
182
+ .with(
183
+ headers: {
184
+ "Authorization" => "Bearer test-bearer-token",
185
+ "Content-Type" => "application/logplex-1",
186
+ "Content-Length" => 70,
187
+ "Logplex-Msg-Count" => 1,
188
+ },
189
+ ).to_return(status: 204)
190
+ message = "hello-bearer"
191
+ described_class.new("https://logplex-next.example.com", bearer_token: "test-bearer-token").publish(message)
192
+ expect(stub).to have_been_requested
116
193
  end
117
194
  end
118
195
  end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webmock/rspec"
4
+
1
5
  RSpec.configure do |config|
2
6
  config.run_all_when_everything_filtered = true
3
7
  config.filter_run :focus
4
- config.order = 'random'
8
+ config.order = "random"
5
9
  end
6
10
 
7
11
  def restore_default_config
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logplex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harold Giménez
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-04-09 00:00:00.000000000 Z
12
+ date: 2026-05-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: valcro
@@ -25,52 +25,28 @@ dependencies:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0'
28
- - !ruby/object:Gem::Dependency
29
- name: excon
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - ">="
33
- - !ruby/object:Gem::Version
34
- version: '0'
35
- type: :runtime
36
- prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- version: '0'
42
- - !ruby/object:Gem::Dependency
43
- name: rspec
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - ">="
47
- - !ruby/object:Gem::Version
48
- version: '0'
49
- type: :development
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- version: '0'
56
- description: Publish and Consume Logplex messages
28
+ description: Logplex client
57
29
  email:
58
30
  - harold.gimenez@gmail.com
59
31
  executables: []
60
32
  extensions: []
61
33
  extra_rdoc_files: []
62
34
  files:
63
- - ".circleci/config.yml"
35
+ - ".github/workflows/ci.yml"
64
36
  - ".gitignore"
65
37
  - ".rspec"
38
+ - ".rubocop.yml"
39
+ - ".rubocop_standardrb.yml"
40
+ - ".rubocop_standardrb_overrides.yml"
41
+ - CHANGELOG.md
66
42
  - CODEOWNERS
67
43
  - Gemfile
68
44
  - LICENSE
69
- - LICENSE.txt
70
45
  - README.md
71
46
  - Rakefile
72
47
  - lib/logplex.rb
73
48
  - lib/logplex/configuration.rb
49
+ - lib/logplex/errors.rb
74
50
  - lib/logplex/message.rb
75
51
  - lib/logplex/publisher.rb
76
52
  - lib/logplex/version.rb
@@ -80,8 +56,12 @@ files:
80
56
  - spec/logplex/publisher_spec.rb
81
57
  - spec/spec_helper.rb
82
58
  homepage: https://github.com/heroku/logplex-gem
83
- licenses: []
84
- metadata: {}
59
+ licenses:
60
+ - MIT
61
+ metadata:
62
+ homepage_uri: https://github.com/heroku/logplex-gem
63
+ source_code_uri: https://github.com/heroku/logplex-gem
64
+ changelog_uri: https://github.com/heroku/logplex-gem/blob/main/CHANGELOG.md
85
65
  post_install_message:
86
66
  rdoc_options: []
87
67
  require_paths:
@@ -90,19 +70,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
90
70
  requirements:
91
71
  - - ">="
92
72
  - !ruby/object:Gem::Version
93
- version: '0'
73
+ version: 3.2.0
94
74
  required_rubygems_version: !ruby/object:Gem::Requirement
95
75
  requirements:
96
76
  - - ">="
97
77
  - !ruby/object:Gem::Version
98
78
  version: '0'
99
79
  requirements: []
100
- rubygems_version: 3.4.6
80
+ rubygems_version: 3.5.22
101
81
  signing_key:
102
82
  specification_version: 4
103
83
  summary: Publish and Consume Logplex messages
104
- test_files:
105
- - spec/logplex/configuration_spec.rb
106
- - spec/logplex/message_spec.rb
107
- - spec/logplex/publisher_spec.rb
108
- - spec/spec_helper.rb
84
+ test_files: []
data/.circleci/config.yml DELETED
@@ -1,15 +0,0 @@
1
- version: 2.1
2
-
3
- jobs:
4
- test:
5
- docker:
6
- - image: cimg/ruby:2.7.4
7
- steps:
8
- - checkout
9
- - run: bundle install
10
- - run: bundle exec rspec
11
-
12
- workflows:
13
- test:
14
- jobs:
15
- - test
data/LICENSE.txt DELETED
@@ -1,22 +0,0 @@
1
- Copyright (c) 2013 Harold Giménez
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.