HBASE-6025 Expose Hadoop Dynamic Metrics through JSON Rest interface

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1390238 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael Stack 2012-09-26 00:31:28 +00:00
parent bbd17c35ca
commit 9a69eb3fc9
11 changed files with 74 additions and 38 deletions

View File

@ -81,6 +81,7 @@ org.apache.hadoop.hbase.HBaseConfiguration;
<li><a href="/logs/">Local logs</a></li>
<li><a href="/logLevel">Log Level</a></li>
<li><a href="/dump">Debug dump</a></li>
<li><a href="/jmx">Metrics Dump</a></li>
<%if HBaseConfiguration.isShowConfInServlet()%>
<li><a href="/conf">HBase Configuration</a></li>
</%if>

View File

@ -77,6 +77,7 @@ org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionLoad;
<li><a href="/logs/">Local logs</a></li>
<li><a href="/logLevel">Log Level</a></li>
<li><a href="/dump">Debug dump</a></li>
<li><a href="/jmx">Metrics Dump</a></li>
<%if HBaseConfiguration.isShowConfInServlet()%>
<li><a href="/conf">HBase Configuration</a></li>
</%if>

View File

@ -97,6 +97,7 @@
<li><a href="/logs/">Local logs</a></li>
<li><a href="/logLevel">Log Level</a></li>
<li><a href="/dump">Debug dump</a></li>
<li><a href="/jmx">Metrics Dump</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>

View File

@ -63,6 +63,7 @@
<li><a href="/logs/">Local logs</a></li>
<li><a href="/logLevel">Log Level</a></li>
<li><a href="/dump">Debug dump</a></li>
<li><a href="/jmx">Metrics Dump</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>

View File

@ -68,6 +68,7 @@
<li><a href="/logs/">Local logs</a></li>
<li><a href="/logLevel">Log Level</a></li>
<li><a href="/dump">Debug dump</a></li>
<li><a href="/jmx">Metrics Dump</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>

View File

@ -26,14 +26,13 @@ module Hbase
class Admin
include HBaseConstants
def initialize(configuration, formatter)
def initialize(configuration)
@admin = org.apache.hadoop.hbase.client.HBaseAdmin.new(configuration)
connection = @admin.getConnection()
@conf = configuration
@zk_wrapper = connection.getZooKeeperWatcher()
zk = @zk_wrapper.getRecoverableZooKeeper().getZooKeeper()
@zk_main = org.apache.zookeeper.ZooKeeperMain.new(zk)
@formatter = formatter
end
#----------------------------------------------------------------------------------------------

View File

@ -39,8 +39,8 @@ module Hbase
end
end
def admin(formatter)
::Hbase::Admin.new(configuration, formatter)
def admin
::Hbase::Admin.new(configuration)
end
# Create new one each time

View File

@ -129,6 +129,8 @@ EOF
p.add(family, qualifier, value.to_s.to_java_bytes)
end
@table.put(p)
#return number of rows added/updated.
return p.size()
end
#----------------------------------------------------------------------------------------------
@ -146,6 +148,8 @@ EOF
d.deleteColumns(family, qualifier, timestamp)
end
@table.delete(d)
#return number of rows deleted.
return d.size()
end
#----------------------------------------------------------------------------------------------

View File

