2 # Copyright 2010 The Apache Software Foundation
4 # Licensed to the Apache Software Foundation (ASF) under one
5 # or more contributor license agreements. See the NOTICE file
6 # distributed with this work for additional information
7 # regarding copyright ownership. The ASF licenses this file
8 # to you under the Apache License, Version 2.0 (the
9 # "License"); you may not use this file except in compliance
10 # with the License. You may obtain a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS,
16 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 # See the License for the specific language governing permissions and
18 # limitations under the License.
23 # Add the $HBASE_HOME/lib directory to the ruby load_path to load jackson
24 if File.exist?(File.join(File.dirname(__FILE__), '..', 'lib'))
25 $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
30 include HBaseConstants
32 #---------------------------------------------------------------------------------------------
33 # Represents information reported by a server on a single MonitoredTask
35 def initialize(taskMap, host)
36 taskMap.entrySet.each do |entry|
41 @statustime = Time.at(v.getAsLong / 1000)
43 @status = v.getAsString
45 @starttime = Time.at(v.getAsLong / 1000)
47 @description = v.getAsString
49 @state = v.getAsString
57 # waiting IPC handlers often have statustime = -1, in this case return starttime
58 return @statustime if @statustime > Time.at(-1)
64 attr_reader :starttime
65 attr_reader :description
69 def initialize(configuration)
71 @conn = org.apache.hadoop.hbase.client.ConnectionFactory.createConnection(@conf)
72 @admin = @conn.getAdmin
75 #---------------------------------------------------------------------------------------------------
76 # Returns a filtered list of tasks on the given host
77 def tasksOnHost(filter, host)
78 java_import 'java.net.URL'
79 java_import 'java.io.InputStreamReader'
80 java_import 'org.apache.hbase.thirdparty.com.google.gson.JsonParser'
82 infoport = @admin.getClusterMetrics.getLiveServerMetrics.get(host).getInfoServerPort.to_s
84 # Note: This condition use constants from hbase-server
85 # if (!@admin.getConfiguration().getBoolean(org.apache.hadoop.hbase.http.ServerConfigurationKeys::HBASE_SSL_ENABLED_KEY,
86 # org.apache.hadoop.hbase.http.ServerConfigurationKeys::HBASE_SSL_ENABLED_DEFAULT))
92 url = schema + host.hostname + ':' + infoport + '/rs-status?format=json&filter=' + filter
94 json = URL.new(url).openStream
95 parser = JsonParser.new
99 tasks_array_list = parser.parse(InputStreamReader.new(json, 'UTF-8')).getAsJsonArray
103 # convert to an array of TaskMonitor::Task instances
105 tasks_array_list.each do |t|
106 tasks.unshift Task.new(t.getAsJsonObject, host)
112 #---------------------------------------------------------------------------------------------------
113 # Prints a table of filtered tasks on requested hosts
114 def tasks(filter, hosts)
115 # put all tasks on all requested hosts in the same list
118 tasks.concat(tasksOnHost(filter, host))
121 puts(format('%d tasks as of: %s', tasks.size, Time.now.strftime('%Y-%m-%d %H:%M:%S')))
124 puts('No ' + filter + ' tasks currently running.')
127 # determine table width
128 longestStatusWidth = 0
129 longestDescriptionWidth = 0
131 longestStatusWidth = [longestStatusWidth, t.status.length].max
132 longestDescriptionWidth = [longestDescriptionWidth, t.description.length].max
135 # set the maximum character width of each column, without padding
139 descriptionWidth = [32, longestDescriptionWidth].min
140 statusWidth = [36, longestStatusWidth + 27].min
142 rowSeparator = '+' + '-' * (hostWidth + 2) +
143 '+' + '-' * (startTimeWidth + 2) +
144 '+' + '-' * (stateWidth + 2) +
145 '+' + '-' * (descriptionWidth + 2) +
146 '+' + '-' * (statusWidth + 2) + '+'
149 cells = [setCellWidth('Host', hostWidth),
150 setCellWidth('Start Time', startTimeWidth),
151 setCellWidth('State', stateWidth),
152 setCellWidth('Description', descriptionWidth),
153 setCellWidth('Status', statusWidth)]
155 line = format('| %s | %s | %s | %s | %s |', *cells)
160 # print table content
162 cells = [setCellWidth(t.host.hostname, hostWidth),
163 setCellWidth(t.starttime.strftime('%Y-%m-%d %H:%M:%S'), startTimeWidth),
164 setCellWidth(t.state, stateWidth),
165 setCellWidth(t.description, descriptionWidth),
166 setCellWidth(format('%s (since %d seconds ago)', t.status, Time.now - t.statustime), statusWidth)]
168 line = format('| %s | %s | %s | %s | %s |', *cells)
178 #---------------------------------------------------------------------------------------------------
183 # right-pad with spaces or truncate with ellipses to match passed width
184 def setCellWidth(cellContent, width)
185 numCharsTooShort = width - cellContent.length
186 if numCharsTooShort < 0
187 # cellContent is too long, so truncate
188 return cellContent[0, [width - 3, 0].max] + '.' * [3, width].min
190 # cellContent is requested width or too short, so right-pad with zero or more spaces
191 return cellContent + ' ' * numCharsTooShort