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.",
|
||||
"type" : "command",
|
||||
"name" : "change_point",
|
||||
"license" : "PLATINUM"
|
||||
"license" : "PLATINUM",
|
||||
"observability_tier" : "COMPLETE"
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"type" : "grouping",
|
||||
"name" : "categorize",
|
||||
"license" : "PLATINUM",
|
||||
"observability_tier" : "COMPLETE",
|
||||
"description" : "Groups text messages into categories of similarly formatted text values.",
|
||||
"signatures" : [
|
||||
{
|
||||
|
|
|
@ -35,6 +35,7 @@ public class ConsumeProcessor implements Processor {
|
|||
@Override
|
||||
public Set<String> getSupportedAnnotationTypes() {
|
||||
return Set.of(
|
||||
"org.elasticsearch.xpack.esql.SupportsObservabilityTier",
|
||||
"org.elasticsearch.core.Nullable",
|
||||
"org.elasticsearch.injection.guice.Inject",
|
||||
"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.license.XPackLicenseState;
|
||||
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.Nullability;
|
||||
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
|
||||
|
@ -27,6 +28,7 @@ import org.elasticsearch.xpack.ml.MachineLearning;
|
|||
import java.io.IOException;
|
||||
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.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}
|
||||
* </p>
|
||||
*/
|
||||
@SupportsObservabilityTier(tier = COMPLETE)
|
||||
public class Categorize extends GroupingFunction.NonEvaluatableGroupingFunction implements LicenseAware {
|
||||
public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(
|
||||
Expression.class,
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.elasticsearch.common.io.stream.StreamOutput;
|
|||
import org.elasticsearch.compute.operator.ChangePointOperator;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.xpack.esql.LicenseAware;
|
||||
import org.elasticsearch.xpack.esql.SupportsObservabilityTier;
|
||||
import org.elasticsearch.xpack.esql.capabilities.PostAnalysisVerificationAware;
|
||||
import org.elasticsearch.xpack.esql.common.Failures;
|
||||
import org.elasticsearch.xpack.esql.core.expression.Attribute;
|
||||
|
@ -27,6 +28,7 @@ import java.io.IOException;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.elasticsearch.xpack.esql.SupportsObservabilityTier.ObservabilityTier.COMPLETE;
|
||||
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
|
||||
* enforced by the Limit in the surrogate plan.
|
||||
*/
|
||||
@SupportsObservabilityTier(tier = COMPLETE)
|
||||
public class ChangePoint extends UnaryPlan implements SurrogateLogicalPlan, PostAnalysisVerificationAware, LicenseAware {
|
||||
|
||||
private final Attribute value;
|
||||
|
|
|
@ -18,6 +18,8 @@ import org.elasticsearch.logging.Logger;
|
|||
import org.elasticsearch.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.xcontent.json.JsonXContent;
|
||||
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.expression.function.fulltext.MatchOperator;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.string.regex.RLike;
|
||||
|
@ -572,7 +574,7 @@ public abstract class DocsV3Support {
|
|||
boolean hasAppendix = renderAppendix(info.appendix());
|
||||
renderFullLayout(info, hasExamples, hasAppendix, hasFunctionOptions);
|
||||
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 {
|
||||
|
@ -666,6 +668,11 @@ public abstract class DocsV3Support {
|
|||
:::
|
||||
""".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 */
|
||||
|
@ -712,7 +719,7 @@ public abstract class DocsV3Support {
|
|||
if (ctor != null) {
|
||||
FunctionInfo functionInfo = ctor.getAnnotation(FunctionInfo.class);
|
||||
assert functionInfo != null;
|
||||
renderDocsForOperators(op.name(), op.titleName(), ctor, functionInfo, op.variadic());
|
||||
renderDocsForOperators(op.name(), op.titleName(), ctor, functionInfo, op.variadic(), getObservabilityTier());
|
||||
} else {
|
||||
logger.info("Skipping rendering docs for operator '" + op.name() + "' with no @FunctionInfo");
|
||||
}
|
||||
|
@ -787,11 +794,17 @@ public abstract class DocsV3Support {
|
|||
}
|
||||
};
|
||||
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)
|
||||
throws Exception {
|
||||
void renderDocsForOperators(
|
||||
String name,
|
||||
String titleName,
|
||||
Constructor<?> ctor,
|
||||
FunctionInfo info,
|
||||
boolean variadic,
|
||||
ObservabilityTier observabilityTier
|
||||
) throws Exception {
|
||||
renderKibanaInlineDocs(name, titleName, info);
|
||||
|
||||
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());
|
||||
renderTypes(name, args);
|
||||
renderExamples(info);
|
||||
|
@ -831,17 +844,35 @@ public abstract class DocsV3Support {
|
|||
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 */
|
||||
public static class CommandsDocsSupport extends DocsV3Support {
|
||||
private final LogicalPlan command;
|
||||
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);
|
||||
this.command = command;
|
||||
this.licenseState = licenseState;
|
||||
this.observabilityTier = observabilityTier;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -867,6 +898,9 @@ public abstract class DocsV3Support {
|
|||
if (license != null && license != License.OperationMode.BASIC) {
|
||||
builder.field("license", license.toString());
|
||||
}
|
||||
if (observabilityTier != null && observabilityTier != ObservabilityTier.LOGS_ESSENTIALS) {
|
||||
builder.field("observability_tier", observabilityTier.toString());
|
||||
}
|
||||
String rendered = Strings.toString(builder.endObject());
|
||||
logger.info("Writing kibana command definition for [{}]:\n{}", name, rendered);
|
||||
writeToTempKibanaDir("definition", "json", rendered);
|
||||
|
@ -1044,7 +1078,8 @@ public abstract class DocsV3Support {
|
|||
String titleName,
|
||||
FunctionInfo info,
|
||||
List<EsqlFunctionRegistry.ArgSignature> args,
|
||||
boolean variadic
|
||||
boolean variadic,
|
||||
ObservabilityTier observabilityTier
|
||||
) throws Exception {
|
||||
|
||||
try (XContentBuilder builder = JsonXContent.contentBuilder().prettyPrint().lfAtEnd().startObject()) {
|
||||
|
@ -1067,6 +1102,9 @@ public abstract class DocsV3Support {
|
|||
if (license != null && license != License.OperationMode.BASIC) {
|
||||
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) {
|
||||
builder.field("titleName", titleName);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ import org.elasticsearch.logging.LogManager;
|
|||
import org.elasticsearch.logging.Logger;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
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.Source;
|
||||
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 {
|
||||
log.info("Running function license checks");
|
||||
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) {
|
||||
log.info("Command " + commandName + " implements LicenseAware.");
|
||||
saveLicenseState(commandName, command, checkLicense.licenseLevel(licenseAware));
|
||||
saveLicenseState(commandName, command, checkLicense.licenseLevel(licenseAware), observabilityTier);
|
||||
} else {
|
||||
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(
|
||||
name.toLowerCase(Locale.ROOT),
|
||||
CommandLicenseTests.class,
|
||||
command,
|
||||
licenseState
|
||||
licenseState,
|
||||
observabilityTier
|
||||
);
|
||||
docs.renderDocs();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue