Skip to content

Commit 1653945

Browse files
committed
TEZ-4347: Add some diagnostic endpoints to TezAM's WebUIService
1 parent f39a51e commit 1653945

16 files changed

Lines changed: 410 additions & 2 deletions

File tree

tez-api/src/main/java/org/apache/tez/dag/api/TezConfiguration.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1936,6 +1936,18 @@ public TezConfiguration(boolean loadDefaults) {
19361936
+ "tez-ui.webservice.enable";
19371937
public static final boolean TEZ_AM_WEBSERVICE_ENABLE_DEFAULT = true;
19381938

1939+
/**
1940+
* String value. Range of ports that the AM can use for the WebUIService. Leave blank
1941+
* to use all possible ports. Expert level setting. It's hadoop standard range configuration.
1942+
* For example 50000-50050,50100-50200
1943+
*/
1944+
@ConfigurationScope(Scope.AM)
1945+
@ConfigurationProperty(type="boolean")
1946+
public static final String TEZ_AM_WEBSERVICE_PORT_RANGE = TEZ_AM_PREFIX
1947+
+ "tez-ui.webservice.port-range";
1948+
1949+
public static final String TEZ_AM_WEBSERVICE_PORT_RANGE_DEFAULT = "50000-50050";
1950+
19391951
// TODO only validate property here, value can also be validated if necessary
19401952
public static void validateProperty(String property, Scope usedScope) {
19411953
Scope validScope = PropertyScope.get(property);

tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClient.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,4 +140,13 @@ public DAGStatus waitForCompletion(long timeMs) throws IOException, TezException
140140
public abstract DAGStatus waitForCompletionWithStatusUpdates(@Nullable Set<StatusGetOpts> statusGetOpts)
141141
throws IOException, TezException, InterruptedException;
142142

143+
/**
144+
* Returns the Tez AM's web ui address if any.
145+
*
146+
* @return The http web UI address
147+
* @throws IOException
148+
* @throws TezException
149+
*/
150+
public abstract String getWebUIAddress() throws IOException, TezException;
151+
143152
}

tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientImpl.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@
2929
import java.util.Set;
3030

3131
import com.google.common.annotations.VisibleForTesting;
32+
3233
import org.apache.hadoop.security.UserGroupInformation;
3334
import org.apache.tez.common.Preconditions;
34-
3535
import org.apache.hadoop.yarn.exceptions.ApplicationNotFoundException;
3636
import org.slf4j.Logger;
3737
import org.slf4j.LoggerFactory;
@@ -640,6 +640,11 @@ public DAGClientInternal getRealClient() {
640640
return realClient;
641641
}
642642

643+
@Override
644+
public String getWebUIAddress() throws IOException, TezException {
645+
return realClient.getWebUIAddress();
646+
}
647+
643648
private double getProgress(Progress progress) {
644649
return (progress.getTotalTaskCount() == 0 ? 0.0 : (double) (progress.getSucceededTaskCount())
645650
/ progress.getTotalTaskCount());

tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientInternal.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,6 @@ public abstract VertexStatus getVertexStatus(String vertexName,
125125
*/
126126
public abstract DAGStatus waitForCompletionWithStatusUpdates(@Nullable Set<StatusGetOpts> statusGetOpts)
127127
throws IOException, TezException, InterruptedException;
128+
129+
public abstract String getWebUIAddress() throws IOException, TezException;
128130
}

tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientTimelineImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,4 +523,9 @@ public DAGStatus getDAGStatus(@Nullable Set<StatusGetOpts> statusOptions,
523523
return getDAGStatus(statusOptions);
524524
}
525525

526+
@Override
527+
public String getWebUIAddress() throws IOException, TezException {
528+
throw new TezException("DAGClientTimelineImpl.getWebUIAddress is not supported");
529+
}
530+
526531
}

tez-api/src/main/java/org/apache/tez/dag/api/client/rpc/DAGClientRPCImpl.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.apache.tez.dag.api.client.VertexStatus;
4949
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetDAGStatusRequestProto;
5050
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetVertexStatusRequestProto;
51+
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetWebUIAddressRequestProto;
5152
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.TryKillDAGRequestProto;
5253

5354
import com.google.common.annotations.VisibleForTesting;
@@ -303,4 +304,15 @@ public DAGStatus waitForCompletionWithStatusUpdates(@Nullable Set<StatusGetOpts>
303304
throw new TezException("not supported");
304305
}
305306

307+
@Override
308+
public String getWebUIAddress() throws IOException, TezException {
309+
LOG.debug("getWebUIAddress via AM for app: {} dag:{}", appId, dagId);
310+
GetWebUIAddressRequestProto.Builder requestProtoBuilder = GetWebUIAddressRequestProto.newBuilder();
311+
try {
312+
return proxy.getWebUIAddress(null, requestProtoBuilder.build()).getWebUiAddress();
313+
} catch (ServiceException e) {
314+
RPCUtil.unwrapAndThrowException(e);
315+
throw new TezException(e);
316+
}
317+
}
306318
}

tez-api/src/main/proto/DAGClientAMProtocol.proto

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ message GetAMStatusResponseProto {
9090
required TezAppMasterStatusProto status = 1;
9191
}
9292

93+
message GetWebUIAddressRequestProto {
94+
}
95+
96+
message GetWebUIAddressResponseProto {
97+
required string web_ui_address = 1;
98+
}
99+
93100
service DAGClientAMProtocol {
94101
rpc getAllDAGs (GetAllDAGsRequestProto) returns (GetAllDAGsResponseProto);
95102
rpc getDAGStatus (GetDAGStatusRequestProto) returns (GetDAGStatusResponseProto);
@@ -98,4 +105,5 @@ service DAGClientAMProtocol {
98105
rpc submitDAG (SubmitDAGRequestProto) returns (SubmitDAGResponseProto);
99106
rpc shutdownSession (ShutdownSessionRequestProto) returns (ShutdownSessionResponseProto);
100107
rpc getAMStatus (GetAMStatusRequestProto) returns (GetAMStatusResponseProto);
108+
rpc getWebUIAddress (GetWebUIAddressRequestProto) returns (GetWebUIAddressResponseProto);
101109
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.tez.common.web;
20+
21+
import java.lang.reflect.InvocationTargetException;
22+
import java.lang.reflect.Method;
23+
import java.util.Enumeration;
24+
import java.util.concurrent.atomic.AtomicBoolean;
25+
26+
import javax.servlet.ServletConfig;
27+
import javax.servlet.ServletContext;
28+
import javax.servlet.ServletException;
29+
import javax.servlet.http.HttpServlet;
30+
import javax.servlet.http.HttpServletRequest;
31+
import javax.servlet.http.HttpServletResponse;
32+
33+
import org.apache.hadoop.yarn.webapp.Controller;
34+
35+
/**
36+
* AbstractServletToControllerAdapter is a common ancestor for classes
37+
* that wish to adapt servlets to yarn webapp controllers.
38+
* The adapter is responsible for:
39+
* 1. creating a servlet instance
40+
* 2. creating a dummy ServletConfig
41+
* 3. delegating calls to the servlet instance's doGet method
42+
*/
43+
public abstract class AbstractServletToControllerAdapter extends Controller {
44+
private AtomicBoolean initialized = new AtomicBoolean(false);
45+
protected HttpServlet servlet;
46+
47+
@Override
48+
public void index() {
49+
if (initialized.compareAndSet(false, true)) {
50+
initServlet();
51+
}
52+
try {
53+
/*
54+
* This reflection workaround is needed because HttpServlet.doGet is protected
55+
* (even if subclasses have it public).
56+
*/
57+
Method doGetMethod =
58+
this.servlet.getClass().getMethod("doGet", HttpServletRequest.class, HttpServletResponse.class);
59+
doGetMethod.setAccessible(true);
60+
doGetMethod.invoke(this.servlet, request(), response());
61+
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
62+
| SecurityException e) {
63+
throw new RuntimeException(e);
64+
}
65+
}
66+
67+
/**
68+
* Creates a dummy servlet config which is suitable for initializing a servlet instance.
69+
* @param servletName
70+
* @return a ServletConfig instance initialized with a ServletContext
71+
*/
72+
private ServletConfig getDummyServletConfig(String servletName) {
73+
return new ServletConfig() {
74+
75+
@Override
76+
public String getServletName() {
77+
return servletName;
78+
}
79+
80+
@Override
81+
public ServletContext getServletContext() {
82+
return request().getServletContext();
83+
}
84+
85+
@Override
86+
public Enumeration<String> getInitParameterNames() {
87+
return null;
88+
}
89+
90+
@Override
91+
public String getInitParameter(String name) {
92+
return null;
93+
}
94+
};
95+
}
96+
97+
private void initServlet() {
98+
try {
99+
servlet.init(getDummyServletConfig(this.servlet.getClass().getSimpleName()));
100+
} catch (ServletException e) {
101+
throw new RuntimeException(e);
102+
}
103+
}
104+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.tez.common.web;
20+
21+
import javax.servlet.ServletException;
22+
23+
import org.apache.hadoop.conf.ConfServlet;
24+
import org.apache.hadoop.http.HttpServer2.StackServlet;
25+
import org.apache.hadoop.jmx.JMXJsonServlet;
26+
27+
public class ServletToControllerAdapters {
28+
public static class JMXJsonServletController extends AbstractServletToControllerAdapter {
29+
public JMXJsonServletController() throws ServletException {
30+
this.servlet = new JMXJsonServlet();
31+
}
32+
}
33+
34+
public static class ConfServletController extends AbstractServletToControllerAdapter {
35+
public ConfServletController() throws ServletException {
36+
this.servlet = new ConfServlet();
37+
}
38+
}
39+
40+
public static class StackServletController extends AbstractServletToControllerAdapter {
41+
public StackServletController() throws ServletException {
42+
this.servlet = new StackServlet();
43+
}
44+
}
45+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
@Private
20+
package org.apache.tez.common.web;
21+
22+
import org.apache.hadoop.classification.InterfaceAudience.Private;

0 commit comments

Comments
 (0)