logplex 0.0.1.pre.4 → 0.0.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 +7 -0
- data/.gitignore +7 -5
- data/.travis.yml +5 -0
- data/README.md +5 -4
- data/lib/logplex/configuration.rb +3 -2
- data/lib/logplex/message.rb +6 -6
- data/lib/logplex/publisher.rb +13 -15
- data/lib/logplex/version.rb +1 -1
- data/logplex.gemspec +3 -4
- data/spec/logplex/configuration_spec.rb +8 -6
- data/spec/logplex/message_spec.rb +8 -8
- data/spec/logplex/publisher_spec.rb +51 -71
- data/spec/spec_helper.rb +0 -2
- metadata +30 -35
- data/spec/support/fake_logplex.rb +0 -108
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dc2d2954418c3b93be55493748e2561c4b7b4b27
|
4
|
+
data.tar.gz: c5fb17e4a46500eb26779b3089b7aeb357e60498
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 35fd6b2c2f5e56e6ed6d2036ae5add5e487f25418a552fdce091c02d2a6ecc5e6693a43a44cfc3dc2a24f4eb75728d3cea58865750a2a141f24e711c338a1f18
|
7
|
+
data.tar.gz: dd7b526faa13b42dd98261bdc7d3bd64c9389e734a7fcdfc106740b03ecaba58f896665e901d003276cdbfc116dddae24537c6cb26616b1493d985414f050422
|
data/.gitignore
CHANGED
@@ -1,13 +1,14 @@
|
|
1
|
-
|
2
|
-
*.rbc
|
1
|
+
_yardoc
|
3
2
|
.bundle
|
4
3
|
.config
|
4
|
+
.ruby-version
|
5
5
|
.yardoc
|
6
|
-
|
7
|
-
|
8
|
-
_yardoc
|
6
|
+
*.gem
|
7
|
+
*.rbc
|
9
8
|
coverage
|
10
9
|
doc/
|
10
|
+
Gemfile.lock
|
11
|
+
InstalledFiles
|
11
12
|
lib/bundler/man
|
12
13
|
pkg
|
13
14
|
rdoc
|
@@ -15,3 +16,4 @@ spec/reports
|
|
15
16
|
test/tmp
|
16
17
|
test/version_tmp
|
17
18
|
tmp
|
19
|
+
.tags
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -8,7 +8,7 @@ Logplex is the Heroku log router, and can be found
|
|
8
8
|
### Publishing messages
|
9
9
|
|
10
10
|
```ruby
|
11
|
-
publisher = Logplex::Publisher.new(
|
11
|
+
publisher = Logplex::Publisher.new(logplex_url)
|
12
12
|
publisher.publish("There's a lady who's sure, all that glitters is gold",
|
13
13
|
process: 'worker.2', host: 'some-host')
|
14
14
|
```
|
@@ -31,7 +31,8 @@ eg: [log2viz](https://blog.heroku.com/archives/2013/3/19/log2viz)
|
|
31
31
|
publisher.publish { vocals: 'Robert Plant', guitar: 'Jimmy Page' }
|
32
32
|
# produces the message: vocals='Robert Plant' guitar='Jimmy Page'
|
33
33
|
```
|
34
|
-
|
34
|
+
|
35
|
+
### Consuming messages
|
35
36
|
|
36
37
|
TBD
|
37
38
|
|
@@ -41,7 +42,7 @@ You can configure default values for logplex message posting:
|
|
41
42
|
|
42
43
|
```ruby
|
43
44
|
Logplex.configure do |config|
|
44
|
-
config.logplex_url = 'https://logplex.example.com'
|
45
|
+
config.logplex_url = 'https://logplex.example.com/logs'
|
45
46
|
config.process = 'stats'
|
46
47
|
config.host = 'host'
|
47
48
|
config.publish_timeout = 2
|
@@ -52,7 +53,7 @@ In the example above, it is now not not necessary to specify a logplex URL,
|
|
52
53
|
process or host when getting a hold of a publisher and publishing messages:
|
53
54
|
|
54
55
|
```ruby
|
55
|
-
publisher = Logplex::Publisher.new
|
56
|
+
publisher = Logplex::Publisher.new
|
56
57
|
publisher.publish "And she's buying a stairway to heaven"
|
57
58
|
```
|
58
59
|
|
@@ -1,14 +1,16 @@
|
|
1
1
|
module Logplex
|
2
2
|
class Configuration
|
3
3
|
attr_accessor :logplex_url,
|
4
|
+
:app_name,
|
4
5
|
:process,
|
5
6
|
:host,
|
6
7
|
:publish_timeout
|
7
8
|
|
8
9
|
def initialize
|
9
|
-
@logplex_url = 'https://east.logplex.io'
|
10
|
+
@logplex_url = 'https://east.logplex.io/logs'
|
10
11
|
@host = 'localhost'
|
11
12
|
@publish_timeout = 1
|
13
|
+
@app_name = 'app'
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
@@ -20,5 +22,4 @@ module Logplex
|
|
20
22
|
self.configuration ||= Configuration.new
|
21
23
|
yield(configuration)
|
22
24
|
end
|
23
|
-
|
24
25
|
end
|
data/lib/logplex/message.rb
CHANGED
@@ -13,8 +13,8 @@ module Logplex
|
|
13
13
|
FIELD_DISABLED = '-'.freeze
|
14
14
|
|
15
15
|
def initialize(message, opts = {})
|
16
|
-
@message
|
17
|
-
@
|
16
|
+
@message = message
|
17
|
+
@app_name = opts[:app_name] || Logplex.configuration.app_name
|
18
18
|
@time = opts[:time] || DateTime.now
|
19
19
|
@process = opts[:process] || Logplex.configuration.process
|
20
20
|
@host = opts[:host] || Logplex.configuration.host
|
@@ -22,7 +22,7 @@ module Logplex
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def syslog_frame
|
25
|
-
temp = "#{FACILITY_AND_PRIORITY} #{formatted_time} #{@host} #{@
|
25
|
+
temp = "#{FACILITY_AND_PRIORITY} #{formatted_time} #{@host} #{@app_name} #{@process} #{@message_id} #{FIELD_DISABLED} #{formatted_message}"
|
26
26
|
length = temp.length
|
27
27
|
"#{length} #{temp}"
|
28
28
|
end
|
@@ -34,7 +34,8 @@ module Logplex
|
|
34
34
|
errors.add(:host, "can't be nil") if @host.nil?
|
35
35
|
end
|
36
36
|
|
37
|
-
|
37
|
+
private
|
38
|
+
|
38
39
|
def formatted_time
|
39
40
|
case @time.class
|
40
41
|
when String
|
@@ -45,7 +46,7 @@ module Logplex
|
|
45
46
|
end
|
46
47
|
|
47
48
|
def formatted_message
|
48
|
-
if @message.
|
49
|
+
if @message.is_a?(Hash)
|
49
50
|
@message.inject([]) do |res, (key, value)|
|
50
51
|
res << %{#{key}="#{value}"}
|
51
52
|
end.join(' ')
|
@@ -53,6 +54,5 @@ module Logplex
|
|
53
54
|
@message
|
54
55
|
end
|
55
56
|
end
|
56
|
-
|
57
57
|
end
|
58
58
|
end
|
data/lib/logplex/publisher.rb
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
-
require '
|
3
|
-
require 'restclient'
|
2
|
+
require 'excon'
|
4
3
|
require 'logplex/message'
|
5
4
|
require 'timeout'
|
6
5
|
|
7
6
|
module Logplex
|
8
7
|
class Publisher
|
9
|
-
PUBLISH_ERRORS = [
|
10
|
-
|
8
|
+
PUBLISH_ERRORS = [Excon::Errors::InternalServerError,
|
9
|
+
Excon::Errors::Unauthorized,
|
11
10
|
Timeout::Error].freeze
|
12
11
|
|
13
|
-
def initialize(
|
14
|
-
@token = token
|
12
|
+
def initialize(logplex_url = nil)
|
15
13
|
@logplex_url = logplex_url || Logplex.configuration.logplex_url
|
14
|
+
@token = URI(@logplex_url).password || Logplex.configuration.app_name
|
16
15
|
end
|
17
16
|
|
18
17
|
def publish(messages, opts={})
|
@@ -20,11 +19,11 @@ module Logplex
|
|
20
19
|
unless messages.is_a? Array
|
21
20
|
message_list = [message_list]
|
22
21
|
end
|
23
|
-
message_list.map! { |m| Message.new(m, opts.merge(
|
22
|
+
message_list.map! { |m| Message.new(m, opts.merge(app_name: @token)) }
|
24
23
|
message_list.each(&:validate)
|
25
24
|
if message_list.inject(true) { |accum, m| m.valid? }
|
26
25
|
begin
|
27
|
-
Timeout
|
26
|
+
Timeout.timeout(Logplex.configuration.publish_timeout) do
|
28
27
|
api_post(message_list.map(&:syslog_frame).join(''))
|
29
28
|
true
|
30
29
|
end
|
@@ -34,14 +33,13 @@ module Logplex
|
|
34
33
|
end
|
35
34
|
end
|
36
35
|
|
37
|
-
|
36
|
+
private
|
37
|
+
|
38
38
|
def api_post(message)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
content_length: message.length,
|
44
|
-
authorization: auth)
|
39
|
+
Excon.post(@logplex_url, body: message, headers: {
|
40
|
+
"Content-Type" => 'application/logplex-1',
|
41
|
+
"Content-Length" => message.length,
|
42
|
+
}, expects: [200, 204])
|
45
43
|
end
|
46
44
|
end
|
47
45
|
end
|
data/lib/logplex/version.rb
CHANGED
data/logplex.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |gem|
|
|
8
8
|
gem.version = Logplex::VERSION
|
9
9
|
gem.authors = ["Harold Giménez"]
|
10
10
|
gem.email = ["harold.gimenez@gmail.com"]
|
11
|
-
gem.description =
|
12
|
-
gem.summary =
|
11
|
+
gem.description = "Publish and Consume Logplex messages"
|
12
|
+
gem.summary = "Publish and Consume Logplex messages"
|
13
13
|
gem.homepage = "https://practiceovertheory.com"
|
14
14
|
|
15
15
|
gem.files = `git ls-files`.split($/)
|
@@ -17,7 +17,6 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
gem.add_dependency "valcro"
|
20
|
-
gem.add_dependency "
|
20
|
+
gem.add_dependency "excon"
|
21
21
|
gem.add_development_dependency "rspec"
|
22
|
-
gem.add_development_dependency "sham_rack"
|
23
22
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'logplex/configuration'
|
3
3
|
|
4
|
-
describe Logplex::Configuration
|
5
|
-
|
6
|
-
|
4
|
+
describe Logplex::Configuration do
|
5
|
+
describe 'defaults' do
|
6
|
+
it 'defaults to the production heroku logplex url' do
|
7
|
+
Logplex.configure { |config| }
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
expect(
|
10
|
+
Logplex.configuration.logplex_url
|
11
|
+
).to eq('https://east.logplex.io/logs')
|
12
|
+
end
|
11
13
|
end
|
12
14
|
end
|
@@ -7,7 +7,7 @@ describe Logplex::Message do
|
|
7
7
|
it 'fills out fields of a syslog message' do
|
8
8
|
message = Logplex::Message.new(
|
9
9
|
'my message here',
|
10
|
-
|
10
|
+
app_name: 't.some-token',
|
11
11
|
time: DateTime.parse("1980-08-23 05:31 00:00"),
|
12
12
|
process: 'heroku-postgres',
|
13
13
|
host: 'some-host',
|
@@ -20,17 +20,17 @@ describe Logplex::Message do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
it 'is invalid for messages longer than 10240 bytes' do
|
23
|
-
short = Logplex::Message.new('a' * 10240,
|
23
|
+
short = Logplex::Message.new('a' * 10240, app_name: 'foo',
|
24
24
|
process: 'proc',
|
25
25
|
host: 'host')
|
26
|
-
long = Logplex::Message.new('a' * 10241,
|
26
|
+
long = Logplex::Message.new('a' * 10241, app_name: 'foo',
|
27
27
|
process: 'proc',
|
28
28
|
host: 'host')
|
29
29
|
short.validate
|
30
30
|
long.validate
|
31
31
|
|
32
|
-
expect(short.valid?).to
|
33
|
-
expect(long.valid?).to
|
32
|
+
expect(short.valid?).to be_truthy
|
33
|
+
expect(long.valid?).to be_falsey
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'is invalid with no process or host' do
|
@@ -39,10 +39,10 @@ describe Logplex::Message do
|
|
39
39
|
conf.process = nil
|
40
40
|
end
|
41
41
|
|
42
|
-
message = Logplex::Message.new("a message",
|
42
|
+
message = Logplex::Message.new("a message", app_name: 't.some-token')
|
43
43
|
message.validate
|
44
44
|
|
45
|
-
expect(message.valid?).to
|
45
|
+
expect(message.valid?).to be_falsey
|
46
46
|
expect(message.errors[:process]).to eq ["can't be nil"]
|
47
47
|
expect(message.errors[:host]).to eq ["can't be nil"]
|
48
48
|
end
|
@@ -50,7 +50,7 @@ describe Logplex::Message do
|
|
50
50
|
it 'formats logs as key/values when given a hash' do
|
51
51
|
message = Logplex::Message.new(
|
52
52
|
{ vocals: 'Robert Plant', guitar: 'Jimmy Page' },
|
53
|
-
|
53
|
+
app_name: 't.some-token',
|
54
54
|
process: 'proc',
|
55
55
|
host: 'host',
|
56
56
|
time: DateTime.parse("1980-08-23 05:31 00:00")
|
@@ -1,96 +1,76 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'sham_rack'
|
3
2
|
require 'logplex/publisher'
|
4
|
-
require 'support/fake_logplex'
|
5
3
|
|
6
|
-
describe Logplex::Publisher
|
7
|
-
|
8
|
-
Logplex.configure do |config|
|
9
|
-
config.process = "postgres"
|
10
|
-
config.host = "host"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
context 'with a working logplex' do
|
4
|
+
describe Logplex::Publisher do
|
5
|
+
describe '#publish' do
|
15
6
|
before do
|
16
|
-
|
17
|
-
|
7
|
+
Excon.defaults[:mock] = true
|
8
|
+
Logplex.configure do |config|
|
9
|
+
config.process = "postgres"
|
10
|
+
config.host = "host"
|
11
|
+
end
|
18
12
|
end
|
19
13
|
|
20
14
|
after do
|
21
|
-
|
22
|
-
FakeLogplex.clear!
|
23
|
-
restore_default_config
|
15
|
+
Excon.stubs.clear
|
24
16
|
end
|
25
17
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
message = 'I have a message for you'
|
30
|
-
publisher = Logplex::Publisher.new('t.some-token', 'https://logplex.example.com')
|
31
|
-
publisher.publish(message)
|
32
|
-
|
33
|
-
expect(FakeLogplex).to have_received_message(message)
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'sends many messages in one request when passed an array' do
|
37
|
-
FakeLogplex.register_token('t.some-token')
|
38
|
-
messages = ['I have a message for you', 'here is another', 'some final thoughts']
|
39
|
-
|
40
|
-
publisher = Logplex::Publisher.new('t.some-token', 'https://logplex.example.com')
|
41
|
-
|
42
|
-
publisher.publish(messages)
|
43
|
-
|
44
|
-
messages.each do |message|
|
45
|
-
expect(FakeLogplex).to have_received_message(message)
|
18
|
+
context 'with a working logplex' do
|
19
|
+
after do
|
20
|
+
restore_default_config
|
46
21
|
end
|
47
22
|
|
48
|
-
|
49
|
-
|
23
|
+
it 'encodes a message and publishes it' do
|
24
|
+
Excon.stub({ method: :post, password: "t.some-token", body: /message for you/ }, status: 204)
|
25
|
+
message = 'I have a message for you'
|
26
|
+
publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
|
27
|
+
publisher.publish(message)
|
28
|
+
end
|
50
29
|
|
51
|
-
|
52
|
-
|
30
|
+
it 'sends many messages in one request when passed an array' do
|
31
|
+
Excon.stub({ method: :post, password: "t.some-token", body: /here is another/ }, status: 204)
|
32
|
+
expect(Excon).to receive(:post).once
|
33
|
+
messages = ['I have a message for you', 'here is another', 'some final thoughts']
|
53
34
|
|
54
|
-
|
55
|
-
publisher = Logplex::Publisher.new('t.some-token', 'https://logplex.example.com')
|
56
|
-
publisher.publish(message)
|
35
|
+
publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
|
57
36
|
|
58
|
-
|
59
|
-
|
37
|
+
publisher.publish(messages)
|
38
|
+
end
|
60
39
|
|
61
|
-
|
62
|
-
|
40
|
+
it 'does the thing' do
|
41
|
+
Excon.stub({ method: :post, password: "t.some-token", body: /hi\="there\"/ }, status: 204)
|
42
|
+
message = { hi: 'there' }
|
43
|
+
publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
|
44
|
+
expect(publisher.publish(message)).to be_truthy
|
45
|
+
end
|
63
46
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
47
|
+
it 'returns true' do
|
48
|
+
Excon.stub({ method: :post, password: "t.some-token" }, status: 204)
|
49
|
+
message = 'I have a message for you'
|
50
|
+
publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
|
51
|
+
expect(publisher.publish(message)).to be_truthy
|
52
|
+
end
|
68
53
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
54
|
+
it "returns false when there's an auth error" do
|
55
|
+
Excon.stub({ method: :post, password: "t.some-token" }, status: 401)
|
56
|
+
message = 'I have a message for you'
|
57
|
+
publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
|
58
|
+
expect(publisher.publish(message)).to be_falsey
|
59
|
+
end
|
73
60
|
end
|
74
|
-
end
|
75
61
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
62
|
+
context 'when the logplex service is acting up' do
|
63
|
+
it 'returns false' do
|
64
|
+
Excon.stub({ method: :post, password: "t.some-token" }, status: 500)
|
65
|
+
publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
|
66
|
+
expect(publisher.publish('hi')).to be_falsey
|
80
67
|
end
|
81
68
|
end
|
82
69
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
publisher
|
87
|
-
expect(publisher.publish('hi')).to be_false
|
70
|
+
it "handles timeouts" do
|
71
|
+
expect(Excon).to receive(:post).and_raise(Timeout::Error)
|
72
|
+
publisher = Logplex::Publisher.new('https://token:t.some-token@logplex.example.com')
|
73
|
+
expect(publisher.publish('hi')).to be_falsey
|
88
74
|
end
|
89
75
|
end
|
90
|
-
|
91
|
-
it "handles timeouts" do
|
92
|
-
RestClient.stub(:post).and_raise Timeout::Error
|
93
|
-
publisher = Logplex::Publisher.new('t.some-token', 'https://logplex.example.com')
|
94
|
-
expect(publisher.publish('hi')).to be_false
|
95
|
-
end
|
96
76
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,60 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logplex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1
|
5
|
-
prerelease: 6
|
4
|
+
version: 0.0.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Harold Giménez
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2016-07-26 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: valcro
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
25
27
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
27
|
-
requirement:
|
28
|
-
none: false
|
28
|
+
name: excon
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
|
-
- -
|
31
|
+
- - ">="
|
31
32
|
- !ruby/object:Gem::Version
|
32
33
|
version: '0'
|
33
34
|
type: :runtime
|
34
35
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
36
41
|
- !ruby/object:Gem::Dependency
|
37
42
|
name: rspec
|
38
|
-
requirement:
|
39
|
-
none: false
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
40
44
|
requirements:
|
41
|
-
- -
|
45
|
+
- - ">="
|
42
46
|
- !ruby/object:Gem::Version
|
43
47
|
version: '0'
|
44
48
|
type: :development
|
45
49
|
prerelease: false
|
46
|
-
version_requirements:
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: sham_rack
|
49
|
-
requirement: &70169923644580 !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
-
type: :development
|
56
|
-
prerelease: false
|
57
|
-
version_requirements: *70169923644580
|
58
55
|
description: Publish and Consume Logplex messages
|
59
56
|
email:
|
60
57
|
- harold.gimenez@gmail.com
|
@@ -62,8 +59,9 @@ executables: []
|
|
62
59
|
extensions: []
|
63
60
|
extra_rdoc_files: []
|
64
61
|
files:
|
65
|
-
- .gitignore
|
66
|
-
- .rspec
|
62
|
+
- ".gitignore"
|
63
|
+
- ".rspec"
|
64
|
+
- ".travis.yml"
|
67
65
|
- Gemfile
|
68
66
|
- LICENSE
|
69
67
|
- LICENSE.txt
|
@@ -79,35 +77,32 @@ files:
|
|
79
77
|
- spec/logplex/message_spec.rb
|
80
78
|
- spec/logplex/publisher_spec.rb
|
81
79
|
- spec/spec_helper.rb
|
82
|
-
- spec/support/fake_logplex.rb
|
83
80
|
homepage: https://practiceovertheory.com
|
84
81
|
licenses: []
|
82
|
+
metadata: {}
|
85
83
|
post_install_message:
|
86
84
|
rdoc_options: []
|
87
85
|
require_paths:
|
88
86
|
- lib
|
89
87
|
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
-
none: false
|
91
88
|
requirements:
|
92
|
-
- -
|
89
|
+
- - ">="
|
93
90
|
- !ruby/object:Gem::Version
|
94
91
|
version: '0'
|
95
92
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
-
none: false
|
97
93
|
requirements:
|
98
|
-
- -
|
94
|
+
- - ">="
|
99
95
|
- !ruby/object:Gem::Version
|
100
|
-
version:
|
96
|
+
version: '0'
|
101
97
|
requirements: []
|
102
98
|
rubyforge_project:
|
103
|
-
rubygems_version:
|
99
|
+
rubygems_version: 2.4.5.1
|
104
100
|
signing_key:
|
105
|
-
specification_version:
|
101
|
+
specification_version: 4
|
106
102
|
summary: Publish and Consume Logplex messages
|
107
103
|
test_files:
|
108
104
|
- spec/logplex/configuration_spec.rb
|
109
105
|
- spec/logplex/message_spec.rb
|
110
106
|
- spec/logplex/publisher_spec.rb
|
111
107
|
- spec/spec_helper.rb
|
112
|
-
- spec/support/fake_logplex.rb
|
113
108
|
has_rdoc:
|
@@ -1,108 +0,0 @@
|
|
1
|
-
class FakeLogplex
|
2
|
-
class Message
|
3
|
-
|
4
|
-
attr_reader :message, :token
|
5
|
-
|
6
|
-
def initialize(opts)
|
7
|
-
@message = opts[:message]
|
8
|
-
@token = opts[:token]
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.from_syslog(syslog_message)
|
12
|
-
messages = []
|
13
|
-
anchor = 0
|
14
|
-
until anchor >= syslog_message.length
|
15
|
-
new_anchor, opts = extract_syslog_field(syslog_message, anchor)
|
16
|
-
raise "same" if anchor == new_anchor
|
17
|
-
anchor = new_anchor
|
18
|
-
messages << new(opts)
|
19
|
-
end
|
20
|
-
messages
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.extract_syslog_field(syslog_message, anchor)
|
24
|
-
start = anchor
|
25
|
-
pos = start
|
26
|
-
pos, bytes = next_syslog_field(syslog_message, anchor, pos)
|
27
|
-
anchor = pos+1
|
28
|
-
pos, facility = next_syslog_field(syslog_message, anchor, pos)
|
29
|
-
anchor = pos+1
|
30
|
-
pos, time = next_syslog_field(syslog_message, anchor, pos)
|
31
|
-
anchor = pos+1
|
32
|
-
pos, host = next_syslog_field(syslog_message, anchor, pos)
|
33
|
-
anchor = pos+1
|
34
|
-
pos, token = next_syslog_field(syslog_message, anchor, pos)
|
35
|
-
anchor = pos+1
|
36
|
-
pos, process = next_syslog_field(syslog_message, anchor, pos)
|
37
|
-
anchor = pos+1
|
38
|
-
pos, message_id = next_syslog_field(syslog_message, anchor, pos)
|
39
|
-
anchor = pos+1
|
40
|
-
pos, unknown = next_syslog_field(syslog_message, anchor, pos)
|
41
|
-
anchor = pos+1
|
42
|
-
|
43
|
-
limit = start + bytes + bytes.to_s.length
|
44
|
-
message = syslog_message[anchor..limit]
|
45
|
-
|
46
|
-
[limit + 1, { message: message, token: token }]
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.next_syslog_field(message, anchor, pos)
|
50
|
-
until char = message[pos+=1] and char == ' '
|
51
|
-
field = message[anchor..pos].to_i
|
52
|
-
end
|
53
|
-
[pos, field]
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
@@tokens = []
|
58
|
-
@@received_messages = []
|
59
|
-
@@requests_received = 0
|
60
|
-
|
61
|
-
def call(env)
|
62
|
-
@@requests_received += 1
|
63
|
-
|
64
|
-
message = env['rack.input'].read
|
65
|
-
method = env['REQUEST_METHOD']
|
66
|
-
path = env['PATH_INFO']
|
67
|
-
content_type = env['CONTENT_TYPE']
|
68
|
-
content_length = env['CONTENT_LENGTH'].to_i
|
69
|
-
auth = env['HTTP_AUTHORIZATION']
|
70
|
-
|
71
|
-
_, auth_token = auth.split(' ')
|
72
|
-
user, pass = Base64.decode64(auth_token).split(':')
|
73
|
-
if @@tokens.include?(pass)
|
74
|
-
if (method == 'POST' &&
|
75
|
-
path == '/logs' &&
|
76
|
-
content_type == 'application/logplex-1' &&
|
77
|
-
content_length == message.length)
|
78
|
-
|
79
|
-
@@received_messages << Message.from_syslog(message)
|
80
|
-
@@received_messages.flatten!
|
81
|
-
[200, {}, []]
|
82
|
-
else
|
83
|
-
[404, {}, []]
|
84
|
-
end
|
85
|
-
else
|
86
|
-
[401, {}, []]
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def self.has_received_message?(message)
|
91
|
-
@@received_messages.map(&:message).include? message
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.register_token(token)
|
95
|
-
@@tokens << token
|
96
|
-
end
|
97
|
-
|
98
|
-
def self.clear!
|
99
|
-
@@tokens = []
|
100
|
-
@@received_messages = []
|
101
|
-
@@requests_received = 0
|
102
|
-
end
|
103
|
-
|
104
|
-
def self.requests_received
|
105
|
-
@@requests_received
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|