-
Notifications
You must be signed in to change notification settings - Fork 58
Remove Mono.Unix dependency
#223
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
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
33dd60b
restore UnixEndPoint
lucaspimentel 487f744
update git ignore
lucaspimentel 8eb8f44
add C project (native library)
lucaspimentel 73f8bcc
use p/invoke to call into native library to get inode
lucaspimentel 7edda64
add tests for calling native library from C#
lucaspimentel f49db22
add scripts to build and test native library in docker
lucaspimentel 139461c
add .gitattributes to fix bash script line endings on Windows
lucaspimentel d446c75
build native library in github workflow
lucaspimentel 145845e
include native library in nuget package
lucaspimentel 55dbc7c
remove Mono.Unix dependency
lucaspimentel 73aa5a2
add BUILD.md
lucaspimentel 8073f20
add CLAUDE.md
lucaspimentel 0391dd5
Use statx instead of a bundled native library for inode lookup
lucaspimentel 5fde553
Fix doc inaccuracies in BUILD.md and CLAUDE.md
lucaspimentel ad2dbb9
tweak code comment
lucaspimentel 8bfd4d0
Remove unused build-and-test.sh dev script
lucaspimentel 9407ecd
Simplify TryStat platform check
lucaspimentel 277f952
check for null input
lucaspimentel 8b5cec7
Trim CLAUDE.md to avoid duplicating BUILD.md
lucaspimentel File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| ############################################################################### | ||
| # Set default behavior to automatically normalize line endings. | ||
| ############################################################################### | ||
| * text=auto | ||
|
|
||
| # Set line endings to LF, even on Windows. Otherwise, execution within Docker fails. | ||
| # See https://help.github.com/articles/dealing-with-line-endings/ | ||
| *.sh text eol=lf | ||
| *.bash text eol=lf |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| # Building and Testing | ||
|
|
||
| This document describes how to build and test the DogStatsD C# client library. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - [.NET SDK 10.0 or above](https://dotnet.microsoft.com/download) | ||
|
|
||
| ## Quick Start | ||
|
|
||
| ```bash | ||
| # Build the .NET library | ||
| dotnet build | ||
|
|
||
| # Run tests for a specific framework | ||
| dotnet test --framework net8.0 | ||
|
|
||
| # Pack the NuGet package | ||
| dotnet pack src/StatsdClient/StatsdClient.csproj -c Release | ||
| # Output: artifacts/package/release/*.nupkg | ||
| ``` | ||
|
|
||
| ## Building | ||
|
|
||
| Build the main .NET library: | ||
|
|
||
| ```bash | ||
| # Restore dependencies | ||
| dotnet restore | ||
|
|
||
| # Build all projects | ||
| dotnet build | ||
|
|
||
| # Build specific project | ||
| dotnet build src/StatsdClient/StatsdClient.csproj | ||
|
|
||
| # Build for specific configuration | ||
| dotnet build -c Release | ||
|
|
||
| # Build for specific target framework | ||
| dotnet build src/StatsdClient/StatsdClient.csproj -f netstandard2.0 | ||
| ``` | ||
|
|
||
| ## Testing | ||
|
|
||
| ### Important: Framework Selection | ||
|
|
||
| **Always specify `--framework` when running tests.** Running tests without a framework specification will run all target frameworks in parallel, causing conflicts due to shared named pipes. | ||
|
|
||
| ### Using dotnet test | ||
|
|
||
| ```bash | ||
| # Run all tests for a specific framework | ||
| dotnet test --framework net8.0 | ||
|
|
||
| # Run tests for specific project and framework | ||
| dotnet test tests/StatsdClient.Tests/ --framework net8.0 | ||
|
|
||
| # Run specific test class | ||
| dotnet test --framework net8.0 --filter FullyQualifiedName~DogStatsdServiceMetricsTests | ||
|
|
||
| # Run specific test method | ||
| dotnet test --framework net8.0 --filter FullyQualifiedName~DogStatsdServiceMetricsTests.Counter | ||
| ``` | ||
|
|
||
| ### Testing All Frameworks Sequentially | ||
|
|
||
| **Linux/macOS:** | ||
| ```bash | ||
| for tfm in netcoreapp2.1 netcoreapp3.0 netcoreapp3.1 net5.0 net6.0 net7.0 net8.0 net9.0 net10.0; do | ||
| dotnet test --framework $tfm | ||
| done | ||
| ``` | ||
|
|
||
| **Windows (includes .NET Framework):** | ||
| ```bash | ||
| for tfm in net48 netcoreapp2.1 netcoreapp3.0 netcoreapp3.1 net5.0 net6.0 net7.0 net8.0 net9.0 net10.0; do | ||
| dotnet test --framework $tfm | ||
| done | ||
| ``` | ||
|
|
||
| ### Supported Test Frameworks | ||
|
|
||
| The test project runs against: | ||
|
|
||
| - .NET Framework 4.8 (Windows only) | ||
| - .NET Core 2.1, 3.0, 3.1 | ||
| - .NET 5, 6, 7, 8, 9, 10 | ||
|
|
||
| The library itself (`src/StatsdClient/StatsdClient.csproj`) targets `net461`, `netstandard2.0`, `netcoreapp3.1`, and `net6.0`. | ||
|
|
||
| ## Packaging | ||
|
|
||
| To create a NuGet package: | ||
|
|
||
| ```bash | ||
| dotnet pack src/StatsdClient/StatsdClient.csproj -c Release | ||
|
|
||
| # Output: artifacts/package/release/*.nupkg | ||
| ``` | ||
|
|
||
| The build uses .NET's artifacts output layout (`UseArtifactsOutput` in `Directory.Build.props`), so build and package outputs go to the top-level `artifacts/` directory rather than per-project `bin/` and `obj/` folders. | ||
|
|
||
| ## Benchmarks | ||
|
|
||
| Run performance benchmarks: | ||
|
|
||
| ```bash | ||
| dotnet run -c Release --project benchmarks/StatsdClient.Benchmarks/StatsdClient.Benchmarks.csproj | ||
| ``` | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### Tests fail with "address already in use" or named pipe conflicts | ||
|
|
||
| Make sure you're specifying `--framework` when running tests. Running multiple frameworks in parallel causes port and named pipe conflicts. | ||
|
|
||
| ```bash | ||
| # ❌ Wrong - runs all frameworks in parallel | ||
| dotnet test | ||
|
|
||
| # ✅ Correct - runs single framework | ||
| dotnet test --framework net8.0 | ||
| ``` | ||
|
|
||
| ## Clean Build | ||
|
|
||
| Remove build artifacts: | ||
|
|
||
| ```bash | ||
| # Clean .NET build outputs | ||
| dotnet clean | ||
|
|
||
| # Remove all build and package outputs | ||
| rm -rf artifacts/ | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # CLAUDE.md | ||
|
|
||
| This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. | ||
|
|
||
| ## Repository Overview | ||
|
|
||
| This is the DogStatsD C# client library (https://github.com/DataDog/dogstatsd-csharp-client), a C# implementation of the DogStatsD protocol for sending metrics, events, and service checks to Datadog. | ||
|
|
||
| ## Building and Testing | ||
|
|
||
| See [BUILD.md](BUILD.md) for build, test, packaging, and benchmark commands, and the list of target frameworks. | ||
|
|
||
| Gotcha: always pass `--framework` to `dotnet test` (e.g. `dotnet test --framework net8.0`). Running all target frameworks in parallel causes named-pipe conflicts. | ||
|
|
||
| ## Architecture | ||
|
|
||
| Metrics flow through: submission API -> router -> client-side aggregation or buffer -> background worker -> transport, with telemetry tracked throughout. | ||
|
|
||
| - **Public API**: `DogStatsdService` is the thread-safe, instance-based entry point; it must be `Configure()`d before use and disposed to flush. The static `DogStatsd` class wraps a single global instance over the same implementation. | ||
| - **Routing and aggregation**: stats are routed to client-side aggregators (Count, Gauge, Set) or sent directly to the buffer (Histogram, Distribution, Timing). Aggregation flushes on an interval (default 2s, configurable; set `StatsdConfig.ClientSideAggregation` to null to disable). | ||
| - **Buffering and transport**: metrics are batched into datagrams up to a max packet size, then sent over UDP, a Unix domain socket, or a Windows named pipe. Submission is non-blocking; only `Flush()` and `Dispose()` block. | ||
| - **Configuration**: `StatsdConfig` holds the server name/port and aggregation settings and reads environment variables such as `DD_AGENT_HOST`, `DD_DOGSTATSD_PORT`, `DD_ENTITY_ID`, `DD_SERVICE`, `DD_ENV`, and `DD_VERSION`. | ||
|
|
||
| ## Design Notes | ||
|
|
||
| - Both `DogStatsdService` and the static `DogStatsd` are thread-safe. Custom worker handlers must be thread-safe when `workerThreadCount > 1`. | ||
| - Hot paths use object pooling and struct-based stats to minimize allocations; keep this in mind before adding heap allocations to the submission path. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| #if !NETFRAMEWORK | ||
|
|
||
| using System; | ||
| using System.Runtime.InteropServices; | ||
|
|
||
| namespace StatsdClient | ||
| { | ||
| /// <summary> | ||
| /// P/Invoke wrapper for the libc <c>statx</c> system call to retrieve file inodes on Linux. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// <c>statx</c> is used instead of <c>stat</c> because its result structure (<c>struct statx</c>) | ||
| /// has a fixed, architecture-independent layout defined by the kernel, so a single managed struct | ||
| /// definition works across all architectures and libc implementations (glibc and musl). The older | ||
| /// <c>stat</c> call has a layout that varies by architecture and libc, which is not safe to marshal directly. | ||
| /// </remarks> | ||
| internal static class NativeMethods | ||
| { | ||
| // Resolve the path relative to the current working directory (used when the path is not a dirfd-relative path). | ||
| private const int AT_FDCWD = -100; | ||
|
|
||
| // Request only the inode number (stx_ino) from statx. | ||
| private const uint STATX_INO = 0x00000100; | ||
|
|
||
| /// <summary> | ||
| /// Gets a value indicating whether the inode lookup is supported on the current platform (Linux only). | ||
| /// </summary> | ||
| public static bool IsSupported => RuntimeInformation.IsOSPlatform(OSPlatform.Linux); | ||
|
|
||
| /// <summary> | ||
| /// Attempts to get the inode number for the specified file path. | ||
| /// </summary> | ||
| /// <param name="path">The file path.</param> | ||
| /// <param name="inode">The inode number if successful, 0 otherwise.</param> | ||
| /// <returns>true if the inode was successfully retrieved, false otherwise.</returns> | ||
| public static bool TryGetInode(string path, out ulong inode) | ||
| { | ||
| inode = 0; | ||
|
|
||
| if (string.IsNullOrEmpty(path)) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| if (!IsSupported) | ||
| { | ||
| return false; | ||
| } | ||
| try | ||
| { | ||
| // flags = 0 means symlinks are followed, matching stat() behavior (needed for the | ||
| // /proc/self/ns/cgroup magic link). statx returns -1 on failure, including ENOSYS on | ||
| // kernels older than 4.11, in which case we fall back to no inode. | ||
| if (Statx(AT_FDCWD, path, 0, STATX_INO, out var buffer) != 0) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| inode = buffer.StatxIno; | ||
| return true; | ||
| } | ||
| catch (DllNotFoundException) | ||
| { | ||
| // libc not available | ||
| return false; | ||
| } | ||
| catch (EntryPointNotFoundException) | ||
| { | ||
| // statx not available (e.g. glibc older than 2.28) | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| [DllImport("libc", EntryPoint = "statx", SetLastError = true, CharSet = CharSet.Ansi)] | ||
| private static extern int Statx(int dirfd, string pathname, int flags, uint mask, out StatxBuffer buffer); | ||
|
|
||
| /// <summary> | ||
| /// Mirror of the kernel's <c>struct statx</c> (256 bytes). Only the inode field is read; the | ||
| /// full size is preserved so the kernel does not write past the buffer. | ||
| /// </summary> | ||
| [StructLayout(LayoutKind.Explicit, Size = 256)] | ||
| private struct StatxBuffer | ||
| { | ||
| // stx_ino lives at byte offset 32 in struct statx. | ||
| [FieldOffset(32)] | ||
| public ulong StatxIno; | ||
| } | ||
| } | ||
| } | ||
| #endif | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.