Skip to content

Commit

Permalink
Identified all exception throws in code base (open-telemetry#2416)
Browse files Browse the repository at this point in the history
  • Loading branch information
mic-max authored Oct 18, 2021
1 parent 84bdf38 commit 6e6afdb
Show file tree
Hide file tree
Showing 92 changed files with 741 additions and 670 deletions.
6 changes: 2 additions & 4 deletions src/OpenTelemetry.Api/Baggage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using System.Collections.Generic;
using System.Linq;
using OpenTelemetry.Context;
using OpenTelemetry.Internal;

namespace OpenTelemetry
{
Expand Down Expand Up @@ -238,10 +239,7 @@ public IReadOnlyDictionary<string, string> GetBaggage()
/// <returns>Baggage item or <see langword="null"/> if nothing was found.</returns>
public string GetBaggage(string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException(nameof(name));
}
Guard.NullOrEmpty(name, nameof(name));

return this.baggage != null && this.baggage.TryGetValue(name, out string value)
? value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

using System;
using System.Collections.Generic;
using OpenTelemetry.Internal;

namespace OpenTelemetry.Context.Propagation
{
Expand All @@ -34,7 +35,9 @@ public class CompositeTextMapPropagator : TextMapPropagator
/// <param name="propagators">List of <see cref="TextMapPropagator"/> wire context propagator.</param>
public CompositeTextMapPropagator(IEnumerable<TextMapPropagator> propagators)
{
this.propagators = new List<TextMapPropagator>(propagators ?? throw new ArgumentNullException(nameof(propagators)));
Guard.Null(propagators, nameof(propagators));

this.propagators = new List<TextMapPropagator>(propagators);
}

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ private static byte HexCharToByte(char c)
return (byte)(c - 'a' + 10);
}

throw new ArgumentOutOfRangeException(nameof(c), c, $"Invalid character: {c}.");
throw new ArgumentOutOfRangeException(nameof(c), c, "Must be within: [0-9] or [a-f]");
}

private static bool ValidateKey(ReadOnlySpan<char> key)
Expand Down
74 changes: 25 additions & 49 deletions src/OpenTelemetry.Api/Context/RuntimeContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using OpenTelemetry.Internal;

namespace OpenTelemetry.Context
{
Expand All @@ -40,16 +41,13 @@ public static class RuntimeContext
/// <returns>The slot registered.</returns>
public static RuntimeContextSlot<T> RegisterSlot<T>(string slotName)
{
if (string.IsNullOrEmpty(slotName))
{
throw new ArgumentException($"{nameof(slotName)} cannot be null or empty string.");
}
Guard.NullOrEmpty(slotName, nameof(slotName));

lock (Slots)
{
if (Slots.ContainsKey(slotName))
{
throw new InvalidOperationException($"The context slot {slotName} is already registered.");
throw new InvalidOperationException($"Context slot already registered: '{slotName}'");
}

var type = ContextSlotType.MakeGenericType(typeof(T));
Expand All @@ -68,17 +66,10 @@ public static RuntimeContextSlot<T> RegisterSlot<T>(string slotName)
/// <returns>The slot previously registered.</returns>
public static RuntimeContextSlot<T> GetSlot<T>(string slotName)
{
if (string.IsNullOrEmpty(slotName))
{
throw new ArgumentException($"{nameof(slotName)} cannot be null or empty string.");
}

if (!Slots.TryGetValue(slotName, out var slot))
{
throw new ArgumentException($"The context slot {slotName} could not be found.");
}

return slot as RuntimeContextSlot<T> ?? throw new ArgumentException($"The context slot {slotName} cannot be cast as {typeof(RuntimeContextSlot<T>)}.");
Guard.NullOrEmpty(slotName, nameof(slotName));
var slot = GuardNotFound(slotName);
var contextSlot = Guard.Type<RuntimeContextSlot<T>>(slot, nameof(slot));
return contextSlot;
}

/*
Expand Down Expand Up @@ -136,23 +127,10 @@ public static T GetValue<T>(string slotName)
/// <param name="value">The value to be set.</param>
public static void SetValue(string slotName, object value)
{
if (string.IsNullOrEmpty(slotName))
{
throw new ArgumentException($"{nameof(slotName)} cannot be null or empty string.");
}

if (!Slots.TryGetValue(slotName, out var slot))
{
throw new ArgumentException($"The context slot {slotName} could not be found.");
}

if (slot is IRuntimeContextSlotValueAccessor runtimeContextSlotValueAccessor)
{
runtimeContextSlotValueAccessor.Value = value;
return;
}

throw new NotSupportedException($"The context slot {slotName} value cannot be accessed as an object.");
Guard.NullOrEmpty(slotName, nameof(slotName));
var slot = GuardNotFound(slotName);
var runtimeContextSlotValueAccessor = Guard.Type<IRuntimeContextSlotValueAccessor>(slot, nameof(slot));
runtimeContextSlotValueAccessor.Value = value;
}

/// <summary>
Expand All @@ -162,28 +140,26 @@ public static void SetValue(string slotName, object value)
/// <returns>The value retrieved from the context slot.</returns>
public static object GetValue(string slotName)
{
if (string.IsNullOrEmpty(slotName))
{
throw new ArgumentException($"{nameof(slotName)} cannot be null or empty string.");
}

if (!Slots.TryGetValue(slotName, out var slot))
{
throw new ArgumentException($"The context slot {slotName} could not be found.");
}

if (slot is IRuntimeContextSlotValueAccessor runtimeContextSlotValueAccessor)
{
return runtimeContextSlotValueAccessor.Value;
}

throw new NotSupportedException($"The context slot {slotName} value cannot be accessed as an object.");
Guard.NullOrEmpty(slotName, nameof(slotName));
var slot = GuardNotFound(slotName);
var runtimeContextSlotValueAccessor = Guard.Type<IRuntimeContextSlotValueAccessor>(slot, nameof(slot));
return runtimeContextSlotValueAccessor.Value;
}

// For testing purpose
internal static void Clear()
{
Slots.Clear();
}

private static object GuardNotFound(string slotName)
{
if (!Slots.TryGetValue(slotName, out var slot))
{
throw new ArgumentException($"Context slot not found: '{slotName}'");
}

return slot;
}
}
}
1 change: 1 addition & 0 deletions src/OpenTelemetry.Api/Internal/EnumerationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using System.Collections;
using System.Collections.Generic;
Expand Down
171 changes: 171 additions & 0 deletions src/OpenTelemetry.Api/Internal/Guard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// <copyright file="Guard.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.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading;

namespace OpenTelemetry.Internal
{
/// <summary>
/// Methods for guarding against exception throwing values.
/// </summary>
public static class Guard
{
private const string DefaultParamName = "N/A";

/// <summary>
/// Throw an exception if the value is null.
/// </summary>
/// <param name="value">The value to check.</param>
/// <param name="paramName">The parameter name to use in the thrown exception.</param>
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Null(object value, string paramName = DefaultParamName)
{
if (value is null)
{
throw new ArgumentNullException(paramName, "Must not be null");
}
}

/// <summary>
/// Throw an exception if the value is null or empty.
/// </summary>
/// <param name="value">The value to check.</param>
/// <param name="paramName">The parameter name to use in the thrown exception.</param>
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void NullOrEmpty(string value, string paramName = DefaultParamName)
{
if (string.IsNullOrEmpty(value))
{
throw new ArgumentException("Must not be null or empty", paramName);
}
}

/// <summary>
/// Throw an exception if the value is null or whitespace.
/// </summary>
/// <param name="value">The value to check.</param>
/// <param name="paramName">The parameter name to use in the thrown exception.</param>
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void NullOrWhitespace(string value, string paramName = DefaultParamName)
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentException("Must not be null or whitespace", paramName);
}
}

/// <summary>
/// Throw an exception if the value is zero.
/// </summary>
/// <param name="value">The value to check.</param>
/// <param name="message">The message to use in the thrown exception.</param>
/// <param name="paramName">The parameter name to use in the thrown exception.</param>
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Zero(int value, string message = "Must not be zero", string paramName = DefaultParamName)
{
if (value == 0)
{
throw new ArgumentException(message, paramName);
}
}

/// <summary>
/// Throw an exception if the value is not considered a valid timeout.
/// </summary>
/// <param name="value">The value to check.</param>
/// <param name="paramName">The parameter name to use in the thrown exception.</param>
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvalidTimeout(int value, string paramName = DefaultParamName)
{
Range(value, paramName, min: Timeout.Infinite, message: $"Must be non-negative or '{nameof(Timeout)}.{nameof(Timeout.Infinite)}'");
}

/// <summary>
/// Throw an exception if the value is not within the given range.
/// </summary>
/// <param name="value">The value to check.</param>
/// <param name="paramName">The parameter name to use in the thrown exception.</param>
/// <param name="min">The inclusive lower bound.</param>
/// <param name="max">The inclusive upper bound.</param>
/// <param name="minName">The name of the lower bound.</param>
/// <param name="maxName">The name of the upper bound.</param>
/// <param name="message">An optional custom message to use in the thrown exception.</param>
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Range(int value, string paramName = DefaultParamName, int min = int.MinValue, int max = int.MaxValue, string minName = null, string maxName = null, string message = null)
{
Range<int>(value, paramName, min, max, minName, maxName, message);
}

/// <summary>
/// Throw an exception if the value is not within the given range.
/// </summary>
/// <param name="value">The value to check.</param>
/// <param name="paramName">The parameter name to use in the thrown exception.</param>
/// <param name="min">The inclusive lower bound.</param>
/// <param name="max">The inclusive upper bound.</param>
/// <param name="minName">The name of the lower bound.</param>
/// <param name="maxName">The name of the upper bound.</param>
/// <param name="message">An optional custom message to use in the thrown exception.</param>
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Range(double value, string paramName = DefaultParamName, double min = double.MinValue, double max = double.MaxValue, string minName = null, string maxName = null, string message = null)
{
Range<double>(value, paramName, min, max, minName, maxName, message);
}

/// <summary>
/// Throw an exception if the value is not within the given range.
/// </summary>
/// <param name="value">The value to check.</param>
/// <param name="paramName">The parameter name to use in the thrown exception.</param>
/// <typeparam name="T">The type to attempt to convert to.</typeparam>
/// <returns>The value casted to the specified type.</returns>
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Type<T>(object value, string paramName = DefaultParamName)
{
if (value is not T result)
{
throw new InvalidCastException($"Cannot cast '{paramName}' from '{value.GetType().Name}' to '{typeof(T).Name}'");
}

return result;
}

[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void Range<T>(T value, string paramName, T min, T max, string minName, string maxName, string message)
where T : IComparable<T>
{
if (value.CompareTo(min) < 0 || value.CompareTo(max) > 0)
{
var minMessage = minName != null ? $": {minName}" : string.Empty;
var maxMessage = maxName != null ? $": {maxName}" : string.Empty;
var exMessage = message ?? $"Must be in the range: [{min}{minMessage}, {max}{maxMessage}]";
throw new ArgumentOutOfRangeException(paramName, value, exMessage);
}
}
}
}
4 changes: 4 additions & 0 deletions src/OpenTelemetry.Api/OpenTelemetry.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="$(SystemReflectionEmitLightweightPkgVer)" />
</ItemGroup>

<ItemGroup>
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Api\Internal\Guard.cs" />
</ItemGroup>

</Project>
12 changes: 3 additions & 9 deletions src/OpenTelemetry.Api/Trace/SpanAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
// limitations under the License.
// </copyright>

using System;
using System.Collections.Generic;
using System.Diagnostics;
using OpenTelemetry.Internal;

namespace OpenTelemetry.Trace
{
Expand All @@ -41,10 +41,7 @@ public SpanAttributes()
public SpanAttributes(IEnumerable<KeyValuePair<string, object>> attributes)
: this()
{
if (attributes == null)
{
throw new ArgumentNullException(nameof(attributes));
}
Guard.Null(attributes, nameof(attributes));

foreach (KeyValuePair<string, object> kvp in attributes)
{
Expand Down Expand Up @@ -136,10 +133,7 @@ public void Add(string key, double[] values)

private void AddInternal(string key, object value)
{
if (key == null)
{
throw new ArgumentNullException(key);
}
Guard.Null(key, nameof(key));

this.Attributes[key] = value;
}
Expand Down
Loading

0 comments on commit 6e6afdb

Please sign in to comment.