HBASE-23232 Remove rsgroup profile from pom.xml of hbase-assembly (#779)
[hbase.git] / hbase-shell / src / main / ruby / hbase / taskmonitor.rb
blob8509b5dc6529a2bba6638c57d01f5aeaa7e9ab95
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.
21 include Java
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')
26 end
28 module Hbase
29   class TaskMonitor
30     include HBaseConstants
32     #---------------------------------------------------------------------------------------------
33     # Represents information reported by a server on a single MonitoredTask
34     class Task
35       def initialize(taskMap, host)
36         taskMap.entrySet.each do |entry|
37           k = entry.getKey
38           v = entry.getValue
39           case k
40           when 'statustimems'
41             @statustime = Time.at(v.getAsLong / 1000)
42           when 'status'
43             @status = v.getAsString
44           when 'starttimems'
45             @starttime = Time.at(v.getAsLong / 1000)
46           when 'description'
47             @description = v.getAsString
48           when 'state'
49             @state = v.getAsString
50           end
51         end
53         @host = host
54       end
56       def statustime
57         # waiting IPC handlers often have statustime = -1, in this case return starttime
58         return @statustime if @statustime > Time.at(-1)
59         @starttime
60       end
62       attr_reader :host
63       attr_reader :status
64       attr_reader :starttime
65       attr_reader :description
66       attr_reader :state
67     end
69     def initialize(configuration)
70       @conf = configuration
71       @conn = org.apache.hadoop.hbase.client.ConnectionFactory.createConnection(@conf)
72       @admin = @conn.getAdmin
73     end
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))
87       #  schema = "http://"
88       # else
89       #  schema = "https://"
90       # end
91       schema = 'http://'
92       url = schema + host.hostname + ':' + infoport + '/rs-status?format=json&filter=' + filter
94       json = URL.new(url).openStream
95       parser = JsonParser.new
97       # read and parse JSON
98       begin
99         tasks_array_list = parser.parse(InputStreamReader.new(json, 'UTF-8')).getAsJsonArray
100       ensure
101         json.close
102       end
103       # convert to an array of TaskMonitor::Task instances
104       tasks = []
105       tasks_array_list.each do |t|
106         tasks.unshift Task.new(t.getAsJsonObject, host)
107       end
109       tasks
110     end
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
116       tasks = []
117       hosts.each do |host|
118         tasks.concat(tasksOnHost(filter, host))
119       end
121       puts(format('%d tasks as of: %s', tasks.size, Time.now.strftime('%Y-%m-%d %H:%M:%S')))
123       if tasks.empty?
124         puts('No ' + filter + ' tasks currently running.')
125       else
127         # determine table width
128         longestStatusWidth = 0
129         longestDescriptionWidth = 0
130         tasks.each do |t|
131           longestStatusWidth = [longestStatusWidth, t.status.length].max
132           longestDescriptionWidth = [longestDescriptionWidth, t.description.length].max
133         end
135         # set the maximum character width of each column, without padding
136         hostWidth = 15
137         startTimeWidth = 19
138         stateWidth = 8
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) + '+'
148         # print table header
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)
157         puts(rowSeparator)
158         puts(line)
160         # print table content
161         tasks.each do |t|
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)
170           puts(rowSeparator)
171           puts(line)
172         end
173         puts(rowSeparator)
175       end
176     end
178     #---------------------------------------------------------------------------------------------------
179     #
180     # Helper methods
181     #
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
189       else
190         # cellContent is requested width or too short, so right-pad with zero or more spaces
191         return cellContent + ' ' * numCharsTooShort
192       end
193     end
194   end