opentelemetry-dotnet/src/OpenTelemetry.Api/Trace/TelemetrySpan.cs

333 lines
12 KiB
C#

// <copyright file="TelemetrySpan.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry 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
//
// http://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.
// </copyright>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace OpenTelemetry.Trace
{
/// <summary>
/// <para>Span represents the execution of the certain span of code or span of time between two events which is part of
/// a distributed trace and has result of execution, context of execution and other properties.</para>
/// </summary>
/// <remarks>Represents OpenTelemetry Span https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/api.md#span.</remarks>
public class TelemetrySpan : IDisposable
{
internal static readonly TelemetrySpan NoopInstance = new TelemetrySpan(null);
internal readonly Activity Activity;
private static readonly IEnumerable<KeyValuePair<string, string>> EmptyBaggage = new KeyValuePair<string, string>[0];
internal TelemetrySpan(Activity activity)
{
this.Activity = activity;
}
/// <summary>
/// Gets the span context.
/// </summary>
public SpanContext Context
{
get
{
if (this.Activity == null)
{
return default;
}
else
{
return new SpanContext(this.Activity.Context);
}
}
}
/// <summary>
/// Gets a value indicating whether this span will be recorded.
/// </summary>
public bool IsRecording
{
get
{
return this.Activity != null && this.Activity.IsAllDataRequested;
}
}
/// <summary>
/// Gets the span baggage.
/// </summary>
public IEnumerable<KeyValuePair<string, string>> Baggage => this.Activity?.Baggage ?? EmptyBaggage;
/// <summary>
/// Sets the status of the span execution.
/// </summary>
/// <param name="value">Status to be set.</param>
public void SetStatus(Status value)
{
this.Activity?.SetStatus(value);
}
/// <summary>
/// Updates the <see cref="TelemetrySpan"/> name.
///
/// If used, this will override the name provided via StartSpan method overload.
/// Upon this update, any sampling behavior based on <see cref="TelemetrySpan"/> name will depend on the
/// implementation.
/// </summary>
/// <param name="name">Name of the span.</param>
/// <returns>The <see cref="TelemetrySpan"/> instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TelemetrySpan UpdateName(string name)
{
if (this.Activity != null)
{
this.Activity.DisplayName = name;
}
return this;
}
/// <summary>
/// Sets a new attribute on the span.
/// </summary>
/// <param name="key">Attribute key.</param>
/// <param name="value">Attribute value.</param>
/// <returns>The <see cref="TelemetrySpan"/> instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TelemetrySpan SetAttribute(string key, string value)
{
this.Activity?.SetTag(key, value);
return this;
}
/// <summary>
/// Sets a new attribute on the span.
/// </summary>
/// <param name="key">Attribute key.</param>
/// <param name="value">Attribute value.</param>
/// <returns>The <see cref="TelemetrySpan"/> instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TelemetrySpan SetAttribute(string key, int value)
{
this.Activity?.SetTag(key, value);
return this;
}
/// <summary>
/// Sets a new attribute on the span.
/// </summary>
/// <param name="key">Attribute key.</param>
/// <param name="value">Attribute value.</param>
/// <returns>The <see cref="TelemetrySpan"/> instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TelemetrySpan SetAttribute(string key, bool value)
{
this.Activity?.SetTag(key, value);
return this;
}
/// <summary>
/// Sets a new attribute on the span.
/// </summary>
/// <param name="key">Attribute key.</param>
/// <param name="value">Attribute value.</param>
/// <returns>The <see cref="TelemetrySpan"/> instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TelemetrySpan SetAttribute(string key, double value)
{
this.Activity?.SetTag(key, value);
return this;
}
/// <summary>
/// Sets a new attribute on the span.
/// </summary>
/// <param name="key">Attribute key.</param>
/// <param name="values">Attribute values.</param>
/// <returns>The <see cref="TelemetrySpan"/> instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TelemetrySpan SetAttribute(string key, string[] values)
{
this.Activity?.SetTag(key, values);
return this;
}
/// <summary>
/// Sets a new attribute on the span.
/// </summary>
/// <param name="key">Attribute key.</param>
/// <param name="values">Attribute values.</param>
/// <returns>The <see cref="TelemetrySpan"/> instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TelemetrySpan SetAttribute(string key, int[] values)
{
this.Activity?.SetTag(key, values);
return this;
}
/// <summary>
/// Sets a new attribute on the span.
/// </summary>
/// <param name="key">Attribute key.</param>
/// <param name="values">Attribute values.</param>
/// <returns>The <see cref="TelemetrySpan"/> instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TelemetrySpan SetAttribute(string key, bool[] values)
{
this.Activity?.SetTag(key, values);
return this;
}
/// <summary>
/// Sets a new attribute on the span.
/// </summary>
/// <param name="key">Attribute key.</param>
/// <param name="values">Attribute values.</param>
/// <returns>The <see cref="TelemetrySpan"/> instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TelemetrySpan SetAttribute(string key, double[] values)
{
this.Activity?.SetTag(key, values);
return this;
}
/// <summary>
/// Adds a single Event to the <see cref="TelemetrySpan"/>.
/// </summary>
/// <param name="name">Name of the event.</param>
/// <returns>The <see cref="TelemetrySpan"/> instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TelemetrySpan AddEvent(string name)
{
this.Activity?.AddEvent(new ActivityEvent(name));
return this;
}
/// <summary>
/// Adds a single Event to the <see cref="TelemetrySpan"/>.
/// </summary>
/// <param name="name">Name of the event.</param>
/// <param name="timestamp">Timestamp of the event.</param>
/// <returns>The <see cref="TelemetrySpan"/> instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TelemetrySpan AddEvent(string name, DateTimeOffset timestamp)
{
this.Activity?.AddEvent(new ActivityEvent(name, timestamp));
return this;
}
/// <summary>
/// Adds a single Event to the <see cref="TelemetrySpan"/>.
/// </summary>
/// <param name="name">Name of the event.</param>
/// <param name="attributes">Attributes for the event.</param>
/// <returns>The <see cref="TelemetrySpan"/> instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TelemetrySpan AddEvent(string name, IDictionary<string, object> attributes)
{
ActivityTagsCollection eventTags = new ActivityTagsCollection(attributes);
this.Activity?.AddEvent(new ActivityEvent(name, default, eventTags));
return this;
}
/// <summary>
/// Adds a single Event to the <see cref="TelemetrySpan"/>.
/// </summary>
/// <param name="name">Name of the event.</param>
/// <param name="timestamp">Timestamp of the event.</param>
/// <param name="attributes">Attributes for the event.</param>
/// <returns>The <see cref="TelemetrySpan"/> instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TelemetrySpan AddEvent(string name, DateTimeOffset timestamp, IDictionary<string, object> attributes)
{
var eventTags = new ActivityTagsCollection(attributes);
this.Activity?.AddEvent(new ActivityEvent(name, timestamp, eventTags));
return this;
}
/// <summary>
/// End the span.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void End()
{
this.Activity?.Stop();
}
/// <summary>
/// End the span.
/// </summary>
/// <param name="endTimestamp">End timestamp.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void End(DateTimeOffset endTimestamp)
{
this.Activity?.SetEndTime(endTimestamp.UtcDateTime);
this.Activity?.Stop();
}
/// <summary>
/// Retrieves a baggage item.
/// </summary>
/// <param name="key">Baggage item key.</param>
/// <returns>Retrieved baggage value or <see langword="null"/> if no match was found.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string GetBaggageItem(string key)
{
return this.Activity?.GetBaggageItem(key);
}
/// <summary>
/// Adds a baggage item to the <see cref="TelemetrySpan"/>.
/// </summary>
/// <param name="key">Baggage item key.</param>
/// <param name="value">Baggage item value.</param>
/// <returns>The <see cref="TelemetrySpan"/> instance for chaining.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TelemetrySpan AddBaggage(string key, string value)
{
this.Activity?.AddBaggage(key, value);
return this;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Marks the span as current.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void Activate()
{
Activity.Current = this.Activity;
}
/// <summary>
/// Releases the unmanaged resources used by this class and optionally releases the managed resources.
/// </summary>
/// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
this.Activity?.Dispose();
}
}
}