logplex 0.0.1.pre.4 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|