arvicco-avalon 0.0.21 → 0.0.22

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -39,8 +39,10 @@ Monitor script is periodically polling the mining units and other types of objec
39
39
  ------- ~/.avalon/monitor.yml --------
40
40
  # Prod configuration (default)
41
41
  prod:
42
- :alert_after: 2 # missed pings or status reports from a miner
43
- :alert_temp: 52 # degrees C and above
42
+ :alert_after: 2 # missed pings or status reports from a miner
43
+ :alert_temp_high: 52 # degrees C and above
44
+ :alert_temp_low: 30 # degrees C and below
45
+ :alert_last_share: 2 # minutes since last share hashed
44
46
  :alert_sounds:
45
47
  :failure: Glass.aiff # [] for no sound
46
48
  :restart: Frog.aiff # [] for no sound
data/lib/avalon/config.rb CHANGED
@@ -4,9 +4,12 @@ module Avalon
4
4
  extend Utils # Helper methods
5
5
 
6
6
  DEFAULT_SOUNDS = {
7
- failure: 'Glass.aiff',
8
7
  restart: 'Frog.aiff',
8
+ failure: 'Glass.aiff',
9
+ perf_low: 'Glass.aiff',
10
+ last_share: 'Glass.aiff',
9
11
  temp_high: 'Ping.aiff',
12
+ temp_low: 'Ping.aiff',
10
13
  block_found: ['Dog.aiff', 'Purr.aiff', 'Dog.aiff'],
11
14
  block_updated: ['Purr.aiff', 'Purr.aiff', 'Purr.aiff']
12
15
  }
@@ -21,7 +24,16 @@ module Avalon
21
24
  @config[:block_file] = find_file( '../../../config/blocks.yml', '~/.avalon/blocks.yml') ||
22
25
  File.expand_path('~/.avalon/blocks.yml')
23
26
 
27
+ # Setting defaults
24
28
  @config[:alert_sounds] = DEFAULT_SOUNDS.merge(@config[:alert_sounds] || {})
29
+ @config[:alert_last_share] ||= 2
30
+ @config[:alert_after] ||= @config[:status_fails_to_alarm] || 2
31
+ @config[:alert_temp_high] ||= @config[:alert_temp] || 55
32
+ @config[:alert_temp_low] ||= 30
33
+ end
34
+
35
+ def self.config
36
+ @config
25
37
  end
26
38
 
27
39
  def self.[] key
data/lib/avalon/miner.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Avalon
2
4
  # "STATUS=S,When=1368715953,Code=11,Msg=Summary,Description=cgminer 2.10.5|
3
5
  # SUMMARY,Elapsed=58219,MHS av=70827.84,Found Blocks=0,Getworks=1899,Accepted=14755,
@@ -18,24 +20,24 @@ module Avalon
18
20
  :uptime => [9, /(?<=Elapsed=)[\d\.]*/, ->(x){ my_time(x, :relative_time)}],
19
21
  :last => [8, /(?<=Status=Alive,).*?Last Share Time=[\d\.]*/,
20
22
  ->(x){ convert_last(x)}],
21
- :temp => [4, /(?<=Temperature=)[\d\.]*/, :i],
23
+ :miner => [5, /(?<=Description=cgminer )[\d\.]*/, :s],
22
24
  :freq => [4, /(?<=frequency=)[\d\.]*/, :i],
25
+ :'°C' => [2, /(?<=Temperature=)[\d\.]*/, :i],
23
26
  :fan2 => [4, /(?<=fan2=)[\d\.]*/, :i],
24
27
  :fan3 => [4, /(?<=fan3=)[\d\.]*/, :i],
25
- :utility => [8, /(?<=,Work Utility=)[\d\.]*/, :f],
28
+ :wu => [4, /(?<=,Work Utility=)[\d\.]*/, :i],
26
29
  :getworks => [8, /(?<=Getworks=)[\d\.]*/, :i],
27
30
  :accepted => [8, /(?<=,Accepted=)[\d\.]*/, :i],
28
31
  :rejected => [8, /(?<=Rejected=)[\d\.]*/, :i],
29
32
  :stale => [6, /(?<=Stale=)[\d\.]*/, :i],
30
33
  :errors => [6, /(?<=Hardware Errors=)[\d\.]*/, :i],
31
34
  :blocks => [6, /(?<=Network Blocks=)[\d\.]*/, :i],
32
- # :found => [2, /(?<=Found Blocks=)[\d\.]*/, :i],
35
+ # :found => [2, /(?<=Found Blocks=)[\d\.]*/, :i],
33
36
  }
