loggregator_emitter 2.0.0.pre → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +12 -9
- data/lib/loggregator_emitter/emit.rb +30 -15
- data/lib/loggregator_messages/log_message.pb.rb +2 -0
- data/lib/loggregator_messages/log_message.proto +2 -0
- data/lib/loggregator_messages/log_message_extender.rb +0 -8
- data/lib/symmetric/encryption.rb +1 -0
- data/loggregator_emitter.gemspec +1 -1
- data/spec/loggregator_emitter/emit_performance_spec.rb +65 -0
- data/spec/loggregator_emitter/emit_spec.rb +34 -8
- data/spec/loggregator_emitter/log_message_extender_spec.rb +2 -61
- metadata +10 -5
data/README.md
CHANGED
@@ -4,18 +4,18 @@
|
|
4
4
|
|
5
5
|
This gem provides an API to emit messages to the loggregator agent from Ruby applications.
|
6
6
|
|
7
|
-
Create an emitter object with the loggregator router host and port,
|
7
|
+
Create an emitter object with the loggregator router host and port, a source name of the emitter, and a shared secret (for signing).
|
8
8
|
|
9
9
|
Call emit() or emit_error() on this emitter with the application GUID and the message string.
|
10
10
|
|
11
|
-
|
11
|
+
##### A valid source name is any 3 character string. Some common component sources are:
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
API (Cloud Controller)
|
14
|
+
RTR (Go Router)
|
15
|
+
UAA
|
16
|
+
DEA
|
17
|
+
APP (Warden container)
|
18
|
+
LGR (Loggregator)
|
19
19
|
|
20
20
|
### Setup
|
21
21
|
|
@@ -27,7 +27,7 @@ Call emit() or emit_error() on this emitter with the application GUID and the me
|
|
27
27
|
|
28
28
|
require "loggregator_emitter"
|
29
29
|
|
30
|
-
emitter = LoggregatorEmitter::Emitter.new("10.10.10.16:38452",
|
30
|
+
emitter = LoggregatorEmitter::Emitter.new("10.10.10.16:38452", "API")
|
31
31
|
|
32
32
|
app_guid = "a8977cb6-3365-4be1-907e-0c878b3a4c6b" # The GUID(UUID) for the user's application
|
33
33
|
|
@@ -35,6 +35,9 @@ Call emit() or emit_error() on this emitter with the application GUID and the me
|
|
35
35
|
|
36
36
|
emitter.emit_error(app_guid,error_message) # Emits messages with a message type of ERR
|
37
37
|
|
38
|
+
### Regenerating Protobuf library
|
39
|
+
protoc --beefcake_out lib/loggregator_messages -I lib/loggregator_messages lib/loggregator_messages/log_message.proto
|
40
|
+
|
38
41
|
### Versioning
|
39
42
|
|
40
43
|
This gem is versioned using [semantic versioning](http://semver.org/).
|
@@ -5,14 +5,33 @@ module LoggregatorEmitter
|
|
5
5
|
MAX_MESSAGE_BYTE_SIZE = (9 * 1024) - 512
|
6
6
|
TRUNCATED_STRING = "TRUNCATED"
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
SOURCE_TYPE_BY_ID = {
|
9
|
+
1 => "CLOUD_CONTROLLER",
|
10
|
+
2 => "ROUTER",
|
11
|
+
3 => "UAA",
|
12
|
+
4 => "DEA",
|
13
|
+
5 => "WARDEN_CONTAINER",
|
14
|
+
6 => "LOGGREGATOR",
|
15
|
+
}
|
16
|
+
|
17
|
+
def initialize(loggregator_server, source_type_or_name, source_id = nil, secret=nil)
|
11
18
|
@host, @port = loggregator_server.split(/:([^:]*$)/)
|
12
19
|
raise ArgumentError, "Must provide valid loggregator server: #{loggregator_server}" if !valid_hostname || !valid_port
|
20
|
+
raise ArgumentError, "Must provide valid source_type_or_name: #{source_type_or_name}" unless source_type_or_name
|
21
|
+
|
22
|
+
case source_type_or_name
|
23
|
+
when LogMessage::SourceType::CLOUD_CONTROLLER..LogMessage::SourceType::LOGGREGATOR
|
24
|
+
@source_type = source_type_or_name
|
25
|
+
@source_name = SOURCE_TYPE_BY_ID[source_type_or_name]
|
26
|
+
when String
|
27
|
+
raise ArgumentError, "Custom Source String must be 3 characters" unless source_type_or_name.size == 3
|
28
|
+
@source_type = LogMessage::SourceType::UNKNOWN
|
29
|
+
@source_name = source_type_or_name
|
30
|
+
else
|
31
|
+
raise ArgumentError, "Invalid source: #{source_type_or_name.inspect} Please use a string or a known source type constant"
|
32
|
+
end
|
13
33
|
|
14
34
|
@secret = secret
|
15
|
-
@source_type = source_type
|
16
35
|
@source_id = source_id && source_id.to_s
|
17
36
|
end
|
18
37
|
|
@@ -34,10 +53,14 @@ module LoggregatorEmitter
|
|
34
53
|
@host && !@host.match(/:\/\//)
|
35
54
|
end
|
36
55
|
|
56
|
+
def split_message(message)
|
57
|
+
message.split(/\n|\r/).reject { |a| a.empty? }
|
58
|
+
end
|
59
|
+
|
37
60
|
def emit_message(app_id, message, type)
|
38
61
|
return unless app_id && message && message.strip.length > 0
|
39
62
|
|
40
|
-
message
|
63
|
+
split_message(message).each do |m|
|
41
64
|
if m.bytesize > MAX_MESSAGE_BYTE_SIZE
|
42
65
|
m = m.byteslice(0, MAX_MESSAGE_BYTE_SIZE-TRUNCATED_STRING.bytesize) + TRUNCATED_STRING
|
43
66
|
end
|
@@ -46,7 +69,7 @@ module LoggregatorEmitter
|
|
46
69
|
send_protobuffer(create_log_message(app_id, m, type))
|
47
70
|
else
|
48
71
|
send_protobuffer(create_log_envelope(app_id, m, type))
|
49
|
-
|
72
|
+
end
|
50
73
|
end
|
51
74
|
end
|
52
75
|
|
@@ -57,6 +80,7 @@ module LoggregatorEmitter
|
|
57
80
|
lm.app_id = app_id
|
58
81
|
lm.source_id = @source_id
|
59
82
|
lm.source_type = @source_type
|
83
|
+
lm.source_name = @source_name
|
60
84
|
lm.message_type = type
|
61
85
|
lm
|
62
86
|
end
|
@@ -80,14 +104,5 @@ module LoggregatorEmitter
|
|
80
104
|
s.do_not_reverse_lookup = true
|
81
105
|
s.sendmsg_nonblock(result, 0, addrinfo_udp)
|
82
106
|
end
|
83
|
-
|
84
|
-
def valid_source_type?(source_type)
|
85
|
-
LogMessage::SourceType.constants.each do |name|
|
86
|
-
if LogMessage::SourceType.const_get(name) == source_type
|
87
|
-
return true
|
88
|
-
end
|
89
|
-
end
|
90
|
-
false
|
91
|
-
end
|
92
107
|
end
|
93
108
|
end
|
@@ -16,6 +16,7 @@ class LogMessage
|
|
16
16
|
DEA = 4
|
17
17
|
WARDEN_CONTAINER = 5
|
18
18
|
LOGGREGATOR = 6
|
19
|
+
UNKNOWN = 7
|
19
20
|
end
|
20
21
|
|
21
22
|
required :message, :bytes, 1
|
@@ -25,6 +26,7 @@ class LogMessage
|
|
25
26
|
required :source_type, LogMessage::SourceType, 5
|
26
27
|
optional :source_id, :string, 6
|
27
28
|
repeated :drain_urls, :string, 7
|
29
|
+
optional :source_name, :string, 8
|
28
30
|
|
29
31
|
end
|
30
32
|
|
@@ -13,6 +13,7 @@ message LogMessage {
|
|
13
13
|
DEA = 4;
|
14
14
|
WARDEN_CONTAINER = 5;
|
15
15
|
LOGGREGATOR = 6;
|
16
|
+
UNKNOWN = 7;
|
16
17
|
}
|
17
18
|
|
18
19
|
required bytes message = 1;
|
@@ -22,6 +23,7 @@ message LogMessage {
|
|
22
23
|
required SourceType source_type = 5;
|
23
24
|
optional string source_id = 6;
|
24
25
|
repeated string drain_urls = 7;
|
26
|
+
optional string source_name = 8;
|
25
27
|
}
|
26
28
|
|
27
29
|
message LogEnvelope {
|
@@ -3,14 +3,6 @@ class LogMessage
|
|
3
3
|
{MessageType::OUT => 'STDOUT', MessageType::ERR => 'STDERR'}[message_type]
|
4
4
|
end
|
5
5
|
|
6
|
-
def source_type_name
|
7
|
-
{SourceType::CLOUD_CONTROLLER => 'CF[CC]',
|
8
|
-
SourceType::ROUTER => 'CF[Router]',
|
9
|
-
SourceType::UAA => 'CF[UAA]',
|
10
|
-
SourceType::DEA => 'CF[DEA]',
|
11
|
-
SourceType::WARDEN_CONTAINER => 'App',}[source_type]
|
12
|
-
end
|
13
|
-
|
14
6
|
def time=(time)
|
15
7
|
self.timestamp = (time.tv_sec * 1000000000) + time.tv_nsec
|
16
8
|
end
|
data/lib/symmetric/encryption.rb
CHANGED
data/loggregator_emitter.gemspec
CHANGED
@@ -0,0 +1,65 @@
|
|
1
|
+
require "support/fake_loggregator_server"
|
2
|
+
require "loggregator_emitter"
|
3
|
+
|
4
|
+
class MessageFixture
|
5
|
+
attr_reader :name, :message
|
6
|
+
|
7
|
+
def initialize(name, message, server_threshold, no_server_threshold)
|
8
|
+
@name = name
|
9
|
+
@message = message
|
10
|
+
@server_threshold = server_threshold
|
11
|
+
@no_server_threshold = no_server_threshold
|
12
|
+
end
|
13
|
+
|
14
|
+
def expected(using_server)
|
15
|
+
using_server ? @server_threshold : @no_server_threshold
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class FreePort
|
20
|
+
def self.next_free_port
|
21
|
+
@@next_free_port ||= 12345
|
22
|
+
@@next_free_port += 1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
shared_examples "a performance test" do |fixture, using_server|
|
27
|
+
let(:free_port) { FreePort.next_free_port }
|
28
|
+
let(:iterations) { using_server ? 100 : 1000 }
|
29
|
+
subject(:emitter) { LoggregatorEmitter::Emitter.new("localhost:#{free_port}", "API", 42, "my-secret") }
|
30
|
+
|
31
|
+
before do
|
32
|
+
if using_server
|
33
|
+
@server = FakeLoggregatorServer.new(free_port)
|
34
|
+
@server.start
|
35
|
+
else
|
36
|
+
emitter.should_receive(:send_protobuffer).at_least(iterations).times
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
after do
|
41
|
+
@server.stop if using_server
|
42
|
+
end
|
43
|
+
|
44
|
+
it "emits #{fixture.name} within a time threshold #{using_server ? 'with' : 'without'} server" do
|
45
|
+
start_time = Time.now.to_f
|
46
|
+
|
47
|
+
iterations.times { emitter.emit("my_app_id", fixture.message) }
|
48
|
+
|
49
|
+
expect(Time.now.to_f - start_time).to be < fixture.expected(using_server)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
describe LoggregatorEmitter do
|
55
|
+
@fixtures = []
|
56
|
+
@fixtures << MessageFixture.new("long_message", (124*1024).times.collect { "a" }.join(""), 2.0, 2.0)
|
57
|
+
@fixtures << MessageFixture.new("message with newlines", 10.times.collect { (6*1024).times.collect { "a" }.join("") + "\n" }.join(""), 3.0, 3.0)
|
58
|
+
@fixtures << MessageFixture.new("message worst case", (124*1024).times.collect { "a" }.join("") + "\n", 2.0, 2.0)
|
59
|
+
|
60
|
+
[true, false].each do |using_server|
|
61
|
+
@fixtures.each do |fixture|
|
62
|
+
it_behaves_like "a performance test", fixture, using_server
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -25,6 +25,10 @@ describe LoggregatorEmitter do
|
|
25
25
|
it "is valid if a server name is given" do
|
26
26
|
expect { LoggregatorEmitter::Emitter.new("some-unknown-address:12345", LogMessage::SourceType::DEA) }.not_to raise_error
|
27
27
|
end
|
28
|
+
|
29
|
+
it "accepts a string as source type/name" do
|
30
|
+
expect { LoggregatorEmitter::Emitter.new("some-unknown-address:12345", "STG") }.not_to raise_error
|
31
|
+
end
|
28
32
|
end
|
29
33
|
|
30
34
|
describe "invalid configurations" do
|
@@ -32,11 +36,22 @@ describe LoggregatorEmitter do
|
|
32
36
|
it "raises if host has protocol" do
|
33
37
|
expect { LoggregatorEmitter::Emitter.new("http://0.0.0.0:12345", LogMessage::SourceType::DEA) }.to raise_error(ArgumentError)
|
34
38
|
end
|
35
|
-
end
|
36
39
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
+
it "raises if source is an unknown integer" do
|
41
|
+
expect { LoggregatorEmitter::Emitter.new("some-unknown-address:12345", 7) }.to raise_error(ArgumentError)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "raises if source is not an integer or string" do
|
45
|
+
expect { LoggregatorEmitter::Emitter.new("some-unknown-address:12345", nil) }.to raise_error(ArgumentError)
|
46
|
+
expect { LoggregatorEmitter::Emitter.new("some-unknown-address:12345", 12.0) }.to raise_error(ArgumentError)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "raises if source is too large of a string" do
|
50
|
+
expect { LoggregatorEmitter::Emitter.new("some-unknown-address:12345", "ABCD") }.to raise_error(ArgumentError)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "raises if source is too small of a string" do
|
54
|
+
expect { LoggregatorEmitter::Emitter.new("some-unknown-address:12345", "AB") }.to raise_error(ArgumentError)
|
40
55
|
end
|
41
56
|
end
|
42
57
|
end
|
@@ -192,7 +207,7 @@ describe LoggregatorEmitter do
|
|
192
207
|
end
|
193
208
|
end
|
194
209
|
|
195
|
-
describe "source
|
210
|
+
describe "source" do
|
196
211
|
before do
|
197
212
|
@server = FakeLoggregatorServer.new(free_port)
|
198
213
|
@server.start
|
@@ -210,17 +225,28 @@ describe LoggregatorEmitter do
|
|
210
225
|
@server.messages[0]
|
211
226
|
end
|
212
227
|
|
213
|
-
it "
|
228
|
+
it "when type is known" do
|
229
|
+
@emitter = LoggregatorEmitter::Emitter.new("0.0.0.0:#{free_port}", LogMessage::SourceType::CLOUD_CONTROLLER)
|
230
|
+
expect(emit_message.source_name).to eq "CLOUD_CONTROLLER"
|
231
|
+
end
|
232
|
+
|
233
|
+
it "when type is unknown" do
|
234
|
+
@emitter = LoggregatorEmitter::Emitter.new("0.0.0.0:#{free_port}", "STG")
|
235
|
+
expect(emit_message.source_name).to eq "STG"
|
236
|
+
expect(emit_message.source_type).to eq LogMessage::SourceType::UNKNOWN
|
237
|
+
end
|
238
|
+
|
239
|
+
it "id can be nil" do
|
214
240
|
@emitter = LoggregatorEmitter::Emitter.new("0.0.0.0:#{free_port}", LogMessage::SourceType::CLOUD_CONTROLLER)
|
215
241
|
expect(emit_message.source_id).to eq nil
|
216
242
|
end
|
217
243
|
|
218
|
-
it "can be passed in as a string" do
|
244
|
+
it "id can be passed in as a string" do
|
219
245
|
@emitter = LoggregatorEmitter::Emitter.new("0.0.0.0:#{free_port}", LogMessage::SourceType::CLOUD_CONTROLLER, "some_source_id")
|
220
246
|
expect(emit_message.source_id).to eq "some_source_id"
|
221
247
|
end
|
222
248
|
|
223
|
-
it "can be passed in as an integer" do
|
249
|
+
it "id can be passed in as an integer" do
|
224
250
|
@emitter = LoggregatorEmitter::Emitter.new("0.0.0.0:#{free_port}", LogMessage::SourceType::CLOUD_CONTROLLER, 13)
|
225
251
|
expect(emit_message.source_id).to eq "13"
|
226
252
|
end
|
@@ -9,7 +9,7 @@ describe LogMessage do
|
|
9
9
|
:message => "thesearebytes",
|
10
10
|
:message_type => 1,
|
11
11
|
:timestamp => 3,
|
12
|
-
:source_type =>
|
12
|
+
:source_type => "UAA"
|
13
13
|
})
|
14
14
|
|
15
15
|
expect(msg.message_type_name).to eq("STDOUT")
|
@@ -21,72 +21,13 @@ describe LogMessage do
|
|
21
21
|
:message => "thesearebytes",
|
22
22
|
:message_type => 2,
|
23
23
|
:timestamp => 3,
|
24
|
-
:source_type =>
|
24
|
+
:source_type => "UAA"
|
25
25
|
})
|
26
26
|
|
27
27
|
expect(msg.message_type_name).to eq("STDERR")
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
describe "#source_type_name" do
|
32
|
-
it "returns CloudController for type == 1" do
|
33
|
-
msg = LogMessage.new(
|
34
|
-
{
|
35
|
-
:message => "thesearebytes",
|
36
|
-
:message_type => 1,
|
37
|
-
:timestamp => 3,
|
38
|
-
:source_type => 1
|
39
|
-
})
|
40
|
-
|
41
|
-
expect(msg.source_type_name).to eq("CF[CC]")
|
42
|
-
end
|
43
|
-
|
44
|
-
it "returns Router for type == 2" do
|
45
|
-
msg = LogMessage.new(
|
46
|
-
{
|
47
|
-
:message => "thesearebytes",
|
48
|
-
:message_type => 2,
|
49
|
-
:timestamp => 3,
|
50
|
-
:source_type => 2
|
51
|
-
})
|
52
|
-
|
53
|
-
expect(msg.source_type_name).to eq("CF[Router]")
|
54
|
-
end
|
55
|
-
it "returns UAA for type == 3" do
|
56
|
-
msg = LogMessage.new(
|
57
|
-
{
|
58
|
-
:message => "thesearebytes",
|
59
|
-
:message_type => 2,
|
60
|
-
:timestamp => 3,
|
61
|
-
:source_type => 3
|
62
|
-
})
|
63
|
-
|
64
|
-
expect(msg.source_type_name).to eq("CF[UAA]")
|
65
|
-
end
|
66
|
-
it "returns DEA for type == 4" do
|
67
|
-
msg = LogMessage.new(
|
68
|
-
{
|
69
|
-
:message => "thesearebytes",
|
70
|
-
:message_type => 2,
|
71
|
-
:timestamp => 3,
|
72
|
-
:source_type => 4
|
73
|
-
})
|
74
|
-
|
75
|
-
expect(msg.source_type_name).to eq("CF[DEA]")
|
76
|
-
end
|
77
|
-
it "returns WardenContainer for type == 5" do
|
78
|
-
msg = LogMessage.new(
|
79
|
-
{
|
80
|
-
:message => "thesearebytes",
|
81
|
-
:message_type => 2,
|
82
|
-
:timestamp => 3,
|
83
|
-
:source_type => 5
|
84
|
-
})
|
85
|
-
|
86
|
-
expect(msg.source_type_name).to eq("App")
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
31
|
describe "#time=" do
|
91
32
|
it "takes a time object" do
|
92
33
|
msg = LogMessage.new
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: loggregator_emitter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0
|
5
|
-
prerelease:
|
4
|
+
version: 2.0.0
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Pivotal
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-11-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: beefcake
|
@@ -95,6 +95,7 @@ files:
|
|
95
95
|
- lib/loggregator_messages/log_message_extender.rb
|
96
96
|
- lib/symmetric/encryption.rb
|
97
97
|
- loggregator_emitter.gemspec
|
98
|
+
- spec/loggregator_emitter/emit_performance_spec.rb
|
98
99
|
- spec/loggregator_emitter/emit_spec.rb
|
99
100
|
- spec/loggregator_emitter/encryption_spec.rb
|
100
101
|
- spec/loggregator_emitter/log_message_extender_spec.rb
|
@@ -115,9 +116,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
115
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
117
|
none: false
|
117
118
|
requirements:
|
118
|
-
- - ! '
|
119
|
+
- - ! '>='
|
119
120
|
- !ruby/object:Gem::Version
|
120
|
-
version:
|
121
|
+
version: '0'
|
122
|
+
segments:
|
123
|
+
- 0
|
124
|
+
hash: 584721548114788876
|
121
125
|
requirements: []
|
122
126
|
rubyforge_project:
|
123
127
|
rubygems_version: 1.8.25
|
@@ -125,6 +129,7 @@ signing_key:
|
|
125
129
|
specification_version: 3
|
126
130
|
summary: Library to emit data to Loggregator
|
127
131
|
test_files:
|
132
|
+
- spec/loggregator_emitter/emit_performance_spec.rb
|
128
133
|
- spec/loggregator_emitter/emit_spec.rb
|
129
134
|
- spec/loggregator_emitter/encryption_spec.rb
|
130
135
|
- spec/loggregator_emitter/log_message_extender_spec.rb
|