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

EnrichmentScope & EnrichingActivityProcessor #969

Closed
wants to merge 26 commits into from

Conversation

CodeBlanch
Copy link
Member

@CodeBlanch CodeBlanch commented Aug 1, 2020

Update: Released on NuGet here: https://www.nuget.org/packages/Macross.OpenTelemetry.Extensions


Relates to #73. Relates to #809 (option 3, StartAction).

Changes

Added the concept of an enrichment scope. The idea is to give users the ability to add contextual data to the Activity created performing some operation, in a global way.

  • Design discussion (this).
  • TODOs.
  • Unit tests.
  • CHANGELOG update.
  • Example + README.

/// <summary>
/// A class for enriching the data of <see cref="Activity"/> objects.
/// </summary>
public class EnrichmentScope : IDisposable
Copy link
Member

Choose a reason for hiding this comment

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

I know I'm always bad at naming things, the name ContextualProcessor keeps popping up in my mind 😂

Copy link
Member Author

Choose a reason for hiding this comment

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

(I'm not opposed to changing the name. I was just waiting to see if anyone else thought similar or had other ideas.)

Copy link
Member

Choose a reason for hiding this comment

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

Should be my last question in this PR: do we envision a similar concept would be introduced for metrics/logs in the future? If yes, we might need to consider how we name things so we won't be cornered in the future.

Copy link
Member

Choose a reason for hiding this comment

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

This is an interesting point. Slight tangent, but my mental model of "instrumentation" before OTel has been one that combines the concepts of collecting of traces, metrics, etc together. High-level I think of something like HTTP instrumentation as a thing that both generates spans in a trace as well as collecting metrics about the operation. From a configuration perspective, I've wondered if these things will continue to be treated as separate - that is, I build up my trace pipeline/configuration separate from my metric configuration.

In the context of EnrichmentScope, should there be a different trace vs. metric vs. log EnrichmentScope concept? Or can all of these be combined in one EnrichmentScope class that includes the ability to configure behavior on traces, metrics, and logs?

Copy link
Member Author

Choose a reason for hiding this comment

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

There's nothing really Activity-specific about the current implementation. It uses @reyang's RuntimeContext stuff. Essentially what it is doing is buffering a callback/closure to be executed when the final thing to be enriched is available. So in that way, it could work for metrics & logs. Maybe you will be able to give it different callbacks depending on what is being enriched? I don't have enough of a mental picture of the metrics & logging APIs to say conclusively, but it would be great if we had one thing for all the spec areas. Open to suggestions.

Copy link
Member

Choose a reason for hiding this comment

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

My suggestion is that we get this PR merged and continue the discussion here 😆

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I'm leaning towards thinking one thing for all the spec areas make sense, though like you my mental picture is still somewhat fuzzy.

This is why I was pondering this thought in the realm of configuration since that's a little more concrete at the moment. For example, I can see the AddOpenTelemetry extension method on IServiceCollection include additional parameters for a "MeterProviderBuilder" and a "LogProviderBuilder" like how you're suggesting distinct callbacks based on type of telemetry data for EnrichmentScope.

Copy link
Member

Choose a reason for hiding this comment

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

My suggestion is that we get this PR merged and continue the discussion here 😆

yes! agreed.

src/OpenTelemetry/Sdk.cs Outdated Show resolved Hide resolved
@CodeBlanch CodeBlanch changed the title For consideration: EnrichmentScope For consideration: EnrichmentScope & EnrichingActivityProcessor Aug 15, 2020
@CodeBlanch
Copy link
Member Author

Updated the design:

  • Added EnrichingActivityProcessor and moved the logic to apply EnrichmentScopes into there. This was a result of @reyang's feedback. Users not interested in the enrichment no longer need to pay for the perf.
  • Added EnrichmentScopeTarget. This was a result of @alanwest's feedback about options for how the scope should be applied. A little tricky to implement, but I think I got it to work using a doubly-linked-list design.

Fire away!

@codecov
Copy link

codecov bot commented Aug 15, 2020

Codecov Report

Merging #969 into master will increase coverage by 0.13%.
The diff coverage is 92.85%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #969      +/-   ##
==========================================
+ Coverage   75.83%   75.96%   +0.12%     
==========================================
  Files         225      227       +2     
  Lines        6225     6267      +42     
==========================================
+ Hits         4721     4761      +40     
- Misses       1504     1506       +2     
Impacted Files Coverage Δ
.../OpenTelemetry/Trace/EnrichingActivityProcessor.cs 75.00% <75.00%> (ø)
...tp/Implementation/HttpHandlerDiagnosticListener.cs 88.00% <100.00%> (+0.50%) ⬆️
src/OpenTelemetry/Trace/EnrichmentScope.cs 100.00% <100.00%> (ø)
...us/Implementation/PrometheusExporterEventSource.cs 72.72% <0.00%> (+9.09%) ⬆️

Copy link
Member

@reyang reyang left a comment

Choose a reason for hiding this comment

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

LGTM.

@CodeBlanch CodeBlanch changed the title For consideration: EnrichmentScope & EnrichingActivityProcessor EnrichmentScope & EnrichingActivityProcessor Aug 15, 2020
@CodeBlanch CodeBlanch marked this pull request as ready for review August 15, 2020 22:50
@CodeBlanch CodeBlanch requested a review from a team August 15, 2020 22:50
CodeBlanch and others added 2 commits August 15, 2020 16:07
Co-authored-by: Reiley Yang <reyang@microsoft.com>
Co-authored-by: Reiley Yang <reyang@microsoft.com>
@eddynaka
Copy link
Contributor

@eddynaka @reyang Markdownlint is complaining about table rows being too long. How do I make that happy? Doesn't seem to be a way to break in the middle of a row.

don't know if you solved already. but you can try adding a
in the row to break and see if it complains.

@CodeBlanch
Copy link
Member Author

@eddynaka

don't know if you solved already. but you can try adding a
in the row to break and see if it complains.

Add a what? 😄 I tried a few things, couldn't get it to work.

Here's the source:

| Name | Description |
| --- | --- |
| FirstChild | The first child `Activity` created under the scope will be enriched and then the scope will automatically be closed. |

Yields:

Name Description
FirstChild The first child Activity created under the scope will be enriched and then the scope will automatically be closed.
| Name | Description |
| --- | --- |
| FirstChild | The first child `Activity` created under the scope will
 be enriched and then the scope will automatically be closed. |

Yields:

Name Description
FirstChild The first child Activity created under the scope will
be enriched and then the scope will automatically be closed.
| Name | Description |
| --- | --- |
| FirstChild | The first child `Activity` created under the scope will |
|            | be enriched and then the scope will automatically be closed. |

Yields:

Name Description
FirstChild The first child Activity created under the scope will
be enriched and then the scope will automatically be closed.

I think we may need to alter the markdownlint config to ignore tables?

@eddynaka
Copy link
Contributor

@eddynaka

don't know if you solved already. but you can try adding a
in the row to break and see if it complains.

Add a what? 😄 I tried a few things, couldn't get it to work.

Here's the source:

| Name | Description |
| --- | --- |
| FirstChild | The first child `Activity` created under the scope will be enriched and then the scope will automatically be closed. |

Yields:

Name Description
FirstChild The first child Activity created under the scope will be enriched and then the scope will automatically be closed.

| Name | Description |
| --- | --- |
| FirstChild | The first child `Activity` created under the scope will
 be enriched and then the scope will automatically be closed. |

Yields:

Name Description
FirstChild The first child Activity created under the scope will
be enriched and then the scope will automatically be closed.

| Name | Description |
| --- | --- |
| FirstChild | The first child `Activity` created under the scope will |
|            | be enriched and then the scope will automatically be closed. |

Yields:

Name Description
FirstChild The first child Activity created under the scope will
be enriched and then the scope will automatically be closed.
I think we may need to alter the markdownlint config to ignore tables?

I sent the tag in gitter...github replaced the tag with the new line LOL

Copy link
Member

@reyang reyang left a comment

Choose a reason for hiding this comment

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

LGTM, left some minor non-blocking comments.

@reyang
Copy link
Member

reyang commented Aug 15, 2020

@eddynaka @reyang Markdownlint is complaining about table rows being too long. How do I make that happy? Doesn't seem to be a way to break in the middle of a row.

Remove the table, use bullet points. In general markdownlint tries to discourage people from putting long statements in a table due to the readability issue.

Comment on lines +23 to +24
**Note:** Order is important. Make sure your `EnrichingActivityProcessor` is
added before your `Exporter` and any other `ActivityProcessor`s you are using.
Copy link
Member

Choose a reason for hiding this comment

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

Not suggesting any action for this PR, but food for thought...

This note makes me wonder if we should consider codifying processor/exporter ordering in an effort to make this less prone to messing up. I don't have a clear suggestion at the moment, but maybe a combination of "type" and "priority".

Like if we know it's an "exporter type" versus "processor type", can the builder be smart enough to make sure to place it at the end?

Furthermore, maybe not all processors are equal. Some may be "high priority" and should therefore be injected at the beginning of the pipeline. This would in turn require some logic to deal with ties.

Copy link
Member Author

Choose a reason for hiding this comment

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

@reyang Tagging you just in case you didn't see this. Some food for thought as we improve/refactor the build-up. The ordering problem is similar to ASP.NET Core Middleware. Not much provided there, other than guidance that order is critical.

Interesting ideas about distinguishing "exporting processors" versus "enriching processors" versus other types.

Copy link
Member

Choose a reason for hiding this comment

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

Reminded me of TSR and IRP.

Comment on lines +95 to +98
using EnrichmentScope.Begin(
target: EnrichmentScopeTarget.AllChildren,
enrichmentAction: a => a.AddTag("mycompany.customer_id", 5678))
{
Copy link
Member

Choose a reason for hiding this comment

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

Cool, I like what is demonstrated here!

@@ -90,6 +90,7 @@ public override void OnStartActivity(Activity activity, object payload)

activity.SetKind(ActivityKind.Client);
activity.DisplayName = HttpTagHelper.GetOperationNameForHttpMethod(request.Method);
activity.SetCustomProperty("HttpHandler.Request", request);
Copy link
Member

Choose a reason for hiding this comment

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

How does this relate to the enrichment stuff?

Copy link
Member Author

Choose a reason for hiding this comment

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

In the demo I wanted to enrich by some context stuff and by adding userAgent from request & contentType from response. Surprised to notice that the raw objects were not available (they are for .NET Framework). So this is making the raw objects available to anyone downstream that might be interested.

Copy link
Member

@alanwest alanwest left a comment

Choose a reason for hiding this comment

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

I'm as excited about this PR as an Enrichard Simmons!

@CodeBlanch
Copy link
Member Author

Had a chat with @cijothomas. I'm going to take a stab at supporting this via CorrelationContext/Baggage.

@CodeBlanch CodeBlanch closed this Aug 19, 2020
@CodeBlanch CodeBlanch mentioned this pull request Aug 20, 2020
4 tasks
@CodeBlanch
Copy link
Member Author

If anyone lands here looking for a way to make this work I have an updated version (for 1.0) here: https://www.nuget.org/packages/Macross.OpenTelemetry.Extensions

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