34
37
 
35
38
  # Last share converter (Miner-specific)
36
39
  def self.convert_last x
37
40
  y = x[/(?<=Last Share Time=)[\d\.]*/]
38
- # p x, y
39
41
  if y.nil? || y == '0'
40
42
  "never"
41
43
  else
@@ -48,13 +50,11 @@ module Avalon
48
50
  FIELDS.map {|name, (width,_,_ )| name.to_s.ljust(width)}.join(' ')
49
51
  end
50
52
 
51
- def initialize ip, min_speed
53
+ def initialize ip, min_speed, config=Avalon::Config.config
52
54
  @ip = ip
53
55
  @min_speed = min_speed * 1000 # Gh/s to Mh/s
56
+ @config = config
54
57
  @fails = 0
55
- @alert_after = Avalon::Config[:alert_after] ||
56
- Avalon::Config[:status_fails_to_alarm] || 2
57
- @alert_temp = Avalon::Config[:alert_temp] || 55
58
58
  super()
59
59
  end
60
60
 
@@ -66,6 +66,7 @@ module Avalon
66
66
  self[:ping] = ping @ip
67
67
 
68
68
  status = get_api('summary') + get_api('pools') + get_api('devs') + get_api('stats')
69
+ # p get_api('summary')
69
70
  # pools = get_api('pools')
70
71
  # p pools[FIELDS[:last][1]]
71
72
  # devs = get_api('devs')
@@ -83,25 +84,34 @@ module Avalon
83
84
  end
84
85
 
85
86
  def upminutes
86
- hour, min, _ = *self[:uptime].split(/:/).map(&:to_i)
87
- hour*60 + min
87
+ duration(self[:uptime])
88
+ end
89
+
90
+ def temp
91
+ self[:'°C']
88
92
  end
89
93
 
90
94
  # Check for any exceptional situations in stats, sound alarm if any
91
95
  def report
92
96
  if data[:ping].nil?
93
97
  @fails += 1
94
- if @fails >= @alert_after
95
- alarm "Miner #{num} did not respond to status query"
98
+ if @fails >= @config[:alert_after]
99
+ alarm "Miner #{num} did not respond to status query", :failure
96
100
  end
97
101
  else
98
102
  @fails = 0
99
- if self[:mhs] < @min_speed and upminutes > 5
100
- alarm "Miner #{num} performance is #{self[:mhs]}, should be #{@min_speed}"
101
- elsif self[:temp] >= @alert_temp
102
- alarm "Miner #{num} too hot at #{self[:temp]}C, needs cooling", :temp_high
103
- elsif upminutes < 2
103
+ if duration(self[:uptime]) < 2
104
104
  alarm "Miner #{num} restarted", :restart
105
+ elsif duration(self[:uptime]) > 5 # Miner settled down
106
+ if self[:mhs] < @min_speed
107
+ alarm "Miner #{num} performance is #{self[:mhs]}, should be #{@min_speed}", :perf_low
108
+ elsif self[:last] == 'never' || duration(self[:last]) > @config[:alert_last_share]
109
+ alarm "Miner #{num} last shares was #{duration(self[:last])} min ago", :last_share
110
+ elsif temp >= @config[:alert_temp_high]
111
+ alarm "Miner #{num} too hot at #{temp}°C, needs cooling", :temp_high
112
+ elsif temp <= @config[:alert_temp_low]
113
+ alarm "Miner #{num} temp low at #{temp}°C, is it hashing at all?", :temp_low
114
+ end
105
115
  end
106
116
  end
107
117
  end
data/lib/avalon/utils.rb CHANGED
@@ -32,6 +32,16 @@ module Avalon
32
32
  play sound
33
33
  end
34
34
 
35
+ # Helper method: from time string 'hh:mm:ss' to duration in minutes
36
+ def duration time_string
37
+ if time_string == 'never'
38
+ 'never'
39
+ else
40
+ hour, min, sec = *time_string.split(/:/).map(&:to_i)
41
+ hour*60.0 + min + sec/60.0
42
+ end
43
+ end
44
+
35
45
  # Helper method: ping the Node, return ping time in ms
36
46
  def ping ip
37
47
  ping_result = `ping -c 1 #{ip}`
@@ -1,3 +1,3 @@
1
1
  module Avalon
2
- VERSION = "0.0.21"
2
+ VERSION = "0.0.22"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arvicco-avalon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.21
4
+ version: 0.0.22
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-25 00:00:00.000000000 Z
12
+ date: 2013-06-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faraday