Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating exporters to use TagObjects instead of Tags #1000

Merged
merged 8 commits into from
Aug 5, 2020
Merged

Updating exporters to use TagObjects instead of Tags #1000

merged 8 commits into from
Aug 5, 2020

Conversation

eddynaka
Copy link
Contributor

@eddynaka eddynaka commented Aug 4, 2020

Fixes part of #940

Part 2 of #954

Changes

Please provide a brief description of the changes here. Update the
CHANGELOG.md for non-trivial changes.

For significant contributions please make sure you have completed the following items:

  • Design discussion issue #
  • Changes in public API reviewed

@eddynaka eddynaka requested a review from a team August 4, 2020 18:03
else if (activityTag.Value is string stringVal)
{
jaegerTag = new JaegerTag(activityTag.Key, JaegerTagType.STRING, stringVal);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add my open qn here: what is the Value is of some other type? (eg: Datetime). Should we try to call .ToString() on it? or drop it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we have a duplicate part of code. let me change and we can review again.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now, we already have a method that converts the default case to string:

        public static JaegerTag ToJaegerTag(this KeyValuePair<string, object> attribute)
        {
            return attribute.Value switch
            {
                string s => new JaegerTag(attribute.Key, JaegerTagType.STRING, vStr: s),
                int i => new JaegerTag(attribute.Key, JaegerTagType.LONG, vLong: Convert.ToInt64(i)),
                long l => new JaegerTag(attribute.Key, JaegerTagType.LONG, vLong: l),
                float f => new JaegerTag(attribute.Key, JaegerTagType.DOUBLE, vDouble: Convert.ToDouble(f)),
                double d => new JaegerTag(attribute.Key, JaegerTagType.DOUBLE, vDouble: d),
                bool b => new JaegerTag(attribute.Key, JaegerTagType.BOOL, vBool: b),
                _ => new JaegerTag(attribute.Key, JaegerTagType.STRING, vStr: attribute.Value.ToString()),
            };
        }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add my open qn here: what is the Value is of some other type? (eg: Datetime). Should we try to call .ToString() on it? or drop it?

This is an interesting question. Has there been any efforts you're aware of at the spec level for this? I like being able to support DateTime versus dropping it, but dates are always hard, particularly handling them across languages. Does it make sense to adopt ISO 8601 as a standard format? I think in .NET that is done with .ToString("o").

TimeSpan can be useful too. I think by default ToString formats these as HH:MM:SS. Does it make sense to just adopt seconds or milliseconds?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not aware of any spec changes coming to support more types for attributes.
Span and SpanEvent has timestamps on it, so probably there is no need of supporting tag of type datetime ?

If one is using OTel API, they can only send supported types - string, int, bool, array. Not possible to send DateTime or any other type.
(Activity support string,object pair, so we need to decide if the exporters should do "ToString" on whatever custom objects are provided)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now, the default is ToString, we could close this and open a new issue specific for other types. What do u think? @cijothomas @alanwest

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merging this now - we need to comeback and decide if we are okay to do .ToString here.

@codecov
Copy link

codecov bot commented Aug 4, 2020

Codecov Report

Merging #1000 into master will increase coverage by 0.02%.
The diff coverage is 68.08%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1000      +/-   ##
==========================================
+ Coverage   68.19%   68.22%   +0.02%     
==========================================
  Files         219      219              
  Lines        5974     5976       +2     
  Branches      978      978              
==========================================
+ Hits         4074     4077       +3     
+ Misses       1626     1622       -4     
- Partials      274      277       +3     
Impacted Files Coverage Δ
...metry.Exporter.Zipkin/Implementation/ZipkinSpan.cs 72.09% <21.42%> (-10.34%) ⬇️
...plementation/ZipkinActivityConversionExtensions.cs 78.94% <82.35%> (+4.75%) ⬆️
....Jaeger/Implementation/JaegerActivityExtensions.cs 89.39% <93.33%> (+4.77%) ⬆️
...metryProtocol/Implementation/ActivityExtensions.cs 87.70% <100.00%> (+0.20%) ⬆️

}

return new JaegerTag(attribute.Key, JaegerTagType.STRING, vStr: attribute.Value.ToString());
string s => new JaegerTag(attribute.Key, JaegerTagType.STRING, vStr: s),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we now need to deal with the array of primitives since #999 is merged.

Copy link
Member

@cijothomas cijothomas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay to have separate PR for handling array of primitives.

@eddynaka
Copy link
Contributor Author

eddynaka commented Aug 4, 2020

Okay to have separate PR for handling array of primitives.

About that, if we receive an array of primitives, should we transmite that? how are we going to handle?
But, sure, i agree that they are different things and we can separate.

I'm asking just to create an issue so we can track :)

@cijothomas cijothomas merged commit 53a579f into open-telemetry:master Aug 5, 2020
DictionaryEnumerator<string, string, TagState>.AllocationFreeForEach(
activity.Tags,
DictionaryEnumerator<string, object, TagState>.AllocationFreeForEach(
activity.TagObjects,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tarekgh Just noticing Activity.TagObjects uses a custom LinkedList and not ActivityTagsCollection like ActivityEvent & ActivityLink use. Because of that, no struct enumerator, perf regression for us anytime we enumerate TagObjects. Is there a compelling reason for the difference? What we really need is for whatever is underneath the IEnumerable returned to have a struct GetEnumerator() operation so we can foreach without allocation.

Something like...

   private class TagsLinkedList : IEnumerable<KeyValuePair<string, object>>
   {
        public Enumerator<KeyValuePair<string, object>> GetEnumerator() { return Enumerator(this); }
        IEnumerator<T> IEnumerable<KeyValuePair<string, object>>.GetEnumerator() { return Enumerator(this); }
        IEnumerator IEnumerable.GetEnumerator() { return Enumerator(this); }

        private struct Enumerator<KeyValuePair<string, object>> { ... }
   }

        public IEnumerable<KeyValuePair<string, object?>> TagObjects
        {
            get => _tags ?? Unsafe.As<IEnumerable<KeyValuePair<string, object?>>>(s_emptyBaggageTags);
        }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something can look at to optimize as everything is implementation details. I didn't change anything from what we used to have. Note that this will be a little bit tricky because it is possible some tags get removed while someone else enumerating the list.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome this would help a lot. When I say perf regression I mean moving from our old Span object to using Activity to drive everything.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are interested, you may submit a PR for that? we can work out the details together if you want.

CC @noahfalk

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eddynaka eddynaka deleted the feature/updating-zipking-newactivity branch August 14, 2020 00:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants