Skip to content

Commit

Permalink
[Extensions.Docker] File scoped namespace (#587)
Browse files Browse the repository at this point in the history
Co-authored-by: Utkarsh Umesan Pillai <[email protected]>
  • Loading branch information
Kielek and utpilla authored Aug 19, 2022
1 parent 3776024 commit 8d91837
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 198 deletions.
61 changes: 30 additions & 31 deletions src/OpenTelemetry.Extensions.Docker/DockerExtensionsEventSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,45 +19,44 @@
using System.Globalization;
using System.Threading;

namespace OpenTelemetry.Extensions.Docker
namespace OpenTelemetry.Extensions.Docker;

[EventSource(Name = "OpenTelemetry-Extensions-Docker")]
internal class DockerExtensionsEventSource : EventSource
{
[EventSource(Name = "OpenTelemetry-Extensions-Docker")]
internal class DockerExtensionsEventSource : EventSource
{
public static DockerExtensionsEventSource Log = new DockerExtensionsEventSource();
public static DockerExtensionsEventSource Log = new DockerExtensionsEventSource();

[NonEvent]
public void ExtractResourceAttributesException(string format, Exception ex)
[NonEvent]
public void ExtractResourceAttributesException(string format, Exception ex)
{
if (this.IsEnabled(EventLevel.Error, (EventKeywords)(-1)))
{
if (this.IsEnabled(EventLevel.Error, (EventKeywords)(-1)))
{
this.FailedToExtractResourceAttributes(format, ToInvariantString(ex));
}
this.FailedToExtractResourceAttributes(format, ToInvariantString(ex));
}
}

[Event(1, Message = "Failed to extract resource attributes in '{0}'.", Level = EventLevel.Error)]
public void FailedToExtractResourceAttributes(string format, string exception)
[Event(1, Message = "Failed to extract resource attributes in '{0}'.", Level = EventLevel.Error)]
public void FailedToExtractResourceAttributes(string format, string exception)
{
this.WriteEvent(1, format, exception);
}

/// <summary>
/// Returns a culture-independent string representation of the given <paramref name="exception"/> object,
/// appropriate for diagnostics tracing.
/// </summary>
private static string ToInvariantString(Exception exception)
{
var originalUICulture = Thread.CurrentThread.CurrentUICulture;

try
{
this.WriteEvent(1, format, exception);
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
return exception.ToString();
}

/// <summary>
/// Returns a culture-independent string representation of the given <paramref name="exception"/> object,
/// appropriate for diagnostics tracing.
/// </summary>
private static string ToInvariantString(Exception exception)
finally
{
var originalUICulture = Thread.CurrentThread.CurrentUICulture;

try
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
return exception.ToString();
}
finally
{
Thread.CurrentThread.CurrentUICulture = originalUICulture;
}
Thread.CurrentThread.CurrentUICulture = originalUICulture;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,112 +20,111 @@
using OpenTelemetry.Extensions.Docker.Utils;
using OpenTelemetry.Resources;

namespace OpenTelemetry.Extensions.Docker.Resources
namespace OpenTelemetry.Extensions.Docker.Resources;

/// <summary>
/// Resource detector for application running in Docker environment.
/// </summary>
public class DockerResourceDetector : IResourceDetector
{
private const string FILEPATH = "/proc/self/cgroup";

/// <summary>
/// Detects the resource attributes from Docker.
/// </summary>
/// <returns>Resource with key-value pairs of resource attributes.</returns>
public Resource Detect()
{
return this.BuildResource(FILEPATH);
}

/// <summary>
/// Resource detector for application running in Docker environment.
/// Builds the resource attributes from Container Id in file path.
/// </summary>
public class DockerResourceDetector : IResourceDetector
/// <param name="path">File path where container id exists.</param>
/// <returns>Returns Resource with list of key-value pairs of container resource attributes if container id exists else empty resource.</returns>
internal Resource BuildResource(string path)
{
private const string FILEPATH = "/proc/self/cgroup";
var containerId = this.ExtractContainerId(path);

/// <summary>
/// Detects the resource attributes from Docker.
/// </summary>
/// <returns>Resource with key-value pairs of resource attributes.</returns>
public Resource Detect()
if (string.IsNullOrEmpty(containerId))
{
return this.BuildResource(FILEPATH);
return Resource.Empty;
}

/// <summary>
/// Builds the resource attributes from Container Id in file path.
/// </summary>
/// <param name="path">File path where container id exists.</param>
/// <returns>Returns Resource with list of key-value pairs of container resource attributes if container id exists else empty resource.</returns>
internal Resource BuildResource(string path)
else
{
var containerId = this.ExtractContainerId(path);

if (string.IsNullOrEmpty(containerId))
{
return Resource.Empty;
}
else
{
return new Resource(new List<KeyValuePair<string, object>>() { new KeyValuePair<string, object>(DockerSemanticConventions.AttributeContainerID, containerId), });
}
return new Resource(new List<KeyValuePair<string, object>>() { new KeyValuePair<string, object>(DockerSemanticConventions.AttributeContainerID, containerId), });
}
}

/// <summary>
/// Extracts Container Id from path.
/// </summary>
/// <param name="path">cgroup path.</param>
/// <returns>Container Id, Null if not found or exception being thrown.</returns>
private string ExtractContainerId(string path)
/// <summary>
/// Extracts Container Id from path.
/// </summary>
/// <param name="path">cgroup path.</param>
/// <returns>Container Id, Null if not found or exception being thrown.</returns>
private string ExtractContainerId(string path)
{
try
{
try
if (!File.Exists(path))
{
if (!File.Exists(path))
{
return null;
}
return null;
}

foreach (string line in File.ReadLines(path))
foreach (string line in File.ReadLines(path))
{
string containerId = (!string.IsNullOrEmpty(line)) ? this.GetIdFromLine(line) : null;
if (!string.IsNullOrEmpty(containerId))
{
string containerId = (!string.IsNullOrEmpty(line)) ? this.GetIdFromLine(line) : null;
if (!string.IsNullOrEmpty(containerId))
{
return containerId;
}
return containerId;
}
}
catch (Exception ex)
{
DockerExtensionsEventSource.Log.ExtractResourceAttributesException($"{nameof(DockerResourceDetector)} : Failed to extract Container id from path", ex);
}

return null;
}

/// <summary>
/// Gets the Container Id from the line after removing the prefix and suffix.
/// </summary>
/// <param name="line">line read from cgroup file.</param>
/// <returns>Container Id.</returns>
private string GetIdFromLine(string line)
catch (Exception ex)
{
// This cgroup output line should have the container id in it
int lastSlashIndex = line.LastIndexOf('/');
if (lastSlashIndex < 0)
{
return null;
}
DockerExtensionsEventSource.Log.ExtractResourceAttributesException($"{nameof(DockerResourceDetector)} : Failed to extract Container id from path", ex);
}

string lastSection = line.Substring(lastSlashIndex + 1);
int startIndex = lastSection.LastIndexOf('-');
int endIndex = lastSection.LastIndexOf('.');
return null;
}

string containerId = this.RemovePrefixAndSuffixIfneeded(lastSection, startIndex, endIndex);
/// <summary>
/// Gets the Container Id from the line after removing the prefix and suffix.
/// </summary>
/// <param name="line">line read from cgroup file.</param>
/// <returns>Container Id.</returns>
private string GetIdFromLine(string line)
{
// This cgroup output line should have the container id in it
int lastSlashIndex = line.LastIndexOf('/');
if (lastSlashIndex < 0)
{
return null;
}

if (string.IsNullOrEmpty(containerId) || !EncodingUtils.IsValidHexString(containerId))
{
return null;
}
string lastSection = line.Substring(lastSlashIndex + 1);
int startIndex = lastSection.LastIndexOf('-');
int endIndex = lastSection.LastIndexOf('.');

return containerId;
}
string containerId = this.RemovePrefixAndSuffixIfneeded(lastSection, startIndex, endIndex);

private string RemovePrefixAndSuffixIfneeded(string input, int startIndex, int endIndex)
if (string.IsNullOrEmpty(containerId) || !EncodingUtils.IsValidHexString(containerId))
{
startIndex = (startIndex == -1) ? 0 : startIndex + 1;
return null;
}

if (endIndex == -1)
{
endIndex = input.Length;
}
return containerId;
}

private string RemovePrefixAndSuffixIfneeded(string input, int startIndex, int endIndex)
{
startIndex = (startIndex == -1) ? 0 : startIndex + 1;

return input.Substring(startIndex, endIndex - startIndex);
if (endIndex == -1)
{
endIndex = input.Length;
}

return input.Substring(startIndex, endIndex - startIndex);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@
// limitations under the License.
// </copyright>

namespace OpenTelemetry.Extensions.Docker.Resources
namespace OpenTelemetry.Extensions.Docker.Resources;

internal static class DockerSemanticConventions
{
internal static class DockerSemanticConventions
{
public const string AttributeContainerID = "container.id";
}
public const string AttributeContainerID = "container.id";
}
27 changes: 13 additions & 14 deletions src/OpenTelemetry.Extensions.Docker/Utils/EncodingUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,20 @@
using System.Collections.Generic;
using System.Linq;

namespace OpenTelemetry.Extensions.Docker.Utils
namespace OpenTelemetry.Extensions.Docker.Utils;

internal class EncodingUtils
{
internal class EncodingUtils
/// <summary>
/// Checks if the string is valid hex.
/// </summary>
/// <param name="hexString">string.</param>
/// <returns>true if valid else false.</returns>
public static bool IsValidHexString(IEnumerable<char> hexString)
{
/// <summary>
/// Checks if the string is valid hex.
/// </summary>
/// <param name="hexString">string.</param>
/// <returns>true if valid else false.</returns>
public static bool IsValidHexString(IEnumerable<char> hexString)
{
return hexString.Select(currentCharacter =>
(currentCharacter >= '0' && currentCharacter <= '9') ||
(currentCharacter >= 'a' && currentCharacter <= 'f') ||
(currentCharacter >= 'A' && currentCharacter <= 'F')).All(isHexCharacter => isHexCharacter);
}
return hexString.Select(currentCharacter =>
(currentCharacter >= '0' && currentCharacter <= '9') ||
(currentCharacter >= 'a' && currentCharacter <= 'f') ||
(currentCharacter >= 'A' && currentCharacter <= 'F')).All(isHexCharacter => isHexCharacter);
}
}
Loading

0 comments on commit 8d91837

Please sign in to comment.