Class: Daikon::Client

Inherits:
Object
  • Object
show all
Includes:
NamespaceTools
Defined in:
lib/daikon/client.rb

Constant Summary collapse

EXCEPTIONS =
[Timeout::Error,
Errno::EINVAL,
Errno::ECONNRESET,
EOFError,
Net::HTTPBadResponse,
Net::HTTPHeaderSyntaxError,
Net::ProtocolError,
Net::HTTP::Persistent::Error,
JSON::ParserError]

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from NamespaceTools

#add_namespace, #denamespace_output, #namespace_input, #remove_namespace

Instance Attribute Details

#configObject

Returns the value of attribute config.



15
16
17
# File 'lib/daikon/client.rb', line 15

def config
  @config
end

#httpObject

Returns the value of attribute http.



15
16
17
# File 'lib/daikon/client.rb', line 15

def http
  @http
end

#loggerObject

Returns the value of attribute logger.



15
16
17
# File 'lib/daikon/client.rb', line 15

def logger
  @logger
end

#monitorObject

Returns the value of attribute monitor.



15
16
17
# File 'lib/daikon/client.rb', line 15

def monitor
  @monitor
end

#redisObject

Returns the value of attribute redis.



15
16
17
# File 'lib/daikon/client.rb', line 15

def redis
  @redis
end

Instance Method Details

#connectObject



31
32
33
# File 'lib/daikon/client.rb', line 31

def connect
  Redis.new(:host => config.redis_host, :port => config.redis_port)
end

#evaluate_redis(command) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/daikon/client.rb', line 95

def evaluate_redis(command)
  # Attempt to parse the given command string.
  argv =
    begin
      Shellwords.shellwords(command.to_s)
    rescue Exception => e
      STDERR.puts e.message
      e.backtrace.each {|bt| STDERR.puts bt}
      return e.message
    end
  return "No command received." unless argv[0]

  begin
    execute_redis(argv)
  rescue Exception => e
    STDERR.puts e.message
    e.backtrace.each {|bt| STDERR.puts bt}
    e.message
  end
end

#execute_redis(argv) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/daikon/client.rb', line 120

def execute_redis(argv)
  # Apply the current namespace to any fields that need it.
  argv = namespace_input(namespace, *argv)

  raise "Not a Redis command." unless argv.kind_of? Array

  # Send the command to Redis.
  result = redis.send(*argv)

  # Remove the namespace from any commands that return a key.
  denamespace_output namespace, argv.first, result
end

#fetch_commandsObject



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/daikon/client.rb', line 54

def fetch_commands
  raw_commands = http_request(:get, "api/v1/commands.json")
  commands = JSON.parse(raw_commands.body)

  commands.each do |id, command|
    result = evaluate_redis(command)
    pretty = StringIO.new
    PP.pp(result, pretty)

    http_request(:put, "api/v1/commands/#{id}.json") do |request|
      request.body = {"response" => pretty.string.strip}.to_json
      request.add_field "Content-Length", request.body.size.to_s
      request.add_field "Content-Type",   "application/json"
    end
  end
rescue *EXCEPTIONS => ex
  log ex.to_s
end

#http_request(method, url) {|request| ... } ⇒ Object

Yields:

  • (request)


43
44
45
46
47
48
49
50
51
52
# File 'lib/daikon/client.rb', line 43

def http_request(method, url)
  request_uri    = URI.parse("#{config.server_prefix}/#{url}")
  request_method = Net::HTTP.const_get method.to_s.capitalize
  request        = request_method.new request_uri.path

  yield request if block_given?

  log "#{method.to_s.upcase} #{request_uri}"
  http.request request_uri, request
end

#log(message) ⇒ Object



39
40
41
# File 'lib/daikon/client.rb', line 39

def log(message)
  logger.info message if logger
end

#namespaceObject



116
117
118
# File 'lib/daikon/client.rb', line 116

def namespace
  nil
end

#report_infoObject



73
74
75
76
77
78
79
80
81
# File 'lib/daikon/client.rb', line 73

def report_info
  http_request(:post, "api/v1/info.json") do |request|
    request.body = redis.info.to_json
    request.add_field "Content-Length", request.body.size.to_s
    request.add_field "Content-Type",   "application/json"
  end
rescue *EXCEPTIONS => ex
  log ex.to_s
end

#rotate_monitorObject



83
84
85
86
87
88
89
90
91
92
93
# File 'lib/daikon/client.rb', line 83

def rotate_monitor
  lines = monitor.rotate

  http_request(:post, "api/v1/monitor.json") do |request|
    request.body = {"lines" => lines}.to_json
    request.add_field "Content-Length", request.body.size.to_s
    request.add_field "Content-Type",   "application/json"
  end
rescue *EXCEPTIONS => ex
  log ex.to_s
end

#setup(config, logger = nil) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/daikon/client.rb', line 17

def setup(config, logger = nil)
  self.config  = config
  self.logger  = logger
  self.redis   = connect
  self.monitor = Monitor.new(connect, logger)

  self.http = Net::HTTP::Persistent.new
  self.http.verify_mode = OpenSSL::SSL::VERIFY_PEER
  self.http.use_ssl = true
  self.http.headers['Authorization'] = config.api_key

  log "Started Daikon v#{VERSION}"
end

#start_monitorObject



35
36
37
# File 'lib/daikon/client.rb', line 35

def start_monitor
  monitor.start
end