Skip to content

Commit

Permalink
Merge pull request #239 from micrometer-metrics/nikoncode-wip-234-oth…
Browse files Browse the repository at this point in the history
…er-types-for-tags

Adds support for tags with typed values
  • Loading branch information
marcingrzejszczak committed Apr 20, 2023
2 parents 7ff0829 + dc04753 commit 13f060c
Show file tree
Hide file tree
Showing 21 changed files with 435 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,12 @@ public FinishedSpan addLinks(List<Link> links) {

private void addLink(long index, Link link) {
TraceContext traceContext = link.getTraceContext();
Map<String, String> tags = link.getTags();
Map<String, Object> tags = link.getTags();
this.mutableSpan.tag(LinkUtils.traceIdKey(index), traceContext.traceId());
this.mutableSpan.tag(LinkUtils.spanIdKey(index), traceContext.spanId());
for (Map.Entry<String, String> e : tags.entrySet()) {
for (Map.Entry<String, Object> e : tags.entrySet()) {
String key = e.getKey();
String value = e.getValue();
String value = String.valueOf(e.getValue());
this.mutableSpan.tag(LinkUtils.tagKey(index, key), value);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public Span.Builder addLink(Link link) {
long nextId = LinkUtils.nextIndex(this.tags);
this.tags.put(LinkUtils.spanIdKey(nextId), braveContext.spanIdString());
this.tags.put(LinkUtils.traceIdKey(nextId), braveContext.traceIdString());
link.getTags().forEach((key, value) -> this.tags.put(LinkUtils.tagKey(nextId, key), value));
link.getTags().forEach((key, value) -> this.tags.put(LinkUtils.tagKey(nextId, key), String.valueOf(value)));
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ static int nextIndex(Map<String, String> tags) {
static Link toLink(List<Map.Entry<String, String>> groupedTags) {
String traceId = "";
String spanId = "";
Map<String, String> tags = new HashMap<>();
Map<String, Object> tags = new HashMap<>();
for (Map.Entry<String, String> groupedTag : groupedTags) {
if (groupedTag.getKey().endsWith(".traceId")) {
traceId = groupedTag.getValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
*/
package io.micrometer.tracing.brave.bridge;

import java.time.Instant;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import brave.Tracer;
import brave.Tracing;
import brave.handler.MutableSpan;
Expand All @@ -25,12 +31,6 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

import java.time.Instant;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static org.assertj.core.api.BDDAssertions.then;

class BraveFinishedSpanTests {
Expand All @@ -41,8 +41,6 @@ class BraveFinishedSpanTests {

Tracer tracer = tracing.tracer();

BraveTracer braveTracer = new BraveTracer(tracer, new BraveCurrentTraceContext(tracing.currentTraceContext()));

@AfterEach
void cleanup() {
tracing.close();
Expand All @@ -62,6 +60,30 @@ void should_calculate_instant_from_brave_timestamps() {
then(finishedSpan.getEndTimestamp().toEpochMilli()).isEqualTo(TimeUnit.MICROSECONDS.toMillis(endMicros));
}

@Test
void should_set_tags() {
FinishedSpan span = BraveFinishedSpan.fromBrave(new MutableSpan(tracer.nextSpan().context(), null));
then(span.getTags()).isEmpty();

Map<String, String> map = new HashMap<>();
map.put("foo", "bar");
span.setTags(map);

then(span.getTags().get("foo")).isEqualTo("bar");
}

@Test
void should_set_typed_tags() {
FinishedSpan span = BraveFinishedSpan.fromBrave(new MutableSpan(tracer.nextSpan().context(), null));
then(span.getTypedTags()).isEmpty();

Map<String, Object> map = new HashMap<>();
map.put("foo", 2L);
span.setTypedTags(map);

then(span.getTypedTags().get("foo")).isEqualTo("2");
}

@Test
void should_set_links() {
Tracer tracer = tracing.tracer();
Expand All @@ -84,8 +106,8 @@ void should_set_links() {
new Link(span3.context(), tags()), new Link(span4.context(), tags()));
}

private Map<String, String> tags() {
Map<String, String> map = new HashMap<>();
private Map<String, Object> tags() {
Map<String, Object> map = new HashMap<>();
map.put("tag1", "value1");
map.put("tag2", "value2");
return map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
*/
package io.micrometer.tracing.brave.bridge;

import java.util.HashMap;
import java.util.Map;

import brave.Tracer;
import brave.Tracing;
import brave.handler.MutableSpan;
Expand All @@ -24,9 +27,6 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.Map;

import static org.assertj.core.api.BDDAssertions.then;

class BraveSpanBuilderTests {
Expand Down Expand Up @@ -70,8 +70,23 @@ void should_set_links() {
.containsEntry("links[1].spanId", span1.context().spanId());
}

private Map<String, String> tags() {
Map<String, String> map = new HashMap<>();
@Test
void should_set_non_string_tags() {
new BraveSpanBuilder(tracing.tracer()).tag("string", "string")
.tag("double", 2.5)
.tag("long", 2)
.tag("boolean", true)
.start()
.end();

then(handler.get(0).tags()).containsEntry("string", "string")
.containsEntry("double", "2.5")
.containsEntry("long", "2")
.containsEntry("boolean", "true");
}

private Map<String, Object> tags() {
Map<String, Object> map = new HashMap<>();
map.put("tag1", "value1");
map.put("tag2", "value2");
return map;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* Copyright 2023 the original author or authors.
*
* Licensed 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
*
* https://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 io.micrometer.tracing.brave.bridge;

import brave.Tracing;
import brave.test.TestSpanHandler;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class BraveSpanTest {

TestSpanHandler handler = new TestSpanHandler();

Tracing tracing = Tracing.newBuilder().addSpanHandler(handler).build();

@Test
void should_set_non_string_tags() {
new BraveSpan(tracing.tracer().nextSpan()).start()
.tag("string", "string")
.tag("double", 2.5)
.tag("long", 2)
.tag("boolean", true)
.end();

assertThat(handler.get(0).tags()).containsEntry("string", "string")
.containsEntry("double", "2.5")
.containsEntry("long", "2")
.containsEntry("boolean", "true");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@
*/
package io.micrometer.tracing.otel.bridge;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.time.Instant;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import io.micrometer.tracing.Link;
import io.micrometer.tracing.Span;
import io.micrometer.tracing.TraceContext;
Expand All @@ -29,12 +41,6 @@
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

/**
* OpenTelemetry implementation of a {@link FinishedSpan}.
*
Expand Down Expand Up @@ -101,6 +107,37 @@ public FinishedSpan setTags(Map<String, String> tags) {

@Override
public Map<String, String> getTags() {
return this.spanData.tags.entrySet()
.stream()
.collect(Collectors.toMap(e -> e.getKey().getKey(), entry -> String.valueOf(entry.getValue())));
}

@Override
public FinishedSpan setTypedTags(Map<String, Object> tags) {
this.spanData.tags.clear();
this.spanData.tags.putAll(tags.entrySet().stream().collect(Collectors.toMap(e -> {
Object value = e.getValue();
return getAttributeKey(e.getKey(), value);
}, Map.Entry::getValue)));
return this;
}

@SuppressWarnings("raw")
private static AttributeKey getAttributeKey(String key, Object value) {
if (value instanceof Double) {
return AttributeKey.doubleKey(key);
}
else if (value instanceof Long) {
return AttributeKey.longKey(key);
}
else if (value instanceof Boolean) {
return AttributeKey.booleanKey(key);
}
return AttributeKey.stringKey(key);
}

@Override
public Map<String, Object> getTypedTags() {
return this.spanData.tags.entrySet()
.stream()
.collect(Collectors.toMap(e -> e.getKey().getKey(), Map.Entry::getValue));
Expand Down Expand Up @@ -260,11 +297,12 @@ public FinishedSpan addLinks(List<Link> links) {
}

@Override
@SuppressWarnings("unchecked")
public FinishedSpan addLink(Link link) {
TraceContext traceContext = link.getTraceContext();
Map<String, String> tags = link.getTags();
Map<String, Object> tags = link.getTags();
AttributesBuilder builder = Attributes.builder();
tags.forEach(builder::put);
tags.forEach((s, o) -> builder.put(getAttributeKey(s, o), o));
this.spanData.getLinks()
.add(LinkData.create(OtelTraceContext.toOtelSpanContext(traceContext), builder.build()));
return this;
Expand Down Expand Up @@ -301,7 +339,7 @@ static class MutableSpanData extends DelegatingSpanData {

long endEpochNanos;

final Map<AttributeKey, String> tags = new HashMap<>();
final Map<AttributeKey, Object> tags = new HashMap<>();

final List<EventData> events = new ArrayList<>();

Expand All @@ -312,7 +350,7 @@ static class MutableSpanData extends DelegatingSpanData {
this.name = delegate.getName();
this.startEpochNanos = delegate.getStartEpochNanos();
this.endEpochNanos = delegate.getEndEpochNanos();
delegate.getAttributes().forEach((key, value) -> this.tags.put(key, String.valueOf(value)));
delegate.getAttributes().forEach(this.tags::put);
this.events.addAll(delegate.getEvents());
this.links.addAll(delegate.getLinks());
}
Expand All @@ -330,7 +368,7 @@ public long getStartEpochNanos() {
@Override
public Attributes getAttributes() {
AttributesBuilder builder = Attributes.builder();
for (Map.Entry<AttributeKey, String> entry : this.tags.entrySet()) {
for (Map.Entry<AttributeKey, Object> entry : this.tags.entrySet()) {
builder = builder.put(entry.getKey(), entry.getValue());
}
return builder.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,24 @@ public Span tag(String key, String value) {
return new OtelSpan(this.delegate);
}

@Override
public Span tag(String key, long value) {
this.delegate.setAttribute(key, value);
return new OtelSpan(this.delegate);
}

@Override
public Span tag(String key, double value) {
this.delegate.setAttribute(key, value);
return new OtelSpan(this.delegate);
}

@Override
public Span tag(String key, boolean value) {
this.delegate.setAttribute(key, value);
return new OtelSpan(this.delegate);
}

@Override
public void end(long time, TimeUnit timeUnit) {
this.delegate.end(time, timeUnit);
Expand Down

0 comments on commit 13f060c

Please sign in to comment.