logstash-codec-protobuf 1.0.0 → 1.0.2
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 +4 -4
- data/CHANGELOG.md +5 -2
- data/Gemfile +10 -2
- data/docs/index.asciidoc +106 -0
- data/lib/logstash/codecs/protobuf.rb +29 -53
- data/logstash-codec-protobuf.gemspec +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 826cf27e43ea66cbabc39b226b229d179fd275d6
|
4
|
+
data.tar.gz: 0e2888f0622344cc8dddf20b03b9c89974d0613f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f49b8820a8a70a686a42c7561621946a426e74f839f18476c84a1e59dc06e2b71cbb2045c8281fb36d6cd432ee22ea896900dbbacf01686b46530b8008a8726
|
7
|
+
data.tar.gz: a162df9db2fed47938ef1cdd2901c28230a6f127351f464288582561b2d0fd5baef1fa59da91af503e2cd1b36e598932af827f0492e8becd5b9e122c19494828
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
@@ -1,3 +1,11 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
gemspec
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
logstash_path = ENV["LOGSTASH_PATH"] || "../../logstash"
|
6
|
+
use_logstash_source = ENV["LOGSTASH_SOURCE"] && ENV["LOGSTASH_SOURCE"].to_s == "1"
|
7
|
+
|
8
|
+
if Dir.exist?(logstash_path) && use_logstash_source
|
9
|
+
gem 'logstash-core', :path => "#{logstash_path}/logstash-core"
|
10
|
+
gem 'logstash-core-plugin-api', :path => "#{logstash_path}/logstash-core-plugin-api"
|
11
|
+
end
|
data/docs/index.asciidoc
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
:plugin: protobuf
|
2
|
+
:type: codec
|
3
|
+
|
4
|
+
///////////////////////////////////////////
|
5
|
+
START - GENERATED VARIABLES, DO NOT EDIT!
|
6
|
+
///////////////////////////////////////////
|
7
|
+
:version: %VERSION%
|
8
|
+
:release_date: %RELEASE_DATE%
|
9
|
+
:changelog_url: %CHANGELOG_URL%
|
10
|
+
:include_path: ../../../../logstash/docs/include
|
11
|
+
///////////////////////////////////////////
|
12
|
+
END - GENERATED VARIABLES, DO NOT EDIT!
|
13
|
+
///////////////////////////////////////////
|
14
|
+
|
15
|
+
[id="plugins-{type}-{plugin}"]
|
16
|
+
|
17
|
+
=== Protobuf codec plugin
|
18
|
+
|
19
|
+
include::{include_path}/plugin_header.asciidoc[]
|
20
|
+
|
21
|
+
==== Description
|
22
|
+
|
23
|
+
This codec converts protobuf encoded messages into logstash events and vice versa.
|
24
|
+
|
25
|
+
Requires the protobuf definitions as ruby files. You can create those using the [ruby-protoc compiler](https://github.com/codekitchen/ruby-protocol-buffers).
|
26
|
+
|
27
|
+
The following shows a usage example for decoding events from a kafka stream:
|
28
|
+
[source,ruby]
|
29
|
+
kafka
|
30
|
+
{
|
31
|
+
zk_connect => "127.0.0.1"
|
32
|
+
topic_id => "your_topic_goes_here"
|
33
|
+
codec => protobuf
|
34
|
+
{
|
35
|
+
class_name => "Animal::Unicorn"
|
36
|
+
include_path => ['/path/to/protobuf/definitions/UnicornProtobuf.pb.rb']
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
|
41
|
+
[id="plugins-{type}s-{plugin}-options"]
|
42
|
+
==== Protobuf Codec Configuration Options
|
43
|
+
|
44
|
+
[cols="<,<,<",options="header",]
|
45
|
+
|=======================================================================
|
46
|
+
|Setting |Input type|Required
|
47
|
+
| <<plugins-{type}s-{plugin}-class_name>> |<<string,string>>|Yes
|
48
|
+
| <<plugins-{type}s-{plugin}-include_path>> |<<array,array>>|Yes
|
49
|
+
|=======================================================================
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
[id="plugins-{type}s-{plugin}-class_name"]
|
54
|
+
===== `class_name`
|
55
|
+
|
56
|
+
* This is a required setting.
|
57
|
+
* Value type is <<string,string>>
|
58
|
+
* There is no default value for this setting.
|
59
|
+
|
60
|
+
Name of the class to decode.
|
61
|
+
If your protobuf definition contains modules, prepend them to the class name with double colons like so:
|
62
|
+
[source,ruby]
|
63
|
+
class_name => "Foods::Dairy::Cheese"
|
64
|
+
|
65
|
+
This corresponds to a protobuf definition starting as follows:
|
66
|
+
[source,ruby]
|
67
|
+
module Foods
|
68
|
+
module Dairy
|
69
|
+
class Cheese
|
70
|
+
# here are your field definitions.
|
71
|
+
|
72
|
+
If your class references other definitions: you only have to add the main class here.
|
73
|
+
|
74
|
+
[id="plugins-{type}s-{plugin}-include_path"]
|
75
|
+
===== `include_path`
|
76
|
+
|
77
|
+
* This is a required setting.
|
78
|
+
* Value type is <<array,array>>
|
79
|
+
* There is no default value for this setting.
|
80
|
+
|
81
|
+
List of absolute pathes to files with protobuf definitions.
|
82
|
+
When using more than one file, make sure to arrange the files in reverse order of dependency so that each class is loaded before it is
|
83
|
+
refered to by another.
|
84
|
+
|
85
|
+
Example: a class _Cheese_ referencing another protobuf class _Milk_
|
86
|
+
[source,ruby]
|
87
|
+
module Foods
|
88
|
+
module Dairy
|
89
|
+
class Cheese
|
90
|
+
set_fully_qualified_name "Foods.Dairy.Cheese"
|
91
|
+
optional ::Foods::Cheese::Milk, :milk, 1
|
92
|
+
optional :int64, :unique_id, 2
|
93
|
+
# here be more field definitions
|
94
|
+
|
95
|
+
would be configured as
|
96
|
+
[source,ruby]
|
97
|
+
include_path => ['/path/to/protobuf/definitions/Milk.pb.rb','/path/to/protobuf/definitions/Cheese.pb.rb']
|
98
|
+
|
99
|
+
When using the codec in an output plugin:
|
100
|
+
* make sure to include all the desired fields in the protobuf definition, including timestamp.
|
101
|
+
Remove fields that are not part of the protobuf definition from the event by using the mutate filter.
|
102
|
+
* the @ symbol is currently not supported in field names when loading the protobuf definitions for encoding. Make sure to call the timestamp field "timestamp"
|
103
|
+
instead of "@timestamp" in the protobuf file. Logstash event fields will be stripped of the leading @ before conversion.
|
104
|
+
|
105
|
+
|
106
|
+
|
@@ -66,32 +66,23 @@ class LogStash::Codecs::Protobuf < LogStash::Codecs::Base
|
|
66
66
|
config :include_path, :validate => :array, :required => true
|
67
67
|
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
69
|
def register
|
73
70
|
@pb_metainfo = {}
|
74
71
|
include_path.each { |path| require_pb_path(path) }
|
75
72
|
@obj = create_object_from_name(class_name)
|
76
73
|
@logger.debug("Protobuf files successfully loaded.")
|
77
|
-
|
78
74
|
end
|
79
75
|
|
80
|
-
def decode(data)
|
81
|
-
decoded = @obj.parse(data.to_s)
|
82
|
-
results = keys2strings(decoded.to_hash)
|
83
|
-
yield LogStash::Event.new(results) if block_given?
|
84
|
-
end # def decode
|
85
76
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
77
|
+
def decode(data)
|
78
|
+
begin
|
79
|
+
decoded = @obj.parse(data.to_s)
|
80
|
+
yield LogStash::Event.new(decoded.to_hash) if block_given?
|
81
|
+
rescue => e
|
82
|
+
@logger.warn("Couldn't decode protobuf: #{e.inspect}.")
|
83
|
+
# raise e
|
93
84
|
end
|
94
|
-
end
|
85
|
+
end # def decode
|
95
86
|
|
96
87
|
|
97
88
|
def encode(event)
|
@@ -99,68 +90,53 @@ class LogStash::Codecs::Protobuf < LogStash::Codecs::Base
|
|
99
90
|
@on_event.call(event, protobytes)
|
100
91
|
end # def encode
|
101
92
|
|
93
|
+
|
102
94
|
private
|
103
|
-
def generate_protobuf(event)
|
104
|
-
meth = self.method("encoder_strategy_1")
|
105
|
-
data = meth.call(event, @class_name)
|
95
|
+
def generate_protobuf(event)
|
106
96
|
begin
|
97
|
+
data = _encode(event, @class_name)
|
107
98
|
msg = @obj.new(data)
|
108
99
|
msg.serialize_to_string
|
109
100
|
rescue NoMethodError
|
110
101
|
@logger.debug("error 2: NoMethodError. Maybe mismatching protobuf definition. Required fields are: " + event.to_hash.keys.join(", "))
|
102
|
+
rescue => e
|
103
|
+
@logger.debug("Couldn't generate protobuf: ${e}")
|
111
104
|
end
|
112
105
|
end
|
113
106
|
|
114
|
-
def encoder_strategy_1(event, class_name)
|
115
|
-
_encoder_strategy_1(event.to_hash, class_name)
|
116
107
|
|
117
|
-
|
118
|
-
|
119
|
-
def _encoder_strategy_1(datahash, class_name)
|
120
|
-
fields = clean_hash_keys(datahash)
|
121
|
-
fields = flatten_hash_values(fields) # TODO we could merge this and the above method back into one to save one iteration, but how are we going to name it?
|
108
|
+
def _encode(datahash, class_name)
|
109
|
+
fields = prepare_for_encoding(datahash)
|
122
110
|
meta = get_complex_types(class_name) # returns a hash with member names and their protobuf class names
|
123
111
|
meta.map do | (k,typeinfo) |
|
124
112
|
if fields.include?(k)
|
125
113
|
original_value = fields[k]
|
126
114
|
proto_obj = create_object_from_name(typeinfo)
|
127
115
|
fields[k] =
|
128
|
-
if original_value.is_a?(::Array)
|
129
|
-
|
130
|
-
|
116
|
+
if original_value.is_a?(::Array)
|
117
|
+
# make this field an array/list of protobuf objects
|
118
|
+
# value is a list of hashed complex objects, each of which needs to be protobuffed and
|
119
|
+
# put back into the list.
|
120
|
+
original_value.map { |x| _encode(x, typeinfo) }
|
121
|
+
original_value
|
131
122
|
else
|
132
|
-
recursive_fix =
|
123
|
+
recursive_fix = _encode(original_value, class_name)
|
133
124
|
proto_obj.new(recursive_fix)
|
134
125
|
end # if is array
|
135
126
|
end
|
136
|
-
|
137
|
-
end
|
138
|
-
|
127
|
+
end
|
139
128
|
fields
|
140
129
|
end
|
141
130
|
|
142
|
-
def ecs1_list_helper(value, proto_obj, class_name)
|
143
|
-
# make this field an array/list of protobuf objects
|
144
|
-
# value is a list of hashed complex objects, each of which needs to be protobuffed and
|
145
|
-
# put back into the list.
|
146
|
-
next unless value.is_a?(::Array)
|
147
|
-
value.map { |x| _encoder_strategy_1(x, class_name) }
|
148
|
-
value
|
149
|
-
end
|
150
131
|
|
151
|
-
def
|
132
|
+
def prepare_for_encoding(datahash)
|
133
|
+
# the data cannot be encoded until certain criteria are met:
|
134
|
+
# 1) remove @ signs from keys
|
152
135
|
# 2) convert timestamps and other objects to strings
|
153
|
-
next unless datahash.is_a?(::Hash)
|
154
|
-
|
155
|
-
::Hash[datahash.map{|(k,v)| [k, (convert_to_string?(v) ? v.to_s : v)] }]
|
136
|
+
next unless datahash.is_a?(::Hash)
|
137
|
+
::Hash[datahash.map{|(k,v)| [remove_atchar(k.to_s), (convert_to_string?(v) ? v.to_s : v)] }]
|
156
138
|
end
|
157
139
|
|
158
|
-
def clean_hash_keys(datahash)
|
159
|
-
# 1) remove @ signs from keys
|
160
|
-
next unless datahash.is_a?(::Hash)
|
161
|
-
|
162
|
-
::Hash[datahash.map{|(k,v)| [remove_atchar(k.to_s), v] }]
|
163
|
-
end #clean_hash_keys
|
164
140
|
|
165
141
|
def convert_to_string?(v)
|
166
142
|
!(v.is_a?(Fixnum) || v.is_a?(::Hash) || v.is_a?(::Array) || [true, false].include?(v))
|
@@ -171,7 +147,7 @@ class LogStash::Codecs::Protobuf < LogStash::Codecs::Base
|
|
171
147
|
key.dup.gsub(/@/,'')
|
172
148
|
end
|
173
149
|
|
174
|
-
|
150
|
+
|
175
151
|
def create_object_from_name(name)
|
176
152
|
begin
|
177
153
|
@logger.debug("Creating instance of " + name)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-codec-protobuf'
|
4
|
-
s.version = '1.0.
|
4
|
+
s.version = '1.0.2'
|
5
5
|
s.licenses = ['Apache License (2.0)']
|
6
6
|
s.summary = "This codec may be used to decode (via inputs) and encode (via outputs) protobuf messages"
|
7
7
|
s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
|
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.require_paths = ["lib"]
|
11
11
|
|
12
12
|
# Files
|
13
|
-
s.files = Dir[
|
13
|
+
s.files = Dir["lib/**/*","spec/**/*","*.gemspec","*.md","CONTRIBUTORS","Gemfile","LICENSE","NOTICE.TXT", "vendor/jar-dependencies/**/*.jar", "vendor/jar-dependencies/**/*.rb", "VERSION", "docs/**/*"]
|
14
14
|
|
15
15
|
# Tests
|
16
16
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-codec-protobuf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Inga Feick
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -71,6 +71,7 @@ files:
|
|
71
71
|
- LICENSE
|
72
72
|
- NOTICE.TXT
|
73
73
|
- README.md
|
74
|
+
- docs/index.asciidoc
|
74
75
|
- lib/logstash/codecs/protobuf.rb
|
75
76
|
- logstash-codec-protobuf.gemspec
|
76
77
|
- spec/codecs/protobuf_spec.rb
|