diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7a70928362..b1ac246a3c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,6 +7,12 @@ updates: interval: "daily" + - package-ecosystem: 'npm' + directory: '/' + schedule: + interval: 'daily' + + - package-ecosystem: nuget directory: /build/nuke schedule: diff --git a/.github/workflows/markdownlint.yml b/.github/workflows/markdownlint.yml new file mode 100644 index 0000000000..8056fb43c0 --- /dev/null +++ b/.github/workflows/markdownlint.yml @@ -0,0 +1,26 @@ +name: markdownlint + +on: + push: + branches: [ main ] + paths: + - '**.md' + - 'package-lock.json' + - 'package.json' + pull_request: + branches: [ main ] + paths: + - '**.md' + - 'package-lock.json' + - 'package.json' + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3.0.1 + + - run: npm install + + - run: npm run markdownlint diff --git a/.gitignore b/.gitignore index 01c22686b6..5f77ff39a4 100644 --- a/.gitignore +++ b/.gitignore @@ -261,7 +261,8 @@ __pycache__/ *.pyc # vscode -.vscode/ +.vscode/* +!.vscode/extensions.json .devcontainer/ # Benchmark results diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 0000000000..30672f8e7f --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,7 @@ +# Default state for all rules +default: true + +# allow long lines for tables and code blocks +MD013: + code_blocks: false + tables: false diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000000..74c685053d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "davidanson.vscode-markdownlint", + ] +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a15a03945..5237572556 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm The is an initial, official beta release, built on top of [OpenTelemetry .NET](https://github.com/open-telemetry/opentelemetry-dotnet): -- [Core components](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/VERSIONING.md#core-components): [`1.2.0`](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/core-1.2.0) +- [Core components](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/VERSIONING.md#core-components): + [`1.2.0`](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/core-1.2.0) - Non-core components: [`1.0.0-rc9.2`](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/1.0.0-rc9.2) - `System.Diagnostics.DiagnosticSource`: [`6.0.0`](https://www.nuget.org/packages/System.Diagnostics.DiagnosticSource/6.0.0) diff --git a/build/nuke/Build.Steps.cs b/build/nuke/Build.Steps.cs index f59e5289cc..5c7fbd4c6f 100644 --- a/build/nuke/Build.Steps.cs +++ b/build/nuke/Build.Steps.cs @@ -10,6 +10,7 @@ using Nuke.Common.Tooling; using Nuke.Common.Tools.DotNet; using Nuke.Common.Tools.MSBuild; +using Nuke.Common.Tools.Npm; using Nuke.Common.Tools.NuGet; using Nuke.Common.Utilities.Collections; using Serilog; @@ -353,6 +354,29 @@ partial class Build }); }); + Target InstallMarkdownLint => _ => _ + .Description("Installs markdownlint-cli locally. npm is required") + .Executes(() => + { + NpmTasks.NpmInstall(); + }); + + Target MarkdownLint => _ => _ + .Description("Executes MarkdownLint") + .After(InstallMarkdownLint) + .Executes(() => + { + NpmTasks.NpmRun(s => s.SetCommand(@"markdownlint")); + }); + + Target MarkdownLintFix => _ => _ + .Description("Trying to fix MarkdownLint issues") + .After(InstallMarkdownLint) + .Executes(() => + { + NpmTasks.NpmRun(s => s.SetCommand(@"markdownlint-fix")); + }); + private AbsolutePath GetResultsDirectory(Project proj) => BuildDataDirectory / "results" / proj.Name; /// diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 8a50e26739..7827cff5f1 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -4,7 +4,8 @@ We'd love your help! -Please join our weekly [SIG meeting](https://github.com/open-telemetry/community#special-interest-groups) or get in touch on [Slack](https://cloud-native.slack.com/archives/C01NR1YLSE7). +Please join our weekly [SIG meeting](https://github.com/open-telemetry/community#special-interest-groups) +or get in touch on [Slack](https://cloud-native.slack.com/archives/C01NR1YLSE7). Meeting notes are available as a public [Google doc](https://docs.google.com/document/d/1XedN2D8_PH4YLej-maT8sp4RKogfuhFpccRi3QpUcoI/edit?usp=sharing). @@ -22,7 +23,7 @@ Reporting bugs is an important contribution. Please make sure to include: If you would like to work on something that is not listed as an issue (e.g. a new feature or enhancement) please first read our [DESIGN.md](DESIGN.md) to make sure your proposal aligns with the goals of the -project, then create an issue and describe your proposal. +project, then create an issue and describe your proposal. ## How to contribute @@ -40,8 +41,9 @@ clarify anything related to it. If you would like to work on something that is not listed as an issue, please [request a feature](#request-a-feature) first. -It is best to do this in advance so that maintainers can decide if the proposal is a good fit for -this repository. This will help avoid situations when you spend significant time +It is best to do this in advance so that maintainers can decide if the proposal +is a good fit for this repository. +This will help avoid situations when you spend significant time on something that maintainers may decide this repo is not the right place for. See [developing.md](developing.md) to learn more about diff --git a/docs/README.md b/docs/README.md index ed654a4534..7938b41ca7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,11 +7,13 @@ to .NET applications without having to modify their source code. OpenTelemetry .NET Automatic Instrumentation is built on top of [OpenTelemetry .NET](https://github.com/open-telemetry/opentelemetry-dotnet): -- [Core components](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/VERSIONING.md#core-components): [`1.2.0`](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/core-1.2.0) +- [Core components](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/VERSIONING.md#core-components): +[`1.2.0`](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/core-1.2.0) - Non-core components: [`1.0.0-rc9.2`](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/1.0.0-rc9.2) - `System.Diagnostics.DiagnosticSource`: [`6.0.0`](https://www.nuget.org/packages/System.Diagnostics.DiagnosticSource/6.0.0) -To automatically instrument applications, the OpenTelemetry .NET Automatic Instrumentation does the following: +To automatically instrument applications, the OpenTelemetry .NET Automatic +Instrumentation does the following: 1. Injects and configures the [OpenTelemetry .NET SDK](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry/README.md#opentelemetry-net-sdk) into the application. diff --git a/docs/config.md b/docs/config.md index aa7fc43d59..4cdf792b5d 100644 --- a/docs/config.md +++ b/docs/config.md @@ -9,7 +9,6 @@ | `OTEL_DOTNET_AUTO_INCLUDE_PROCESSES` | Names of the executable files that the profiler can instrument. Supports multiple comma-separated values, for example: `MyApp.exe,dotnet.exe`. If unset, the profiler attaches to all processes by default. | | | `OTEL_DOTNET_AUTO_EXCLUDE_PROCESSES` | Names of the executable files that the profiler cannot instrument. Supports multiple comma-separated values, for example: `ReservedProcess.exe,powershell.exe`. The list is processed after `OTEL_DOTNET_AUTO_INCLUDE_PROCESSES`. If unset, the profiler attaches to all processes by default. | | | `OTEL_DOTNET_AUTO_AZURE_APP_SERVICES` | Set to indicate that the profiler is running in the context of Azure App Services. | `false` | - ## Resources @@ -49,7 +48,8 @@ for more details. ASP.NET instrumentation on .NET Framework requires to install the [`OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule`](https://www.nuget.org/packages/OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule/) NuGet package in the instrumented project. -See [the WebConfig section](https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry.Instrumentation.AspNet#step-2-modify-webconfig) for more information. +See [the WebConfig section](https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry.Instrumentation.AspNet#step-2-modify-webconfig) +for more information. ## Logging @@ -59,7 +59,8 @@ The default log directory paths are: - Linux: `/var/log/opentelemetry/dotnet` If the default log directories can't be created, -the instrumentation uses the path of the current user's [temporary folder](https://docs.microsoft.com/en-us/dotnet/api/System.IO.Path.GetTempPath?view=net-6.0) instead. +the instrumentation uses the path of the current user's [temporary folder](https://docs.microsoft.com/en-us/dotnet/api/System.IO.Path.GetTempPath?view=net-6.0) +instead. | Environment variable | Description | Default | |-|-|-| @@ -89,8 +90,9 @@ Exporters output the telemetry. **[1]**: Considerations on the `OTEL_EXPORTER_OTLP_PROTOCOL`: - On .NET 5 and higher, the application must reference [`Grpc.Net.Client`](https://www.nuget.org/packages/Grpc.Net.Client/) - to use the `grpc` OTLP exporter protocol. For example, by adding - `` to the `.csproj` file. + to use the `grpc` OTLP exporter protocol. For example, by adding + `` to the `.csproj` + file. - On .NET Framework, the `grpc` OTLP exporter protocol is not supported. ## Batch span processor @@ -114,7 +116,6 @@ The batch span processor batches finished spans before sending them through the | `OTEL_DOTNET_AUTO_FLUSH_ON_UNHANDLEDEXCEPTION` | Controls whether the telemetry data is flushed when an [AppDomain.UnhandledException](https://docs.microsoft.com/en-us/dotnet/api/system.appdomain.unhandledexception) event is raised. Set to `true` when you suspect that you are experiencing a problem with missing telemetry data and also experiencing unhandled exceptions. | `false` | | `OTEL_DOTNET_AUTO_INSTRUMENTATION_PLUGINS` | Colon-separated list of OTel SDK instrumentation plugins represented by `System.Type.AssemblyQualifiedName`. | | - You can use `OTEL_DOTNET_AUTO_INSTRUMENTATION_PLUGINS` to extend the configuration of the OpenTelemetry .NET SDK Tracer. A plugin must be a non-static, non-abstract class which has a default constructor and a method @@ -131,7 +132,7 @@ OpenTelemetry .NET Automatic Instrumentation. To perform bytecode instrumentation, configure the OpenTelemetry .NET Automatic Instrumentation as a .NET CLR Profiler. The CLR uses the following -environment variables to set up the profiler. +environment variables to set up the profiler. > Notice that .NET Framework uses the `COR_` prefix instead of `CORECLR_`. @@ -143,9 +144,11 @@ environment variables to set up the profiler. | `CORECLR_PROFILER_PATH_32` | Path to the 32-bit profiler. Bitness-specific paths take precedence over generic paths. | `%InstallationLocation%/win-x86/OpenTelemetry.AutoInstrumentation.Native.dll` for Windows | | `CORECLR_PROFILER_PATH_64` | Path to the 64-bit profiler. Bitness-specific paths take precedence over generic paths. | `%InstallationLocation%/win-x64/OpenTelemetry.AutoInstrumentation.Native.dll` for Windows | -The `*_PROFILER_PATH_*` environment variable is not needed on Windows if the DLL file is already registered. +The `*_PROFILER_PATH_*` environment variable is not needed on Windows if the DLL +file is already registered. -See [.NET Runtime Profiler Loading](https://github.com/dotnet/runtime/blob/main/docs/design/coreclr/profiling/Profiler%20Loading.md) for more information. +See [.NET Runtime Profiler Loading](https://github.com/dotnet/runtime/blob/main/docs/design/coreclr/profiling/Profiler%20Loading.md) +for more information. ## .NET Runtime additional dependencies and package store diff --git a/docs/design.md b/docs/design.md index 819cda3618..ea16f6d2ca 100644 --- a/docs/design.md +++ b/docs/design.md @@ -2,43 +2,52 @@ ## Vision -The following are the goals that define the long-term vision for the project. The vision guides daily activities, design, and feature acceptance. - -- **High performance**: Automatic instrumentation performance impact should not be a concern for users. -- **Reliability**: Stable and performant under different loads. Well-behaved under extreme load, with low, predictable resource consumption. -- **Visibility**: Users should be able to generate telemetry that provides deep and detailed visibility into their applications. Such telemetry must allow users to identify and solve application-related issues in production. -- **Useful by default**: After installations users should be able to get telemetry from targeted libraries with none or minimal configuration, thanks to a good selection of default settings. +The following are the goals that define the long-term vision for the project. +The vision guides daily activities, design, and feature acceptance. + +- **High performance**: Automatic instrumentation performance impact +should not be a concern for users. +- **Reliability**: Stable and performant under different loads. Well-behaved +under extreme load, with low, predictable resource consumption. +- **Visibility**: Users should be able to generate telemetry that provides deep +and detailed visibility into their applications. Such telemetry must allow users +to identify and solve application-related issues in production. +- **Useful by default**: After installations users should be able to get telemetry +from targeted libraries with none or minimal configuration, +thanks to a good selection of default settings. - **Extensible**: Users can choose key components through configuration and plugins. ## Supported and unsupported scenarios ### Supported scenarios -- **Zero-touch source code instrumentation**: Users can instrument applications without changing -the source. Build changes may be required through the addition of specific NuGet packages. -- **Custom SDK support**: The instrumentation can initialize the OpenTelemetry .NET SDK, though -what OpenTelemetry SDK implementation is used and its initialization can also be delegated -to the application code. +- **Zero-touch source code instrumentation**: Users can instrument applications +without changing the source. Build changes may be required through the addition +of specific NuGet packages. +- **Custom SDK support**: The instrumentation can initialize +the OpenTelemetry .NET SDK, though what OpenTelemetry SDK implementation is used +and its initialization can also be delegated to the application code. -### Unsupported scenarios: +### Unsupported scenarios -- **Applications using Ahead-of-Time (AOT) compilation**: The current implementation relies on the -[CLR Profiler APIs](https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/profiling/) +- **Applications using Ahead-of-Time (AOT) compilation**: +The current implementation relies on the [CLR Profiler APIs](https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/profiling/) and doesn't support AOT. - **Side-by-side usage with other CLR Profiler based tools**: Various tools for .NET -are also implemented using a CLR Profiler. However, only a single CLR Profiler can be used when running -the application. +are also implemented using a CLR Profiler. However, only a single CLR Profiler +can be used when running the application. ## Error handling -Initialization errors, usually caused by invalid configuration, are logged and crash the application. +Initialization errors, usually caused by invalid configuration, +are logged and crash the application. Errors occurring at application runtime are logged and should never crash the application. ## Architecture -To instrument a .NET application without requiring source code changes, the OpenTelemetry .NET Instrumentation uses the -[CLR Profiler APIs](https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/profiling/) +To instrument a .NET application without requiring source code changes, +the OpenTelemetry .NET Instrumentation uses the [CLR Profiler APIs](https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/profiling/) to bootstrap the [OpenTelemetry .NET SDK](https://github.com/open-telemetry/opentelemetry-dotnet#readme) and inject the selected instrumentations into the targeted application. @@ -46,14 +55,15 @@ The main components of the project are: - [**CLR Profiler DLL**](../src/OpenTelemetry.AutoInstrumentation.Native): Native component that implements a CLR Profiler. The CLR Profiler is used to -modify the application [intermediate language](https://en.wikipedia.org/wiki/Common_Intermediate_Language) (IL), -including the IL of packages used by the application, to add and collect observability data. +modify the application [intermediate language](https://en.wikipedia.org/wiki/Common_Intermediate_Language) + (IL), including the IL of packages used by the application, to add and collect + observability data. - [**Loader**](../src/OpenTelemetry.AutoInstrumentation.Loader): Managed library shipped as a resource of the native CLR Profiler. It loads the bootstrap code into the targeted application and extends the assembly -load paths to include the folders with the OpenTelemetry .NET SDK and the instrumentations to be -injected into the application. +load paths to include the folders with the OpenTelemetry .NET SDK +and the instrumentations to be injected into the application. - [**Managed Profiler**](../src/OpenTelemetry.AutoInstrumentation): Contains the code to set up the OpenTelemetry .NET SDK and configured instrumentations, @@ -61,17 +71,19 @@ as well as support code to run and implement bytecode instrumentations. Set the `OTEL_DOTNET_AUTO_LOAD_AT_STARTUP` environment variable to `false` when the application initializes the OpenTelemetry .NET SDK Tracer on its own. -- **Source Instrumentations**: Instrumentations created on top of API hooks or callbacks provided -directly by the library or framework being instrumented. This type of instrumentation depends on the -OpenTelemetry API and the specific library or framework that they instrument. Some examples include: +- **Source Instrumentations**: Instrumentations created on top of API hooks +or callbacks provided directly by the library or framework being instrumented. +This type of instrumentation depends on the OpenTelemetry API and the specific +library or framework that they instrument. Some examples include: - [ASP.NET Core Instrumentation](https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry.Instrumentation.AspNetCore) - [gRPC Client Instrumentation](https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry.Instrumentation.GrpcNetClient) - [HttpClient and HttpWebRequest Instrumentation](https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry.Instrumentation.Http) -- **Bytecode Instrumentations**: Instrumentations created for libraries or frameworks that lack proper -hooks or callbacks to allow the collection of observability data. These instrumentations must be -implemented following the proper attribute annotation so that the native CLR Profiler implementation +- **Bytecode Instrumentations**: Instrumentations created for libraries +or frameworks that lack proper hooks or callbacks to allow the collection +of observability data. These instrumentations must be implemented following +the proper attribute annotation so that the native CLR Profiler implementation can inject them at runtime. Some examples include: - [GraphQL](../src/OpenTelemetry.AutoInstrumentation/Instrumentations/GraphQL) @@ -80,49 +92,58 @@ can inject them at runtime. Some examples include: ### Injecting the OpenTelemetry .NET SDK and instrumentations -The OpenTelemetry .NET SDK and selected source instrumentations are injected into the target process -through a series of steps started by the CLR Profiler DLL: +The OpenTelemetry .NET SDK and selected source instrumentations are injected +into the target process through a series of steps started by the CLR Profiler DLL: 1. On the [CorProfiler::ModuleLoadFinished](https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/profiling/icorprofilercallback-moduleloadfinished-method) callback, the CLR Profiler DLL takes the following actions: - - If the loaded module is in the set of modules for which there is bytecode instrumentation, - or if it's the first non-corelib module or not in one of the special cases, the profiler adds - the module to a map of modules to be instrumented. - - If there is bytecode instrumentation for the module, the profiler requests a JIT recompilation using - [ICorProfilerInfo::RequestReJIT](https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/profiling/icorprofilerinfo4-requestrejit-method) - for the methods targeted by the bytecode instrumentation. + - If the loaded module is in the set of modules for which there is bytecode instrumentation, + or if it's the first non-corelib module or not in one of the special cases, + the profiler adds the module to a map of modules to be instrumented. + - If there is bytecode instrumentation for the module, the profiler requests + a JIT recompilation using + [ICorProfilerInfo::RequestReJIT](https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/profiling/icorprofilerinfo4-requestrejit-method) + for the methods targeted by the bytecode instrumentation. 2. On the [CorProfiler::JITCompilationStarted](https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/profiling/icorprofilercallback-jitcompilationstarted-method) callback, the CLR Profiler DLL takes the following actions: - - If instrumenting he first module in the current AppDomain, the profiler injects the IL calling the - Loader `Startup` type constructor. This type of constructor: - * Adds an event handler to the - [`AssemblyResolve`](https://docs.microsoft.com/en-us/dotnet/api/system.appdomain.assemblyresolve?view=net-5.0), - so that it can add any assembly needed by the SDK itself or by any instrumentation. - * Runs, through reflection, the `Initialization` method from the Managed Profiler assembly. - - The `Initialization` code bootstraps the OpenTelemetry .NET SDK, adding configured processors, exporters, - and so on, and initializes any configured source instrumentations. - - If the first method observed by JITCompilationStarted is IIS startup code, the profiler invokes - `AppDomain.CurrentDomain.SetData("OpenTelemetry_IISPreInitStart", true)`, so that automatic instrumentation + - If instrumenting he first module in the current AppDomain, + the profiler injects the IL calling the Loader `Startup` type constructor. + This type of constructor: + + - Adds an event handler to the + [`AssemblyResolve`](https://docs.microsoft.com/en-us/dotnet/api/system.appdomain.assemblyresolve?view=net-5.0), + so that it can add any assembly needed by the SDK itself or by any instrumentation. + - Runs, through reflection, the `Initialization` method from + the Managed Profiler assembly. + - The `Initialization` code bootstraps the OpenTelemetry .NET SDK, + adding configured processors, exporters, and so on, + and initializes any configured source instrumentations. + - If the first method observed by JITCompilationStarted is IIS startup code, + the profiler invokes + `AppDomain.CurrentDomain.SetData("OpenTelemetry_IISPreInitStart", true)`, + so that automatic instrumentation correctly handles IIS startup scenarios. ### Bytecode instrumentations -The bytecode instrumentation, called "call target" in this repo, relies on the JIT recompilation -capability of the CLR to rewrite the IL for instrumented methods. This adds logic at -the beginning and end of the instrumented methods to invoke instrumentation written in this repo, and -wraps the calls with try-catch blocks to prevent instrumentation errors from affecting the normal operation +The bytecode instrumentation, called "call target" in this repo, relies on +the JIT recompilation capability of the CLR to rewrite the IL for instrumented +methods. This adds logic at the beginning and end of the instrumented methods +to invoke instrumentation written in this repo, and wraps the calls with +try-catch blocks to prevent instrumentation errors from affecting the normal operation of the application. -Bytecode instrumentation methods should not have direct dependencies with the libraries that they instrument. -This way, they can work with multiple versions of the assemblies targeted for instrumentation -and reduce the number of shipped files. +Bytecode instrumentation methods should not have direct dependencies with +the libraries that they instrument. This way, they can work with multiple +versions of the assemblies targeted for instrumentation and reduce the number +of shipped files. -When operating with parameters and return values of the targeted methods, the instrumentation methods must use -[DuckTyping](../src/OpenTelemetry.AutoInstrumentation.Managed/DuckTyping/README.md) or -[reflection](https://docs.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/reflection) +When operating with parameters and return values of the targeted methods, +the instrumentation methods must use [DuckTyping](../src/OpenTelemetry.AutoInstrumentation.Managed/DuckTyping/README.md) +or [reflection](https://docs.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/reflection) to access objects from the APIs being instrumented. ### Assembly conflict resolution @@ -132,37 +153,44 @@ the risk of assembly version conflicts. This issue is more likely with the [NuGet package System.Diagnostic.DiagnosticSource](https://www.nuget.org/packages/System.Diagnostics.DiagnosticSource/) and its dependencies, because it contains the [Activity type](https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.activity?view=net-5.0) used by the OpenTelemetry .NET API to represent a span. This package, previously -released by Microsoft, is already used by various applications. +released by Microsoft, is already used by various applications. Two issues might arise from incorrect versioning: -1. Version required by the OpenTelemetry .NET SDK or the instrumentations is not met. -2. Multiple versions of the assembly in the same process, as the runtime treats them independently. +1. Version required by the OpenTelemetry .NET SDK or the instrumentations + is not met. +2. Multiple versions of the assembly in the same process, + as the runtime treats them independently. #### Configuration resolution -.NET Core [Framework-dependent deployment](https://docs.microsoft.com/en-us/dotnet/core/deploying/deploy-with-cli#framework-dependent-deployment) applications might use -[DOTNET_ADDITIONAL_DEPS](https://github.com/dotnet/runtime/blob/main/docs/design/features/additional-deps.md) and -[DOTNET_SHARED_STORE](https://docs.microsoft.com/en-us/dotnet/core/deploying/runtime-store) from -OpenTelemetry .NET Automatic Instrumentation installation location to resolve assembly conflicts. +.NET Core [Framework-dependent deployment](https://docs.microsoft.com/en-us/dotnet/core/deploying/deploy-with-cli#framework-dependent-deployment) +applications might use [DOTNET_ADDITIONAL_DEPS](https://github.com/dotnet/runtime/blob/main/docs/design/features/additional-deps.md) +and [DOTNET_SHARED_STORE](https://docs.microsoft.com/en-us/dotnet/core/deploying/runtime-store) +from OpenTelemetry .NET Automatic Instrumentation installation location +to resolve assembly conflicts. #### Build time resolution -Currently, the path to resolving such conflicts is to add or update any package reference used by -the application to the versions required by the OpenTelemetry .NET SDK and the instrumentations. -Even if the application itself doesn't directly reference a conflicting dependency, this might still -be necessary due to conflicts created by any indirect dependency. +Currently, the path to resolving such conflicts is to add or update any package +reference used by the application to the versions required by +the OpenTelemetry .NET SDK and the instrumentations. +Even if the application itself doesn't directly reference a conflicting +dependency, this might still be necessary due to conflicts created by +any indirect dependency. -Adding or updating package references works because of the way +Adding or updating package references works because of the way [NuGet Package Dependency Resolution](https://docs.microsoft.com/en-us/nuget/concepts/dependency-resolution) -is implemented. Conflicts are resolved by having explicit package references to the correct package versions. +is implemented. Conflicts are resolved by having explicit package references +to the correct package versions. -To simplify this process, we plan to create a NuGet package that installs the CLR Profiler and its managed dependencies. +To simplify this process, we plan to create a NuGet package that installs +the CLR Profiler and its managed dependencies. #### Runtime time resolution -If you can't change the application build to add or update the necessary package versions, -you can still address conflicts using the methods described in +If you can't change the application build to add or update the necessary package +versions, you can still address conflicts using the methods described in [Handling of Assembly version Conflicts](./troubleshooting.md#handling-of-assembly-version-conflicts). ## Further reading diff --git a/docs/developing.md b/docs/developing.md index 0c6b08b2d9..90fa09a140 100644 --- a/docs/developing.md +++ b/docs/developing.md @@ -36,7 +36,7 @@ follow these steps to set `omnisharp.useGlobalMono` to `never`: 2. Change `Omnisharp: Use Global Mono` to `never`. 3. Restart OmniSharp by pressing `F1` and selecting `OmniSharp: Restart OmniSharp`. -If you get errors due to projects targeting .NET Framework, use +If you get errors due to projects targeting .NET Framework, use `OmniSharp: Select Project` in Visual Studio Code to load a subset of projects which work without any issues. You can also try building the projects which throw errors. @@ -47,12 +47,13 @@ This repository uses [Nuke](https://nuke.build/) for build automation. Support plugins are available for: -- JetBrains ReSharper https://nuke.build/resharper -- JetBrains Rider https://nuke.build/rider -- Microsoft VisualStudio https://nuke.build/visualstudio -- Microsoft VSCode https://nuke.build/vscode +- JetBrains ReSharper +- JetBrains Rider +- Microsoft VisualStudio +- Microsoft VSCode -Restore dotnet tools to prepare build tools for solution. This installs the dotnet `nuke` tool locally. +Restore dotnet tools to prepare build tools for solution. +This installs the dotnet `nuke` tool locally. ```cmd dotnet tool restore @@ -78,6 +79,23 @@ Clean your repository by running: git clean -fXd ``` +### Documentation lint + +If you made changes to the Markdown documents (`*.md` files), ensure that lint +tool passed without any issues by executing: + +```cmd +nuke InstallMarkdownLint MarkdownLint +``` + +Some issues can be automatically fixed by: + +```cmd +nuke MarkdownLintFix +``` + +All MarkdownLint tasks require [Node.js](https://nodejs.org/) installed locally. + ## Manual testing ### Test environment @@ -110,8 +128,8 @@ For example: ./dev/instrument.sh OTEL_DOTNET_AUTO_ENABLED_INSTRUMENTATIONS=HttpClient dotnet run -f netcoreapp3.1 --project ./examples/ConsoleApp/Examples.ConsoleApp.csproj ``` -You can use [`dev/envvars.sh`](../dev/envvars.sh) to export profiler environmental variables to your -current shell session. +You can use [`dev/envvars.sh`](../dev/envvars.sh) to export profiler +environmental variables to your current shell session. You must run `dev/envvars.sh` from the root of this repository. For example: @@ -124,7 +142,8 @@ export OTEL_DOTNET_AUTO_ENABLED_INSTRUMENTATIONS=HttpClient ### Running the examples You can use the example applications to see the local changes in action. See -[`examples/README.md`](../examples/README.md) for instructions on how to run the examples. +[`examples/README.md`](../examples/README.md) for instructions on +how to run the examples. ## Release process diff --git a/docs/manual-instrumentation.md b/docs/manual-instrumentation.md index 8cf52e4383..d6d76a5b9f 100644 --- a/docs/manual-instrumentation.md +++ b/docs/manual-instrumentation.md @@ -2,7 +2,8 @@ The automatic instrumentation provides a base you can build on by adding your own manual instrumentation. By using both automatic and manual instrumentation, you can -better instrument the logic and functionality of your applications, clients, and frameworks. +better instrument the logic and functionality of your applications, clients, +and frameworks. To create your custom traces manually, follow these steps: diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index d1776aaeb5..7f050e9a60 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -3,20 +3,20 @@ ## Handling of assembly version conflicts OpenTelemetry SDK NuGet packages are deployed with the OpenTelemetry .NET Instrumentation. -To handle conflicts in assemblies referenced by "source instrumentations", update the project -references to ensure that they are on the same versions as the ones used by the instrumentation. +To handle conflicts in assemblies referenced by "source instrumentations", +update the project references to ensure that they are on the same versions +as the ones used by the instrumentation. -Previous workarounds only work at build time. When a rebuild is not possible, use one of the -following suggestions to force the application to use the assembly versions shipped with the -instrumentation. +Previous workarounds only work at build time. When a rebuild is not possible, +use one of the following suggestions to force the application to use +the assembly versions shipped with the instrumentation. -For .NET Framework applications, the workaround is to use binding redirects. For .NET Core -[Framework-dependent deployment](https://docs.microsoft.com/en-us/dotnet/core/deploying/deploy-with-vs?tabs=vs156#framework-dependent-deployment) -applications, -[Additional-deps](https://github.com/dotnet/runtime/blob/main/docs/design/features/additional-deps.md), +For .NET Framework applications, the workaround is to use binding redirects. +For .NET Core [Framework-dependent deployment](https://docs.microsoft.com/en-us/dotnet/core/deploying/deploy-with-vs?tabs=vs156#framework-dependent-deployment) +applications, [Additional-deps](https://github.com/dotnet/runtime/blob/main/docs/design/features/additional-deps.md), and [runtime package store](https://docs.microsoft.com/en-us/dotnet/core/deploying/runtime-store) -from OpenTelemetry .NET, use the automatic instrumentation installation path. For other .NET Core -deployment models, edit the `deps.json` file. +from OpenTelemetry .NET, use the automatic instrumentation installation path. +For other .NET Core deployment models, edit the `deps.json` file. ### .NET Framework binding redirects @@ -28,15 +28,16 @@ that is not available at build time. ### .NET Core dependency file -To fix assembly version conflicts in .NET Core, edit the default `.deps.json` file -generated at build for .NET Core applications. Build a .NET Core app with package -references using the required version, and use the respective `deps.json` file to see what changes -are needed. +To fix assembly version conflicts in .NET Core, edit the default +`.deps.json` file generated at build for .NET Core applications. +Build a .NET Core app with package references using the required version, +and use the respective `deps.json` file to see what changes are needed. -To test your edits to the `deps.json` file, add a reference to the required version of the OpenTelemetry -package to the [examples/CoreAppOldReference](./../examples/CoreAppOldReference/) example and rebuild the -application. Save the generated `deps.json` file, remove the package reference, and rebuild the -example app. Compare the files to explore the changes. +To test your edits to the `deps.json` file, add a reference to the required +version of the OpenTelemetry package to the [examples/CoreAppOldReference](./../examples/CoreAppOldReference/) +example and rebuild the application. Save the generated `deps.json` file, +remove the package reference, and rebuild the example app. +Compare the files to explore the changes. ## No proper relationship between spans @@ -44,11 +45,14 @@ On .NET Framework, strong name signing can force the loading of multiple version of the same assembly on the same process. This causes a separate hierarchy of Activity objects. If you are referencing packages in your application that use a version of the `System.Diagnostics.DiagnosticSource` different than the `OpenTelemetry.Api` -version used by the OpenTelemetry .NET Automatic Instrumentation, reference the correct version of the `System.Diagnostics.DiagnosticSource` package in your application. +version used by the OpenTelemetry .NET Automatic Instrumentation, reference +the correct version of the `System.Diagnostics.DiagnosticSource` package +in your application. This causes automatic binding redirection to solve the issue. If automatic binding redirection is [disabled](https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/how-to-enable-and-disable-automatic-binding-redirection) -you can also manually add binding redirection to the [`App.config`](../examples/BindingRedirect/App.config) file. +you can also manually add binding redirection to the [`App.config`](../examples/BindingRedirect/App.config) +file. ## High CPU usage diff --git a/examples/README.md b/examples/README.md index 37c169f166..c501c4bade 100644 --- a/examples/README.md +++ b/examples/README.md @@ -9,10 +9,14 @@ The example script instruments two .NET processes. These processes are identifie as [OpenTelemetry services](https://github.com/open-telemetry/opentelemetry-specification/blob/d6bcc0cb072d8d6f6ced856f1f23c451648a3caa/specification/resource/semantic_conventions/README.md#service) with the following names: - 1. **`aspnet-server`**: ASP.NET Core application that makes requests to MongoDB and Redis databases. - 2. **`{exampleApp}`**: .NET application that makes a few HTTP requests to the `aspnet-server` and some public websites. The exact name is equal to `exampleApp` value. - -The script creates Docker containers for MongoDB, Redis, Jaeger, and the [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/). + 1. **`aspnet-server`**: ASP.NET Core application that makes requests to MongoDB + and Redis databases. + 2. **`{exampleApp}`**: .NET application that makes a few HTTP requests + to the `aspnet-server` and some public websites. The exact name is equal + to `exampleApp` value. + +The script creates Docker containers for MongoDB, Redis, Jaeger, +and the [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/). You can see the traces generated by the example in the Jaeger container. The number and organization of traces generated depends on the `http-client` used in the specific run. The script waits for your input before stopping the containers. @@ -48,9 +52,11 @@ exampleAppTargetFramework="net6.0" ./run-example.sh ### AspNetCoreMvc -An ASP.NET Core MVC application used to simulate a server application capable of making calls -to MongoDB and Redis. In addition to these calls, it also supports various other endpoints. Check -the [Controllers](./AspNetCoreMvc/Controllers/) for some of the endpoints you can use. +An ASP.NET Core MVC application used to simulate a server application capable +of making calls to MongoDB and Redis. In addition to these calls, +it also supports various other endpoints. +Check the [Controllers](./AspNetCoreMvc/Controllers/) for some +of the endpoints you can use. Usage example: @@ -60,14 +66,17 @@ aspNetAppTargetFramework="net6.0" ./run-example.sh ### BindingRedirect -Example client app that uses .NET Framework binding redirects to handle assembly version conflict -between automatic instrumentation and third-party libraries that cannot be updated to the same -version required by OpenTelemetry. See the `OldReference` project for more information. +Example client app that uses .NET Framework binding redirects to handle assembly +version conflict between automatic instrumentation and third-party libraries +that cannot be updated to the same version required by OpenTelemetry. +See the `OldReference` project for more information. The project representing the third-party library has a legacy Activity named `InstrumentedHttpCall.GetAsync` -set [`OTEL_DOTNET_AUTO_LEGACY_SOURCES`](../docs/config.md#customization) to capture it. +set [`OTEL_DOTNET_AUTO_LEGACY_SOURCES`](../docs/config.md#customization) +to capture it. -The following usage example is for Windows, as binding redirection only applies to .NET Framework: +The following usage example is for Windows, as binding redirection only applies +to .NET Framework: ```bash OTEL_DOTNET_AUTO_LEGACY_SOURCES="InstrumentedHttpCall.GetAsync" exampleApp=BindingRedirect exampleAppTargetFramework=net472 ./run-example.sh @@ -87,14 +96,16 @@ exampleAppTargetFramework="net6.0" ./run-example.sh A client app that bootstraps the OpenTelemetry SDK. It uses an [ActivitySource](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry/README.md#activity-source) -to implement manual instrumentation. The bootstrap code takes care of adding the ActivitySource name -for the automatic instrumentation and the manual instrumentation. +to implement manual instrumentation. The bootstrap code takes care of adding +the ActivitySource name for the automatic instrumentation and the manual instrumentation. The bootstrap code enables the [Zipkin exporter](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry.Exporter.Zipkin/README.md) -provided by the SDK. The OpenTelemetry collector container is also configured to accept Zipkin spans. +provided by the SDK. The OpenTelemetry collector container is also configured +to accept Zipkin spans. -Use the environment variable `exampleAppInjectSDK` in the script to control the value of -[`OTEL_DOTNET_AUTO_LOAD_AT_STARTUP`](../docs/config.md#customization). For example: +Use the environment variable `exampleAppInjectSDK` in the script to control +the value of [`OTEL_DOTNET_AUTO_LOAD_AT_STARTUP`](../docs/config.md#customization). +For example: ```bash exampleAppInjectSDK=false exampleApp=ConsoleApp.SelfBootstrap ./run-example.sh @@ -102,11 +113,14 @@ exampleAppInjectSDK=false exampleApp=ConsoleApp.SelfBootstrap ./run-example.sh ### CoreAppOldReference -Example client application that uses NuGet package version resolution at build time to handle assembly version conflict -between automatic instrumentation and third-party libraries that can't be updated to the same version required by OpenTelemetry. See the `OldReference` project for more information. +Example client application that uses NuGet package version resolution at build +time to handle assembly version conflict between automatic instrumentation +and third-party libraries that can't be updated to the same version required +by OpenTelemetry. See the `OldReference` project for more information. The project representing the third-party library has a legacy Activity named `InstrumentedHttpCall.GetAsync` -set [`OTEL_DOTNET_AUTO_LEGACY_SOURCES`](../docs/config.md#customization) to capture it. +set [`OTEL_DOTNET_AUTO_LEGACY_SOURCES`](../docs/config.md#customization) +to capture it. Usage example: @@ -126,8 +140,8 @@ OTEL_DOTNET_AUTO_ADDITIONAL_SOURCES="Examples.ManualInstrumentations.*" exampleA ### OldReference -Represents a third-party project that can't be updated to use the same version of the assemblies -required by OpenTelemetry .NET SDK used by the automatic instrumentation. +Represents a third-party project that can't be updated to use the same version +of the assemblies required by OpenTelemetry .NET SDK used by the automatic instrumentation. ### OpenTracing.Library diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..4686b37fdd --- /dev/null +++ b/package-lock.json @@ -0,0 +1,487 @@ +{ + "name": "opentelemetry-dotnet-instrumentation", + "version": "0.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "opentelemetry-dotnet-instrumentation", + "version": "0.0.1", + "license": "Apache-2.0", + "dependencies": { + "markdownlint-cli": "^0.31.1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/commander": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.0.0.tgz", + "integrity": "sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==" + }, + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdownlint": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.25.1.tgz", + "integrity": "sha512-AG7UkLzNa1fxiOv5B+owPsPhtM4D6DoODhsJgiaNg1xowXovrYgOnLqAgOOFQpWOlHFVQUzjMY5ypNNTeov92g==", + "dependencies": { + "markdown-it": "12.3.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/markdownlint-cli": { + "version": "0.31.1", + "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.31.1.tgz", + "integrity": "sha512-keIOMwQn+Ch7MoBwA+TdkyVMuxAeZFEGmIIlvwgV0Z1TGS5MxPnRr29XCLhkNzCHU+uNKGjU+VEjLX+Z9kli6g==", + "dependencies": { + "commander": "~9.0.0", + "get-stdin": "~9.0.0", + "glob": "~7.2.0", + "ignore": "~5.2.0", + "js-yaml": "^4.1.0", + "jsonc-parser": "~3.0.0", + "markdownlint": "~0.25.1", + "markdownlint-rule-helpers": "~0.16.0", + "minimatch": "~3.0.5", + "run-con": "~1.2.10" + }, + "bin": { + "markdownlint": "markdownlint.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/markdownlint-rule-helpers": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.16.0.tgz", + "integrity": "sha512-oEacRUVeTJ5D5hW1UYd2qExYI0oELdYK72k1TKGvIeYJIbqQWAz476NAc7LNixSySUhcNl++d02DvX0ccDk9/w==" + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + }, + "node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/run-con": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/run-con/-/run-con-1.2.10.tgz", + "integrity": "sha512-n7PZpYmMM26ZO21dd8y3Yw1TRtGABjRtgPSgFS/nhzfvbJMXFtJhJVyEgayMiP+w/23craJjsnfDvx4W4ue/HQ==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~2.0.0", + "minimist": "^1.2.5", + "strip-json-comments": "~3.1.1" + }, + "bin": { + "run-con": "cli.js" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + } + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "commander": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.0.0.tgz", + "integrity": "sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==" + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==" + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + }, + "jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==" + }, + "linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "requires": { + "uc.micro": "^1.0.1" + } + }, + "markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "requires": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "markdownlint": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.25.1.tgz", + "integrity": "sha512-AG7UkLzNa1fxiOv5B+owPsPhtM4D6DoODhsJgiaNg1xowXovrYgOnLqAgOOFQpWOlHFVQUzjMY5ypNNTeov92g==", + "requires": { + "markdown-it": "12.3.2" + } + }, + "markdownlint-cli": { + "version": "0.31.1", + "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.31.1.tgz", + "integrity": "sha512-keIOMwQn+Ch7MoBwA+TdkyVMuxAeZFEGmIIlvwgV0Z1TGS5MxPnRr29XCLhkNzCHU+uNKGjU+VEjLX+Z9kli6g==", + "requires": { + "commander": "~9.0.0", + "get-stdin": "~9.0.0", + "glob": "~7.2.0", + "ignore": "~5.2.0", + "js-yaml": "^4.1.0", + "jsonc-parser": "~3.0.0", + "markdownlint": "~0.25.1", + "markdownlint-rule-helpers": "~0.16.0", + "minimatch": "~3.0.5", + "run-con": "~1.2.10" + } + }, + "markdownlint-rule-helpers": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.16.0.tgz", + "integrity": "sha512-oEacRUVeTJ5D5hW1UYd2qExYI0oELdYK72k1TKGvIeYJIbqQWAz476NAc7LNixSySUhcNl++d02DvX0ccDk9/w==" + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + }, + "minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "run-con": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/run-con/-/run-con-1.2.10.tgz", + "integrity": "sha512-n7PZpYmMM26ZO21dd8y3Yw1TRtGABjRtgPSgFS/nhzfvbJMXFtJhJVyEgayMiP+w/23craJjsnfDvx4W4ue/HQ==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~2.0.0", + "minimist": "^1.2.5", + "strip-json-comments": "~3.1.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000000..12a5cc4e8f --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "opentelemetry-dotnet-instrumentation", + "version": "0.0.1", + "description": "Application to configure and execute markdownlint", + "scripts": { + "markdownlint": "npx markdownlint . -i node_modules", + "markdownlint-fix": "npx markdownlint . -i node_modules --fix" + }, + "license": "Apache-2.0", + "dependencies": { + "markdownlint-cli": "^0.31.1" + } +} diff --git a/src/OpenTelemetry.AutoInstrumentation.Native/lib/coreclr/src/README.md b/src/OpenTelemetry.AutoInstrumentation.Native/lib/coreclr/src/README.md index 3ff9777802..d85d6459ed 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Native/lib/coreclr/src/README.md +++ b/src/OpenTelemetry.AutoInstrumentation.Native/lib/coreclr/src/README.md @@ -1,15 +1,25 @@ -The files here were copied from https://github.com/dotnet/runtime/tree/v5.0.5/src/coreclr/src. +# Info + +The files here were copied from . This is to allow using the runtime's Platform Adaptation Layer. Add back the definition of g_tkCorEncodeToken in cor.h l.2096: replace + +```cpp extern const mdToken g_tkCorEncodeToken[]; +``` + by + +```cpp const mdToken g_tkCorEncodeToken[4] = { mdtTypeDef, mdtTypeRef, mdtTypeSpec, mdtBaseType }; +``` -Commented #define statements because there is naming conflicts when compiling with the stdlibc++ 8 (+ C++17) +Commented #define statements because there is naming conflicts when compiling +with the stdlibc++ 8 (+ C++17) in `dotnet-runtime-coreclr\pal\inc\rt\sal.h` l.2612 // commented because it conflicts with stdlibc++ 8 l.2613 //#define __valid @@ -17,4 +27,4 @@ l.2613 //#define __valid and l.2622 // commented because it conflicts with stdlibc++ 8 -l.2623 //#define __pre \ No newline at end of file +l.2623 //#define __pre diff --git a/src/OpenTelemetry.AutoInstrumentation.Native/lib/coreclr/src/inc/readme.md b/src/OpenTelemetry.AutoInstrumentation.Native/lib/coreclr/src/inc/readme.md index 1e7754ea5e..d1baf38674 100644 --- a/src/OpenTelemetry.AutoInstrumentation.Native/lib/coreclr/src/inc/readme.md +++ b/src/OpenTelemetry.AutoInstrumentation.Native/lib/coreclr/src/inc/readme.md @@ -1,12 +1,18 @@ # Updating idl files -This directory has a variety of .idl files (such as corprof.idl) that need a little special handling when you make changes. Originally when we built on Windows only -the build rules would automatically convert the idls into corresponding .h/.c files and include them in compilations. On non-windows platforms we don't have an equivalent -for midl.exe which did that conversion so we work around the issue by doing: +This directory has a variety of .idl files (such as corprof.idl) that need +a little special handling when you make changes. Originally when we built +on Windows only the build rules would automatically convert the idls into +corresponding .h/.c files and include them in compilations. On non-windows +platforms we don't have an equivalent for midl.exe which did that conversion +so we work around the issue by doing: - Build on Windows as normal, which will generate files in artifacts\obj\Windows_NT.x64.Debug\src\inc\idls_out\ - Copy any updated headers into src\pal\prebuilt\inc\ -- If needed, adjust any of the .cpp files in src\pal\prebuilt\idl\ by hand, using the corresponding artifacts\obj\Windows_NT.x64.Debug\src\inc\idls_out\*_i.c as a guide. Typically -this is just adding MIDL_DEFINE_GUID(...) for any new classes/interfaces that have been added to the idl file. +- If needed, adjust any of the .cpp files in src\pal\prebuilt\idl\ by hand, + using the corresponding + artifacts\obj\Windows_NT.x64.Debug\src\inc\idls_out\*_i.c as a guide. + Typically this is just adding MIDL_DEFINE_GUID(...) + for any new classes/interfaces that have been added to the idl file. -Include these src changes with the remainder of your work when you submit a PR. \ No newline at end of file +Include these src changes with the remainder of your work when you submit a PR. diff --git a/src/OpenTelemetry.AutoInstrumentation/DuckTyping/README.md b/src/OpenTelemetry.AutoInstrumentation/DuckTyping/README.md index 2f42a00502..c21603ea77 100644 --- a/src/OpenTelemetry.AutoInstrumentation/DuckTyping/README.md +++ b/src/OpenTelemetry.AutoInstrumentation/DuckTyping/README.md @@ -1,48 +1,55 @@ # OpenTelemetry.AutoInstrumentation.DuckTyping -The duck typing library allows us to get and set data from fields and properties and call methods from an object without having the type definition at compile time. This is done by creating a proxy type to an object instance using a proxy definition at runtime. +The duck typing library allows us to get and set data from fields and properties +and call methods from an object without having the type definition at compile +time. This is done by creating a proxy type to an object instance using a proxy +definition at runtime. -The goal of the library is to have an unify code to access unknown types as fastest and with the minimum allocations as possible. +The goal of the library is to have an unify code to access unknown types +as fastest and with the minimum allocations as possible. -### Example -Given the following scenario, where we want to access the data from an anonymous class instance in another method, a code example to do that would be: +## Example + +Given the following scenario, where we want to access the data from an anonymous +class instance in another method, a code example to do that would be: ```csharp public class Program { - public static void Main() - { - // We create an anonymous object - var anonymousObject = new { Name = ".NET Core", Version = "3.1" }; - - Process(anonymousObject); - } - - public static void Process(object obj) - { + public static void Main() + { + // We create an anonymous object + var anonymousObject = new { Name = ".NET Core", Version = "3.1" }; + + Process(anonymousObject); + } + + public static void Process(object obj) + { // First, we create a proxy instance using IDuckAnonymous type // as a proxy definition and the obj instance as the target. - // Now the proxyInstance implements IDuckAnonymous type and all + // Now the proxyInstance implements IDuckAnonymous type and all // getters to access the anonymous object internals were generated // automatically for us. // We use the `As` extension method to call the duck typing proxy creator. - var proxyInstance = obj.As(); - - // Here we can access the internal properties - Console.WriteLine($"Name: {proxyInstance.Name}"); - Console.WriteLine($"Version: {proxyInstance.Version}"); - } - - public interface IDuckAnonymous - { - string Name { get; } - string Version { get; } - } + var proxyInstance = obj.As(); + + // Here we can access the internal properties + Console.WriteLine($"Name: {proxyInstance.Name}"); + Console.WriteLine($"Version: {proxyInstance.Version}"); + } + + public interface IDuckAnonymous + { + string Name { get; } + string Version { get; } + } } ``` -For this particular case the generated proxy type by the Duck Type library will look like this: +For this particular case the generated proxy type by the Duck Type library will +look like this: ```csharp public readonly struct IDuckAnonymous___<>f__AnonymousType0`2[System.String,System.String] : IDuckAnonymous, IDuckType @@ -60,7 +67,9 @@ public readonly struct IDuckAnonymous___<>f__AnonymousType0`2[System.String,Syst ``` ## Proxy types -Depending on the proxy definition type, the library will create different proxy types as shown in the following table: + +Depending on the proxy definition type, the library will create different proxy +types as shown in the following table: | Proxy Definition Type | Resulting Proxy Type | |----------------------------|--------------------------------------------------| @@ -68,7 +77,8 @@ Depending on the proxy definition type, the library will create different proxy | Abstract class | Class inherits and overriding the abstract class | | Class with virtual members | Class inherits and overriding the virtual class | -Also, all resulting proxy types implements the `IDuckType` interface to expose the target instance and type. The interface has the following definition: +Also, all resulting proxy types implements the `IDuckType` interface to expose +the target instance and type. The interface has the following definition: ```csharp public interface IDuckType @@ -87,7 +97,8 @@ public interface IDuckType ## Controlling bindings -To control the bindings between the proxy definition and the target type, we can make use of the `DuckAttribute` attribute type defined as: +To control the bindings between the proxy definition and the target type, we can +make use of the `DuckAttribute` attribute type defined as: ```csharp /// @@ -148,9 +159,10 @@ public enum DuckKind } ``` -This attribute can be used in `Properties` or `Methods` in the proxy definition and is used by the library to select the members we want to access. +This attribute can be used in `Properties` or `Methods` in the proxy definition +and is used by the library to select the members we want to access. -### Example +### Example with control bindings The following example shows multiple uses of the `DuckAttribute`: @@ -222,10 +234,12 @@ public interface IMyProxy } ``` - ## Accessor modifiers (AM) -In order to support all accessor modifiers for: instance types, parameters and return value types, the Duck Type library applies some `tricks` to avoid the visibility checks. This is done automatically when the library is creating the proxy type. In summary the following logic is applied depending on each case: +In order to support all accessor modifiers for: instance types, parameters +and return value types, the Duck Type library applies some `tricks` to avoid +the visibility checks. This is done automatically when the library is creating +the proxy type. In summary the following logic is applied depending on each case: | Target Type AM | Target Member Type | Target Member AM | Access Method | |------------------------------|--------------------|------------------------------|-----------------------------------------------| @@ -244,10 +258,14 @@ In order to support all accessor modifiers for: instance types, parameters and r ## Generics methods -Calling generics methods are supported by the library, but due the use of `DynamicMethod`in some scenarios we can´t define it as a normal generic method (Please note if we know that the target type is Public, then we can declare a normal generic method). - -For those scenarios were we can´t use the generic definition, the alternative is to specify the generic parameters to be match in the duck attribute of the proxy definition. +Calling generics methods are supported by the library, but due +the use of `DynamicMethod`in some scenarios we can´t define it as a normal +generic method (Please note if we know that the target type is Public, +then we can declare a normal generic method). +For those scenarios were we can´t use the generic definition, the alternative +is to specify the generic parameters to be match in the duck attribute +of the proxy definition. ### Example with public type @@ -286,7 +304,8 @@ private class PrivateType } ``` -Because the type is non public we have to define each generic arguments we want to use in different calls. +Because the type is non public we have to define each generic arguments we want +to use in different calls. ```csharp public interface IMyProxy @@ -303,9 +322,11 @@ public interface IMyProxy ## Duck chaining -Duck chaining enables the possibility to interact with properties or methods returning or using non public type parameters to be wrapped with a new duck type proxy, so we can access the internals of those objects. +Duck chaining enables the possibility to interact with properties or methods +returning or using non public type parameters to be wrapped with a new duck type +proxy, so we can access the internals of those objects. -### Example +### Example with chanining Consider the following types: @@ -338,17 +359,22 @@ public interface IProxyMyHandlerConfiguration } ``` -In this example the non public instance of `MyHandlerConfiguration` when calling the `Configuration` property is going to be wrapped with a `IProxyMyHandlerConfiguration` instance automatically. That allow us to access the internal data of that non public type. +In this example the non public instance of `MyHandlerConfiguration` when calling +the `Configuration` property is going to be wrapped with +a `IProxyMyHandlerConfiguration` instance automatically. That allow us to access +the internal data of that non public type. ## Benchmarks -Several benchmark tests were run for multiple cases to keep track of the time execution and heap allocations of the library, these are the results: +Several benchmark tests were run for multiple cases to keep track of the time +execution and heap allocations of the library, these are the results: ### Fields Getter and Setter The `proxy` column indicates the target type access modifier. -Tests with `blank` proxy are the direct access of the value through an interface without creating any ducktype proxy. +Tests with `blank` proxy are the direct access of the value through an interface +without creating any ducktype proxy. ``` ini BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.508 (2004/?/20H1) @@ -358,6 +384,7 @@ Intel Core i7-1068NG7 CPU 2.30GHz, 1 CPU, 2 logical and 2 physical cores Job-LJAVIR : .NET Framework 4.8 (4.8.4220.0), X64 RyuJIT Job-OHOUFK : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT ``` + | Method | Runtime | Categories | proxy | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | |------------------------ |-------------- |-------------- |--------- |---------:|----------:|----------:|------:|--------:|------:|------:|------:|----------:| | GetPublicStaticField | .NET 4.7.2 | Static Getter | Internal | 3.207 ns | 0.0623 ns | 0.0553 ns | 1.00 | 0.00 | - | - | - | - | @@ -508,7 +535,8 @@ Intel Core i7-1068NG7 CPU 2.30GHz, 1 CPU, 2 logical and 2 physical cores The `proxy` column indicates the target type access modifier. -Tests with `blank` proxy are the direct access of the value through an interface without creating any ducktype proxy. +Tests with `blank` proxy are the direct access of the value through an interface +without creating any ducktype proxy. ``` ini BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.508 (2004/?/20H1) @@ -518,6 +546,7 @@ Intel Core i7-1068NG7 CPU 2.30GHz, 1 CPU, 2 logical and 2 physical cores Job-QIOTKF : .NET Framework 4.8 (4.8.4220.0), X64 RyuJIT Job-FEKUVA : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT ``` + | Method | Runtime | Categories | proxy | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | |--------------------------- |-------------- |--------------- |--------- |---------:|----------:|----------:|------:|--------:|------:|------:|------:|----------:| | GetPublicProperty | .NET 4.7.2 | Getter | | 1.046 ns | 0.0457 ns | 0.0449 ns | 1.00 | 0.00 | - | - | - | - | @@ -698,7 +727,8 @@ Intel Core i7-1068NG7 CPU 2.30GHz, 1 CPU, 2 logical and 2 physical cores The `proxy` column indicates the target type access modifier. -Tests with `blank` proxy are the direct access of the value through an interface without creating any ducktype proxy. +Tests with `blank` proxy are the direct access of the value through an interface +without creating any ducktype proxy. ``` ini BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.508 (2004/?/20H1) @@ -708,6 +738,7 @@ Intel Core i7-1068NG7 CPU 2.30GHz, 1 CPU, 2 logical and 2 physical cores Job-CGLGGF : .NET Framework 4.8 (4.8.4220.0), X64 RyuJIT Job-GEDFFR : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT ``` + | Method | Runtime | Categories | proxy | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | |-------------------------- |-------------- |----------------- |--------- |----------:|----------:|----------:|------:|--------:|------:|------:|------:|----------:| | PublicVoidMethod | .NET 4.7.2 | Void Method | | 1.3457 ns | 0.0441 ns | 0.0391 ns | 1.00 | 0.00 | - | - | - | - | @@ -772,4 +803,3 @@ Intel Core i7-1068NG7 CPU 2.30GHz, 1 CPU, 2 logical and 2 physical cores | | | | | | | | | | | | | | | PrivateOutParameterMethod | .NET 4.7.2 | Out-Param Method | Public | 3.7001 ns | 0.0380 ns | 0.0318 ns | 1.00 | 0.00 | - | - | - | - | | PrivateOutParameterMethod | .NET Core 3.1 | Out-Param Method | Public | 3.9932 ns | 0.0553 ns | 0.0490 ns | 1.08 | 0.01 | - | - | - | - | -