loggregator_emitter 2.0.0.pre → 2.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.
- 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
|