vnstat-ruby 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +14 -0
  3. data/.document +5 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +1171 -0
  6. data/.travis.yml +14 -0
  7. data/Gemfile +11 -0
  8. data/Gemfile.lock +84 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +81 -0
  11. data/Rakefile +28 -0
  12. data/VERSION +1 -0
  13. data/lib/vnstat-ruby.rb +1 -0
  14. data/lib/vnstat.rb +65 -0
  15. data/lib/vnstat/configuration.rb +35 -0
  16. data/lib/vnstat/document.rb +56 -0
  17. data/lib/vnstat/error.rb +6 -0
  18. data/lib/vnstat/errors/executable_not_found.rb +7 -0
  19. data/lib/vnstat/errors/unknown_interface.rb +12 -0
  20. data/lib/vnstat/interface.rb +161 -0
  21. data/lib/vnstat/interface_collection.rb +106 -0
  22. data/lib/vnstat/parser.rb +54 -0
  23. data/lib/vnstat/result.rb +55 -0
  24. data/lib/vnstat/result/date_delegation.rb +31 -0
  25. data/lib/vnstat/result/day.rb +45 -0
  26. data/lib/vnstat/result/hour.rb +56 -0
  27. data/lib/vnstat/result/minute.rb +62 -0
  28. data/lib/vnstat/result/month.rb +47 -0
  29. data/lib/vnstat/result/time_comparable.rb +16 -0
  30. data/lib/vnstat/system_call.rb +90 -0
  31. data/lib/vnstat/traffic.rb +11 -0
  32. data/lib/vnstat/traffic/base.rb +46 -0
  33. data/lib/vnstat/traffic/daily.rb +40 -0
  34. data/lib/vnstat/traffic/hourly.rb +44 -0
  35. data/lib/vnstat/traffic/monthly.rb +27 -0
  36. data/lib/vnstat/traffic/tops.rb +39 -0
  37. data/lib/vnstat/utils.rb +68 -0
  38. data/spec/lib/vnstat/configuration_spec.rb +72 -0
  39. data/spec/lib/vnstat/document_spec.rb +54 -0
  40. data/spec/lib/vnstat/errors/executable_not_found_spec.rb +5 -0
  41. data/spec/lib/vnstat/errors/unknown_interface_spec.rb +5 -0
  42. data/spec/lib/vnstat/interface_collection_spec.rb +124 -0
  43. data/spec/lib/vnstat/interface_spec.rb +213 -0
  44. data/spec/lib/vnstat/result/day_spec.rb +39 -0
  45. data/spec/lib/vnstat/result/hour_spec.rb +43 -0
  46. data/spec/lib/vnstat/result/minute_spec.rb +52 -0
  47. data/spec/lib/vnstat/result/month_spec.rb +39 -0
  48. data/spec/lib/vnstat/result_spec.rb +86 -0
  49. data/spec/lib/vnstat/system_call_spec.rb +209 -0
  50. data/spec/lib/vnstat/traffic/daily_spec.rb +109 -0
  51. data/spec/lib/vnstat/traffic/hourly_spec.rb +153 -0
  52. data/spec/lib/vnstat/traffic/monthly_spec.rb +46 -0
  53. data/spec/lib/vnstat/traffic/tops_spec.rb +48 -0
  54. data/spec/lib/vnstat/utils_spec.rb +128 -0
  55. data/spec/lib/vnstat_spec.rb +61 -0
  56. data/spec/spec_helper.rb +98 -0
  57. data/spec/support/shared_examples/shared_examples_for_date_delegation.rb +19 -0
  58. data/spec/support/shared_examples/shared_examples_for_traffic_collection.rb +19 -0
  59. data/vnstat-ruby.gemspec +113 -0
  60. metadata +187 -0
