This is an automated email from the ASF dual-hosted git repository. kezhenxu94 pushed a commit to branch feature/multiple-definitions in repository https://gitbox.apache.org/repos/asf/skywalking.git
commit b1ff8c236f113acd5a434a69a5c5197c0fea0a95 Author: kezhenxu94 <[email protected]> AuthorDate: Wed May 12 22:50:31 2021 +0800 Allow multiple definitions as fallback in metadata-service-mapping.yaml file --- CHANGES.md | 1 + .../main/resources/metadata-service-mapping.yaml | 2 +- .../server/core/query/MetadataQueryService.java | 3 +- .../server/receiver/envoy/als/mx/FieldsHelper.java | 84 ++++++++++++++-------- .../receiver/envoy/als/mx/FieldsHelperTest.java | 10 +++ 5 files changed, 69 insertions(+), 31 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 6091d64..e209ae1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -40,6 +40,7 @@ Release Notes. * Support analyzing Envoy TCP access logs and persist error TCP logs. * Fix: Envoy error logs are not persisted when no metrics are generated * Fix: Memory leakage of low version etcd client. [fix-issue](https://github.com/jurmous/etcd4j/pull/185) +* Allow multiple definitions as fallback in metadata-service-mapping.yaml file. #### UI * Add logo for kong plugin. diff --git a/oap-server/server-bootstrap/src/main/resources/metadata-service-mapping.yaml b/oap-server/server-bootstrap/src/main/resources/metadata-service-mapping.yaml index 941ece6..7737432 100644 --- a/oap-server/server-bootstrap/src/main/resources/metadata-service-mapping.yaml +++ b/oap-server/server-bootstrap/src/main/resources/metadata-service-mapping.yaml @@ -13,5 +13,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -serviceName: ${LABELS."service.istio.io/canonical-name"} +serviceName: ${LABELS."service.istio.io/canonical-name",LABELS."app.kubernetes.io/name",LABELS.app} serviceInstanceName: ${NAME} diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetadataQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetadataQueryService.java index a5f1e8b..7f6d674 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetadataQueryService.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetadataQueryService.java @@ -50,11 +50,10 @@ public class MetadataQueryService implements org.apache.skywalking.oap.server.li public List<Service> getAllServices(final String group) throws IOException { return getMetadataQueryDAO().getAllServices(group).stream() - .map(service -> { + .peek(service -> { if (service.getGroup() == null) { service.setGroup(Const.EMPTY_STRING); } - return service; }).collect(Collectors.toList()); } diff --git a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelper.java b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelper.java index 04ad511..a615284 100644 --- a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelper.java +++ b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelper.java @@ -30,7 +30,9 @@ import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import lombok.experimental.Delegate; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.skywalking.oap.server.library.module.ModuleStartException; @@ -39,9 +41,6 @@ import org.apache.skywalking.oap.server.receiver.envoy.als.ServiceMetaInfo; import org.yaml.snakeyaml.Yaml; @Slf4j -/** - * FieldsHelper - */ public enum FieldsHelper { SINGLETON; @@ -79,30 +78,33 @@ public enum FieldsHelper { final String serviceMetaInfoFieldName = entry.getKey(); final String flatBuffersFieldName = entry.getValue(); - final Pattern p = Pattern.compile("(\\$\\{(?<property>.+?)})"); + final Pattern p = Pattern.compile("(\\$\\{(?<properties>.+?)})"); final Matcher m = p.matcher(flatBuffersFieldName); - final List<List<String>> flatBuffersFieldNames = new ArrayList<>(m.groupCount()); + final List<Property> flatBuffersFieldNames = new ArrayList<>(m.groupCount()); final StringBuffer serviceNamePattern = new StringBuffer(); while (m.find()) { - final String property = m.group("property"); - List<String> tokens = Splitter.on('.').omitEmptyStrings().splitToList(property); - - StringBuilder tokenBuffer = new StringBuilder(); - List<String> compactedTokens = new ArrayList<>(tokens.size()); - for (String token : tokens) { - if (tokenBuffer.length() == 0 && token.startsWith("\"")) { - tokenBuffer.append(token); - } else if (tokenBuffer.length() > 0) { - tokenBuffer.append(".").append(token); - if (token.endsWith("\"")) { - compactedTokens.add(tokenBuffer.toString().replaceAll("\"", "")); - tokenBuffer.setLength(0); + final String properties = m.group("properties"); + final List<Field> fields = Splitter.on(',').omitEmptyStrings().splitToList(properties).stream().map(candidate -> { + List<String> tokens = Splitter.on('.').omitEmptyStrings().splitToList(candidate); + + StringBuilder tokenBuffer = new StringBuilder(); + List<String> candidateFields = new ArrayList<>(tokens.size()); + for (String token : tokens) { + if (tokenBuffer.length() == 0 && token.startsWith("\"")) { + tokenBuffer.append(token); + } else if (tokenBuffer.length() > 0) { + tokenBuffer.append(".").append(token); + if (token.endsWith("\"")) { + candidateFields.add(tokenBuffer.toString().replaceAll("\"", "")); + tokenBuffer.setLength(0); + } + } else { + candidateFields.add(token); } - } else { - compactedTokens.add(token); } - } - flatBuffersFieldNames.add(compactedTokens); + return new Field(candidateFields); + }).collect(Collectors.toList()); + flatBuffersFieldNames.add(new Property(fields)); m.appendReplacement(serviceNamePattern, "%s"); } @@ -136,12 +138,18 @@ public enum FieldsHelper { final ServiceNameFormat serviceNameFormat = entry.getValue(); final Object[] values = new String[serviceNameFormat.properties.size()]; for (int i = 0; i < serviceNameFormat.properties.size(); i++) { - final List<String> properties = serviceNameFormat.properties.get(i); - Value value = root; - for (final String property : properties) { - value = value.getStructValue().getFieldsOrDefault(property, empty); + values[i] = "-"; // Give it a default value + final Property property = serviceNameFormat.properties.get(i); + for (final Field field : property) { + Value value = root; + for (final String segment : field.dsvSegments) { + value = value.getStructValue().getFieldsOrDefault(segment, empty); + } + if (Strings.isNullOrEmpty(value.getStringValue()) || "-".equals(value.getStringValue())) { + continue; + } + values[i] = value.getStringValue(); } - values[i] = value.getStringValue(); } final String value = Strings.lenientFormat(serviceNameFormat.format, values); if (!Strings.isNullOrEmpty(value)) { @@ -154,6 +162,26 @@ public enum FieldsHelper { private static class ServiceNameFormat { private final String format; - private final List<List<String>> properties; + private final List<Property> properties; + } + + /** + * A property in the metadata map, it may have multiple candidates, of which the first is non empty will be used. + * For example, to look up the service name, you may set candidates like ${LABELS."service.istio.io/canonical-name",LABELS."app.kubernetes.io/name","app"}. + */ + @RequiredArgsConstructor + private static class Property implements Iterable<Field> { + @Delegate + private final List<Field> candidateFields; + } + + /** + * A field in the property, it may be nested such as LABELS.app, LABELS.revision, etc. + * {@link #dsvSegments} are the `.` separated segment list, such as ["LABELS", "app"], ["LABELS", "revision"]. + */ + @RequiredArgsConstructor + private static class Field implements Iterable<String> { + @Delegate + private final List<String> dsvSegments; } } diff --git a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelperTest.java b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelperTest.java index 8a38c18..448b343 100644 --- a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelperTest.java +++ b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelperTest.java @@ -69,6 +69,16 @@ public class FieldsHelperTest { "serviceName: fixed-${LABELS.\"service.istio.io/canonical-name\"}\nserviceInstanceName: yeah_${NAME}", "fixed-productpage", "yeah_productpage-v1-65576bb7bf-4mzsp" + }, + { + "serviceName: fixed-${LABELS.\"service.istio.io/not-exist\",LABELS.\"service.istio.io/canonical-name\"}\nserviceInstanceName: yeah_${NAME}", + "fixed-productpage", + "yeah_productpage-v1-65576bb7bf-4mzsp" + }, + { + "serviceName: fixed-${LABELS.\"service.istio.io/not-exist\",LABELS.\"service.istio.io/not-exist-2\"}\nserviceInstanceName: yeah_${NAME}", + "fixed--", + "yeah_productpage-v1-65576bb7bf-4mzsp" } }); }
