Skip to content

Commit

Permalink
Add full null checking to MongoDB and AWS.SDK integrations (#4815)
Browse files Browse the repository at this point in the history
* Add missing sourcelink tags

* Sprinkle some nullables everywhere

* Sprinkle some more nullable
  • Loading branch information
andrewlock authored Nov 6, 2023
1 parent 3cad33b commit d135982
Show file tree
Hide file tree
Showing 25 changed files with 241 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

#nullable enable

using System.Net;
using Datadog.Trace.DuckTyping;

namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK
{
/// <summary>
/// AmazonWebServiceResponse interface for ducktyping
/// </summary>
internal interface IAmazonWebServiceResponse
internal interface IAmazonWebServiceResponse : IDuckType
{
/// <summary>
/// Gets the length of the content
Expand All @@ -20,7 +23,7 @@ internal interface IAmazonWebServiceResponse
/// <summary>
/// Gets the response metadata
/// </summary>
IResponseMetadata ResponseMetadata { get; }
IResponseMetadata? ResponseMetadata { get; }

/// <summary>
/// Gets the http status code of the AWS request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

#nullable enable

namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK
{
/// <summary>
Expand All @@ -13,6 +15,6 @@ internal interface IClientConfig
/// <summary>
/// Gets the region endpoint of the config
/// </summary>
IRegionEndpoint RegionEndpoint { get; }
IRegionEndpoint? RegionEndpoint { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

#nullable enable

namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK
{
/// <summary>
Expand All @@ -13,11 +15,11 @@ internal interface IExecutionContext
/// <summary>
/// Gets the RequestContext
/// </summary>
IRequestContext RequestContext { get; }
IRequestContext? RequestContext { get; }

/// <summary>
/// Gets the ResponseContext
/// </summary>
IResponseContext ResponseContext { get; }
IResponseContext? ResponseContext { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

#nullable enable

namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

#nullable enable

using System;

namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK
Expand All @@ -15,16 +17,16 @@ internal interface IRequest
/// <summary>
/// Gets the service endpoint
/// </summary>
Uri Endpoint { get; }
Uri? Endpoint { get; }

/// <summary>
/// Gets the HTTP method
/// </summary>
string HttpMethod { get; }
string? HttpMethod { get; }

/// <summary>
/// Gets the resource path
/// </summary>
string ResourcePath { get; }
string? ResourcePath { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

#nullable enable

namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK
{
/// <summary>
Expand All @@ -13,11 +15,11 @@ internal interface IRequestContext
/// <summary>
/// Gets the client config
/// </summary>
IClientConfig ClientConfig { get; }
IClientConfig? ClientConfig { get; }

/// <summary>
/// Gets the Request
/// </summary>
IRequest Request { get; }
IRequest? Request { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

#nullable enable

namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK
{
/// <summary>
Expand All @@ -13,6 +15,6 @@ internal interface IResponseContext
/// <summary>
/// Gets the SDK response
/// </summary>
IAmazonWebServiceResponse Response { get; }
IAmazonWebServiceResponse? Response { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

#nullable enable

using System.Collections.Generic;

namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK
Expand All @@ -15,7 +17,7 @@ internal interface IResponseMetadata
/// <summary>
/// Gets the ID of the request
/// </summary>
string RequestId { get; }
string? RequestId { get; }

/// <summary>
/// Gets the metadata associated with the request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

#nullable enable

using System;
using System.ComponentModel;
using Datadog.Trace.ClrProfiler.CallTarget;
Expand Down Expand Up @@ -48,7 +50,7 @@ internal static CallTargetState OnMethodBegin<TTarget, TExecutionContext>(TTarge
var scope = Tracer.Instance.InternalActiveScope;
if (scope?.Span.Tags is AwsSdkTags tags)
{
tags.Region = executionContext.RequestContext.ClientConfig.RegionEndpoint?.SystemName;
tags.Region = executionContext.RequestContext?.ClientConfig?.RegionEndpoint?.SystemName;
}

return new CallTargetState(scope, state: executionContext);
Expand All @@ -69,11 +71,11 @@ internal static TResponse OnAsyncMethodEnd<TTarget, TResponse>(TTarget instance,
{
if (state.Scope?.Span.Tags is AwsSdkTags tags)
{
if (state.State is IExecutionContext executionContext)
if (state.State is IExecutionContext { RequestContext.Request: { } request })
{
var uri = executionContext.RequestContext.Request.Endpoint;
var absolutePath = uri.AbsolutePath;
var path = executionContext.RequestContext.Request.ResourcePath switch
var uri = request.Endpoint;
var absolutePath = uri?.AbsolutePath;
var path = request.ResourcePath switch
{
null => absolutePath,
string resourcePath when absolutePath == "/" => resourcePath,
Expand All @@ -82,12 +84,15 @@ internal static TResponse OnAsyncMethodEnd<TTarget, TResponse>(TTarget instance,

// The request object is populated later by the Marshaller,
// so we wait until the method end callback to read it
tags.HttpMethod = executionContext.RequestContext.Request.HttpMethod.ToUpperInvariant();
tags.HttpUrl = $"{uri.Scheme}{Uri.SchemeDelimiter}{uri.Authority}{path}";
tags.HttpMethod = request.HttpMethod?.ToUpperInvariant();
tags.HttpUrl = $"{uri?.Scheme}{Uri.SchemeDelimiter}{uri?.Authority}{path}";
}

tags.RequestId = response.ResponseMetadata.RequestId;
state.Scope.Span.SetHttpStatusCode((int)response.HttpStatusCode, false, Tracer.Instance.Settings);
if (response.Instance is not null)
{
tags.RequestId = response.ResponseMetadata?.RequestId;
state.Scope.Span.SetHttpStatusCode((int)response.HttpStatusCode, false, Tracer.Instance.Settings);
}
}

// Do not dispose the scope (if present) when exiting.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

#nullable enable

using System;
using System.ComponentModel;
using Datadog.Trace.ClrProfiler.CallTarget;
Expand Down Expand Up @@ -48,7 +50,7 @@ internal static CallTargetState OnMethodBegin<TTarget, TExecutionContext>(TTarge
var scope = Tracer.Instance.InternalActiveScope;
if (scope?.Span.Tags is AwsSdkTags tags)
{
tags.Region = executionContext.RequestContext.ClientConfig.RegionEndpoint?.SystemName;
tags.Region = executionContext.RequestContext?.ClientConfig?.RegionEndpoint?.SystemName;
}

return new CallTargetState(scope, state: executionContext);
Expand All @@ -65,15 +67,15 @@ internal static CallTargetState OnMethodBegin<TTarget, TExecutionContext>(TTarge
/// <param name="state">Calltarget state value</param>
/// <returns>A response value, in an async scenario will be T of Task of T</returns>
internal static CallTargetReturn<TResponseContext> OnMethodEnd<TTarget, TResponseContext>(TTarget instance, TResponseContext responseContext, Exception exception, in CallTargetState state)
where TResponseContext : IResponseContext
where TResponseContext : IResponseContext, IDuckType
{
if (state.Scope?.Span.Tags is AwsSdkTags tags)
{
if (state.State is IExecutionContext executionContext)
if (state.State is IExecutionContext { RequestContext.Request: { } request })
{
var uri = executionContext.RequestContext.Request.Endpoint;
var absolutePath = uri.AbsolutePath;
var path = executionContext.RequestContext.Request.ResourcePath switch
var uri = request.Endpoint;
var absolutePath = uri?.AbsolutePath;
var path = request.ResourcePath switch
{
null => absolutePath,
string resourcePath when absolutePath == "/" => resourcePath,
Expand All @@ -82,12 +84,15 @@ internal static CallTargetReturn<TResponseContext> OnMethodEnd<TTarget, TRespons

// The request object is populated later by the Marshaller,
// so we wait until the method end callback to read it
tags.HttpMethod = executionContext.RequestContext.Request.HttpMethod.ToUpperInvariant();
tags.HttpUrl = $"{uri.Scheme}{Uri.SchemeDelimiter}{uri.Authority}{path}";
tags.HttpMethod = request.HttpMethod?.ToUpperInvariant();
tags.HttpUrl = $"{uri?.Scheme}{Uri.SchemeDelimiter}{uri?.Authority}{path}";
}

tags.RequestId = responseContext.Response.ResponseMetadata.RequestId;
state.Scope.Span.SetHttpStatusCode((int)responseContext.Response.HttpStatusCode, false, Tracer.Instance.Settings);
if (responseContext.Instance is not null && responseContext.Response is { } response)
{
tags.RequestId = response.ResponseMetadata?.RequestId;
state.Scope.Span.SetHttpStatusCode((int)response.HttpStatusCode, false, Tracer.Instance.Settings);
}
}

// Do not dispose the scope (if present) when exiting.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

#nullable enable

using Datadog.Trace.DuckTyping;

namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.MongoDb
Expand All @@ -21,6 +23,6 @@ internal struct BsonElementStruct
/// <summary>
/// Gets the value of the element.
/// </summary>
public object Value;
public object? Value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,13 @@ static BsonSerializationHelper()
/// Serializes a bson document object, stripping out binary data, and truncating
/// at the maximum number of characters accepted in tags
/// </summary>
public static string? ToShortString(object obj)
public static string? ToShortString(object? obj)
{
if (obj is null)
{
return null;
}

if (Helper is not { } helper)
{
// Fallback if there was an issue creating the proxies in the constructor
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.MongoDb.BsonSerializatio
internal interface IBsonSerializerLookupProxy
{
// static lookup function
// LookupSerializer _always_ returns non-null (it throws otherwise), so the duck type will be non null
IBsonSerializerProxy LookupSerializer(Type type);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

#nullable enable

using Datadog.Trace.DuckTyping;

namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.MongoDb
Expand All @@ -16,6 +18,6 @@ internal struct DatabaseNamespaceStruct
/// <summary>
/// Gets the name of the database
/// </summary>
public string DatabaseName;
public string? DatabaseName;
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
// <copyright file="BsonDocumentProxy.cs" company="Datadog">
// <copyright file="IBsonDocumentProxy.cs" company="Datadog">
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

using Datadog.Trace.DuckTyping;

namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.MongoDb
{
/// <summary>
/// MongoDB.Bson.BsonDocument interface for duck-typing
/// </summary>
internal class BsonDocumentProxy
internal interface IBsonDocumentProxy : IDuckType
{
/// <summary>
/// Gets an element of this document.
/// </summary>
/// <param name="index">The zero based index of the element.</param>
/// <returns>The element.</returns>
public virtual BsonElementStruct GetElement(int index)
{
return default;
}
public BsonElementStruct GetElement(int index);
}
}
Loading

0 comments on commit d135982

Please sign in to comment.