@ -19,7 +19,9 @@
# Shell commands module
module Shell
require 'shell/formatter'
@@commands = {}
@@formatters={}
def self.commands
@@commands
end
@ -29,7 +31,17 @@ module Shell
@@command_groups
end
def self.load_command(name, group)
def self.getFormatter (type = :RowFormatter)
type ||= :RowFormatter
format = @@formatters[type]
unless format
@@formatters[type] = eval("::Shell::Formatter::#{type}").new
return getFormatter type
end
return format
end
def self.load_command(name, group,formatter)
return if commands[name]
# Register command in the group
@ -40,7 +52,7 @@ module Shell
begin
require "shell/commands/#{name}"
klass_name = name.to_s.gsub(/(?:^|_)(.)/) { $1.upcase } # camelize
commands[name] = eval("Commands::#{klass_name}")
commands[name] = {:command => eval("Commands::#{klass_name}"), :formatter => formatter}
rescue => e
raise "Can't load hbase shell command: #{name}. Error: #{e}\n#{e.backtrace.join("\n")}"
end
@ -56,8 +68,11 @@ module Shell
:comment => opts[:comment]
}
formatterType = opts[:formatterType]
formatter = getFormatter formatterType
opts[:commands].each do |command|
load_command(command, group)
load_command(command, group, formatter)
end
end
@ -69,13 +84,12 @@ module Shell
@debug = false
attr_accessor :debug
def initialize(hbase, formatter)
def initialize(hbase)
self.hbase = hbase
self.formatter = formatter
end
def hbase_admin
@hbase_admin ||= hbase.admin(formatter)
@hbase_admin ||= hbase.admin
end
def hbase_table(name)
@ -107,7 +121,8 @@ module Shell
end
def command_instance(command)
::Shell.commands[command.to_s].new(self)
commandObj = ::Shell.commands[command.to_s]
commandObj[:command].new(self, commandObj[:formatter])
end
#call the method 'command' on the specified command
@ -250,7 +265,8 @@ Shell.load_command_group(
alter_status
alter_async
get_table
]
],
:formatterType => 'AdminFormatter'
)
Shell.load_command_group(
@ -266,7 +282,8 @@ Shell.load_command_group(
put
scan
truncate
]
],
:formatterType => 'RowFormatter'
)
Shell.load_command_group(

View File

@ -20,9 +20,10 @@
module Shell
module Commands
class Command
def initialize(shell)
attr_reader :formatter
def initialize(shell, formatter)
@shell = shell
@formatter = formatter
end
#wrap an execution of cmd to catch hbase exceptions
@ -60,22 +61,18 @@ module Shell
#----------------------------------------------------------------------
def formatter
@shell.formatter
end
def format_simple_command
now = Time.now
yield
formatter.header
formatter.footer(now)
ret = yield
@formatter.header
@formatter.footer(now, ret)
end
def format_and_return_simple_command
now = Time.now
ret = yield
formatter.header
formatter.footer(now)
@formatter.header
@formatter.footer(now, ret)
return ret
end

View File

@ -146,25 +146,39 @@ module Shell
end
end
def footer(start_time = nil, row_count = nil)
def calculateRunTime(start_time = nil)
return unless start_time
row_count ||= @row_count
# Only output elapsed time and row count if startTime passed
@out.puts("%d row(s) in %.4f seconds" % [row_count, Time.now - start_time])
return (Time.now - start_time)
end
end
class Console < Base
#RowFormatter formats the return response with number of rows altered.
#Use this for operations (command groups) for which row count makes sense, eg: delete, add etc.
#Formatter is now defined at command group level.
class RowFormatter < Base
def footer(start_time = nil, row_count = nil)
timeSpent = calculateRunTime(start_time)
unless(row_count.is_a?(Integer))
row_count = nil
end
row_count ||= @row_count
# Only output elapsed time and row count if startTime passed
@out.puts("%d row(s) in %.4f seconds" % [row_count, timeSpent])
end
end
class XHTMLFormatter < Base
# http://www.germane-software.com/software/rexml/doc/classes/REXML/Document.html
# http://www.crummy.com/writing/RubyCookbook/test_results/75942.html
end
class JSON < Base
#AdminFormatter is used for all non row specific operations (command groups) such as version, status etc.
#Formatter is now defined at command group level.
class AdminFormatter < Base
def footer(start_time = nil, msg = "")
timeSpent = calculateRunTime(start_time)
if(msg.is_a?(Integer))
msg = msg, " rows"
end
@out.puts("Succeeded in %.4f seconds.\n%s" % [timeSpent, msg])
end
end
end
end