fluent-plugin-juniper-telemetry 0.2.8

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.
@@ -0,0 +1,83 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # This file is auto-generated. DO NOT EDIT!
5
+ #
6
+ require 'protobuf/message'
7
+
8
+
9
+ ##
10
+ # Imports
11
+ #
12
+ require 'jvision_top.pb'
13
+
14
+
15
+ ##
16
+ # Message Classes
17
+ #
18
+ class Firewall < ::Protobuf::Message; end
19
+ class FirewallStats < ::Protobuf::Message; end
20
+ class MemoryUsage < ::Protobuf::Message; end
21
+ class CounterStats < ::Protobuf::Message; end
22
+ class PolicerStats < ::Protobuf::Message; end
23
+ class ExtendedPolicerStats < ::Protobuf::Message; end
24
+ class HierarchicalPolicerStats < ::Protobuf::Message; end
25
+
26
+
27
+ ##
28
+ # Message Fields
29
+ #
30
+ class Firewall
31
+ repeated ::FirewallStats, :firewall_stats, 1
32
+ end
33
+
34
+ class FirewallStats
35
+ required :string, :filter_name, 1
36
+ optional :uint64, :timestamp, 2
37
+ repeated ::MemoryUsage, :memory_usage, 3
38
+ repeated ::CounterStats, :counter_stats, 4
39
+ repeated ::PolicerStats, :policer_stats, 5
40
+ repeated ::HierarchicalPolicerStats, :hierarchical_policer_stats, 6
41
+ end
42
+
43
+ class MemoryUsage
44
+ required :string, :name, 1
45
+ optional :uint64, :allocated, 2
46
+ end
47
+
48
+ class CounterStats
49
+ required :string, :name, 1
50
+ optional :uint64, :packets, 2
51
+ optional :uint64, :bytes, 3
52
+ end
53
+
54
+ class PolicerStats
55
+ required :string, :name, 1
56
+ optional :uint64, :out_of_spec_packets, 2
57
+ optional :uint64, :out_of_spec_bytes, 3
58
+ optional ::ExtendedPolicerStats, :extended_policer_stats, 4
59
+ end
60
+
61
+ class ExtendedPolicerStats
62
+ optional :uint64, :offered_packets, 1
63
+ optional :uint64, :offered_bytes, 2
64
+ optional :uint64, :transmitted_packets, 3
65
+ optional :uint64, :transmitted_bytes, 4
66
+ end
67
+
68
+ class HierarchicalPolicerStats
69
+ required :string, :name, 1
70
+ optional :uint64, :premium_packets, 2
71
+ optional :uint64, :premium_bytes, 3
72
+ optional :uint64, :aggregate_packets, 4
73
+ optional :uint64, :aggregate_bytes, 5
74
+ end
75
+
76
+
77
+ ##
78
+ # Extended Message Fields
79
+ #
80
+ class ::JuniperNetworksSensors < ::Protobuf::Message
81
+ optional ::Firewall, :jnpr_firewall_ext, 6, :extension => true
82
+ end
83
+
@@ -0,0 +1,125 @@
1
+ module Fluent
2
+ class TextParser
3
+ class JuniperAnalyticsdParser < Parser
4
+
5
+ Plugin.register_parser("juniper_analyticsd", self)
6
+
7
+ config_param :output_format, :string, :default => 'structured'
8
+
9
+ # This method is called after config_params have read configuration parameters
10
+ def configure(conf)
11
+ super
12
+
13
+ ## Check if "output_format" has a valid value
14
+ unless @output_format.to_s == "structured" ||
15
+ @output_format.to_s == "flat" ||
16
+ @output_format.to_s == "statsd"
17
+
18
+ raise ConfigError, "output_format value '#{@output_format}' is not valid. Must be : structured, flat or statsd"
19
+ end
20
+ end
21
+
22
+ def parse(text)
23
+
24
+ payload = JSON.parse(text)
25
+ time = Engine.now
26
+
27
+ ## Extract contextual info
28
+ record_type = payload["record-type"]
29
+ record_time = payload["time"]
30
+ device_name = payload["router-id"]
31
+ port_name = payload["port"]
32
+
33
+ ## Record time is in microsecond and until 0.14 Fluentd do not support lower than 1s
34
+ ## We need to trim record time for now to fit fluentd
35
+ json_time = (record_time/1000000).to_i
36
+
37
+ if record_type == 'traffic-stats'
38
+
39
+ ## Delete contextual info
40
+ payload.delete("record-type")
41
+ payload.delete("time")
42
+ payload.delete("router-id")
43
+ payload.delete("port")
44
+
45
+ payload.each do |key, value|
46
+ record = {}
47
+
48
+ if output_format.to_s == 'flat'
49
+ full_name = "device.#{clean_up_name(device_name)}.interface.#{clean_up_name(port_name)}.type.#{key}"
50
+
51
+ record[full_name.downcase]= value
52
+
53
+ elsif output_format.to_s == 'structured'
54
+ record['device'] = device_name
55
+ record['type'] = record_type + '.' + key
56
+ record['interface'] = port_name
57
+ record['value'] = value
58
+
59
+ elsif output_format.to_s == 'statsd'
60
+
61
+ full_name = "interface.#{clean_up_name(port_name)}.type.#{key}"
62
+ record[:statsd_type] = 'gauge'
63
+ record[:statsd_key] = full_name.downcase
64
+ record[:statsd_gauge] = value
65
+ else
66
+ $log.warn "Output_format '#{output_format.to_s}' not supported for #{record_type}"
67
+ end
68
+
69
+ yield json_time, record
70
+ end
71
+ elsif record_type == 'queue-stats'
72
+
73
+ ## Delete contextual info
74
+ payload.delete("record-type")
75
+ payload.delete("time")
76
+ payload.delete("router-id")
77
+ payload.delete("port")
78
+
79
+ payload.each do |key, value|
80
+ record = {}
81
+
82
+ if output_format.to_s == 'flat'
83
+
84
+ full_name = "device.#{clean_up_name(device_name)}.interface.#{clean_up_name(port_name)}.queue.#{key}"
85
+
86
+ record[full_name.downcase]= value
87
+
88
+ elsif output_format.to_s == 'structured'
89
+ record['device'] = device_name
90
+ record['type'] = record_type + '.' + key
91
+ record['interface'] = port_name
92
+ record['value'] = value
93
+
94
+ elsif output_format.to_s == 'statsd'
95
+ full_name = "interface.#{clean_up_name(port_name)}.queue.#{key}"
96
+ record[:statsd_type] = 'gauge'
97
+ record[:statsd_key] = full_name.downcase
98
+ record[:statsd_gauge] = value
99
+
100
+ else
101
+ $log.warn "Output_format '#{output_format.to_s}' not supported for #{record_type}"
102
+ end
103
+
104
+ yield json_time, record
105
+ end
106
+ else
107
+ $log.warn "Recard type '#{record_type}' not supported"
108
+ end
109
+ end
110
+
111
+ ## Clean up device name and interface name to remove restricted caracter
112
+ ## Used for flat and statsd format
113
+ def clean_up_name(name)
114
+
115
+ tmp = name
116
+
117
+ tmp.gsub!('/', '_')
118
+ tmp.gsub!(':', '_')
119
+ tmp.gsub!('.', '_')
120
+
121
+ return tmp.to_s
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,282 @@
1
+ require 'protobuf'
2
+ require 'jvision_top.pb.rb'
3
+ require 'port.pb.rb'
4
+ require 'logical_port.pb.rb'
5
+ require 'firewall.pb.rb'
6
+
7
+ module Fluent
8
+ class TextParser
9
+ class JuniperJtiParser < Parser
10
+
11
+ Plugin.register_parser("juniper_jti", self)
12
+
13
+ config_param :output_format, :string, :default => 'structured'
14
+
15
+ # This method is called after config_params have read configuration parameters
16
+ def configure(conf)
17
+ super
18
+
19
+ ## Check if "output_format" has a valid value
20
+ unless @output_format.to_s == "structured" ||
21
+ @output_format.to_s == "flat" ||
22
+ @output_format.to_s == "statsd"
23
+
24
+ raise ConfigError, "output_format value '#{@output_format}' is not valid. Must be : structured, flat or statsd"
25
+ end
26
+ end
27
+
28
+ def parse(text)
29
+
30
+ ## Decode GBP packet
31
+ jti_msg = TelemetryStream.decode(text)
32
+
33
+ resource = ""
34
+
35
+ ## Extract device name & Timestamp
36
+ device_name = jti_msg.system_id
37
+ gpb_time = jti_msg.timestamp
38
+
39
+ ## Extract sensor
40
+ begin
41
+ jnpr_sensor = jti_msg.enterprise.juniperNetworks
42
+ datas_sensors = JSON.parse(jnpr_sensor.to_json)
43
+ $log.debug "Extract sensor data from " + device_name
44
+ rescue
45
+ $log.warn "Unable to extract sensor data sensor from jti_msg.enterprise.juniperNetworks, something went wrong"
46
+ $log.debug "Unable to extract sensor data sensor from jti_msg.enterprise.juniperNetworks, Data Dump : " + jti_msg.inspect.to_s
47
+ return
48
+ end
49
+
50
+ ## Go over each Sensor
51
+ datas_sensors.each do |sensor, s_data|
52
+
53
+ ##############################################################
54
+ ### Support for resource /junos/system/linecard/interface/ ##
55
+ ##############################################################
56
+ if sensor == "jnpr_interface_ext"
57
+
58
+ resource = "/junos/system/linecard/interface/"
59
+
60
+ datas_sensors[sensor]['interface_stats'].each do |datas|
61
+
62
+ # Save all info extracted on a list
63
+ sensor_data = []
64
+
65
+ # Catch Exception during parsing
66
+ begin
67
+ ## Extract interface name and clean up
68
+ # interface_name = datas['if_name']
69
+ sensor_data.push({ 'device' => device_name })
70
+ sensor_data.push({ 'interface' => datas['if_name'] })
71
+
72
+ # Check if the interface has a parent
73
+ if datas.key?('parent_ae_name')
74
+ sensor_data.push({ 'interface_parent' => datas['parent_ae_name'] })
75
+ datas.delete("parent_ae_name")
76
+ end
77
+
78
+ ## Clean up Current object
79
+ datas.delete("if_name")
80
+ datas.delete("init_time")
81
+ datas.delete("snmp_if_index")
82
+
83
+ datas.each do |section, data|
84
+
85
+ ## egress_queue_info is an Array
86
+ if data.kind_of?(Array)
87
+ data.each do |queue|
88
+
89
+ ## Create local copy to avoid variable sharing
90
+ local_sensor_data = sensor_data.dup
91
+
92
+ ## Save and Cleanup Queue number
93
+ local_sensor_data.push({ 'egress_queue' => queue['queue_number'] })
94
+ queue.delete("queue_number")
95
+
96
+ queue.each do |type,value|
97
+ local_sensor_data.push({ 'type' => section + '.' + type })
98
+ local_sensor_data.push({ 'value' => value })
99
+
100
+ record = build_record(output_format, local_sensor_data)
101
+ yield gpb_time, record
102
+ end
103
+ end
104
+ else
105
+ data.each do |type,value|
106
+
107
+ ## Create local copy to avoid using some variable
108
+ local_sensor_data = sensor_data.dup
109
+
110
+ local_sensor_data.push({ 'type' => section + '.' + type })
111
+ local_sensor_data.push({ 'value' => value })
112
+
113
+ record = build_record(output_format, local_sensor_data)
114
+ yield gpb_time, record
115
+ end
116
+ end
117
+ end
118
+ rescue
119
+ $log.warn "Unable to parse " + sensor + " sensor, an error occured.."
120
+ $log.debug "Unable to parse " + sensor + " sensor, Data Dump : " + datas.inspect.to_s
121
+ end
122
+ end
123
+ ##############################################################
124
+ ### Support for resource /junos/system/linecard/firewall/ ##
125
+ ##############################################################
126
+ # elsif sensor == "jnpr_firewall_ext"
127
+ #
128
+ # resource = "/junos/system/linecard/firewall"
129
+ #
130
+ # datas_sensors[sensor]['firewall_stats'].each do |datas|
131
+ #
132
+ # begin
133
+ # ## Extract interface name and clean up
134
+ # sensor_data.push({ 'device' => device_name })
135
+ # sensor_data.push({ 'filter_name' => datas['filter_name'] })
136
+ #
137
+ # ## Clean up Current object
138
+ # # datas.delete("filter_name")
139
+ #
140
+ # $log.warn "Sensor Filter : " + datas['filter_name']
141
+ #
142
+ # rescue
143
+ # $log.warn "Unable to parse " + sensor + " sensor, an error occured.."
144
+ # $log.debug "Unable to parse " + sensor + " sensor, Data Dump : " + datas.inspect.to_s
145
+ # end
146
+ # end
147
+
148
+ ##############################################################
149
+ ### Support for resource /junos/system/linecard/interface/logical/usage ##
150
+ ##############################################################
151
+ elsif sensor == "jnprLogicalInterfaceExt"
152
+
153
+ resource = "/junos/system/linecard/interface/logical/usage"
154
+
155
+ datas_sensors[sensor]['interface_info'].each do |datas|
156
+
157
+ # Save all info extracted on a list
158
+ sensor_data = []
159
+
160
+ begin
161
+ ## Extract interface name and clean up
162
+ sensor_data.push({ 'device' => device_name })
163
+ sensor_data.push({ 'interface' => datas['if_name'] })
164
+
165
+ ## Clean up Current object
166
+ datas.delete("if_name")
167
+ datas.delete("init_time")
168
+ datas.delete("snmp_if_index")
169
+ datas.delete("op_state")
170
+
171
+ datas.each do |section, data|
172
+ data.each do |type, value|
173
+
174
+ sensor_data.push({ 'type' => section + '.' + type })
175
+ sensor_data.push({ 'value' => value })
176
+
177
+ record = build_record(output_format, sensor_data)
178
+ yield gpb_time, record
179
+
180
+ end
181
+ end
182
+ rescue
183
+ $log.warn "Unable to parse " + sensor + " sensor, an error occured.."
184
+ $log.debug "Unable to parse " + sensor + " sensor, Data Dump : " + datas.inspect.to_s
185
+ end
186
+ end
187
+ else
188
+ $log.warn "Unsupported sensor : " + sensor
189
+ # puts datas_sensors[sensor].inspect.to_s
190
+ end
191
+ end
192
+ end
193
+
194
+ def clean_up_name(name)
195
+
196
+ tmp = name
197
+ ## Clean up device name and interface name to remove restricted caracter
198
+ tmp.gsub!('/', '_')
199
+ tmp.gsub!(':', '_')
200
+ tmp.gsub!('.', '_')
201
+
202
+ return tmp
203
+ end
204
+
205
+ def build_record(type, data_to_build)
206
+
207
+ if type.to_s == 'flat'
208
+
209
+ # initialize variables
210
+ name = ""
211
+ sensor_value = ""
212
+
213
+ ## Concatene all key/value into a string and stop at "value"
214
+ data_to_build.each do |entry|
215
+ entry.each do |key, value|
216
+
217
+ if key == "value"
218
+ sensor_value = value
219
+ next
220
+ end
221
+
222
+ if name == ""
223
+ name = key + "." + clean_up_name(value).to_s
224
+ else
225
+ name = name + "." + key + "." + clean_up_name(value).to_s
226
+ end
227
+ end
228
+ end
229
+
230
+ record = { name => sensor_value }
231
+ return record
232
+ elsif output_format.to_s == 'structured'
233
+ record = {}
234
+ ## Convert list into Hash
235
+ ## Each entry on the list is a hash with 1 key/value
236
+ data_to_build.each do |entry|
237
+ entry.each do |key, value|
238
+ record[key] = value
239
+ end
240
+ end
241
+
242
+ return record
243
+
244
+ elsif output_format.to_s == 'statsd'
245
+
246
+ record = {}
247
+
248
+ # initialize variables
249
+ name = ""
250
+ sensor_value = ""
251
+
252
+ ## Concatene all key/value into a string, exclude device & stop at "value"
253
+ data_to_build.each do |entry|
254
+ entry.each do |key, value|
255
+
256
+ if key == "value"
257
+ sensor_value = value
258
+ next
259
+ elsif key == "device"
260
+ next
261
+ else
262
+ if name == ""
263
+ name = key + "." + clean_up_name(value).to_s
264
+ else
265
+ name = name + "." + key + "." + clean_up_name(value).to_s
266
+ end
267
+ end
268
+ end
269
+ end
270
+
271
+ record[:statsd_type] = 'gauge'
272
+ record[:statsd_key] = name.downcase
273
+ record[:statsd_gauge] = sensor_value
274
+
275
+ return record
276
+ else
277
+ $log.warn "Output_format '#{type.to_s}' not supported"
278
+ end
279
+ end
280
+ end
281
+ end
282
+ end