Skip to content
This repository was archived by the owner on Dec 23, 2023. It is now read-only.

Commit 1489b5c

Browse files
committed
Always return implementation classes from TagContextsImpl methods.
Now TagContextsImpl.getCurrentTagContext() always returns a TagContextImpl, and TagContextsImpl.withTagContext(TagContext) always puts a TagContextImpl into scope, even when they encounter other subclasses of TagContext.
1 parent 8d4372e commit 1489b5c

File tree

3 files changed

+141
-28
lines changed

3 files changed

+141
-28
lines changed

core/src/main/java/io/opencensus/tags/TagContexts.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,8 @@ public abstract class TagContexts {
4040
*
4141
* @return the current {@code TagContext}.
4242
*/
43-
// TODO(sebright): Should we let the implementation override this method?
44-
public final TagContext getCurrentTagContext() {
45-
TagContext tags = CurrentTagContextUtils.getCurrentTagContext();
46-
return tags == null ? empty() : tags;
43+
public TagContext getCurrentTagContext() {
44+
return CurrentTagContextUtils.getCurrentTagContext();
4745
}
4846

4947
/**
@@ -68,7 +66,7 @@ public TagContextBuilder emptyBuilder() {
6866
* @return a new builder created from the current {@code TagContext}.
6967
*/
7068
public final TagContextBuilder currentBuilder() {
71-
return toBuilder(getCurrentTagContext());
69+
return toBuilder(CurrentTagContextUtils.getCurrentTagContext());
7270
}
7371

7472
/**
@@ -80,7 +78,7 @@ public final TagContextBuilder currentBuilder() {
8078
* @return an object that defines a scope where the given {@code TagContext} is set to the current
8179
* context.
8280
*/
83-
public final Scope withTagContext(TagContext tags) {
81+
public Scope withTagContext(TagContext tags) {
8482
return CurrentTagContextUtils.withTagContext(tags);
8583
}
8684

core_impl/src/main/java/io/opencensus/implcore/tags/TagContextsImpl.java

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,36 +16,75 @@
1616

1717
package io.opencensus.implcore.tags;
1818

19+
import io.opencensus.common.Scope;
1920
import io.opencensus.tags.Tag;
2021
import io.opencensus.tags.TagContext;
21-
import io.opencensus.tags.TagContextBuilder;
2222
import io.opencensus.tags.TagContexts;
2323
import java.util.Iterator;
2424

2525
public final class TagContextsImpl extends TagContexts {
26+
// All methods in this class use TagContextImpl and TagContextBuilderImpl. For example,
27+
// withTagContext(...) always puts a TagContextImpl into scope, even if the argument is another
28+
// TagContext subclass.
29+
//
30+
// TODO(sebright): Consider treating an unknown TagContext as empty. That would allow us to
31+
// remove TagContext.unsafeGetIterator().
2632

2733
@Override
2834
public TagContextImpl empty() {
2935
return TagContextImpl.EMPTY;
3036
}
3137

3238
@Override
33-
public TagContextBuilder emptyBuilder() {
39+
public TagContextImpl getCurrentTagContext() {
40+
return toTagContextImpl(super.getCurrentTagContext());
41+
}
42+
43+
@Override
44+
public TagContextBuilderImpl emptyBuilder() {
3445
return new TagContextBuilderImpl();
3546
}
3647

3748
@Override
38-
public TagContextBuilder toBuilder(TagContext tags) {
39-
// TODO(sebright): Consider treating an unknown TagContext as empty. That would allow us to
40-
// remove TagContext.unsafeGetIterator().
49+
public TagContextBuilderImpl toBuilder(TagContext tags) {
50+
return toTagContextBuilderImpl(tags);
51+
}
52+
53+
@Override
54+
public Scope withTagContext(TagContext tags) {
55+
return super.withTagContext(toTagContextImpl(tags));
56+
}
57+
58+
private static TagContextImpl toTagContextImpl(TagContext tags) {
59+
if (tags instanceof TagContextImpl) {
60+
return (TagContextImpl) tags;
61+
} else {
62+
Iterator<Tag> i = tags.unsafeGetIterator();
63+
if (!i.hasNext()) {
64+
return TagContextImpl.EMPTY;
65+
}
66+
TagContextBuilderImpl builder = new TagContextBuilderImpl();
67+
while (i.hasNext()) {
68+
Tag tag = i.next();
69+
if (tag != null) {
70+
TagContextUtils.addTagToBuilder(tag, builder);
71+
}
72+
}
73+
return builder.build();
74+
}
75+
}
4176

77+
private static TagContextBuilderImpl toTagContextBuilderImpl(TagContext tags) {
4278
// Copy the tags more efficiently in the expected case, when the TagContext is a TagContextImpl.
4379
if (tags instanceof TagContextImpl) {
4480
return new TagContextBuilderImpl(((TagContextImpl) tags).getTags());
4581
} else {
4682
TagContextBuilderImpl builder = new TagContextBuilderImpl();
4783
for (Iterator<Tag> i = tags.unsafeGetIterator(); i.hasNext(); ) {
48-
TagContextUtils.addTagToBuilder(i.next(), builder);
84+
Tag tag = i.next();
85+
if (tag != null) {
86+
TagContextUtils.addTagToBuilder(tag, builder);
87+
}
4988
}
5089
return builder;
5190
}

core_impl/src/test/java/io/opencensus/implcore/tags/TagContextsImplTest.java

Lines changed: 92 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,14 @@
1919
import static com.google.common.truth.Truth.assertThat;
2020

2121
import com.google.common.collect.Lists;
22+
import io.grpc.Context;
23+
import io.opencensus.common.Scope;
2224
import io.opencensus.tags.Tag;
2325
import io.opencensus.tags.Tag.TagBoolean;
2426
import io.opencensus.tags.Tag.TagLong;
2527
import io.opencensus.tags.Tag.TagString;
2628
import io.opencensus.tags.TagContext;
29+
import io.opencensus.tags.TagContextBuilder;
2730
import io.opencensus.tags.TagContexts;
2831
import io.opencensus.tags.TagKey.TagKeyBoolean;
2932
import io.opencensus.tags.TagKey.TagKeyLong;
@@ -32,12 +35,11 @@
3235
import io.opencensus.tags.TagValue.TagValueLong;
3336
import io.opencensus.tags.TagValue.TagValueString;
3437
import io.opencensus.tags.UnreleasedApiAccessor;
38+
import io.opencensus.tags.unsafe.ContextUtils;
3539
import java.util.Collections;
3640
import java.util.Iterator;
3741
import java.util.List;
38-
import org.junit.Rule;
3942
import org.junit.Test;
40-
import org.junit.rules.ExpectedException;
4143
import org.junit.runner.RunWith;
4244
import org.junit.runners.JUnit4;
4345

@@ -55,44 +57,118 @@ public class TagContextsImplTest {
5557
private static final TagValueLong VL = TagValueLong.create(10L);
5658
private static final TagValueBoolean VB = TagValueBoolean.create(false);
5759

58-
@Rule public final ExpectedException thrown = ExpectedException.none();
60+
private static final Tag TAG1 = TagString.create(KS, VS1);
61+
private static final Tag TAG2 = TagLong.create(KL, VL);
62+
private static final Tag TAG3 = TagBoolean.create(KB, VB);
5963

6064
@Test
6165
public void empty() {
6266
assertThat(asList(tagContexts.empty())).isEmpty();
67+
assertThat(tagContexts.empty()).isInstanceOf(TagContextImpl.class);
6368
}
6469

6570
@Test
6671
public void emptyBuilder() {
67-
assertThat(asList(tagContexts.emptyBuilder().build())).isEmpty();
72+
TagContextBuilder builder = tagContexts.emptyBuilder();
73+
assertThat(builder).isInstanceOf(TagContextBuilderImpl.class);
74+
assertThat(asList(builder.build())).isEmpty();
6875
}
6976

7077
@Test
7178
public void toBuilder_ConvertUnknownTagContextToTagContextImpl() {
72-
Tag tag1 = TagString.create(KS, VS1);
73-
Tag tag2 = TagLong.create(KL, VL);
74-
Tag tag3 = TagBoolean.create(KB, VB);
75-
TagContext unknownTagContext = new SimpleTagContext(tag1, tag2, tag3);
79+
TagContext unknownTagContext = new SimpleTagContext(TAG1, TAG2, TAG3);
7680
TagContext newTagContext = tagContexts.toBuilder(unknownTagContext).build();
77-
assertThat(asList(newTagContext)).containsExactly(tag1, tag2, tag3);
81+
assertThat(asList(newTagContext)).containsExactly(TAG1, TAG2, TAG3);
7882
assertThat(newTagContext).isInstanceOf(TagContextImpl.class);
7983
}
8084

8185
@Test
8286
public void toBuilder_RemoveDuplicatesFromUnknownTagContext() {
8387
Tag tag1 = TagString.create(KS, VS1);
8488
Tag tag2 = TagString.create(KS, VS2);
85-
TagContext unknownTagContext = new SimpleTagContext(tag1, tag2);
86-
TagContext newTagContext = tagContexts.toBuilder(unknownTagContext).build();
89+
TagContext tagContextWithDuplicateTags = new SimpleTagContext(tag1, tag2);
90+
TagContext newTagContext = tagContexts.toBuilder(tagContextWithDuplicateTags).build();
8791
assertThat(asList(newTagContext)).containsExactly(tag2);
8892
}
8993

9094
@Test
91-
public void toBuilder_HandleNullTag() {
92-
TagContext unknownTagContext =
93-
new SimpleTagContext(TagString.create(KS, VS2), null, TagLong.create(KL, VL));
94-
thrown.expect(NullPointerException.class);
95-
tagContexts.toBuilder(unknownTagContext).build();
95+
public void toBuilder_SkipNullTag() {
96+
TagContext tagContextWithNullTag = new SimpleTagContext(TAG1, null, TAG2);
97+
TagContext newTagContext = tagContexts.toBuilder(tagContextWithNullTag).build();
98+
assertThat(asList(newTagContext)).containsExactly(TAG1, TAG2);
99+
}
100+
101+
@Test
102+
public void getCurrentTagContext_DefaultIsEmptyTagContextImpl() {
103+
TagContext currentTagContext = tagContexts.getCurrentTagContext();
104+
assertThat(asList(currentTagContext)).isEmpty();
105+
assertThat(currentTagContext).isInstanceOf(TagContextImpl.class);
106+
}
107+
108+
@Test
109+
public void getCurrentTagContext_ConvertUnknownTagContextToTagContextImpl() {
110+
TagContext unknownTagContext = new SimpleTagContext(TAG1, TAG2, TAG3);
111+
TagContext result = getResultOfGetCurrentTagContext(unknownTagContext);
112+
assertThat(result).isInstanceOf(TagContextImpl.class);
113+
assertThat(asList(result)).containsExactly(TAG1, TAG2, TAG3);
114+
}
115+
116+
@Test
117+
public void getCurrentTagContext_RemoveDuplicatesFromUnknownTagContext() {
118+
Tag tag1 = TagString.create(KS, VS1);
119+
Tag tag2 = TagString.create(KS, VS2);
120+
TagContext tagContextWithDuplicateTags = new SimpleTagContext(tag1, tag2);
121+
TagContext result = getResultOfGetCurrentTagContext(tagContextWithDuplicateTags);
122+
assertThat(asList(result)).containsExactly(tag2);
123+
}
124+
125+
@Test
126+
public void getCurrentTagContext_SkipNullTag() {
127+
TagContext tagContextWithNullTag = new SimpleTagContext(TAG1, null, TAG2);
128+
TagContext result = getResultOfGetCurrentTagContext(tagContextWithNullTag);
129+
assertThat(asList(result)).containsExactly(TAG1, TAG2);
130+
}
131+
132+
private TagContext getResultOfGetCurrentTagContext(TagContext tagsToSet) {
133+
Context orig = Context.current().withValue(ContextUtils.TAG_CONTEXT_KEY, tagsToSet).attach();
134+
try {
135+
return tagContexts.getCurrentTagContext();
136+
} finally {
137+
Context.current().detach(orig);
138+
}
139+
}
140+
141+
@Test
142+
public void withTagContext_ConvertUnknownTagContextToTagContextImpl() {
143+
TagContext unknownTagContext = new SimpleTagContext(TAG1, TAG2, TAG3);
144+
TagContext result = getResultOfWithTagContext(unknownTagContext);
145+
assertThat(result).isInstanceOf(TagContextImpl.class);
146+
assertThat(asList(result)).containsExactly(TAG1, TAG2, TAG3);
147+
}
148+
149+
@Test
150+
public void withTagContext_RemoveDuplicatesFromUnknownTagContext() {
151+
Tag tag1 = TagString.create(KS, VS1);
152+
Tag tag2 = TagString.create(KS, VS2);
153+
TagContext tagContextWithDuplicateTags = new SimpleTagContext(tag1, tag2);
154+
TagContext result = getResultOfWithTagContext(tagContextWithDuplicateTags);
155+
assertThat(asList(result)).containsExactly(tag2);
156+
}
157+
158+
@Test
159+
public void withTagContext_SkipNullTag() {
160+
TagContext tagContextWithNullTag = new SimpleTagContext(TAG1, null, TAG2);
161+
TagContext result = getResultOfWithTagContext(tagContextWithNullTag);
162+
assertThat(asList(result)).containsExactly(TAG1, TAG2);
163+
}
164+
165+
private TagContext getResultOfWithTagContext(TagContext tagsToSet) {
166+
Scope scope = tagContexts.withTagContext(tagsToSet);
167+
try {
168+
return ContextUtils.TAG_CONTEXT_KEY.get();
169+
} finally {
170+
scope.close();
171+
}
96172
}
97173

98174
private static List<Tag> asList(TagContext tags) {

0 commit comments

Comments
 (0)