Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaomi7732 committed Feb 1, 2018
2 parents a38acd8 + 65a4a7c commit 0b82e08
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 13 deletions.
28 changes: 28 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/tests/UnitTests/bin/Debug/netcoreapp2.0/Microsoft.ApplicationInsights.Kubernetes.UnitTests.dll",
"args": [],
"cwd": "${workspaceFolder}/tests/UnitTests",
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
"console": "internalConsole",
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart"
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}
15 changes: 15 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": "2.0.0",
"tasks": [
{
"taskName": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/tests/UnitTests/UnitTests.csproj"
],
"problemMatcher": "$msCompile"
}
]
}
51 changes: 50 additions & 1 deletion src/TelemetryInitializers/KubernetesTelemetryInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,27 @@
using Newtonsoft.Json;

using static Microsoft.ApplicationInsights.Kubernetes.StringUtils;
using static Microsoft.ApplicationInsights.Kubernetes.TelemetryInitializers.Prefixes;

#if !NETSTANDARD1_3 && !NETSTANDARD1_6
using System.Diagnostics;
using System.Globalization;
#endif

/// <summary>
/// Telemetry Initializer for K8s Environment
/// </summary>
public class KubernetesTelemetryInitializer : ITelemetryInitializer
{
public const string Container = "Container";
public const string Deployment = "Deployment";
public const string K8s = "Kubernetes";
public const string Node = "Node";
public const string Pod = "Pod";
public const string ReplicaSet = "ReplicaSet";
public const string ProcessString = "Process";
public const string CPU = "CPU";
public const string Memory = "Memory";

private ILogger<KubernetesTelemetryInitializer> logger;
internal IK8sEnvironment K8sEnvironment { get; private set; }

Expand All @@ -39,13 +53,21 @@ public void Initialize(ITelemetry telemetry)
{
if (K8sEnvironment != null)
{
#if NETSTANDARD2_0
Stopwatch cpuWatch = Stopwatch.StartNew();
TimeSpan startCPUTime = Process.GetCurrentProcess().TotalProcessorTime;
#endif
// Setting the container name to role name
if (string.IsNullOrEmpty(telemetry.Context.Cloud.RoleName))
{
telemetry.Context.Cloud.RoleName = this.K8sEnvironment.ContainerName;
}

#if NETSTANDARD2_0
SetCustomDimensions(telemetry, cpuWatch, startCPUTime);
#else
SetCustomDimensions(telemetry);
#endif

logger?.LogTrace(JsonConvert.SerializeObject(telemetry));
}
Expand Down Expand Up @@ -79,6 +101,33 @@ private void SetCustomDimensions(ITelemetry telemetry)
SetCustomDimension(telemetry, Invariant($"{K8s}.{Node}.Name"), this.K8sEnvironment.NodeName);
}

#if NETSTANDARD2_0
private void SetCustomDimensions(ITelemetry telemetry, Stopwatch cpuWatch, TimeSpan startCPUTime)
{
SetCustomDimensions(telemetry);

// Add CPU/Memory metrics to telemetry.
Process process = Process.GetCurrentProcess();
TimeSpan endCPUTime = process.TotalProcessorTime;
cpuWatch.Stop();

string cpuString = "NaN";
if (cpuWatch.ElapsedMilliseconds > 0)
{
int processorCount = Environment.ProcessorCount;
Debug.Assert(processorCount > 0, $"How could process count be {processorCount}?");
// A very simple but not that accruate evaluation of how much CPU the process is take out of a core.
double CPUPercentage = (endCPUTime - startCPUTime).TotalMilliseconds / (double)(cpuWatch.ElapsedMilliseconds);
cpuString = CPUPercentage.ToString("P2", CultureInfo.InvariantCulture);
}

long memoryInBytes = process.VirtualMemorySize64;

SetCustomDimension(telemetry, Invariant($"{ProcessString}.{CPU}(%)"), cpuString);
SetCustomDimension(telemetry, Invariant($"{ProcessString}.{Memory}"), memoryInBytes.GetReadableSize());
}
#endif

private void SetCustomDimension(ITelemetry telemetry, string key, string value)
{
if (telemetry == null)
Expand Down
12 changes: 0 additions & 12 deletions src/TelemetryInitializers/Prefixes.cs

This file was deleted.

14 changes: 14 additions & 0 deletions src/Utilities/StringUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,19 @@ public static string Invariant(FormattableString formattable)
{
return formattable.ToString(CultureInfo.InvariantCulture);
}

public static string GetReadableSize(this long numInBytes)
{
double doubleBytes = numInBytes;
string[] sizes = { "B", "KB", "MB", "GB", "TB" };
int order = 0;
while (doubleBytes >= 1024 && order < sizes.Length - 1)
{
order++;
doubleBytes /= 1024.0;
}

return String.Format(CultureInfo.InvariantCulture, "{0:0.#}{1}", doubleBytes, sizes[order]);
}
}
}
5 changes: 5 additions & 0 deletions tests/UnitTests/KubernetesTelemtryInitializerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ public void InitializeSetsCustomDimensions()

Assert.Equal("Nid", telemetry.Context.Properties["Kubernetes.Node.ID"]);
Assert.Equal("NName", telemetry.Context.Properties["Kubernetes.Node.Name"]);

#if !NETSTANDARD1_3 && !NETSTANDARD1_6
Assert.NotNull(telemetry.Context.Properties["Process.CPU(%)"]);
Assert.NotNull(telemetry.Context.Properties["Process.Memory"]);
#endif
}

[Fact(DisplayName = "K8sTelemetryInitializer will not overwrite custom dimension when it exists already.")]
Expand Down
22 changes: 22 additions & 0 deletions tests/UnitTests/StringUtilsTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Microsoft.ApplicationInsights.Kubernetes;
using Xunit;
namespace Microsoft.ApplicationInsights.Netcore.Kubernetes
{
public class StringUtilsTest
{
[Theory(DisplayName = "Verify proper output of size")]
[InlineData(25, "25B")]
[InlineData(1023, "1023B")]
[InlineData(1024, "1KB")]
[InlineData(1025, "1KB")]
[InlineData(2097152, "2MB")]
[InlineData(3758096384, "3.5GB")]
[InlineData(3848290697216, "3.5TB")]

public void VerifyServerCertificateShouldVerifyIssuer(long input, string expected)
{
string actual = input.GetReadableSize();
Assert.Equal(expected, actual);
}
}
}

0 comments on commit 0b82e08

Please sign in to comment.