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

Telemetry: Fixes Trace error when not using Azure VMs #3227

Merged
merged 9 commits into from
May 31, 2022
51 changes: 28 additions & 23 deletions Microsoft.Azure.Cosmos/src/Telemetry/VmMetadataApiHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,39 +45,44 @@ internal static void TryInitialize(CosmosHttpClient httpClient)

VmMetadataApiHandler.isInitialized = true;

_ = Task.Run(() => MetadataApiCallAsync(httpClient), default)
imanvt marked this conversation as resolved.
Show resolved Hide resolved
.ContinueWith(t => DefaultTrace.TraceWarning($"Exception while making metadata call {t.Exception}"),
TaskContinuationOptions.OnlyOnFaulted);

_ = Task.Run(() => MetadataApiCallAsync(httpClient), default);
}

}

private static async Task MetadataApiCallAsync(CosmosHttpClient httpClient)
{
DefaultTrace.TraceInformation($"Loading VM Metadata");

static ValueTask<HttpRequestMessage> CreateRequestMessage()
try
{
HttpRequestMessage request = new HttpRequestMessage()
{
RequestUri = VmMetadataApiHandler.vmMetadataEndpointUrl,
Method = HttpMethod.Get,
};
request.Headers.Add("Metadata", "true");
DefaultTrace.TraceInformation($"Loading VM Metadata");

return new ValueTask<HttpRequestMessage>(request);
}
static ValueTask<HttpRequestMessage> CreateRequestMessage()
{
HttpRequestMessage request = new HttpRequestMessage()
{
RequestUri = VmMetadataApiHandler.vmMetadataEndpointUrl,
Method = HttpMethod.Get,
};
request.Headers.Add("Metadata", "true");

return new ValueTask<HttpRequestMessage>(request);
}

HttpResponseMessage response = await httpClient
.SendHttpAsync(createRequestMessageAsync: CreateRequestMessage,
resourceType: ResourceType.Telemetry,
timeoutPolicy: HttpTimeoutPolicyNoRetry.Instance,
clientSideRequestStatistics: null,
cancellationToken: default);
HttpResponseMessage response = await httpClient
.SendHttpAsync(createRequestMessageAsync: CreateRequestMessage,
resourceType: ResourceType.Telemetry,
timeoutPolicy: HttpTimeoutPolicyNoRetry.Instance,
clientSideRequestStatistics: null,
cancellationToken: default);

azMetadata = await VmMetadataApiHandler.ProcessResponseAsync(response);
azMetadata = await VmMetadataApiHandler.ProcessResponseAsync(response);

DefaultTrace.TraceInformation($"Succesfully get Instance Metadata Response : {azMetadata.Compute.VMId}");
DefaultTrace.TraceInformation($"Succesfully get Instance Metadata Response : {azMetadata.Compute.VMId}");
}
catch (Exception e)
{
DefaultTrace.TraceInformation($"Azure Environment metadata information not available. {e.Message}");
}
}

internal static async Task<AzureVMMetadata> ProcessResponseAsync(HttpResponseMessage httpResponseMessage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
namespace Microsoft.Azure.Cosmos
{
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Core.Trace;
using Microsoft.Azure.Cosmos.Telemetry;
using Microsoft.Azure.Cosmos.Tests;
using Microsoft.VisualStudio.TestTools.UnitTesting;
Expand Down Expand Up @@ -103,6 +105,35 @@ public async Task ParseAzureVMMetadataTest()
Assert.AreEqual("vmId:d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd", metadata.Compute.VMId);
}

[TestMethod]
public void CatchMetadataApiCallExceptionTest()
{
static Task<HttpResponseMessage> sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) { throw new Exception("error while making API call"); };

HttpMessageHandler messageHandler = new MockMessageHandler(sendFunc);
CosmosHttpClient cosmoshttpClient = MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(messageHandler));

string expectedMsg = "Azure Environment metadata information not available.";
ManualResetEvent manualResetEvent = new ManualResetEvent(false);

void TraceHandler(string message)
{
Console.WriteLine(message);
imanvt marked this conversation as resolved.
Show resolved Hide resolved
if (message.Contains(expectedMsg))
{
manualResetEvent.Set();
}
}

DefaultTrace.TraceSource.Listeners.Add(new TestTraceListener { Callback = TraceHandler });
DefaultTrace.InitEventListener();

VmMetadataApiHandler.TryInitialize(cosmoshttpClient);

int timeout = 30000;
Assert.IsTrue(manualResetEvent.WaitOne(timeout));
}

private class MockMessageHandler : HttpMessageHandler
{
private readonly Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> sendFunc;
Expand All @@ -116,5 +147,19 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
return await this.sendFunc(request, cancellationToken);
}
}
private class TestTraceListener : TraceListener
{
public Action<string> Callback { get; set; }
public override bool IsThreadSafe => true;
public override void Write(string message)
{
this.Callback(message);
}

public override void WriteLine(string message)
{
this.Callback(message);
}
}
}
}