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

Client Telemetry : Refactors code to compute hash of VM ID and Process Name information #3376

Merged
merged 6 commits into from
Aug 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry
using Microsoft.Azure.Documents.Collections;
using Microsoft.Azure.Documents.Rntbd;
using Newtonsoft.Json;
using Util;

/// <summary>
/// This class collects and send all the telemetry information.
Expand Down Expand Up @@ -99,7 +100,7 @@ private ClientTelemetry(

this.clientTelemetryInfo = new ClientTelemetryProperties(
clientId: clientId,
processId: System.Diagnostics.Process.GetCurrentProcess().ProcessName,
processId: HashingExtension.ComputeHash(System.Diagnostics.Process.GetCurrentProcess().ProcessName),
userAgent: userAgent,
connectionMode: connectionMode,
preferredRegions: preferredRegions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry
using Microsoft.Azure.Cosmos.Core.Trace;
using Microsoft.Azure.Documents;
using Newtonsoft.Json;
using Util;

internal static class ClientTelemetryOptions
{
Expand Down
3 changes: 2 additions & 1 deletion Microsoft.Azure.Cosmos/src/Telemetry/Compute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry
{
using System;
using Newtonsoft.Json;
using Util;

[Serializable]
internal sealed class Compute
Expand All @@ -24,7 +25,7 @@ public Compute(
this.AzEnvironment = azEnvironment;
this.OSType = oSType;
this.VMSize = vMSize;
this.VMId = "vmId:" + vMId;
this.VMId = $"{VmMetadataApiHandler.HashedVmIdPrefix}{HashingExtension.ComputeHash(vMId)}";
}

[JsonProperty(PropertyName = "location")]
Expand Down
34 changes: 8 additions & 26 deletions Microsoft.Azure.Cosmos/src/Telemetry/VmMetadataApiHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry
using Microsoft.Azure.Cosmos.Core.Trace;
using Microsoft.Azure.Documents;
using Newtonsoft.Json.Linq;
using Util;

/// <summary>
/// Task to collect virtual machine metadata information. using instance metedata service API.
Expand All @@ -20,7 +21,12 @@ namespace Microsoft.Azure.Cosmos.Telemetry
/// </summary>
internal static class VmMetadataApiHandler
{
internal const string HashedMachineNamePrefix = "hashedMachineName:";
internal const string HashedVmIdPrefix = "hashedVmId:";
internal const string UuidPrefix = "uuid:";

internal static readonly Uri vmMetadataEndpointUrl = new ("http://169.254.169.254/metadata/instance?api-version=2020-06-01");

private static readonly string nonAzureCloud = "NonAzureVM";

private static readonly object lockObject = new object();
Expand Down Expand Up @@ -139,42 +145,18 @@ internal static string GetCloudInformation()
return VmMetadataApiHandler.azMetadata?.Compute?.AzEnvironment ?? VmMetadataApiHandler.nonAzureCloud;
}

/// <summary>
/// Hash a passed Value
/// </summary>
/// <param name="rawData"></param>
/// <returns>hashed Value</returns>
internal static string ComputeHash(string rawData)
{
if (string.IsNullOrEmpty(rawData))
{
throw new ArgumentNullException(nameof(rawData));
}

// Create a SHA256
using (SHA256 sha256Hash = SHA256.Create())
{
// ComputeHash - returns byte array
byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));
Array.Resize(ref bytes, 16);

// Convert byte array to a string
return new Guid(bytes).ToString();
}
}

private static readonly Lazy<string> uniqueId = new Lazy<string>(() =>
{
try
{
return "hashedMachineName:" + VmMetadataApiHandler.ComputeHash(Environment.MachineName);
return $"{VmMetadataApiHandler.HashedMachineNamePrefix}{HashingExtension.ComputeHash(Environment.MachineName)}";
}
catch (Exception ex)
{
DefaultTrace.TraceWarning("Error while generating hashed machine name " + ex.Message);
}

return "uuid:" + Guid.NewGuid().ToString();
return $"{VmMetadataApiHandler.UuidPrefix}{Guid.NewGuid()}";
});

}
Expand Down
38 changes: 38 additions & 0 deletions Microsoft.Azure.Cosmos/src/Util/HashingExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Util
{
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;

internal class HashingExtension
{
/// <summary>
/// Hash a passed Value
/// </summary>
/// <param name="rawData"></param>
/// <returns>hashed Value</returns>
internal static string ComputeHash(string rawData)
{
if (string.IsNullOrEmpty(rawData))
{
throw new ArgumentNullException(nameof(rawData));
}

// Create a SHA256
using (SHA256 sha256Hash = SHA256.Create())
{
// ComputeHash - returns byte array
byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));
Array.Resize(ref bytes, 16);

// Convert byte array to a string
return new Guid(bytes).ToString();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests
using Documents.Rntbd;
using System.Globalization;
using System.Linq;
using Cosmos.Util;

[TestClass]
public class ClientTelemetryTests : BaseCosmosClientHelper
Expand Down Expand Up @@ -935,6 +936,7 @@ private static void AssertAccountLevelInformation(
Assert.IsNull(telemetryInfo.AcceleratedNetworking);
Assert.IsNotNull(telemetryInfo.ClientId);
Assert.IsNotNull(telemetryInfo.ProcessId);
Assert.AreEqual(HashingExtension.ComputeHash(System.Diagnostics.Process.GetCurrentProcess().ProcessName), telemetryInfo.ProcessId);
Assert.IsNotNull(telemetryInfo.UserAgent);
Assert.IsNotNull(telemetryInfo.ConnectionMode);

Expand All @@ -948,15 +950,14 @@ private static void AssertAccountLevelInformation(
{
if (isAzureInstance.Value)
{
Assert.AreEqual("vmId:d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd", machineId.First(), $"Generated Machine id is : {machineId.First()}");
Assert.AreEqual($"{VmMetadataApiHandler.HashedVmIdPrefix}{HashingExtension.ComputeHash("d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd")}", machineId.First(), $"Generated Machine id is : {machineId.First()}");
}
else
{
Assert.AreNotEqual("vmId:d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd", machineId.First(), $"Generated Machine id is : {machineId.First()}");
Assert.AreNotEqual($"{VmMetadataApiHandler.HashedVmIdPrefix}{HashingExtension.ComputeHash("d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd")}", machineId.First(), $"Generated Machine id is : {machineId.First()}");
Assert.AreEqual(1, machineId.Count, $"Multiple Machine Id has been generated i.e {JsonConvert.SerializeObject(machineId)}");
}
}

}

[TestMethod]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace Microsoft.Azure.Cosmos
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Newtonsoft.Json;
using Util;

[TestClass]
public class VmMetadataApiHandlerTest
Expand Down Expand Up @@ -56,7 +57,7 @@ static Task<HttpResponseMessage> sendFunc(HttpRequestMessage request, Cancellati
VmMetadataApiHandler.TryInitialize(cosmoshttpClient);

await Task.Delay(2000);
Assert.AreEqual("vmId:d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd", VmMetadataApiHandler.GetMachineId());
Assert.AreEqual($"{VmMetadataApiHandler.HashedVmIdPrefix}{HashingExtension.ComputeHash("d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd")}", VmMetadataApiHandler.GetMachineId());
Assert.AreEqual(VmMetadataApiHandler.GetMachineRegion(), "eastus");
}

Expand Down Expand Up @@ -88,7 +89,7 @@ static Task<HttpResponseMessage> sendFunc(HttpRequestMessage request, Cancellati
[TestMethod]
public async Task GetHashedMachineNameAsMachineIdTest()
{
string expectedMachineId = "hashedMachineName:" + VmMetadataApiHandler.ComputeHash(Environment.MachineName);
string expectedMachineId = VmMetadataApiHandler.HashedMachineNamePrefix + HashingExtension.ComputeHash(Environment.MachineName);

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

Expand All @@ -105,7 +106,7 @@ public async Task GetHashedMachineNameAsMachineIdTest()
[TestMethod]
public void ComputeHashTest()
{
string hashedValue = VmMetadataApiHandler.ComputeHash("abc");
string hashedValue = HashingExtension.ComputeHash("abc");
Assert.AreEqual("bf1678ba-018f-eacf-4141-40de5dae2223", hashedValue);
}

Expand All @@ -128,7 +129,7 @@ public async Task ParseAzureVMMetadataTest()
Assert.AreEqual("AzurePublicCloud", metadata.Compute.AzEnvironment);
Assert.AreEqual("Linux", metadata.Compute.OSType);
Assert.AreEqual("Standard_D2s_v3", metadata.Compute.VMSize);
Assert.AreEqual("vmId:d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd", metadata.Compute.VMId);
Assert.AreEqual($"{VmMetadataApiHandler.HashedVmIdPrefix}{HashingExtension.ComputeHash("d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd")}", metadata.Compute.VMId);
}

[TestMethod]
Expand Down