Opentelemetry-dotnet: Adding resource tags dinamically after initialization

Created on 5 Nov 2020  路  6Comments  路  Source: open-telemetry/opentelemetry-dotnet

Question

First of all, congratulations on the awesome work!

On OpenTelemetry initialization we do something similar to the following:
c# var resource = Resources.CreateServiceResource(conf.ServiceName, serviceVersion: conf.ServiceVersion) .Merge(new Resource(new Dictionary<string, object> { {"deployment.environment", conf.DeploymentEnvironment}, {"os.type", conf.OsType}, {"os.description", conf.OsDescription}, {"cloud.zone", conf.CloudZone}, {"host.id", conf.HostID}, {"host.name", conf.HostName}, {"host.type", conf.HostType}, })); builder.SetResource(resource); ...
However, to fetch host and cloud information we have to block the initialization process to make calls to AWS API. We would prefer not to block initialization because of this.

Is there a way to add tags to the resource after initialization? Do you guys think of an alternative solution?

question

Most helpful comment

For the caching strategy, yes, that would help with the allocation since we would only need to allocate the new Resource once.

For the enrichment part, it will affect performance when you use Enrich.

I thought I did commit the benchmark for that. I will create a new PR adding it. But you can look here: https://github.com/open-telemetry/opentelemetry-dotnet/pull/1261#issuecomment-695062784

For the processor question, yes that should work as well.

All 6 comments

@tiagonapoli , depending on what kind of instrumentation you are using, you could Enrich from the options to do something like this:

private static void ActivityEnrichment(Activity activity, string method, object obj)
{
    switch (method)
    {
        case "OnStartActivity":
            var resource = activity.GetResource();
            resource.Merge(new Resources.Resource(new Dictionary<string, object>()));
            activity.SetResource(resource);
            break;

        case "OnStopActivity":
            Assert.True(obj is HttpResponse);
            break;

        default:
            break;
    }
}

Currently we're using AspNetCore and Http auto instrumentations. About the enrich solution, we would have to merge the resource for every activity created, do you think the overhead would be considerable?

Does caching the merged resource would be better?

public static class GlobalResource {
  // this initially is set with some tags
  // once data is fetched from AWS this is replaced with a new resource with all data
  public static Resource Data;
}
private static void ActivityEnrichment(Activity activity, string method, object obj)
{
    switch (method)
    {
        case "OnStartActivity":
            activity.SetResource(GlobalResource.Data);
            break;

        case "OnStopActivity":
            // is this necessary?
            Assert.True(obj is HttpResponse);
            break;

        default:
            break;
    }
}

Also, the enrichment would work for Activities created using a ActivitySource? Should we use a processor for this?

For the caching strategy, yes, that would help with the allocation since we would only need to allocate the new Resource once.

For the enrichment part, it will affect performance when you use Enrich.

I thought I did commit the benchmark for that. I will create a new PR adding it. But you can look here: https://github.com/open-telemetry/opentelemetry-dotnet/pull/1261#issuecomment-695062784

For the processor question, yes that should work as well.

Awesome! Thanks a lot!

As per the current spec for Resource, resource is associated with a TracerProvider/MeterProvider, and is same for all the traces/metrics from that provider, and cannot be changed after provider creation.
It is a bug that we allow overriding resource on a per span/activity level. This will very likely be fixed with one of the pending PRs. So do not count on this behaviour.

Closing this issue as no pending items here.

Was this page helpful?
0 / 5 - 0 ratings