未验证 提交 85a993fa 编写于 作者: Z Zhenxu Ke 提交者: GitHub

Allow multiple definitions as fallback in metadata-service-mapping.yaml file (#6933)

上级 60604647
......@@ -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.
......
......@@ -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}
......@@ -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());
}
......
......@@ -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;
}
}
......@@ -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"
}
});
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册