/*
* Licensed 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 com.facebook.presto.server;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import com.google.common.io.Resources;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.nio.charset.StandardCharsets;
import java.util.Comparator;
import java.util.List;
import static com.facebook.presto.server.ThreadResource.Info.byName;
import static com.google.common.io.Resources.getResource;
@Path("/")
public class ThreadResource
{
@GET
@Path("/ui/thread")
@Produces(MediaType.TEXT_HTML)
public String getUi()
throws IOException
{
return Resources.toString(getResource(getClass(), "thread.html"), StandardCharsets.UTF_8);
}
@GET
@Path("/v1/thread")
@Produces(MediaType.APPLICATION_JSON)
public static List<Info> getThreadInfo()
{
ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
ImmutableList.Builder<Info> builder = ImmutableList.builder();
for (ThreadInfo info : mbean.getThreadInfo(mbean.getAllThreadIds(), Integer.MAX_VALUE)) {
builder.add(new Info(
info.getThreadId(),
info.getThreadName(),
info.getThreadState().name(),
info.getLockOwnerId() == -1 ? null : info.getLockOwnerId(),
toStackTrace(info.getStackTrace())));
}
return Ordering.from(byName()).sortedCopy(builder.build());
}
private static List<StackLine> toStackTrace(StackTraceElement[] stackTrace)
{
ImmutableList.Builder<StackLine> builder = ImmutableList.builder();
for (StackTraceElement item : stackTrace) {
builder.add(new StackLine(
item.getFileName(),
item.getLineNumber(),
item.getClassName(),
item.getMethodName()));
}
return builder.build();
}
public static class Info
{
private final long id;
private final String name;
private final String state;
private final Long lockOwnerId;
private final List<StackLine> stackTrace;
@JsonCreator
public Info(
@JsonProperty("id") long id,
@JsonProperty("name") String name,
@JsonProperty("state") String state,
@JsonProperty("lockOwner") Long lockOwnerId,
@JsonProperty("stackTrace") List<StackLine> stackTrace)
{
this.id = id;
this.name = name;
this.state = state;
this.lockOwnerId = lockOwnerId;
this.stackTrace = stackTrace;
}
@JsonProperty
public long getId()
{
return id;
}
@JsonProperty
public String getName()
{
return name;
}
@JsonProperty
public String getState()
{
return state;
}
@JsonProperty
public Long getLockOwnerId()
{
return lockOwnerId;
}
@JsonProperty
public List<StackLine> getStackTrace()
{
return stackTrace;
}
public static Comparator<Info> byName()
{
return new Comparator<Info>()
{
@Override
public int compare(Info info, Info info2)
{
return info.getName().compareTo(info2.getName());
}
};
}
}
public static class StackLine
{
private final String file;
private final int line;
private final String className;
private final String method;
@JsonCreator
public StackLine(
@JsonProperty("file") String file,
@JsonProperty("line") int line,
@JsonProperty("class") String className,
@JsonProperty("method") String method)
{
this.file = file;
this.line = line;
this.className = className;
this.method = method;
}
@JsonProperty
public String getFile()
{
return file;
}
@JsonProperty
public int getLine()
{
return line;
}
@JsonProperty
public String getClassName()
{
return className;
}
@JsonProperty
public String getMethod()
{
return method;
}
}
}