Document logs essentials restricted ESQL commands for Kibana (#130346)
This commit is contained in:
parent
8b6acd06f4
commit
7d4ba31681
|
@ -2,5 +2,6 @@
|
||||||
"comment" : "This is generated by ESQL’s DocsV3Support. Do not edit it. See ../README.md for how to regenerate it.",
|
"comment" : "This is generated by ESQL’s DocsV3Support. Do not edit it. See ../README.md for how to regenerate it.",
|
||||||
"type" : "command",
|
"type" : "command",
|
||||||
"name" : "change_point",
|
"name" : "change_point",
|
||||||
"license" : "PLATINUM"
|
"license" : "PLATINUM",
|
||||||
|
"observability_tier" : "COMPLETE"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
"type" : "grouping",
|
"type" : "grouping",
|
||||||
"name" : "categorize",
|
"name" : "categorize",
|
||||||
"license" : "PLATINUM",
|
"license" : "PLATINUM",
|
||||||
|
"observability_tier" : "COMPLETE",
|
||||||
"description" : "Groups text messages into categories of similarly formatted text values.",
|
"description" : "Groups text messages into categories of similarly formatted text values.",
|
||||||
"signatures" : [
|
"signatures" : [
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,7 @@ public class ConsumeProcessor implements Processor {
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getSupportedAnnotationTypes() {
|
public Set<String> getSupportedAnnotationTypes() {
|
||||||
return Set.of(
|
return Set.of(
|
||||||
|
"org.elasticsearch.xpack.esql.SupportsObservabilityTier",
|
||||||
"org.elasticsearch.core.Nullable",
|
"org.elasticsearch.core.Nullable",
|
||||||
"org.elasticsearch.injection.guice.Inject",
|
"org.elasticsearch.injection.guice.Inject",
|
||||||
"org.elasticsearch.xpack.esql.expression.function.FunctionInfo",
|
"org.elasticsearch.xpack.esql.expression.function.FunctionInfo",
|
||||||
|
|
|
@ -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.esql;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
public @interface SupportsObservabilityTier {
|
||||||
|
|
||||||
|
ObservabilityTier tier();
|
||||||
|
|
||||||
|
enum ObservabilityTier {
|
||||||
|
COMPLETE,
|
||||||
|
LOGS_ESSENTIALS
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
import org.elasticsearch.license.XPackLicenseState;
|
import org.elasticsearch.license.XPackLicenseState;
|
||||||
import org.elasticsearch.xpack.esql.LicenseAware;
|
import org.elasticsearch.xpack.esql.LicenseAware;
|
||||||
|
import org.elasticsearch.xpack.esql.SupportsObservabilityTier;
|
||||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||||
import org.elasticsearch.xpack.esql.core.expression.Nullability;
|
import org.elasticsearch.xpack.esql.core.expression.Nullability;
|
||||||
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
|
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
|
||||||
|
@ -27,6 +28,7 @@ import org.elasticsearch.xpack.ml.MachineLearning;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.elasticsearch.xpack.esql.SupportsObservabilityTier.ObservabilityTier.COMPLETE;
|
||||||
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT;
|
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT;
|
||||||
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isString;
|
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isString;
|
||||||
|
|
||||||
|
@ -39,6 +41,7 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isStr
|
||||||
* For the implementation, see {@link org.elasticsearch.compute.aggregation.blockhash.CategorizeBlockHash}
|
* For the implementation, see {@link org.elasticsearch.compute.aggregation.blockhash.CategorizeBlockHash}
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
|
@SupportsObservabilityTier(tier = COMPLETE)
|
||||||
public class Categorize extends GroupingFunction.NonEvaluatableGroupingFunction implements LicenseAware {
|
public class Categorize extends GroupingFunction.NonEvaluatableGroupingFunction implements LicenseAware {
|
||||||
public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(
|
public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(
|
||||||
Expression.class,
|
Expression.class,
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
import org.elasticsearch.compute.operator.ChangePointOperator;
|
import org.elasticsearch.compute.operator.ChangePointOperator;
|
||||||
import org.elasticsearch.license.XPackLicenseState;
|
import org.elasticsearch.license.XPackLicenseState;
|
||||||
import org.elasticsearch.xpack.esql.LicenseAware;
|
import org.elasticsearch.xpack.esql.LicenseAware;
|
||||||
|
import org.elasticsearch.xpack.esql.SupportsObservabilityTier;
|
||||||
import org.elasticsearch.xpack.esql.capabilities.PostAnalysisVerificationAware;
|
import org.elasticsearch.xpack.esql.capabilities.PostAnalysisVerificationAware;
|
||||||
import org.elasticsearch.xpack.esql.common.Failures;
|
import org.elasticsearch.xpack.esql.common.Failures;
|
||||||
import org.elasticsearch.xpack.esql.core.expression.Attribute;
|
import org.elasticsearch.xpack.esql.core.expression.Attribute;
|
||||||
|
@ -27,6 +28,7 @@ import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static org.elasticsearch.xpack.esql.SupportsObservabilityTier.ObservabilityTier.COMPLETE;
|
||||||
import static org.elasticsearch.xpack.esql.common.Failure.fail;
|
import static org.elasticsearch.xpack.esql.common.Failure.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,6 +43,7 @@ import static org.elasticsearch.xpack.esql.common.Failure.fail;
|
||||||
* Furthermore, ChangePoint should be called with at most 1000 data points. That's
|
* Furthermore, ChangePoint should be called with at most 1000 data points. That's
|
||||||
* enforced by the Limit in the surrogate plan.
|
* enforced by the Limit in the surrogate plan.
|
||||||
*/
|
*/
|
||||||
|
@SupportsObservabilityTier(tier = COMPLETE)
|
||||||
public class ChangePoint extends UnaryPlan implements SurrogateLogicalPlan, PostAnalysisVerificationAware, LicenseAware {
|
public class ChangePoint extends UnaryPlan implements SurrogateLogicalPlan, PostAnalysisVerificationAware, LicenseAware {
|
||||||
|
|
||||||
private final Attribute value;
|
private final Attribute value;
|
||||||
|
|
|
@ -18,6 +18,8 @@ import org.elasticsearch.logging.Logger;
|
||||||
import org.elasticsearch.xcontent.XContentBuilder;
|
import org.elasticsearch.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.xcontent.json.JsonXContent;
|
import org.elasticsearch.xcontent.json.JsonXContent;
|
||||||
import org.elasticsearch.xpack.esql.CsvTestsDataLoader;
|
import org.elasticsearch.xpack.esql.CsvTestsDataLoader;
|
||||||
|
import org.elasticsearch.xpack.esql.SupportsObservabilityTier;
|
||||||
|
import org.elasticsearch.xpack.esql.SupportsObservabilityTier.ObservabilityTier;
|
||||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||||
import org.elasticsearch.xpack.esql.expression.function.fulltext.MatchOperator;
|
import org.elasticsearch.xpack.esql.expression.function.fulltext.MatchOperator;
|
||||||
import org.elasticsearch.xpack.esql.expression.function.scalar.string.regex.RLike;
|
import org.elasticsearch.xpack.esql.expression.function.scalar.string.regex.RLike;
|
||||||
|
@ -572,7 +574,7 @@ public abstract class DocsV3Support {
|
||||||
boolean hasAppendix = renderAppendix(info.appendix());
|
boolean hasAppendix = renderAppendix(info.appendix());
|
||||||
renderFullLayout(info, hasExamples, hasAppendix, hasFunctionOptions);
|
renderFullLayout(info, hasExamples, hasAppendix, hasFunctionOptions);
|
||||||
renderKibanaInlineDocs(name, null, info);
|
renderKibanaInlineDocs(name, null, info);
|
||||||
renderKibanaFunctionDefinition(name, null, info, description.args(), description.variadic());
|
renderKibanaFunctionDefinition(name, null, info, description.args(), description.variadic(), getObservabilityTier());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderFunctionNamedParams(EsqlFunctionRegistry.MapArgSignature mapArgSignature) throws IOException {
|
private void renderFunctionNamedParams(EsqlFunctionRegistry.MapArgSignature mapArgSignature) throws IOException {
|
||||||
|
@ -666,6 +668,11 @@ public abstract class DocsV3Support {
|
||||||
:::
|
:::
|
||||||
""".replace("$NAME$", name).replace("$SECTION$", section);
|
""".replace("$NAME$", name).replace("$SECTION$", section);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ObservabilityTier getObservabilityTier() {
|
||||||
|
SupportsObservabilityTier supportsObservabilityTier = definition.clazz().getAnnotation(SupportsObservabilityTier.class);
|
||||||
|
return supportsObservabilityTier != null ? supportsObservabilityTier.tier() : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Operator specific docs generating, since it is currently quite different from the function docs generating */
|
/** Operator specific docs generating, since it is currently quite different from the function docs generating */
|
||||||
|
@ -712,7 +719,7 @@ public abstract class DocsV3Support {
|
||||||
if (ctor != null) {
|
if (ctor != null) {
|
||||||
FunctionInfo functionInfo = ctor.getAnnotation(FunctionInfo.class);
|
FunctionInfo functionInfo = ctor.getAnnotation(FunctionInfo.class);
|
||||||
assert functionInfo != null;
|
assert functionInfo != null;
|
||||||
renderDocsForOperators(op.name(), op.titleName(), ctor, functionInfo, op.variadic());
|
renderDocsForOperators(op.name(), op.titleName(), ctor, functionInfo, op.variadic(), getObservabilityTier());
|
||||||
} else {
|
} else {
|
||||||
logger.info("Skipping rendering docs for operator '" + op.name() + "' with no @FunctionInfo");
|
logger.info("Skipping rendering docs for operator '" + op.name() + "' with no @FunctionInfo");
|
||||||
}
|
}
|
||||||
|
@ -787,11 +794,17 @@ public abstract class DocsV3Support {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
String name = "not_" + baseName;
|
String name = "not_" + baseName;
|
||||||
renderDocsForOperators(name, null, ctor, functionInfo, op.variadic());
|
renderDocsForOperators(name, null, ctor, functionInfo, op.variadic(), getObservabilityTier());
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderDocsForOperators(String name, String titleName, Constructor<?> ctor, FunctionInfo info, boolean variadic)
|
void renderDocsForOperators(
|
||||||
throws Exception {
|
String name,
|
||||||
|
String titleName,
|
||||||
|
Constructor<?> ctor,
|
||||||
|
FunctionInfo info,
|
||||||
|
boolean variadic,
|
||||||
|
ObservabilityTier observabilityTier
|
||||||
|
) throws Exception {
|
||||||
renderKibanaInlineDocs(name, titleName, info);
|
renderKibanaInlineDocs(name, titleName, info);
|
||||||
|
|
||||||
var params = ctor.getParameters();
|
var params = ctor.getParameters();
|
||||||
|
@ -808,7 +821,7 @@ public abstract class DocsV3Support {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
renderKibanaFunctionDefinition(name, titleName, info, args, variadic);
|
renderKibanaFunctionDefinition(name, titleName, info, args, variadic, observabilityTier);
|
||||||
renderDetailedDescription(info.detailedDescription(), info.note());
|
renderDetailedDescription(info.detailedDescription(), info.note());
|
||||||
renderTypes(name, args);
|
renderTypes(name, args);
|
||||||
renderExamples(info);
|
renderExamples(info);
|
||||||
|
@ -831,17 +844,35 @@ public abstract class DocsV3Support {
|
||||||
writeToTempSnippetsDir("detailedDescription", rendered.toString());
|
writeToTempSnippetsDir("detailedDescription", rendered.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ObservabilityTier getObservabilityTier() {
|
||||||
|
if (op != null) {
|
||||||
|
SupportsObservabilityTier supportsObservabilityTier = op.clazz().getAnnotation(SupportsObservabilityTier.class);
|
||||||
|
if (supportsObservabilityTier != null) {
|
||||||
|
return supportsObservabilityTier.tier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Command specific docs generating, currently very empty since we only render kibana definition files */
|
/** Command specific docs generating, currently very empty since we only render kibana definition files */
|
||||||
public static class CommandsDocsSupport extends DocsV3Support {
|
public static class CommandsDocsSupport extends DocsV3Support {
|
||||||
private final LogicalPlan command;
|
private final LogicalPlan command;
|
||||||
private final XPackLicenseState licenseState;
|
private final XPackLicenseState licenseState;
|
||||||
|
private final ObservabilityTier observabilityTier;
|
||||||
|
|
||||||
public CommandsDocsSupport(String name, Class<?> testClass, LogicalPlan command, XPackLicenseState licenseState) {
|
public CommandsDocsSupport(
|
||||||
|
String name,
|
||||||
|
Class<?> testClass,
|
||||||
|
LogicalPlan command,
|
||||||
|
XPackLicenseState licenseState,
|
||||||
|
ObservabilityTier observabilityTier
|
||||||
|
) {
|
||||||
super("commands", name, testClass, Map::of);
|
super("commands", name, testClass, Map::of);
|
||||||
this.command = command;
|
this.command = command;
|
||||||
this.licenseState = licenseState;
|
this.licenseState = licenseState;
|
||||||
|
this.observabilityTier = observabilityTier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -867,6 +898,9 @@ public abstract class DocsV3Support {
|
||||||
if (license != null && license != License.OperationMode.BASIC) {
|
if (license != null && license != License.OperationMode.BASIC) {
|
||||||
builder.field("license", license.toString());
|
builder.field("license", license.toString());
|
||||||
}
|
}
|
||||||
|
if (observabilityTier != null && observabilityTier != ObservabilityTier.LOGS_ESSENTIALS) {
|
||||||
|
builder.field("observability_tier", observabilityTier.toString());
|
||||||
|
}
|
||||||
String rendered = Strings.toString(builder.endObject());
|
String rendered = Strings.toString(builder.endObject());
|
||||||
logger.info("Writing kibana command definition for [{}]:\n{}", name, rendered);
|
logger.info("Writing kibana command definition for [{}]:\n{}", name, rendered);
|
||||||
writeToTempKibanaDir("definition", "json", rendered);
|
writeToTempKibanaDir("definition", "json", rendered);
|
||||||
|
@ -1044,7 +1078,8 @@ public abstract class DocsV3Support {
|
||||||
String titleName,
|
String titleName,
|
||||||
FunctionInfo info,
|
FunctionInfo info,
|
||||||
List<EsqlFunctionRegistry.ArgSignature> args,
|
List<EsqlFunctionRegistry.ArgSignature> args,
|
||||||
boolean variadic
|
boolean variadic,
|
||||||
|
ObservabilityTier observabilityTier
|
||||||
) throws Exception {
|
) throws Exception {
|
||||||
|
|
||||||
try (XContentBuilder builder = JsonXContent.contentBuilder().prettyPrint().lfAtEnd().startObject()) {
|
try (XContentBuilder builder = JsonXContent.contentBuilder().prettyPrint().lfAtEnd().startObject()) {
|
||||||
|
@ -1067,6 +1102,9 @@ public abstract class DocsV3Support {
|
||||||
if (license != null && license != License.OperationMode.BASIC) {
|
if (license != null && license != License.OperationMode.BASIC) {
|
||||||
builder.field("license", license.toString());
|
builder.field("license", license.toString());
|
||||||
}
|
}
|
||||||
|
if (observabilityTier != null && observabilityTier != ObservabilityTier.LOGS_ESSENTIALS) {
|
||||||
|
builder.field("observability_tier", observabilityTier.toString());
|
||||||
|
}
|
||||||
if (titleName != null && titleName.equals(name) == false) {
|
if (titleName != null && titleName.equals(name) == false) {
|
||||||
builder.field("titleName", titleName);
|
builder.field("titleName", titleName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ import org.elasticsearch.logging.LogManager;
|
||||||
import org.elasticsearch.logging.Logger;
|
import org.elasticsearch.logging.Logger;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
import org.elasticsearch.xpack.esql.LicenseAware;
|
import org.elasticsearch.xpack.esql.LicenseAware;
|
||||||
|
import org.elasticsearch.xpack.esql.SupportsObservabilityTier;
|
||||||
|
import org.elasticsearch.xpack.esql.SupportsObservabilityTier.ObservabilityTier;
|
||||||
import org.elasticsearch.xpack.esql.core.tree.Node;
|
import org.elasticsearch.xpack.esql.core.tree.Node;
|
||||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||||
import org.elasticsearch.xpack.esql.expression.function.DocsV3Support;
|
import org.elasticsearch.xpack.esql.expression.function.DocsV3Support;
|
||||||
|
@ -74,21 +76,32 @@ public class CommandLicenseTests extends ESTestCase {
|
||||||
private static void checkLicense(String commandName, LogicalPlan command) throws Exception {
|
private static void checkLicense(String commandName, LogicalPlan command) throws Exception {
|
||||||
log.info("Running function license checks");
|
log.info("Running function license checks");
|
||||||
TestCheckLicense checkLicense = new TestCheckLicense();
|
TestCheckLicense checkLicense = new TestCheckLicense();
|
||||||
|
ObservabilityTier observabilityTier = null;
|
||||||
|
SupportsObservabilityTier supportsObservabilityTier = command.getClass().getAnnotation(SupportsObservabilityTier.class);
|
||||||
|
if (supportsObservabilityTier != null) {
|
||||||
|
observabilityTier = supportsObservabilityTier.tier();
|
||||||
|
}
|
||||||
if (command instanceof LicenseAware licenseAware) {
|
if (command instanceof LicenseAware licenseAware) {
|
||||||
log.info("Command " + commandName + " implements LicenseAware.");
|
log.info("Command " + commandName + " implements LicenseAware.");
|
||||||
saveLicenseState(commandName, command, checkLicense.licenseLevel(licenseAware));
|
saveLicenseState(commandName, command, checkLicense.licenseLevel(licenseAware), observabilityTier);
|
||||||
} else {
|
} else {
|
||||||
log.info("Command " + commandName + " does not implement LicenseAware.");
|
log.info("Command " + commandName + " does not implement LicenseAware.");
|
||||||
saveLicenseState(commandName, command, checkLicense.basicLicense);
|
saveLicenseState(commandName, command, checkLicense.basicLicense, observabilityTier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void saveLicenseState(String name, LogicalPlan command, XPackLicenseState licenseState) throws Exception {
|
private static void saveLicenseState(
|
||||||
|
String name,
|
||||||
|
LogicalPlan command,
|
||||||
|
XPackLicenseState licenseState,
|
||||||
|
SupportsObservabilityTier.ObservabilityTier observabilityTier
|
||||||
|
) throws Exception {
|
||||||
DocsV3Support.CommandsDocsSupport docs = new DocsV3Support.CommandsDocsSupport(
|
DocsV3Support.CommandsDocsSupport docs = new DocsV3Support.CommandsDocsSupport(
|
||||||
name.toLowerCase(Locale.ROOT),
|
name.toLowerCase(Locale.ROOT),
|
||||||
CommandLicenseTests.class,
|
CommandLicenseTests.class,
|
||||||
command,
|
command,
|
||||||
licenseState
|
licenseState,
|
||||||
|
observabilityTier
|
||||||
);
|
);
|
||||||
docs.renderDocs();
|
docs.renderDocs();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue