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

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/changelog/96272.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 96272
summary: "[Profiling] Add status API"
area: Application
type: enhancement
issues: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.profiler;

import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.ActionType;
import org.elasticsearch.action.support.master.AcknowledgedRequest;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.xcontent.ToXContentObject;
import org.elasticsearch.xcontent.XContentBuilder;

import java.io.IOException;
import java.util.Objects;

public class GetStatusAction extends ActionType<GetStatusAction.Response> {
public static final GetStatusAction INSTANCE = new GetStatusAction();
public static final String NAME = "cluster:monitor/profiling/status/get";

protected GetStatusAction() {
super(NAME, GetStatusAction.Response::new);
}

public static class Response extends ActionResponse implements ToXContentObject {

private boolean profilingEnabled;
private boolean resourceManagementEnabled;
private boolean resourcesCreated;

public Response(StreamInput in) throws IOException {
super(in);
profilingEnabled = in.readBoolean();
resourceManagementEnabled = in.readBoolean();
resourcesCreated = in.readBoolean();
}

public Response(boolean profilingEnabled, boolean resourceManagementEnabled, boolean resourcesCreated) {
this.profilingEnabled = profilingEnabled;
this.resourceManagementEnabled = resourceManagementEnabled;
this.resourcesCreated = resourcesCreated;
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.startObject("profiling").field("enabled", profilingEnabled).endObject();
builder.startObject("resource_management").field("enabled", resourceManagementEnabled).endObject();
builder.startObject("resources").field("created", resourcesCreated).endObject();
builder.endObject();
return builder;
}

@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeBoolean(profilingEnabled);
out.writeBoolean(resourceManagementEnabled);
out.writeBoolean(resourcesCreated);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Response response = (Response) o;
return profilingEnabled == response.profilingEnabled
&& resourceManagementEnabled == response.resourceManagementEnabled
&& resourcesCreated == response.resourcesCreated;
}

@Override
public int hashCode() {
return Objects.hash(profilingEnabled, resourceManagementEnabled, resourcesCreated);
}

@Override
public String toString() {
return Strings.toString(this, true, true);
}

}

public static class Request extends AcknowledgedRequest<GetStatusAction.Request> {

public Request(StreamInput in) throws IOException {
super(in);
}

public Request() {}

@Override
public ActionRequestValidationException validate() {
return null;
}

@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,12 @@
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.xpack.core.XPackSettings;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;

import static java.util.Collections.singletonList;

public class ProfilingPlugin extends Plugin implements ActionPlugin {
private static final Logger logger = LogManager.getLogger(ProfilingPlugin.class);
public static final Setting<Boolean> PROFILING_TEMPLATES_ENABLED = Setting.boolSetting(
Expand Down Expand Up @@ -117,11 +116,12 @@ public List<RestHandler> getRestHandlers(
final IndexNameExpressionResolver indexNameExpressionResolver,
final Supplier<DiscoveryNodes> nodesInCluster
) {
List<RestHandler> handlers = new ArrayList<>();
handlers.add(new RestGetStatusAction());
if (enabled) {
return singletonList(new RestGetProfilingAction());
} else {
return Collections.emptyList();
handlers.add(new RestGetProfilingAction());
}
return Collections.unmodifiableList(handlers);
}

@Override
Expand Down Expand Up @@ -150,7 +150,10 @@ public static ExecutorBuilder<?> responseExecutorBuilder() {

@Override
public List<ActionHandler<? extends ActionRequest, ? extends ActionResponse>> getActions() {
return List.of(new ActionHandler<>(GetProfilingAction.INSTANCE, TransportGetProfilingAction.class));
return List.of(
new ActionHandler<>(GetProfilingAction.INSTANCE, TransportGetProfilingAction.class),
new ActionHandler<>(GetStatusAction.INSTANCE, TransportGetStatusAction.class)
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.profiler;

import org.elasticsearch.client.internal.node.NodeClient;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestToXContentListener;

import java.util.List;

import static org.elasticsearch.rest.RestRequest.Method.GET;

public class RestGetStatusAction extends BaseRestHandler {

@Override
public List<Route> routes() {
return List.of(new Route(GET, "/_profiling/status"));
}

@Override
public String getName() {
return "get_profiling_status_action";
}

@Override
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) {
GetStatusAction.Request request = new GetStatusAction.Request();
request.timeout(restRequest.paramAsTime("timeout", request.timeout()));
request.masterNodeTimeout(restRequest.paramAsTime("master_timeout", request.masterNodeTimeout()));
return channel -> client.execute(GetStatusAction.INSTANCE, request, new RestToXContentListener<>(channel));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.profiler;

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.master.TransportMasterNodeAction;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.core.XPackSettings;

public class TransportGetStatusAction extends TransportMasterNodeAction<GetStatusAction.Request, GetStatusAction.Response> {

@Inject
public TransportGetStatusAction(
TransportService transportService,
ClusterService clusterService,
ThreadPool threadPool,
ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver
) {
super(
GetStatusAction.NAME,
transportService,
clusterService,
threadPool,
actionFilters,
GetStatusAction.Request::new,
indexNameExpressionResolver,
GetStatusAction.Response::new,
ThreadPool.Names.SAME
);
}

@Override
protected void masterOperation(
Task task,
GetStatusAction.Request request,
ClusterState state,
ActionListener<GetStatusAction.Response> listener
) {
boolean pluginEnabled = XPackSettings.PROFILING_ENABLED.get(state.getMetadata().settings());
boolean resourceManagementEnabled = ProfilingPlugin.PROFILING_TEMPLATES_ENABLED.get(state.getMetadata().settings());
boolean resourcesCreated = ProfilingIndexTemplateRegistry.areAllTemplatesCreated(state);
listener.onResponse(new GetStatusAction.Response(pluginEnabled, resourceManagementEnabled, resourcesCreated));
}

@Override
protected ClusterBlockException checkBlock(GetStatusAction.Request request, ClusterState state) {
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_READ);
}
}