Page MenuHomeGRNET

No OneTemporary

File Metadata

Created
Fri, Aug 29, 2:11 PM
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..9340eea
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,5 @@
+source 'https://rubygems.org'
+
+# Specify your gem's dependencies in fluent-plugi-grpc-oc-keyvale.gemspec
+gemspec
+
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..d4be693
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,10 @@
+require "bundler/gem_tasks"
+require 'rake/testtask'
+
+Rake::TestTask.new(:test) do |test|
+ test.libs << 'lib' << 'test'
+ test.pattern = 'test/**/test_*.rb'
+ test.verbose = true
+end
+
+task :default => :test
diff --git a/fluent-plugin-udp-native-sensors.gemspec b/fluent-plugin-udp-native-sensors.gemspec
new file mode 100644
index 0000000..5f0c251
--- /dev/null
+++ b/fluent-plugin-udp-native-sensors.gemspec
@@ -0,0 +1,23 @@
+# -*- encoding: utf-8 -*-
+lib = File.expand_path('../lib', __FILE__)
+$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
+
+Gem::Specification.new do |s|
+ s.name = "fluent-plugin-udp-native-sensors"
+ s.version = '0.0.1'
+ s.authors = ["Vijay Kumar gadde"]
+ s.email = ["vijaygadde@gmail.com"]
+
+ s.description = %q{Input plugin for Fluentd for Juniper devices telemetry data streaming native sensor data in UDP}
+ s.summary = %q{Input plugin for Fluentd for Juniper devices telemetry data streaming native sensor data in UDP}
+ s.homepage = ""
+ s.license = 'Apache 2.0'
+
+ s.files = Dir['lib/fluent/plugin/parser*.rb', 'lib/*.rb', 'lib/google/protobuf/*.rb' ]
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
+ s.require_paths = %w(lib)
+
+ s.add_runtime_dependency "fluentd", ">= 0.12.29"
+ s.add_runtime_dependency "protobuf"
+ s.add_development_dependency "rake"
+end
diff --git a/lib/cpu_memory_utilization.pb.rb b/lib/cpu_memory_utilization.pb.rb
new file mode 100644
index 0000000..05b7b1c
--- /dev/null
+++ b/lib/cpu_memory_utilization.pb.rb
@@ -0,0 +1,53 @@
+# encoding: utf-8
+
+##
+# This file is auto-generated. DO NOT EDIT!
+#
+require 'protobuf'
+
+
+##
+# Imports
+#
+require 'telemetry_top.pb'
+
+
+##
+# Message Classes
+#
+class CpuMemoryUtilization < ::Protobuf::Message; end
+class CpuMemoryUtilizationSummary < ::Protobuf::Message; end
+class CpuMemoryUtilizationPerApplication < ::Protobuf::Message; end
+
+
+##
+# Message Fields
+#
+class CpuMemoryUtilization
+ repeated ::CpuMemoryUtilizationSummary, :utilization, 1
+end
+
+class CpuMemoryUtilizationSummary
+ optional :string, :name, 1
+ optional :uint64, :size, 2
+ optional :uint64, :bytes_allocated, 3
+ optional :int32, :utilization, 4
+ repeated ::CpuMemoryUtilizationPerApplication, :application_utilization, 5
+end
+
+class CpuMemoryUtilizationPerApplication
+ optional :string, :name, 1
+ optional :uint64, :bytes_allocated, 2
+ optional :uint64, :allocations, 3
+ optional :uint64, :frees, 4
+ optional :uint64, :allocations_failed, 5
+end
+
+
+##
+# Extended Message Fields
+#
+class ::JuniperNetworksSensors < ::Protobuf::Message
+ optional ::CpuMemoryUtilization, :".cpu_memory_util_ext", 1, :extension => true
+end
+
diff --git a/lib/firewall.pb.rb b/lib/firewall.pb.rb
new file mode 100644
index 0000000..87c9f5e
--- /dev/null
+++ b/lib/firewall.pb.rb
@@ -0,0 +1,83 @@
+# encoding: utf-8
+
+##
+# This file is auto-generated. DO NOT EDIT!
+#
+require 'protobuf'
+
+
+##
+# Imports
+#
+require 'telemetry_top.pb'
+
+
+##
+# Message Classes
+#
+class Firewall < ::Protobuf::Message; end
+class FirewallStats < ::Protobuf::Message; end
+class MemoryUsage < ::Protobuf::Message; end
+class CounterStats < ::Protobuf::Message; end
+class PolicerStats < ::Protobuf::Message; end
+class ExtendedPolicerStats < ::Protobuf::Message; end
+class HierarchicalPolicerStats < ::Protobuf::Message; end
+
+
+##
+# Message Fields
+#
+class Firewall
+ repeated ::FirewallStats, :firewall_stats, 1
+end
+
+class FirewallStats
+ required :string, :filter_name, 1
+ optional :uint64, :timestamp, 2
+ repeated ::MemoryUsage, :memory_usage, 3
+ repeated ::CounterStats, :counter_stats, 4
+ repeated ::PolicerStats, :policer_stats, 5
+ repeated ::HierarchicalPolicerStats, :hierarchical_policer_stats, 6
+end
+
+class MemoryUsage
+ required :string, :name, 1
+ optional :uint64, :allocated, 2
+end
+
+class CounterStats
+ required :string, :name, 1
+ optional :uint64, :packets, 2
+ optional :uint64, :bytes, 3
+end
+
+class PolicerStats
+ required :string, :name, 1
+ optional :uint64, :out_of_spec_packets, 2
+ optional :uint64, :out_of_spec_bytes, 3
+ optional ::ExtendedPolicerStats, :extended_policer_stats, 4
+end
+
+class ExtendedPolicerStats
+ optional :uint64, :offered_packets, 1
+ optional :uint64, :offered_bytes, 2
+ optional :uint64, :transmitted_packets, 3
+ optional :uint64, :transmitted_bytes, 4
+end
+
+class HierarchicalPolicerStats
+ required :string, :name, 1
+ optional :uint64, :premium_packets, 2
+ optional :uint64, :premium_bytes, 3
+ optional :uint64, :aggregate_packets, 4
+ optional :uint64, :aggregate_bytes, 5
+end
+
+
+##
+# Extended Message Fields
+#
+class ::JuniperNetworksSensors < ::Protobuf::Message
+ optional ::Firewall, :".jnpr_firewall_ext", 6, :extension => true
+end
+
diff --git a/lib/fluent/plugin/parser_juniper_udp_native.rb b/lib/fluent/plugin/parser_juniper_udp_native.rb
new file mode 100644
index 0000000..681f740
--- /dev/null
+++ b/lib/fluent/plugin/parser_juniper_udp_native.rb
@@ -0,0 +1,172 @@
+require 'juniper_telemetry_lib.rb'
+require 'protobuf'
+require 'telemetry_top.pb.rb'
+require 'port.pb.rb'
+require 'lsp_stats.pb.rb'
+require 'logical_port.pb.rb'
+require 'firewall.pb.rb'
+require 'cpu_memory_utilization.pb.rb'
+require 'socket'
+require 'json'
+
+module Fluent
+ class TextParser
+ class JuniperJtiParser < Parser
+
+ Plugin.register_parser("juniper_udp_native", self)
+
+ config_param :output_format, :string, :default => 'structured'
+
+ # This method is called after config_params have read configuration parameters
+ def configure(conf)
+ super
+
+ ## Check if "output_format" has a valid value
+ unless @output_format.to_s == "structured" ||
+ @output_format.to_s == "flat" ||
+ @output_format.to_s == "statsd"
+
+ raise ConfigError, "output_format value '#{@output_format}' is not valid. Must be : structured, flat or statsd"
+ end
+ end
+
+ def parse_hash(data, jnpr_sensor, master_key='')
+ leaf_data = Hash.new
+ arr_data = Array.new
+ arr_key = Array.new
+ fin_data = Array.new
+ data.each do |key, value|
+ if master_key == ''
+ new_master_key = key
+ else
+ new_master_key = master_key + '.' + key
+ end
+
+ if not [Hash, Array].include?(value.class)
+ leaf_data[new_master_key] = value
+ elsif value.is_a? Array
+ arr_data << parse_array(value, jnpr_sensor, new_master_key)
+ arr_key << new_master_key
+ elsif value.is_a? Hash
+ arr_data << parse_hash(value, jnpr_sensor, new_master_key)
+ arr_key << new_master_key
+ end
+ end
+ #puts arr_data
+ # Put all the data from Array to hash.
+ # If the key names with list name to avoid overwriting
+ if not leaf_data.empty?
+ arr_key.length.times do |i|
+ for data_aa in arr_data[i]
+ leaf_tmp = leaf_data.clone
+ if not data_aa == nil
+ data_aa.each do |key_aa, value_aa|
+ leaf_tmp[key_aa] = value_aa
+ end
+ end
+ fin_data += [leaf_tmp]
+ end
+ end
+ else
+ #puts arr_data.to_json
+ fin_data = arr_data.clone
+ #puts fin_data.to_json
+ end
+ arr_data.clear
+
+ #if (fin_data.to_a.empty?) && (not leaf_data.empty?) && (leaf_flag)
+ if (fin_data.to_a.empty?) && (not leaf_data.empty?)
+ fin_data += [leaf_data]
+ end
+
+ return fin_data
+ end
+
+ def parse_array(data, jnpr_sensor, master_key)
+
+ arr_data = []
+ for value in data
+ # if value.is_a? Array
+ # arr_data << parse_array(value, jnpr_sensor)
+ if value.is_a? Hash
+ arr_data += parse_hash(value, jnpr_sensor, master_key)
+ else
+ $log.error "Leaf elements in array are not coded. Please open a issue."
+ end
+ end
+
+ return arr_data
+
+ end
+
+ def parse(text)
+
+ host = Socket.gethostname
+
+ ## Decode GBP packet
+ jti_msg = TelemetryStream.decode(text)
+
+ resource = ""
+
+ ## Extract device name & Timestamp
+ device_name = jti_msg.system_id
+ gpb_time = epoc_to_sec(jti_msg.timestamp)
+ measurement_prefix = "enterprise.juniperNetworks"
+
+ ## Extract sensor
+ begin
+ jnpr_sensor = jti_msg.enterprise.juniperNetworks
+ datas_sensors = JSON.parse(jnpr_sensor.to_json)
+ $log.debug "Extract sensor data from #{device_name} with output #{output_format}"
+ rescue => e
+ $log.warn "Unable to extract sensor data sensor from jti_msg.enterprise.juniperNetworks, Error during processing: #{$!}"
+ $log.debug "Unable to extract sensor data sensor from jti_msg.enterprise.juniperNetworks, Data Dump : " + jti_msg.inspect.to_s
+ return
+ end
+
+ $log.debug "=============================================================="
+ $log.debug "TEXT: #{text}"
+ $log.debug "JTI_MSG: #{jti_msg}"
+ $log.debug "JNPR_SENSOR: #{jnpr_sensor}"
+ $log.debug "INSPECT : " + jnpr_sensor.inspect
+ $log.debug datas_sensors
+ #$log.debug jnpr_sensor.jnpr_interface_ext.interface_stats.inspect
+ #for var in jnpr.sensor.inspect
+ # $log.debug " ---: " + var
+ #end
+
+ $log.debug "=============================================================="
+
+ ## Go over each Sensor
+ #datas_sensors = {"firts"=> [{'a'=> 1, 'b': 2}, {:c=>3, d:4}]}
+ #datas_sensors = {"jnpr_interface_ext1"=>{"interface_stats1"=>[{:a=>1, :b=>2}, {:c=>3, :d=>4}]}}
+ final_data = Array.new
+ datas_sensors.each do |sensor, s_data|
+ #$log.debug "#{datas_sensors}"
+ #final_data = Array.new
+ if s_data.is_a? Hash
+ final_data = parse_hash(s_data, jnpr_sensor)[0]
+ end
+ end
+
+
+ for data in final_data
+ data['device'] = device_name
+ data['host'] = host
+ data['sensor_name'] = datas_sensors.keys[0]
+ end
+
+ #puts "++++++++++++++"
+ #puts final_data
+ #puts final_data.to_json
+ #puts "++++++++++++++"
+
+ for data in final_data
+ yield gpb_time, data
+ end
+
+
+ end
+ end
+ end
+end
diff --git a/lib/google/protobuf/descriptor.pb.rb b/lib/google/protobuf/descriptor.pb.rb
new file mode 100644
index 0000000..379e949
--- /dev/null
+++ b/lib/google/protobuf/descriptor.pb.rb
@@ -0,0 +1,290 @@
+# encoding: utf-8
+
+##
+# This file is auto-generated. DO NOT EDIT!
+#
+require 'protobuf'
+
+module Google
+ module Protobuf
+ ::Protobuf::Optionable.inject(self) { ::Google::Protobuf::FileOptions }
+
+ ##
+ # Message Classes
+ #
+ class FileDescriptorSet < ::Protobuf::Message; end
+ class FileDescriptorProto < ::Protobuf::Message; end
+ class DescriptorProto < ::Protobuf::Message
+ class ExtensionRange < ::Protobuf::Message; end
+ class ReservedRange < ::Protobuf::Message; end
+
+ end
+
+ class FieldDescriptorProto < ::Protobuf::Message
+ class Type < ::Protobuf::Enum
+ define :TYPE_DOUBLE, 1
+ define :TYPE_FLOAT, 2
+ define :TYPE_INT64, 3
+ define :TYPE_UINT64, 4
+ define :TYPE_INT32, 5
+ define :TYPE_FIXED64, 6
+ define :TYPE_FIXED32, 7
+ define :TYPE_BOOL, 8
+ define :TYPE_STRING, 9
+ define :TYPE_GROUP, 10
+ define :TYPE_MESSAGE, 11
+ define :TYPE_BYTES, 12
+ define :TYPE_UINT32, 13
+ define :TYPE_ENUM, 14
+ define :TYPE_SFIXED32, 15
+ define :TYPE_SFIXED64, 16
+ define :TYPE_SINT32, 17
+ define :TYPE_SINT64, 18
+ end
+
+ class Label < ::Protobuf::Enum
+ define :LABEL_OPTIONAL, 1
+ define :LABEL_REQUIRED, 2
+ define :LABEL_REPEATED, 3
+ end
+
+ end
+
+ class OneofDescriptorProto < ::Protobuf::Message; end
+ class EnumDescriptorProto < ::Protobuf::Message; end
+ class EnumValueDescriptorProto < ::Protobuf::Message; end
+ class ServiceDescriptorProto < ::Protobuf::Message; end
+ class MethodDescriptorProto < ::Protobuf::Message; end
+ class FileOptions < ::Protobuf::Message
+ class OptimizeMode < ::Protobuf::Enum
+ define :SPEED, 1
+ define :CODE_SIZE, 2
+ define :LITE_RUNTIME, 3
+ end
+
+ end
+
+ class MessageOptions < ::Protobuf::Message; end
+ class FieldOptions < ::Protobuf::Message
+ class CType < ::Protobuf::Enum
+ define :STRING, 0
+ define :CORD, 1
+ define :STRING_PIECE, 2
+ end
+
+ class JSType < ::Protobuf::Enum
+ define :JS_NORMAL, 0
+ define :JS_STRING, 1
+ define :JS_NUMBER, 2
+ end
+
+ end
+
+ class EnumOptions < ::Protobuf::Message; end
+ class EnumValueOptions < ::Protobuf::Message; end
+ class ServiceOptions < ::Protobuf::Message; end
+ class MethodOptions < ::Protobuf::Message; end
+ class UninterpretedOption < ::Protobuf::Message
+ class NamePart < ::Protobuf::Message; end
+
+ end
+
+ class SourceCodeInfo < ::Protobuf::Message
+ class Location < ::Protobuf::Message; end
+
+ end
+
+
+
+ ##
+ # Message Fields
+ #
+ class FileDescriptorSet
+ repeated ::Google::Protobuf::FileDescriptorProto, :file, 1
+ end
+
+ class FileDescriptorProto
+ optional :string, :name, 1
+ optional :string, :package, 2
+ repeated :string, :dependency, 3
+ repeated :int32, :public_dependency, 10
+ repeated :int32, :weak_dependency, 11
+ repeated ::Google::Protobuf::DescriptorProto, :message_type, 4
+ repeated ::Google::Protobuf::EnumDescriptorProto, :enum_type, 5
+ repeated ::Google::Protobuf::ServiceDescriptorProto, :service, 6
+ repeated ::Google::Protobuf::FieldDescriptorProto, :extension, 7
+ optional ::Google::Protobuf::FileOptions, :options, 8
+ optional ::Google::Protobuf::SourceCodeInfo, :source_code_info, 9
+ optional :string, :syntax, 12
+ end
+
+ class DescriptorProto
+ class ExtensionRange
+ optional :int32, :start, 1
+ optional :int32, :end, 2
+ end
+
+ class ReservedRange
+ optional :int32, :start, 1
+ optional :int32, :end, 2
+ end
+
+ optional :string, :name, 1
+ repeated ::Google::Protobuf::FieldDescriptorProto, :field, 2
+ repeated ::Google::Protobuf::FieldDescriptorProto, :extension, 6
+ repeated ::Google::Protobuf::DescriptorProto, :nested_type, 3
+ repeated ::Google::Protobuf::EnumDescriptorProto, :enum_type, 4
+ repeated ::Google::Protobuf::DescriptorProto::ExtensionRange, :extension_range, 5
+ repeated ::Google::Protobuf::OneofDescriptorProto, :oneof_decl, 8
+ optional ::Google::Protobuf::MessageOptions, :options, 7
+ repeated ::Google::Protobuf::DescriptorProto::ReservedRange, :reserved_range, 9
+ repeated :string, :reserved_name, 10
+ end
+
+ class FieldDescriptorProto
+ optional :string, :name, 1
+ optional :int32, :number, 3
+ optional ::Google::Protobuf::FieldDescriptorProto::Label, :label, 4
+ optional ::Google::Protobuf::FieldDescriptorProto::Type, :type, 5
+ optional :string, :type_name, 6
+ optional :string, :extendee, 2
+ optional :string, :default_value, 7
+ optional :int32, :oneof_index, 9
+ optional :string, :json_name, 10
+ optional ::Google::Protobuf::FieldOptions, :options, 8
+ end
+
+ class OneofDescriptorProto
+ optional :string, :name, 1
+ end
+
+ class EnumDescriptorProto
+ optional :string, :name, 1
+ repeated ::Google::Protobuf::EnumValueDescriptorProto, :value, 2
+ optional ::Google::Protobuf::EnumOptions, :options, 3
+ end
+
+ class EnumValueDescriptorProto
+ optional :string, :name, 1
+ optional :int32, :number, 2
+ optional ::Google::Protobuf::EnumValueOptions, :options, 3
+ end
+
+ class ServiceDescriptorProto
+ optional :string, :name, 1
+ repeated ::Google::Protobuf::MethodDescriptorProto, :method, 2
+ optional ::Google::Protobuf::ServiceOptions, :options, 3
+ end
+
+ class MethodDescriptorProto
+ optional :string, :name, 1
+ optional :string, :input_type, 2
+ optional :string, :output_type, 3
+ optional ::Google::Protobuf::MethodOptions, :options, 4
+ optional :bool, :client_streaming, 5, :default => false
+ optional :bool, :server_streaming, 6, :default => false
+ end
+
+ class FileOptions
+ optional :string, :java_package, 1
+ optional :string, :java_outer_classname, 8
+ optional :bool, :java_multiple_files, 10, :default => false
+ optional :bool, :java_generate_equals_and_hash, 20, :default => false
+ optional :bool, :java_string_check_utf8, 27, :default => false
+ optional ::Google::Protobuf::FileOptions::OptimizeMode, :optimize_for, 9, :default => ::Google::Protobuf::FileOptions::OptimizeMode::SPEED
+ optional :string, :go_package, 11
+ optional :bool, :cc_generic_services, 16, :default => false
+ optional :bool, :java_generic_services, 17, :default => false
+ optional :bool, :py_generic_services, 18, :default => false
+ optional :bool, :deprecated, 23, :default => false
+ optional :bool, :cc_enable_arenas, 31, :default => false
+ optional :string, :objc_class_prefix, 36
+ optional :string, :csharp_namespace, 37
+ optional :bool, :javanano_use_deprecated_package, 38
+ repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999
+ # Extension Fields
+ extensions 1000...536870912
+ end
+
+ class MessageOptions
+ optional :bool, :message_set_wire_format, 1, :default => false
+ optional :bool, :no_standard_descriptor_accessor, 2, :default => false
+ optional :bool, :deprecated, 3, :default => false
+ optional :bool, :map_entry, 7
+ repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999
+ # Extension Fields
+ extensions 1000...536870912
+ end
+
+ class FieldOptions
+ optional ::Google::Protobuf::FieldOptions::CType, :ctype, 1, :default => ::Google::Protobuf::FieldOptions::CType::STRING
+ optional :bool, :packed, 2
+ optional ::Google::Protobuf::FieldOptions::JSType, :jstype, 6, :default => ::Google::Protobuf::FieldOptions::JSType::JS_NORMAL
+ optional :bool, :lazy, 5, :default => false
+ optional :bool, :deprecated, 3, :default => false
+ optional :bool, :weak, 10, :default => false
+ repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999
+ # Extension Fields
+ extensions 1000...536870912
+ end
+
+ class EnumOptions
+ optional :bool, :allow_alias, 2
+ optional :bool, :deprecated, 3, :default => false
+ repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999
+ # Extension Fields
+ extensions 1000...536870912
+ end
+
+ class EnumValueOptions
+ optional :bool, :deprecated, 1, :default => false
+ repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999
+ # Extension Fields
+ extensions 1000...536870912
+ end
+
+ class ServiceOptions
+ optional :bool, :deprecated, 33, :default => false
+ repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999
+ # Extension Fields
+ extensions 1000...536870912
+ end
+
+ class MethodOptions
+ optional :bool, :deprecated, 33, :default => false
+ repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999
+ # Extension Fields
+ extensions 1000...536870912
+ end
+
+ class UninterpretedOption
+ class NamePart
+ required :string, :name_part, 1
+ required :bool, :is_extension, 2
+ end
+
+ repeated ::Google::Protobuf::UninterpretedOption::NamePart, :name, 2
+ optional :string, :identifier_value, 3
+ optional :uint64, :positive_int_value, 4
+ optional :int64, :negative_int_value, 5
+ optional :double, :double_value, 6
+ optional :bytes, :string_value, 7
+ optional :string, :aggregate_value, 8
+ end
+
+ class SourceCodeInfo
+ class Location
+ repeated :int32, :path, 1, :packed => true
+ repeated :int32, :span, 2, :packed => true
+ optional :string, :leading_comments, 3
+ optional :string, :trailing_comments, 4
+ repeated :string, :leading_detached_comments, 6
+ end
+
+ repeated ::Google::Protobuf::SourceCodeInfo::Location, :location, 1
+ end
+
+ end
+
+end
+
diff --git a/lib/juniper_telemetry_lib.rb b/lib/juniper_telemetry_lib.rb
new file mode 100644
index 0000000..8ca00f9
--- /dev/null
+++ b/lib/juniper_telemetry_lib.rb
@@ -0,0 +1,21 @@
+
+##############################
+## Supporting functions ##
+##############################
+
+def epoc_to_sec(epoc)
+
+ # Check if sec, usec or msec
+ nbr_digit = epoc.to_s.size
+
+ if nbr_digit == 10
+ return epoc.to_i
+ elsif nbr_digit == 13
+ return (epoc.to_i/1000).to_i
+ elsif nbr_digit == 16
+ return (epoc.to_i/1000000).to_i
+ end
+
+ return epoc
+end
+
diff --git a/lib/logical_port.pb.rb b/lib/logical_port.pb.rb
new file mode 100644
index 0000000..a1a9934
--- /dev/null
+++ b/lib/logical_port.pb.rb
@@ -0,0 +1,74 @@
+# encoding: utf-8
+
+##
+# This file is auto-generated. DO NOT EDIT!
+#
+require 'protobuf'
+
+
+##
+# Imports
+#
+require 'telemetry_top.pb'
+
+
+##
+# Message Classes
+#
+class LogicalPort < ::Protobuf::Message; end
+class LogicalInterfaceInfo < ::Protobuf::Message; end
+class IngressInterfaceStats < ::Protobuf::Message; end
+class EgressInterfaceStats < ::Protobuf::Message; end
+class OperationalState < ::Protobuf::Message; end
+class ForwardingClassAccounting < ::Protobuf::Message; end
+
+
+##
+# Message Fields
+#
+class LogicalPort
+ repeated ::LogicalInterfaceInfo, :interface_info, 1
+end
+
+class LogicalInterfaceInfo
+ required :string, :if_name, 1
+ required :uint64, :init_time, 2
+ optional :uint32, :snmp_if_index, 3
+ optional :string, :parent_ae_name, 4
+ optional ::IngressInterfaceStats, :ingress_stats, 5
+ optional ::EgressInterfaceStats, :egress_stats, 6
+ optional ::OperationalState, :op_state, 7
+end
+
+class IngressInterfaceStats
+ required :uint64, :if_packets, 1
+ required :uint64, :if_octets, 2
+ optional :uint64, :if_ucast_packets, 3
+ required :uint64, :if_mcast_packets, 4
+ repeated ::ForwardingClassAccounting, :if_fc_stats, 5
+end
+
+class EgressInterfaceStats
+ required :uint64, :if_packets, 1
+ required :uint64, :if_octets, 2
+end
+
+class OperationalState
+ optional :string, :operational_status, 1
+end
+
+class ForwardingClassAccounting
+ optional :string, :if_family, 1
+ optional :uint32, :fc_number, 2
+ optional :uint64, :if_packets, 3
+ optional :uint64, :if_octets, 4
+end
+
+
+##
+# Extended Message Fields
+#
+class ::JuniperNetworksSensors < ::Protobuf::Message
+ optional ::LogicalPort, :".jnprLogicalInterfaceExt", 7, :extension => true
+end
+
diff --git a/lib/lsp_mon.pb.rb b/lib/lsp_mon.pb.rb
new file mode 100644
index 0000000..5d4a0e9
--- /dev/null
+++ b/lib/lsp_mon.pb.rb
@@ -0,0 +1,109 @@
+# encoding: utf-8
+
+##
+# This file is auto-generated. DO NOT EDIT!
+#
+require 'protobuf'
+
+
+##
+# Enum Classes
+#
+class Lsp_event < ::Protobuf::Enum
+ define :INITIATED, 0
+ define :CONCLUDED_UP, 1
+ define :CONCLUDED_TORN_DOWN, 2
+ define :PROTECTION_AVAILABLE, 3
+ define :PROTECTION_UNAVAILABLE, 4
+ define :AUTOBW_SUCCESS, 5
+ define :AUTOBW_FAIL, 6
+ define :RESV_TEAR_RECEIVED, 7
+ define :DESELECT_ACTIVE_PATH, 8
+ define :CHANGE_ACTIVE_PATH, 9
+ define :DETOUR_UP, 10
+ define :DETOUR_DOWN, 11
+ define :ORIGINATE_MBB, 12
+ define :SELECT_ACTIVE_PATH, 13
+ define :CSPF_NO_ROUTE, 14
+ define :CSPF_SUCCESS, 15
+ define :RESTART_RECOVERY_FAIL, 16
+ define :PATHERR_RECEIVED, 17
+ define :PATH_MTU_CHANGE, 18
+ define :TUNNEL_LOCAL_REPAIRED, 19
+end
+
+class Event_subcode < ::Protobuf::Enum
+ define :ADMISSION_CONTROL_FAILURE, 1
+ define :SESSION_PREEMPTED, 2
+ define :BAD_LOOSE_ROUTE, 3
+ define :BAD_STRICT_ROUTE, 4
+ define :LABEL_ALLOCATION_FAILURE, 5
+ define :NON_RSVP_CAPABLE_ROUTER, 6
+ define :TTL_EXPIRED, 7
+ define :ROUTING_LOOP_DETECTED, 8
+ define :REQUESTED_BANDWIDTH_UNAVAILABLE, 9
+end
+
+
+##
+# Message Classes
+#
+class Key < ::Protobuf::Message; end
+class Lsp_monitor_data_event < ::Protobuf::Message; end
+class Ero_type_entry < ::Protobuf::Message; end
+class Ero_ipv4_type < ::Protobuf::Message; end
+class Rro_type_entry < ::Protobuf::Message; end
+class Rro_ipv4_type < ::Protobuf::Message; end
+class Lsp_monitor_data_property < ::Protobuf::Message; end
+class Lsp_mon < ::Protobuf::Message; end
+
+
+##
+# Message Fields
+#
+class Key
+ required :string, :name, 1
+ required :int32, :instance_identifier, 2
+ required :uint64, :time_stampg, 3
+end
+
+class Lsp_monitor_data_event
+ required ::Lsp_event, :event_identifier, 1
+ optional ::Event_subcode, :subcode, 2
+end
+
+class Ero_type_entry
+ required :uint32, :ip, 1
+ optional :string, :flags, 2
+end
+
+class Ero_ipv4_type
+ repeated ::Ero_type_entry, :entry, 1
+end
+
+class Rro_type_entry
+ optional :uint32, :nodeid, 1
+ optional :uint32, :flags, 2
+ optional :uint32, :intf_addr, 3
+ optional :uint32, :label, 4
+end
+
+class Rro_ipv4_type
+ repeated ::Rro_type_entry, :rro_entry, 1
+end
+
+class Lsp_monitor_data_property
+ optional :uint64, :bandwidth, 1
+ optional :string, :path_name, 2
+ optional :int32, :metric, 3
+ optional :float, :max_avg_bw, 4
+ optional ::Ero_ipv4_type, :ero, 5
+ optional ::Rro_ipv4_type, :rro, 6
+end
+
+class Lsp_mon
+ required ::Key, :key_field, 1
+ optional ::Lsp_monitor_data_event, :event_field, 2
+ optional ::Lsp_monitor_data_property, :property_field, 3
+end
+
diff --git a/lib/lsp_stats.pb.rb b/lib/lsp_stats.pb.rb
new file mode 100644
index 0000000..74e93ca
--- /dev/null
+++ b/lib/lsp_stats.pb.rb
@@ -0,0 +1,46 @@
+# encoding: utf-8
+
+##
+# This file is auto-generated. DO NOT EDIT!
+#
+require 'protobuf'
+
+
+##
+# Imports
+#
+require 'telemetry_top.pb'
+
+
+##
+# Message Classes
+#
+class LspStats < ::Protobuf::Message; end
+class LspStatsRecord < ::Protobuf::Message; end
+
+
+##
+# Message Fields
+#
+class LspStats
+ repeated ::LspStatsRecord, :lsp_stats_records, 1
+end
+
+class LspStatsRecord
+ required :string, :name, 1
+ required :uint32, :instance_identifier, 2
+ required :string, :counter_name, 3
+ optional :uint64, :packets, 4
+ optional :uint64, :bytes, 5
+ optional :uint64, :packet_rate, 6
+ optional :uint64, :byte_rate, 7
+end
+
+
+##
+# Extended Message Fields
+#
+class ::JuniperNetworksSensors < ::Protobuf::Message
+ optional ::LspStats, :".jnpr_lsp_statistics_ext", 5, :extension => true
+end
+
diff --git a/lib/port.pb.rb b/lib/port.pb.rb
new file mode 100644
index 0000000..0934371
--- /dev/null
+++ b/lib/port.pb.rb
@@ -0,0 +1,89 @@
+# encoding: utf-8
+
+##
+# This file is auto-generated. DO NOT EDIT!
+#
+require 'protobuf'
+
+
+##
+# Imports
+#
+require 'telemetry_top.pb'
+
+
+##
+# Message Classes
+#
+class GPort < ::Protobuf::Message; end
+class InterfaceInfos < ::Protobuf::Message; end
+class InterfaceStats < ::Protobuf::Message; end
+class IngressInterfaceErrors < ::Protobuf::Message; end
+class QueueStats < ::Protobuf::Message; end
+
+
+##
+# Message Fields
+#
+class GPort
+ repeated ::InterfaceInfos, :interface_stats, 1
+end
+
+class InterfaceInfos
+ required :string, :if_name, 1
+ required :uint64, :init_time, 2
+ optional :uint32, :snmp_if_index, 3
+ optional :string, :parent_ae_name, 4
+ repeated ::QueueStats, :egress_queue_info, 5
+ repeated ::QueueStats, :ingress_queue_info, 6
+ optional ::InterfaceStats, :ingress_stats, 7
+ optional ::InterfaceStats, :egress_stats, 8
+ optional ::IngressInterfaceErrors, :ingress_errors, 9
+end
+
+class InterfaceStats
+ required :uint64, :if_pkts, 1
+ required :uint64, :if_octets, 2
+ required :uint64, :if_1sec_pkts, 3
+ required :uint64, :if_1sec_octets, 4
+ required :uint64, :if_uc_pkts, 5
+ required :uint64, :if_mc_pkts, 6
+ required :uint64, :if_bc_pkts, 7
+end
+
+class IngressInterfaceErrors
+ optional :uint64, :if_in_errors, 1
+ optional :uint64, :if_in_qdrops, 2
+ optional :uint64, :if_in_frame_errors, 3
+ optional :uint64, :if_in_discards, 4
+ optional :uint64, :if_in_runts, 5
+ optional :uint64, :if_in_l3_incompletes, 6
+ optional :uint64, :if_in_l2chan_errors, 7
+ optional :uint64, :if_in_l2_mismatch_timeouts, 8
+ optional :uint64, :if_in_fifo_errors, 9
+ optional :uint64, :if_in_resource_errors, 10
+end
+
+class QueueStats
+ optional :uint32, :queue_number, 1
+ optional :uint64, :packets, 2
+ optional :uint64, :bytes, 3
+ optional :uint64, :tail_drop_packets, 4
+ optional :uint64, :rl_drop_packets, 5
+ optional :uint64, :rl_drop_bytes, 6
+ optional :uint64, :red_drop_packets, 7
+ optional :uint64, :red_drop_bytes, 8
+ optional :uint64, :avg_buffer_occupancy, 9
+ optional :uint64, :cur_buffer_occupancy, 10
+ optional :uint64, :peak_buffer_occupancy, 11
+ optional :uint64, :allocated_buffer_size, 12
+end
+
+
+##
+# Extended Message Fields
+#
+class ::JuniperNetworksSensors < ::Protobuf::Message
+ optional ::GPort, :".jnpr_interface_ext", 3, :extension => true
+end
+
diff --git a/lib/telemetry_top.pb.rb b/lib/telemetry_top.pb.rb
new file mode 100644
index 0000000..ad70a73
--- /dev/null
+++ b/lib/telemetry_top.pb.rb
@@ -0,0 +1,59 @@
+# encoding: utf-8
+
+##
+# This file is auto-generated. DO NOT EDIT!
+#
+require 'protobuf'
+
+
+##
+# Imports
+#
+require 'google/protobuf/descriptor.pb'
+
+
+##
+# Message Classes
+#
+class TelemetryFieldOptions < ::Protobuf::Message; end
+class TelemetryStream < ::Protobuf::Message; end
+class IETFSensors < ::Protobuf::Message; end
+class EnterpriseSensors < ::Protobuf::Message; end
+class JuniperNetworksSensors < ::Protobuf::Message; end
+
+
+##
+# Message Fields
+#
+class TelemetryFieldOptions
+ optional :bool, :is_key, 1
+ optional :bool, :is_timestamp, 2
+ optional :bool, :is_counter, 3
+ optional :bool, :is_gauge, 4
+end
+
+class TelemetryStream
+ required :string, :system_id, 1
+ optional :uint32, :component_id, 2
+ optional :uint32, :sub_component_id, 3
+ optional :string, :sensor_name, 4
+ optional :uint32, :sequence_number, 5
+ optional :uint64, :timestamp, 6
+ optional :uint32, :version_major, 7
+ optional :uint32, :version_minor, 8
+ optional ::IETFSensors, :ietf, 100
+ optional ::EnterpriseSensors, :enterprise, 101
+end
+
+
+##
+# Extended Message Fields
+#
+class ::Google::Protobuf::FieldOptions < ::Protobuf::Message
+ optional ::TelemetryFieldOptions, :".telemetry_options", 1024, :extension => true
+end
+
+class ::EnterpriseSensors < ::Protobuf::Message
+ optional ::JuniperNetworksSensors, :".juniperNetworks", 2636, :extension => true
+end
+
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..624e7bc
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,4 @@
+pytest
+pytest-cov
+docker-py
+requests

Event Timeline