blob: 4b4ba09a6bbb35eab802db815873665cb04326a2 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.servicecomb.tests.tracing;
import static org.apache.servicecomb.foundation.common.base.ServiceCombConstants.CONFIG_TRACING_COLLECTOR_ADDRESS;
import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
import java.lang.invoke.MethodHandles;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.apache.servicecomb.tests.EmbeddedAppender;
import org.apache.servicecomb.tests.Log4jConfig;
import org.awaitility.Awaitility;
import org.hamcrest.MatcherAssert;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestTemplate;
import zipkin2.Span;
import zipkin2.junit.ZipkinRule;
public class TracingTestBase {
@ClassRule
public static final ZipkinRule zipkin = new ZipkinRule();
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
protected static final EmbeddedAppender appender = new EmbeddedAppender();
final RestTemplate restTemplate = new RestTemplate();
@BeforeClass
public static void setUpClass() throws Exception {
System.setProperty(CONFIG_TRACING_COLLECTOR_ADDRESS, zipkin.httpUrl());
Log4jConfig.addAppender(appender);
}
protected void assertThatSpansReceivedByZipkin(Collection<String> logs, String... values) {
logs.forEach(message -> log.info("Received log: " + message));
List<String> loggedIds = logs.stream()
.map(this::extractIds)
.collect(Collectors.toList());
Awaitility.await().atMost(10, TimeUnit.SECONDS).until(() -> zipkin.getTrace(traceId(loggedIds)) != null);
List<Span> spans = zipkin.getTrace(traceId(loggedIds));
List<String> tracedValues = tracedValues(spans);
int times = 100;
while (tracedValues.size() < values.length && times > 0) {
try {
Thread.sleep(10);
times--;
spans = zipkin.getTrace(traceId(loggedIds));
tracedValues = tracedValues(spans);
} catch (InterruptedException e) {
log.error("Thread interrupted, {}", e.getMessage());
Thread.currentThread().interrupt();
}
}
tracedValues.forEach(value -> log.info("Received value {}", value));
log.info("values: " + String.join(",", values));
MatcherAssert.assertThat(tracedValues, containsInAnyOrder(values));
}
private List<String> tracedValues(List<Span> spans) {
return spans.stream()
.filter(span -> span.tags() != null)
.map(span -> span.tags().entrySet())
.flatMap(Collection::stream)
.filter(span -> "call.path".equals(span.getKey()) || "http.path".equals(span.getKey())
|| "http.status_code".equals(span.getKey()))
.filter(span -> span.getValue() != null)
.map(Map.Entry::getValue)
.distinct()
.collect(Collectors.toList());
}
private String extractIds(String message) {
return message.replaceFirst(".*\\[(\\w+/\\w+/\\w*)\\].*", "$1").trim();
}
private String traceId(List<String> ids) {
return ids.get(0).split("/")[0];
}
}