Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Universal Profiling as Enterprise feature #100333

Merged
5 changes: 5 additions & 0 deletions docs/changelog/100333.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 100333
summary: Enable Universal Profiling as Enterprise feature
area: Application
type: enhancement
issues: []
4 changes: 4 additions & 0 deletions docs/reference/rest-api/info.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ Example response:
"enterprise_search": {
"available": true,
"enabled": true
},
"universal_profiling": {
"available": true,
"enabled": true
}
},
"tagline" : "You know, for X"
Expand Down
4 changes: 4 additions & 0 deletions docs/reference/rest-api/usage.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,10 @@ GET /_xpack/usage
"min_rule_count": 0,
"max_rule_count": 0
}
},
"universal_profiling" : {
"available" : true,
"enabled" : true
}
}
------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ static TransportVersion def(int id) {
public static final TransportVersion NODE_INFO_REQUEST_SIMPLIFIED = def(8_510_00_0);
public static final TransportVersion NESTED_KNN_VECTOR_QUERY_V = def(8_511_00_0);
public static final TransportVersion ML_PACKAGE_LOADER_PLATFORM_ADDED = def(8_512_00_0);
public static final TransportVersion UNIVERSAL_PROFILING_LICENSE_ADDED = def(8_513_00_0);

/*
* STOP! READ THIS FIRST! No, really,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ public final class XPackField {

/** Name constant for the redact processor feature. */
public static final String REDACT_PROCESSOR = "redact_processor";
/* Name for Universal Profiling. */
public static final String UNIVERSAL_PROFILING = "universal_profiling";

private XPackField() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class XPackInfoFeatureAction extends ActionType<XPackInfoFeatureResponse>
public static final XPackInfoFeatureAction AGGREGATE_METRIC = new XPackInfoFeatureAction(XPackField.AGGREGATE_METRIC);
public static final XPackInfoFeatureAction ARCHIVE = new XPackInfoFeatureAction(XPackField.ARCHIVE);
public static final XPackInfoFeatureAction ENTERPRISE_SEARCH = new XPackInfoFeatureAction(XPackField.ENTERPRISE_SEARCH);
public static final XPackInfoFeatureAction UNIVERSAL_PROFILING = new XPackInfoFeatureAction(XPackField.UNIVERSAL_PROFILING);

public static final List<XPackInfoFeatureAction> ALL;
static {
Expand Down Expand Up @@ -80,7 +81,8 @@ public class XPackInfoFeatureAction extends ActionType<XPackInfoFeatureResponse>
DATA_TIERS,
AGGREGATE_METRIC,
ARCHIVE,
ENTERPRISE_SEARCH
ENTERPRISE_SEARCH,
UNIVERSAL_PROFILING
)
);
ALL = Collections.unmodifiableList(actions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class XPackUsageFeatureAction extends ActionType<XPackUsageFeatureRespons
public static final XPackUsageFeatureAction HEALTH = new XPackUsageFeatureAction(XPackField.HEALTH_API);
public static final XPackUsageFeatureAction REMOTE_CLUSTERS = new XPackUsageFeatureAction(XPackField.REMOTE_CLUSTERS);
public static final XPackUsageFeatureAction ENTERPRISE_SEARCH = new XPackUsageFeatureAction(XPackField.ENTERPRISE_SEARCH);
public static final XPackUsageFeatureAction UNIVERSAL_PROFILING = new XPackUsageFeatureAction(XPackField.UNIVERSAL_PROFILING);

static final List<XPackUsageFeatureAction> ALL = List.of(
AGGREGATE_METRIC,
Expand Down Expand Up @@ -78,7 +79,8 @@ public class XPackUsageFeatureAction extends ActionType<XPackUsageFeatureRespons
ARCHIVE,
HEALTH,
REMOTE_CLUSTERS,
ENTERPRISE_SEARCH
ENTERPRISE_SEARCH,
UNIVERSAL_PROFILING
);

// public for testing
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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.profiling;

import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin;

import java.nio.file.Path;

public class LocalStateProfilingXPackPlugin extends LocalStateCompositeXPackPlugin {
public LocalStateProfilingXPackPlugin(final Settings settings, final Path configPath) {
super(settings, configPath);
plugins.add(new ProfilingPlugin(settings) {
@Override
protected ProfilingLicenseChecker createLicenseChecker() {
return new ProfilingLicenseChecker(LocalStateProfilingXPackPlugin.this::getLicenseState);
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.datastreams.DataStreamsPlugin;
import org.elasticsearch.license.LicenseSettings;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.transport.netty4.Netty4Plugin;
import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.ilm.LifecycleSettings;
import org.elasticsearch.xpack.ilm.IndexLifecycle;
Expand All @@ -37,9 +37,8 @@ public abstract class ProfilingTestCase extends ESIntegTestCase {
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return List.of(
LocalStateCompositeXPackPlugin.class,
DataStreamsPlugin.class,
ProfilingPlugin.class,
LocalStateProfilingXPackPlugin.class,
IndexLifecycle.class,
UnsignedLongMapperPlugin.class,
VersionFieldPlugin.class,
Expand All @@ -58,6 +57,7 @@ protected Settings nodeSettings(int nodeOrdinal, Settings otherSettings) {
// .put(LicenseSettings.SELF_GENERATED_LICENSE_TYPE.getKey(), "trial")
// Disable ILM history index so that the tests don't have to clean it up
.put(LifecycleSettings.LIFECYCLE_HISTORY_INDEX_ENABLED_SETTING.getKey(), false)
.put(LicenseSettings.SELF_GENERATED_LICENSE_TYPE.getKey(), "trial")
.build();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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.profiling;

import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.core.XPackField;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.action.XPackInfoFeatureAction;
import org.elasticsearch.xpack.core.action.XPackInfoFeatureTransportAction;

public class ProfilingInfoTransportAction extends XPackInfoFeatureTransportAction {
private final boolean enabled;
private final ProfilingLicenseChecker licenseChecker;

@Inject
public ProfilingInfoTransportAction(
TransportService transportService,
ActionFilters actionFilters,
Settings settings,
ProfilingLicenseChecker licenseChecker
) {
super(XPackInfoFeatureAction.UNIVERSAL_PROFILING.name(), transportService, actionFilters);
this.enabled = XPackSettings.PROFILING_ENABLED.get(settings);
this.licenseChecker = licenseChecker;
}

@Override
public String name() {
return XPackField.UNIVERSAL_PROFILING;
}

@Override
public boolean available() {
return licenseChecker.isSupportedLicense();
}

@Override
public boolean enabled() {
return enabled;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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.profiling;

import org.elasticsearch.license.License;
import org.elasticsearch.license.LicenseUtils;
import org.elasticsearch.license.LicensedFeature;
import org.elasticsearch.license.XPackLicenseState;

import java.util.function.Supplier;

public final class ProfilingLicenseChecker {
private static final LicensedFeature.Momentary UNIVERSAL_PROFILING_FEATURE = LicensedFeature.momentary(
null,
"universal_profiling",
License.OperationMode.ENTERPRISE
);

private final Supplier<XPackLicenseState> licenseStateResolver;

public ProfilingLicenseChecker(Supplier<XPackLicenseState> licenseStateResolver) {
this.licenseStateResolver = licenseStateResolver;
}

public boolean isSupportedLicense() {
return UNIVERSAL_PROFILING_FEATURE.checkWithoutTracking(licenseStateResolver.get());
}

public void requireSupportedLicense() {
if (UNIVERSAL_PROFILING_FEATURE.check(licenseStateResolver.get()) == false) {
throw LicenseUtils.newComplianceException(UNIVERSAL_PROFILING_FEATURE.getName());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.xpack.core.XPackPlugin;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.action.XPackInfoFeatureAction;
import org.elasticsearch.xpack.core.action.XPackUsageFeatureAction;

import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -108,10 +111,12 @@ public Collection<Object> createComponents(
registry.get().initialize();
indexManager.get().initialize();
dataStreamManager.get().initialize();
return List.of(registry.get(), indexManager.get(), dataStreamManager.get());
} else {
return Collections.emptyList();
}
return Collections.singletonList(createLicenseChecker());
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #97546 (comment) for context on why we are returning the license checker in all cases (but no other components).

}

protected ProfilingLicenseChecker createLicenseChecker() {
return new ProfilingLicenseChecker(XPackPlugin::getSharedLicenseState);
}

public void updateCheckOutdatedIndices(boolean newValue) {
Expand Down Expand Up @@ -179,7 +184,9 @@ public static ExecutorBuilder<?> responseExecutorBuilder() {
return List.of(
new ActionHandler<>(GetStackTracesAction.INSTANCE, TransportGetStackTracesAction.class),
new ActionHandler<>(GetFlamegraphAction.INSTANCE, TransportGetFlamegraphAction.class),
new ActionHandler<>(GetStatusAction.INSTANCE, TransportGetStatusAction.class)
new ActionHandler<>(GetStatusAction.INSTANCE, TransportGetStatusAction.class),
new ActionHandler<>(XPackUsageFeatureAction.UNIVERSAL_PROFILING, ProfilingUsageTransportAction.class),
new ActionHandler<>(XPackInfoFeatureAction.UNIVERSAL_PROFILING, ProfilingInfoTransportAction.class)
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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.profiling;

import org.elasticsearch.TransportVersion;
import org.elasticsearch.TransportVersions;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.xpack.core.XPackFeatureSet;
import org.elasticsearch.xpack.core.XPackField;

import java.io.IOException;

public class ProfilingUsage extends XPackFeatureSet.Usage {
public ProfilingUsage(StreamInput input) throws IOException {
super(input);
}

public ProfilingUsage(boolean available, boolean enabled) {
super(XPackField.UNIVERSAL_PROFILING, available, enabled);
}

@Override
public TransportVersion getMinimalSupportedVersion() {
return TransportVersions.UNIVERSAL_PROFILING_LICENSE_ADDED;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* 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.profiling;

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.protocol.xpack.XPackUsageRequest;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.action.XPackUsageFeatureAction;
import org.elasticsearch.xpack.core.action.XPackUsageFeatureResponse;
import org.elasticsearch.xpack.core.action.XPackUsageFeatureTransportAction;

public class ProfilingUsageTransportAction extends XPackUsageFeatureTransportAction {
private final ProfilingLicenseChecker licenseChecker;

private final boolean enabled;

@Inject
public ProfilingUsageTransportAction(
TransportService transportService,
ClusterService clusterService,
ThreadPool threadPool,
ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver,
ProfilingLicenseChecker licenseChecker,
Settings settings
) {
super(
XPackUsageFeatureAction.UNIVERSAL_PROFILING.name(),
transportService,
clusterService,
threadPool,
actionFilters,
indexNameExpressionResolver
);
this.licenseChecker = licenseChecker;
this.enabled = XPackSettings.PROFILING_ENABLED.get(settings);
}

@Override
protected void masterOperation(
Task task,
XPackUsageRequest request,
ClusterState state,
ActionListener<XPackUsageFeatureResponse> listener
) {
ProfilingUsage profilingUsage = new ProfilingUsage(licenseChecker.isSupportedLicense(), enabled);
listener.onResponse(new XPackUsageFeatureResponse(profilingUsage));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public class TransportGetStackTracesAction extends HandledTransportAction<GetSta
);

private final NodeClient nodeClient;
private final ProfilingLicenseChecker licenseChecker;
private final ClusterService clusterService;
private final TransportService transportService;
private final Executor responseExecutor;
Expand All @@ -105,10 +106,12 @@ public TransportGetStackTracesAction(
TransportService transportService,
ActionFilters actionFilters,
NodeClient nodeClient,
ProfilingLicenseChecker licenseChecker,
IndexNameExpressionResolver resolver
) {
super(GetStackTracesAction.NAME, transportService, actionFilters, GetStackTracesRequest::new, EsExecutors.DIRECT_EXECUTOR_SERVICE);
this.nodeClient = nodeClient;
this.licenseChecker = licenseChecker;
this.clusterService = clusterService;
this.transportService = transportService;
this.responseExecutor = threadPool.executor(ProfilingPlugin.PROFILING_THREAD_POOL_NAME);
Expand All @@ -120,6 +123,7 @@ public TransportGetStackTracesAction(

@Override
protected void doExecute(Task submitTask, GetStackTracesRequest request, ActionListener<GetStackTracesResponse> submitListener) {
licenseChecker.requireSupportedLicense();
long start = System.nanoTime();
Client client = new ParentTaskAssigningClient(this.nodeClient, transportService.getLocalNode(), submitTask);
EventsIndex mediumDownsampled = EventsIndex.MEDIUM_DOWNSAMPLED;
Expand Down
Loading