1
0
Эх сурвалжийг харах

Document logs essentials restricted ESQL commands for Kibana (#130346)

Mark Vieira 3 сар өмнө
parent
commit
7d4ba31681

+ 2 - 1
docs/reference/query-languages/esql/kibana/definition/commands/change_point.json

@@ -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"
 }

+ 1 - 0
docs/reference/query-languages/esql/kibana/definition/functions/categorize.json

@@ -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" : [
     {

+ 1 - 0
x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/ConsumeProcessor.java

@@ -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",

+ 25 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/SupportsObservabilityTier.java

@@ -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
+    }
+}

+ 3 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/grouping/Categorize.java

@@ -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,

+ 3 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/logical/ChangePoint.java

@@ -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;

+ 46 - 8
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/DocsV3Support.java

@@ -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);
             }

+ 17 - 4
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plan/logical/CommandLicenseTests.java

@@ -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();
     }