Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions hbase-http/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>tools.profiler</groupId>
<artifactId>async-profiler</artifactId>
<version>${async-profiler.version}</version>
<optional>true</optional>
</dependency>
</dependencies>

<build>
Expand Down Expand Up @@ -320,6 +326,16 @@
<!-- General Resources -->
</build>
<profiles>
<profile>
<id>async-profiler</id>
<dependencies>
<dependency>
<groupId>tools.profiler</groupId>
<artifactId>async-profiler</artifactId>
<version>${async-profiler.version}</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>build-with-jdk11</id>
<activation>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ public class HttpServer implements FilterContainer {
"hbase.security.authentication.ui.config.protected";
public static final String HTTP_UI_NO_CACHE_ENABLE_KEY = "hbase.http.filter.no-store.enable";
public static final boolean HTTP_PRIVILEGED_CONF_DEFAULT = false;
public static final String PROFILER_ENABLED_KEY = "hbase.profiler.enabled";
public static final boolean PROFILER_ENABLED_DEFAULT = true;

// The ServletContext attribute where the daemon Configuration
// gets stored.
Expand Down Expand Up @@ -871,8 +873,12 @@ protected void addDefaultServlets(ContextHandlerCollection contexts, Configurati
} else {
addUnprivilegedServlet("conf", "/conf", ConfServlet.class);
}
final String asyncProfilerHome = ProfileServlet.getAsyncProfilerHome();
if (asyncProfilerHome != null && !asyncProfilerHome.trim().isEmpty()) {

if (!conf.getBoolean(PROFILER_ENABLED_KEY, PROFILER_ENABLED_DEFAULT)) {
addUnprivilegedServlet("prof", "/prof", ProfileServlet.DisabledServlet.class);
LOG.info("Profiler disabled by configuration ({}=false). Disabling /prof endpoint.",
PROFILER_ENABLED_KEY);
} else if (ProfileServlet.isAvailable()) {
addPrivilegedServlet("prof", "/prof", ProfileServlet.class);
Path tmpDir = Paths.get(ProfileServlet.OUTPUT_DIR);
if (Files.notExists(tmpDir)) {
Expand All @@ -884,8 +890,8 @@ protected void addDefaultServlets(ContextHandlerCollection contexts, Configurati
genCtx.setDisplayName("prof-output-hbase");
} else {
addUnprivilegedServlet("prof", "/prof", ProfileServlet.DisabledServlet.class);
LOG.info("ASYNC_PROFILER_HOME environment variable and async.profiler.home system property "
+ "not specified. Disabling /prof endpoint.");
LOG.info("async-profiler not available (no library on classpath and ASYNC_PROFILER_HOME "
+ "not set). Disabling /prof endpoint.");
}

/* register metrics servlets */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hbase.http;

import java.io.File;
import java.io.IOException;
import one.profiler.AsyncProfiler;
import org.apache.yetus.audience.InterfaceAudience;

/**
* Backend that uses the async-profiler Java API (in-process). Requires the
* {@code tools.profiler:async-profiler} JAR and its native library on the classpath.
* <p>
* This class is intentionally isolated in its own file so that the JVM never loads
* {@code one.profiler.AsyncProfiler} on systems where the JAR is absent. It is only instantiated
* reflectively from {@link ProfilerBackend#detect} after confirming the class is resolvable.
*/
@InterfaceAudience.Private
final class LibraryBackend implements ProfilerBackend {

@Override
public String executeStart(ProfileServlet.ProfileRequest request, File outputFile)
throws IOException {
String cmd = ProfilerCommandMapper.toLibraryStartCommand(request);
return AsyncProfiler.getInstance().execute(cmd);
}

@Override
public String executeStop(ProfileServlet.ProfileRequest request, File outputFile)
throws IOException {
String cmd = ProfilerCommandMapper.toLibraryStopCommand(request, outputFile);
return AsyncProfiler.getInstance().execute(cmd);
}

@Override
public void destroy() {
try {
AsyncProfiler.getInstance().execute("stop");
} catch (Exception e) {
// ignored — profiler may not have been active at shutdown time
}
}
}
Loading