@@ -0,0 +1,161 @@
1
+ module Vnstat
2
+ ##
3
+ # A class encapsulating traffic information for a specific network interface.
4
+ #
5
+ # @attr_reader [String] id The network interface identifier.
6
+ class Interface < Document
7
+ attr_reader :id
8
+
9
+ ##
10
+ # Initializes the {Interface}.
11
+ #
12
+ # @param [String] id The network interface identifier.
13
+ # @param [String] data The raw XML data.
14
+ def initialize(id, data)
15
+ super(data)
16
+ @id = id
17
+ end
18
+
19
+ ##
20
+ # Retrieves the raw XML data for the given interface identifier.
21
+ #
22
+ # @param [String] id The network interface identifier.
23
+ # @return [String]
24
+ def self.load_data(id)
25
+ Utils.call_executable('-i', id, '--xml')
26
+ end
27
+
28
+ ##
29
+ # Determines whether the interface is the same as another.
30
+ #
31
+ # @param [Interface] other The compared object.
32
+ # @return [true, false]
33
+ def ==(other)
34
+ return false unless other.respond_to?(:id)
35
+ id == other.id
36
+ end
37
+
38
+ ##
39
+ # Refreshes data cached in the current instance.
40
+ #
41
+ # @return [Interface]
42
+ def reload
43
+ self.data = self.class.load_data(id)
44
+ @nick = nil
45
+ self
46
+ end
47
+
48
+ ##
49
+ # Deletes the traffic database for the interface.
50
+ #
51
+ # @return [true, false]
52
+ def delete
53
+ Utils.call_executable_returning_status('--delete', '-i', id)
54
+ end
55
+
56
+ ##
57
+ # Reset the internal counters in the database for the selected interface.
58
+ # Use this if the interface goes down and back up, otherwise that interface
59
+ # will get some extra traffic to its database. Not needed when the daemon is
60
+ # used.
61
+ #
62
+ # @return [Interface]
63
+ def reset
64
+ Utils.call_executable_returning_status('--reset', '-i', id)
65
+ reload
66
+ end
67
+
68
+ ##
69
+ # Returns the alias name for the interface.
70
+ #
71
+ # @return [String]
72
+ def nick
73
+ @nick ||= interface_data.xpath('nick').text
74
+ end
75
+
76
+ #
77
+ # Sets the alias name for the interface.
78
+ #
79
+ # @param [String] nick The alias name for the interface.
80
+ def nick=(nick)
81
+ Utils.call_executable_returning_status(
82
+ '-i', id, '--nick', nick, '--update'
83
+ )
84
+ @nick = nick
85
+ end
86
+
87
+ alias_method :name, :nick
88
+ alias_method :name=, :nick=
89
+
90
+ ##
91
+ # The date on which tracking of the interface began.
92
+ # @return [Date]
93
+ #
94
+ def created_on
95
+ Parser.extract_date_from_xml_element(interface_data.xpath('created'))
96
+ end
97
+
98
+ ##
99
+ # The date and time on which the tracking information for the interface
100
+ # were updated.
101
+ #
102
+ # @return [DateTime]
103
+ def updated_at
104
+ Parser.extract_datetime_from_xml_element(interface_data.xpath('updated'))
105
+ end
106
+
107
+ ##
108
+ # Returns information about the total traffic.
109
+ #
110
+ # @return [Result]
111
+ def total
112
+ Result.extract_from_xml_element(interface_data.xpath('traffic/total'))
113
+ end
114
+
115
+ ##
116
+ # Returns information about the hourly traffic.
117
+ #
118
+ # @return [Traffic::Hourly]
119
+ def hours
120
+ @hours ||= Traffic::Hourly.new(self)
121
+ end
122
+
123
+ ##
124
+ # Returns information about the daily traffic.
125
+ #
126
+ # @return [Traffic::Daily]
127
+ def days
128
+ @days ||= Traffic::Daily.new(self)
129
+ end
130
+
131
+ ##
132
+ # Returns information about the monthly traffic.
133
+ #
134
+ # @return [Traffic::Monthly]
135
+ def months
136
+ @months ||= Traffic::Monthly.new(self)
137
+ end
138
+
139
+ ##
140
+ # Returns information about the traffic tops.
141
+ #
142
+ # @return [Traffic::Tops]
143
+ def tops
144
+ @tops ||= Traffic::Tops.new(self)
145
+ end
146
+
147
+ ##
148
+ # A human readable representation of the {Interface}.
149
+ #
150
+ # @return [String]
151
+ def inspect
152
+ "#<#{self.class.name} id: #{id.inspect}>"
153
+ end
154
+
155
+ private
156
+
157
+ def interface_data
158
+ data.xpath("//interface[@id='#{id}']")
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,106 @@
1
+ module Vnstat
2
+ ##
3
+ # A class encapsulating traffic information for all known network interfaces.
4
+ class InterfaceCollection < Document
5
+ include Enumerable
6
+
7
+ ##
8
+ # Retrieves the raw XML data for all interfaces.
9
+ #
10
+ # @return [String]
11
+ def self.load_data
12
+ Utils.call_executable('--xml')
13
+ end
14
+
15
+ ##
16
+ # Sets the raw XML data for the {InterfaceCollection}.
17
+ #
18
+ # @param [String] data A string representing the document.
19
+ def data=(data)
20
+ super
21
+ each { |interface| interface.data = data }
22
+ end
23
+
24
+ ##
25
+ # Refreshes data cached in the current instance.
26
+ #
27
+ # @return [InterfaceCollection]
28
+ def reload
29
+ self.data = self.class.load_data
30
+ self
31
+ end
32
+
33
+ ##
34
+ # Returns the names of known interfaces.
35
+ #
36
+ # @return [Array<String>]
37
+ def ids
38
+ interfaces_hash.keys
39
+ end
40
+
41
+ ##
42
+ # Returns traffic information for a certain interface.
43
+ #
44
+ # @param [String] id The name of the interface.
45
+ # @raise [UnknownInterface] An error that is raised if the
46
+ # specified interface is not tracked.
47
+ # @return [Interface]
48
+ def [](id)
49
+ interfaces_hash.fetch(id.to_s) do
50
+ fail UnknownInterface.new(id.to_s),
51
+ "Unknown interface: #{id}"
52
+ end
53
+ end
54
+
55
+ ##
56
+ # Iterates over each interface.
57
+ #
58
+ # @yieldparam [Interface] interface
59
+ def each(&block)
60
+ interfaces_hash.each_value(&block)
61
+ end
62
+
63
+ ##
64
+ # Creates the traffic database for the given interface.
65
+ #
66
+ # @param [String] id The network interface identifier
67
+ # @return [Interface, nil] The interface that has justed been added to
68
+ # tracking.
69
+ def create(id)
70
+ success = Utils.call_executable_returning_status('--create', '-i', id)
71
+ return nil unless success
72
+ reload
73
+ self[id]
74
+ end
75
+
76
+ ##
77
+ # Reset the total traffic counters and recount those using recorded months.
78
+ #
79
+ # @return [InterfaceCollection]
80
+ def rebuild
81
+ success = Utils.call_executable_returning_status('--rebuildtotal')
82
+ reload if success
83
+ self
84
+ end
85
+
86
+ ##
87
+ # A human readable representation of the {InterfaceCollection}.
88
+ #
89
+ # @return [String]
90
+ def inspect
91
+ "#<#{self.class.name} ids: #{ids.inspect}>"
92
+ end
93
+
94
+ private
95
+
96
+ def interfaces_hash
97
+ @interfaces_hash ||= begin
98
+ elements = data.xpath('//interface')
99
+ elements.each_with_object({}) do |node, hash|
100
+ id = node[:id]
101
+ hash[id] = Interface.new(id, data)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,54 @@
1
+ module Vnstat
2
+ ##
3
+ # A module containing several utility methods responsible for document
4
+ # parsing.
5
+ module Parser
6
+ module_function
7
+
8
+ ##
9
+ # Extracts the year and month from the given XML element.
10
+ #
11
+ # @param [Nokogiri::XML::Element] element The XML element.
12
+ # @return [Array<Integer, Integer>] An Array consisting of year and month.
13
+ def extract_month_from_xml_element(element)
14
+ month = element.xpath('date/month').text.to_i
15
+ year = element.xpath('date/year').text.to_i
16
+ [year, month]
17
+ end
18
+
19
+ ##
20
+ # Extracts the date from the given XML element.
21
+ #
22
+ # @param [Nokogiri::XML::Element] element The XML element.
23
+ # @return [Date]
24
+ def extract_date_from_xml_element(element)
25
+ day = element.xpath('date/day').text.to_i
26
+ year, month = extract_month_from_xml_element(element)
27
+ Date.new(year, month, day)
28
+ end
29
+
30
+ ##
31
+ # Extracts the date and time from the given XML element.
32
+ #
33
+ # @param [Nokogiri::XML::Element] element The XML element.
34
+ # @return [DateTime]
35
+ def extract_datetime_from_xml_element(element)
36
+ date = extract_date_from_xml_element(element)
37
+ hour = element.xpath('time/hour').text.to_i
38
+ minute = element.xpath('time/minute').text.to_i
39
+ DateTime.new(date.year, date.month, date.day, hour, minute)
40
+ end
41
+
42
+ ##
43
+ # Extracts the bytes received and sent from the given XML element.
44
+ #
45
+ # @param [Nokogiri::XML::Element] element The XML element.
46
+ # @return [Array<Integer, Integer>] An Array consisting of bytes received
47
+ # and bytes sent.
48
+ def extract_transmitted_bytes_from_xml_element(element)
49
+ bytes_received = element.xpath('rx').text.to_i * 1024
50
+ bytes_sent = element.xpath('tx').text.to_i * 1024
51
+ [bytes_received, bytes_sent]
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,55 @@
1
+ module Vnstat
2
+ ##
3
+ # A class representing a tracking result.
4
+ #
5
+ # @attr_reader [Integer] bytes_received The received bytes.
6
+ # @attr_reader [Integer] bytes_sent The sent bytes.
7
+ class Result
8
+ autoload :Minute, 'vnstat/result/minute'
9
+ autoload :Day, 'vnstat/result/day'
10
+ autoload :Hour, 'vnstat/result/hour'
11
+ autoload :Month, 'vnstat/result/month'
12
+
13
+ autoload :DateDelegation, 'vnstat/result/date_delegation'
14
+ autoload :TimeComparable, 'vnstat/result/time_comparable'
15
+
16
+ include Comparable
17
+
18
+ attr_reader :bytes_received, :bytes_sent
19
+
20
+ ##
21
+ # Initializes the {Result}.
22
+ #
23
+ # @param [Integer] bytes_received The received bytes.
24
+ # @param [Integer] bytes_sent The sent bytes.
25
+ def initialize(bytes_received, bytes_sent)
26
+ @bytes_received = bytes_received
27
+ @bytes_sent = bytes_sent
28
+ end
29
+
30
+ ##
31
+ # Initializes a {Result} using the the data contained in the given XML
32
+ # element.
33
+ #
34
+ # @param [Nokogiri::XML::Element] element The XML element.
35
+ # @return [Result]
36
+ def self.extract_from_xml_element(element)
37
+ new(*Parser.extract_transmitted_bytes_from_xml_element(element))
38
+ end
39
+
40
+ ##
41
+ # The transmitted bytes (both sent and received).
42
+ #
43
+ # @return [Integer]
44
+ def bytes_transmitted
45
+ bytes_received + bytes_sent
46
+ end
47
+
48
+ ##
49
+ # @return [Integer, nil]
50
+ def <=>(other)
51
+ return nil unless other.respond_to?(:bytes_transmitted)
52
+ bytes_transmitted <=> other.bytes_transmitted
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,31 @@
1
+ module Vnstat
2
+ class Result
3
+ ##
4
+ # A module that is included by result types that contain date information.
5
+ module DateDelegation
6
+ ##
7
+ # The year the result was captured in.
8
+ #
9
+ # @return [Integer]
10
+ def year
11
+ date.year
12
+ end
13
+
14
+ ##
15
+ # The month the result was captured in.
16
+ #
17
+ # @return [Integer]
18
+ def month
19
+ date.month
20
+ end
21
+
22
+ ##
23
+ # The day the result was captured on.
24
+ #
25
+ # @return [Integer]
26
+ def day
27
+ date.day
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,45 @@
1
+ module Vnstat
2
+ class Result
3
+ ##
4
+ # A class representing a tracking result for a specific day.
5
+ #
6
+ # @attr_reader [Date] date The date the result was captured on.
7
+ class Day < Result
8
+ include DateDelegation
9
+
10
+ attr_reader :date
11
+
12
+ ##
13
+ # Initializes the {Day}.
14
+ #
15
+ # @param [Date] date The date the result was captured on.
16
+ # @param [Integer] bytes_received The received bytes.
17
+ # @param [Integer] bytes_sent The sent bytes.
18
+ def initialize(date, bytes_received, bytes_sent)
19
+ @date = date
20
+ super(bytes_received, bytes_sent)
21
+ end
22
+
23
+ ##
24
+ # Initializes a {Day} using the the data contained in the given XML
25
+ # element.
26
+ #
27
+ # @param [Nokogiri::XML::Element] element The XML element.
28
+ # @return [Day]
29
+ def self.extract_from_xml_element(element)
30
+ new(
31
+ Parser.extract_date_from_xml_element(element),
32
+ *Parser.extract_transmitted_bytes_from_xml_element(element)
33
+ )
34
+ end
35
+
36
+ ##
37
+ # @return [Integer, nil]
38
+ def <=>(other)
39
+ return nil unless other.respond_to?(:bytes_transmitted)
40
+ return nil unless other.respond_to?(:date)
41
+ [date, bytes_transmitted] <=> [other.date, other.bytes_transmitted]
42
+ end
43
+ end
44
+ end
45
+ end