Compare commits

..

No commits in common. "main" and "core-1.8.0-beta.1" have entirely different histories.

982 changed files with 37154 additions and 25878 deletions

View File

@ -1,4 +0,0 @@
# see https://github.com/cncf/clomonitor/blob/main/docs/checks.md#exemptions
exemptions:
- check: artifacthub_badge
reason: "Artifact Hub doesn't support .NET packages"

View File

@ -10,9 +10,6 @@ indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.sh]
end_of_line = lf
[*.{cs,cshtml,htm,html,md,py,sln,xml}]
indent_size = 4
@ -44,7 +41,7 @@ csharp_indent_labels = flush_left
# Modifier preferences
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async:suggestion
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
# this. preferences
dotnet_style_qualification_for_field = true:suggestion
@ -56,8 +53,8 @@ dotnet_style_qualification_for_event = true:suggestion
csharp_style_var_for_built_in_types = true:silent
csharp_style_var_when_type_is_apparent = true:silent
csharp_style_var_elsewhere = true:silent
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
dotnet_style_predefined_type_for_member_access = true:silent
# name all constant fields using PascalCase
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
@ -78,7 +75,6 @@ dotnet_style_readonly_field = true:suggestion
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
dotnet_style_prefer_simplified_interpolation = true:suggestion
dotnet_style_object_initializer = true:suggestion
csharp_style_prefer_primary_constructors = false:none
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
@ -86,23 +82,21 @@ dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_auto_properties = true:suggestion
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_unused_value_expression_statement_preference = discard_variable:none
# Expression-bodied members
csharp_style_expression_bodied_methods = true:suggestion
dotnet_diagnostic.IDE0022.severity = suggestion # dotnet format doesn't respect the suggestion in the line above
csharp_style_expression_bodied_constructors = false:warning
csharp_style_expression_bodied_operators = true:suggestion
csharp_style_expression_bodied_properties = true:suggestion
csharp_style_expression_bodied_indexers = true:suggestion
csharp_style_expression_bodied_accessors = true:suggestion
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_accessors = true:silent
# Pattern matching
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
@ -119,7 +113,6 @@ csharp_style_prefer_range_operator = false:none
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_style_namespace_declarations = file_scoped:warning
dotnet_style_namespace_match_folder = false:none
# Space preferences
csharp_space_after_cast = false
@ -135,10 +128,10 @@ csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggestion
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggestion
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
# Code analyzers
# CA1031: Do not catch general exception types
@ -159,14 +152,7 @@ dotnet_diagnostic.IDE0005.severity = warning
# RS0041: Public members should not use oblivious types
dotnet_diagnostic.RS0041.severity = suggestion
[*Tests.cs]
# CA1515: Disable making types internal for Tests classes. It is required by xunit
dotnet_diagnostic.CA1515.severity = none
# CA2007: Disable Consider calling ConfigureAwait on the awaited task. It is not working with xunit
dotnet_diagnostic.CA2007.severity = none
[**/obj/**.cs]
[obj/**.cs]
generated_code = true
[*.csproj]

1
.gitattributes vendored
View File

@ -1 +0,0 @@
*.sh eol=lf

45
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,45 @@
---
name: Bug Report
about: Create a report to help us improve
labels: bug
---
# Bug Report
List of [all OpenTelemetry NuGet
packages](https://www.nuget.org/profiles/OpenTelemetry) and version that you are
using (e.g. `OpenTelemetry 1.0.2`):
* TBD
Runtime version (e.g. `net462`, `net48`, `netcoreapp3.1`, `net6.0` etc. You can
find this information from the `*.csproj` file):
* TBD
## Symptom
A clear and concise description of what the bug is.
**What is the expected behavior?**
What did you expect to see?
**What is the actual behavior?**
What did you see instead?
## Reproduce
Create a self-contained project using the template of your choice, apply the
minimum required code to result in the issue you're observing.
We will close this issue if:
* The repro project you share with us is complex. We can't investigate custom
projects, so don't point us to such, please.
* If we can not reproduce the behavior you're reporting.
## Additional Context
Add any other context about the problem here.

View File

@ -1,94 +0,0 @@
name: Bug report
title: "[bug] "
description: Create a report to help us improve
labels: [bug,needs-triage]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report! Please make sure to fill out the entire form below, providing as much context as you can in order to help us triage and track down the bug as quickly as possible.
Before filing a bug, please be sure you have searched through [existing bugs](https://github.com/open-telemetry/opentelemetry-dotnet/issues?q=is%3Aissue+is%3Aopen+label%3Abug) to see if an existing issue covers the bug.
- type: dropdown
id: package
attributes:
label: Package
description: Which NuGet package does this bug report concern?
multiple: false
options:
- OpenTelemetry
- OpenTelemetry.Api
- OpenTelemetry.Api.ProviderBuilderExtensions
- OpenTelemetry.Exporter.Console
- OpenTelemetry.Exporter.InMemory
- OpenTelemetry.Exporter.OpenTelemetryProtocol
- OpenTelemetry.Exporter.Prometheus.AspNetCore
- OpenTelemetry.Exporter.Prometheus.HttpListener
- OpenTelemetry.Exporter.Zipkin
- OpenTelemetry.Extensions.Hosting
- OpenTelemetry.Extensions.Propagators
- OpenTelemetry.Shims.OpenTracing
validations:
required: true
- type: textarea
attributes:
label: Package Version
description: List of [all OpenTelemetry NuGet packages](https://www.nuget.org/profiles/OpenTelemetry) and version that you are using (e.g. `OpenTelemetry 1.0.2`)
value: |
| Package Name | Version |
| ------------------------------------- | ------- |
| OpenTelemetry.Api | 1.8.0 |
| OpenTelemetry | 1.8.0 |
| TBD | TBD |
validations:
required: true
- type: input
attributes:
label: Runtime Version
description: What .NET runtime version did you use? (e.g. `net462`, `net48`, `net8.0`, etc. You can find this information from the `*.csproj` file)
validations:
required: true
- type: textarea
attributes:
label: Description
description: What happened? Please provide as much detail as you reasonably can.
validations:
required: true
- type: textarea
attributes:
label: Steps to Reproduce
description: Provide a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). We will close the issue if the repro project you share with us is complex or we cannot reproduce the behavior you are reporting. We cannot investigate custom projects, so don't point us to such, please.
validations:
required: true
- type: textarea
attributes:
label: Expected Result
description: What did you expect to see?
validations:
required: true
- type: textarea
attributes:
label: Actual Result
description: What did you see instead?
validations:
required: true
- type: textarea
attributes:
label: Additional Context
description: Any additional information you think may be relevant to this issue.
- type: dropdown
attributes:
label: Tip
description: This element is static, used to render a helpful sub-heading for end-users and community members to help prioritize issues. Please leave as is.
options:
- "<sub>[React](https://github.blog/news-insights/product-news/add-reactions-to-pull-requests-issues-and-comments/) with :+1: to help prioritize this issue. Please use comments to provide useful context, avoiding `+1` or `me too`, to help us triage it. Learn more [here](https://opentelemetry.io/community/end-user/issue-participation/).</sub>"
default: 0

View File

@ -1,7 +0,0 @@
# https://docs.github.com/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
blank_issues_enabled: false
contact_links:
- name: Question
url: https://github.com/open-telemetry/opentelemetry-dotnet/discussions/new?category=q-a
about: Ask a question to help us improve our knowledge base and documentation.

View File

@ -0,0 +1,29 @@
---
name: Feature Request
about: Suggest an idea for this project
labels: enhancement
---
# Feature Request
Before opening a feature request against this repo, consider whether the feature
should/could be implemented in the [other OpenTelemetry client
libraries](https://github.com/open-telemetry/). If so, please [open an issue on
opentelemetry-specification](https://github.com/open-telemetry/opentelemetry-specification/issues/new)
first.
**Is your feature request related to a problem?**
If so, provide a concise description of the problem.
**Describe the solution you'd like:**
What do you want to happen instead? What is the expected behavior?
**Describe alternatives you've considered.**
Which alternative solutions or features have you considered?
## Additional Context
Add any other context about the feature request here.

View File

@ -1,63 +0,0 @@
name: Feature request
title: "[feature request] "
description: Suggest an idea for this project
labels: [enhancement,needs-triage]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this feature request! Please make sure to fill out the entire form below, providing as much context as you can in order to help us triage and track down your request as quickly as possible.
Before opening a feature request, consider whether the feature should/could be implemented in the [other OpenTelemetry client libraries](https://github.com/open-telemetry/). If so, please [open an issue on opentelemetry-specification](https://github.com/open-telemetry/opentelemetry-specification/issues/new) first.
- type: dropdown
id: package
attributes:
label: Package
description: Which NuGet package does this feature request concern?
multiple: false
options:
- OpenTelemetry
- OpenTelemetry.Api
- OpenTelemetry.Api.ProviderBuilderExtensions
- OpenTelemetry.Exporter.Console
- OpenTelemetry.Exporter.InMemory
- OpenTelemetry.Exporter.OpenTelemetryProtocol
- OpenTelemetry.Exporter.Prometheus.AspNetCore
- OpenTelemetry.Exporter.Prometheus.HttpListener
- OpenTelemetry.Exporter.Zipkin
- OpenTelemetry.Extensions.Hosting
- OpenTelemetry.Extensions.Propagators
- OpenTelemetry.Shims.OpenTracing
- type: textarea
attributes:
label: Is your feature request related to a problem?
description: If so, provide a concise description of the problem.
- type: textarea
attributes:
label: What is the expected behavior?
description: Describe the solution you would like.
validations:
required: true
- type: textarea
attributes:
label: Which alternative solutions or features have you considered?
description: Describe alternatives you've considered.
validations:
required: true
- type: textarea
attributes:
label: Additional context
description: Any additional information you think may be relevant to this feature request.
- type: dropdown
attributes:
label: Tip
description: This element is static, used to render a helpful sub-heading for end-users and community members to help prioritize issues. Please leave as is.
options:
- "<sub>[React](https://github.blog/news-insights/product-news/add-reactions-to-pull-requests-issues-and-comments/) with :+1: to help prioritize this issue. Please use comments to provide useful context, avoiding `+1` or `me too`, to help us triage it. Learn more [here](https://opentelemetry.io/community/end-user/issue-participation/).</sub>"
default: 0

9
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View File

@ -0,0 +1,9 @@
---
name: Question
about: Create a question to help us improve our knowledge base and documentation
labels: question
---
# Question
Use [Github Discussions](https://github.com/open-telemetry/opentelemetry-dotnet/discussions/new).

8
.github/codecov.yml vendored
View File

@ -33,22 +33,22 @@ ignore:
- "test"
flags:
unittests-Solution:
unittests-Solution-Stable:
carryforward: true
paths:
- src
unittests-Project-Stable:
unittests-Solution-Experimental:
carryforward: true
paths:
- src
unittests-Project-Experimental:
unittests-Instrumentation-Stable:
carryforward: true
paths:
- src
unittests-UnstableCoreLibraries-Experimental:
unittests-Instrumentation-Experimental:
carryforward: true
paths:
- src

View File

@ -6,70 +6,3 @@ updates:
interval: "daily"
labels:
- "infra"
- package-ecosystem: "docker"
directory: "/examples/MicroserviceExample/WebApi"
schedule:
interval: "weekly"
day: "wednesday"
labels:
- "infra"
ignore:
- dependency-name: "*"
update-types:
- "version-update:semver-major"
- "version-update:semver-minor"
- package-ecosystem: "docker"
directory: "examples/MicroserviceExample/WorkerService"
schedule:
interval: "weekly"
day: "wednesday"
labels:
- "infra"
ignore:
- dependency-name: "*"
update-types:
- "version-update:semver-major"
- "version-update:semver-minor"
- package-ecosystem: "docker"
directory: "test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTest"
schedule:
interval: "weekly"
day: "wednesday"
labels:
- "infra"
ignore:
- dependency-name: "*"
update-types:
- "version-update:semver-major"
- "version-update:semver-minor"
- package-ecosystem: "docker"
directory: "test/OpenTelemetry.Instrumentation.W3cTraceContext.Tests"
schedule:
interval: "weekly"
day: "wednesday"
labels:
- "infra"
ignore:
- dependency-name: "*"
update-types:
- "version-update:semver-major"
- "version-update:semver-minor"
- package-ecosystem: "dotnet-sdk"
directory: "/"
schedule:
interval: "weekly"
day: "wednesday"
labels:
- "infra"
ignore:
- dependency-name: "*"
update-types:
- "version-update:semver-major"
- "version-update:semver-minor"
- package-ecosystem: "pip"
directory: "test/OpenTelemetry.Instrumentation.W3cTraceContext.Tests"
schedule:
interval: "weekly"
day: "wednesday"
labels:
- "infra"

View File

@ -20,17 +20,14 @@ on:
required: false
type: string
os-list:
default: '[ "windows-latest", "ubuntu-22.04", "ubuntu-22.04-arm" ]'
default: '[ "windows-latest", "ubuntu-latest" ]'
required: false
type: string
tfm-list:
default: '[ "net462", "net8.0", "net9.0" ]'
default: '[ "net462", "net6.0", "net7.0", "net8.0" ]'
required: false
type: string
permissions:
contents: read
jobs:
build-test:
@ -40,30 +37,20 @@ jobs:
os: ${{ fromJSON(inputs.os-list) }}
version: ${{ fromJSON(inputs.tfm-list) }}
exclude:
- os: ubuntu-22.04
- os: ubuntu-latest
version: net462
- os: ubuntu-22.04-arm
version: net462
- os: ubuntu-22.04-arm
version: net8.0
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@v4
with:
# Note: By default GitHub only fetches 1 commit. MinVer needs to find
# the version tag which is typically NOT on the first commit so we
# retrieve them all.
fetch-depth: 0
- name: Setup previous .NET runtimes
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
with:
dotnet-version: |
8.0.x
- name: Setup .NET
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
- name: Setup dotnet
uses: actions/setup-dotnet@v4
- name: dotnet restore ${{ inputs.project-name }}
run: dotnet restore ${{ inputs.project-name }} ${{ inputs.project-build-commands }}
@ -72,44 +59,24 @@ jobs:
run: dotnet build ${{ inputs.project-name }} --configuration Release --no-restore ${{ inputs.project-build-commands }}
- name: dotnet test ${{ inputs.project-name }}
run: >
dotnet test ${{ inputs.project-name }}
--collect:"Code Coverage"
--results-directory:TestResults
--framework ${{ matrix.version }}
--configuration Release
--no-restore
--no-build
--logger:"console;verbosity=detailed"
--logger:"GitHubActions;report-warnings=false"
--logger:"junit;LogFilePath=TestResults/junit.xml"
-- RunConfiguration.DisableAppDomain=true
run: dotnet test ${{ inputs.project-name }} --collect:"Code Coverage" --results-directory:TestResults --framework ${{ matrix.version }} --configuration Release --no-restore --no-build --logger:"console;verbosity=detailed" -- RunConfiguration.DisableAppDomain=true
- name: Install coverage tool
run: dotnet tool install -g dotnet-coverage
- name: Merging test results
run: dotnet-coverage merge -f cobertura -o ./TestResults/Cobertura.xml ./TestResults/**/*.coverage
run: dotnet-coverage merge -r -f cobertura -o ./TestResults/Cobertura.xml ./TestResults/*.coverage
- name: Upload code coverage ${{ inputs.code-cov-prefix }}-${{ inputs.code-cov-name }}
uses: codecov/codecov-action@fdcc8476540edceab3de004e990f80d881c6cc00 # v5.5.0
uses: codecov/codecov-action@v4
continue-on-error: true # Note: Don't fail for upload failures
env:
OS: ${{ matrix.os }}
TFM: ${{ matrix.version }}
token: ${{ secrets.CODECOV_TOKEN }}
with:
files: TestResults/Cobertura.xml
file: TestResults/Cobertura.xml
env_vars: OS,TFM
flags: ${{ inputs.code-cov-prefix }}-${{ inputs.code-cov-name }}
name: Code Coverage for ${{ inputs.code-cov-prefix }}-${{ inputs.code-cov-name }} on [${{ matrix.os }}.${{ matrix.version }}]
codecov_yml_path: .github/codecov.yml
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload test results ${{ inputs.code-cov-prefix }}-${{ inputs.code-cov-name }}
if: ${{ !cancelled() && hashFiles('./**/TestResults/junit.xml') != '' }}
uses: codecov/test-results-action@47f89e9acb64b76debcd5ea40642d25a4adced9f # v1.1.1
with:
env_vars: OS,TFM
flags: ${{ inputs.code-cov-prefix }}-${{ inputs.code-cov-name }}
name: Test results for ${{ inputs.code-cov-prefix }}-${{ inputs.code-cov-name }} on [${{ matrix.os }}.${{ matrix.version }}]
token: ${{ secrets.CODECOV_TOKEN }}

View File

@ -1,58 +0,0 @@
name: 'Add labels to issues and pull requests'
on:
issues:
types: [ opened ]
pull_request_target:
branches: [ 'main*' ]
permissions:
contents: read
jobs:
add-labels-on-issues:
permissions:
issues: write
if: github.event_name == 'issues' && !github.event.issue.pull_request
runs-on: ubuntu-22.04
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Add labels for package found in bug issue descriptions
shell: pwsh
run: |
Import-Module .\build\scripts\add-labels.psm1
AddLabelsOnIssuesForPackageFoundInBody `
-issueNumber ${{ github.event.issue.number }} `
-issueBody $env:ISSUE_BODY
env:
GH_TOKEN: ${{ github.token }}
ISSUE_BODY: ${{ github.event.issue.body }}
add-labels-on-pull-requests:
permissions:
pull-requests: write
if: github.event_name == 'pull_request_target'
runs-on: ubuntu-22.04
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
ref: ${{ github.event.repository.default_branch }} # Note: Do not run on the PR branch we want to execute add-labels.psm1 from main on the base repo only because pull_request_target can see secrets
- name: Add labels for files changed on pull requests
shell: pwsh
run: |
Import-Module .\build\scripts\add-labels.psm1
AddLabelsOnPullRequestsBasedOnFilesChanged `
-pullRequestNumber ${{ github.event.pull_request.number }} `
-labelPackagePrefix 'pkg:'
env:
GH_TOKEN: ${{ github.token }}

View File

@ -1,37 +0,0 @@
name: Resolve automation settings
on:
workflow_call:
outputs:
enabled:
value: ${{ jobs.resolve-automation.outputs.enabled == 'true' }}
token-secret-name:
value: ${{ jobs.resolve-automation.outputs.token-secret-name }}
username:
value: ${{ vars.AUTOMATION_USERNAME }}
email:
value: ${{ vars.AUTOMATION_EMAIL }}
secrets:
OPENTELEMETRYBOT_GITHUB_TOKEN:
required: false
permissions:
contents: read
jobs:
resolve-automation:
runs-on: ubuntu-22.04
outputs:
enabled: ${{ steps.evaluate.outputs.enabled }}
token-secret-name: ${{ steps.evaluate.outputs.token-secret-name }}
env:
OPENTELEMETRYBOT_GITHUB_TOKEN_EXISTS: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN != '' }}
steps:
- id: evaluate
run: |
echo "enabled=${{ env.OPENTELEMETRYBOT_GITHUB_TOKEN_EXISTS == 'true' }}" >> "$GITHUB_OUTPUT"
echo "token-secret-name=OPENTELEMETRYBOT_GITHUB_TOKEN" >> "$GITHUB_OUTPUT"

View File

@ -9,9 +9,6 @@ on:
pull_request:
branches: [ 'main*' ]
permissions:
contents: read
jobs:
lint-misspell-sanitycheck:
uses: ./.github/workflows/sanitycheck.yml
@ -21,23 +18,22 @@ jobs:
outputs:
changes: ${{ steps.changes.outputs.changes }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: AurorNZ/paths-filter@3b1f3abc3371cca888d8eb03dfa70bc8a9867629 # v4.0.0
- uses: actions/checkout@v4
- uses: AurorNZ/paths-filter@v4
id: changes
with:
filters: |
md: ['**.md']
build: ['build/**', '.github/**/*.yml', '**/*.targets', '**/*.props', 'global.json']
build: ['build/**', '.github/**/*.yml', '**/*.targets', '**/*.props']
shared: ['src/Shared/**']
code: ['**.cs', '**.csproj', '.editorconfig']
solution: ['OpenTelemetry.sln']
packaged-code: ['src/**', '!**/*.md']
api-code: ['*/OpenTelemetry.Api*/**', '!**/*.md']
api-packages: ['src/OpenTelemetry.Api*/**', '!**/*.md']
instrumentation: ['*/OpenTelemetry.Instrumentation*/**', 'test/TestApp.AspNetCore/**', '!**/*.md']
instrumentation-packages: ['src/OpenTelemetry.Instrumentation*/**', '!**/*.md']
sdk-code: ['src/OpenTelemetry/**', 'test/OpenTelemetry.Tests/**', '!**/*.md']
sdk-package: ['src/OpenTelemetry/**', '!**/*.md']
unstable-core-packages: ['src/OpenTelemetry.Exporter.Prometheus.AspNetCore/**', 'src/OpenTelemetry.Exporter.Prometheus.HttpListener/**', 'src/OpenTelemetry.Shims.OpenTracing/**', '!**/*.md']
otlp: ['*/OpenTelemetry.Exporter.OpenTelemetryProtocol*/**', '!**/*.md']
lint-md:
@ -54,30 +50,19 @@ jobs:
|| contains(needs.detect-changes.outputs.changes, 'build')
uses: ./.github/workflows/dotnet-format.yml
build-test-solution:
build-test-solution-stable:
needs: detect-changes
if: |
contains(needs.detect-changes.outputs.changes, 'solution')
contains(needs.detect-changes.outputs.changes, 'code')
|| contains(needs.detect-changes.outputs.changes, 'build')
|| contains(needs.detect-changes.outputs.changes, 'shared')
uses: ./.github/workflows/Component.BuildTest.yml
with:
project-name: 'OpenTelemetry.sln'
code-cov-name: 'Solution'
build-test-project-stable:
needs: detect-changes
if: |
contains(needs.detect-changes.outputs.changes, 'code')
|| contains(needs.detect-changes.outputs.changes, 'build')
|| contains(needs.detect-changes.outputs.changes, 'shared')
uses: ./.github/workflows/Component.BuildTest.yml
with:
project-name: './build/OpenTelemetry.proj'
project-build-commands: '-p:ExposeExperimentalFeatures=false'
code-cov-name: 'Project-Stable'
code-cov-name: 'Solution-Stable'
build-test-project-experimental:
build-test-solution-experimental:
needs: detect-changes
if: |
contains(needs.detect-changes.outputs.changes, 'code')
@ -85,22 +70,35 @@ jobs:
|| contains(needs.detect-changes.outputs.changes, 'shared')
uses: ./.github/workflows/Component.BuildTest.yml
with:
project-name: './build/OpenTelemetry.proj'
project-name: 'OpenTelemetry.sln'
project-build-commands: '-p:ExposeExperimentalFeatures=true'
code-cov-name: 'Project-Experimental'
code-cov-name: 'Solution-Experimental'
# Build unstable core libraries using stable packages released to NuGet
build-test-unstable-core:
# Build instrumentation libraries using stable packages released to NuGet
build-test-instrumentation-stable:
needs: detect-changes
if: |
contains(needs.detect-changes.outputs.changes, 'unstable-core-packages')
contains(needs.detect-changes.outputs.changes, 'instrumentation-packages')
|| contains(needs.detect-changes.outputs.changes, 'build')
|| contains(needs.detect-changes.outputs.changes, 'shared')
uses: ./.github/workflows/Component.BuildTest.yml
with:
project-name: './build/UnstableCoreLibraries.proj'
project-name: './build/InstrumentationLibraries.proj'
project-build-commands: '-p:RunningDotNetPack=true -p:ExposeExperimentalFeatures=false'
code-cov-name: 'Instrumentation-Stable'
# Build instrumentation libraries using stable packages released to NuGet
build-test-instrumentation-experimental:
needs: detect-changes
if: |
contains(needs.detect-changes.outputs.changes, 'instrumentation-packages')
|| contains(needs.detect-changes.outputs.changes, 'build')
|| contains(needs.detect-changes.outputs.changes, 'shared')
uses: ./.github/workflows/Component.BuildTest.yml
with:
project-name: './build/InstrumentationLibraries.proj'
project-build-commands: '-p:RunningDotNetPack=true -p:ExposeExperimentalFeatures=true'
code-cov-name: 'UnstableCoreLibraries-Experimental'
code-cov-name: 'Instrumentation-Experimental'
otlp-integration-test:
needs: detect-changes
@ -110,15 +108,15 @@ jobs:
|| contains(needs.detect-changes.outputs.changes, 'otlp')
|| contains(needs.detect-changes.outputs.changes, 'build')
|| contains(needs.detect-changes.outputs.changes, 'shared')
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
version: [ net8.0, net9.0 ]
version: [ net6.0, net7.0, net8.0 ]
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Run OTLP Exporter docker compose
run: docker compose --file=test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTest/docker-compose.yml --file=build/docker-compose.${{ matrix.version }}.yml --project-directory=. up --exit-code-from=tests --build
- uses: actions/checkout@v4
- name: Run OTLP Exporter docker-compose
run: docker-compose --file=test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTest/docker-compose.yml --file=build/docker-compose.${{ matrix.version }}.yml --project-directory=. up --exit-code-from=tests --build
w3c-trace-context-integration-test:
needs: detect-changes
@ -128,15 +126,15 @@ jobs:
|| contains(needs.detect-changes.outputs.changes, 'instrumentation')
|| contains(needs.detect-changes.outputs.changes, 'build')
|| contains(needs.detect-changes.outputs.changes, 'shared')
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
version: [ net8.0, net9.0 ]
version: [ net6.0, net7.0 ]
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Run W3C Trace Context docker compose
run: docker compose --file=test/OpenTelemetry.Instrumentation.W3cTraceContext.Tests/docker-compose.yml --file=build/docker-compose.${{ matrix.version }}.yml --project-directory=. up --exit-code-from=tests --build
- uses: actions/checkout@v4
- name: Run W3C Trace Context docker-compose
run: docker-compose --file=test/OpenTelemetry.Instrumentation.W3cTraceContext.Tests/docker-compose.yml --file=build/docker-compose.${{ matrix.version }}.yml --project-directory=. up --exit-code-from=tests --build
validate-packages:
needs: detect-changes
@ -174,14 +172,14 @@ jobs:
build-test:
needs: [
detect-changes,
lint-misspell-sanitycheck,
detect-changes,
lint-md,
lint-dotnet-format,
build-test-solution,
build-test-project-stable,
build-test-project-experimental,
build-test-unstable-core,
build-test-solution-stable,
build-test-solution-experimental,
build-test-instrumentation-stable,
build-test-instrumentation-experimental,
otlp-integration-test,
w3c-trace-context-integration-test,
validate-packages,
@ -189,8 +187,7 @@ jobs:
verify-aot-compat,
concurrency-tests
]
if: always() && !cancelled()
runs-on: ubuntu-22.04
if: always() && !cancelled() && !contains(needs.*.result, 'failure')
runs-on: windows-latest
steps:
- run: |
if ( ${{ contains(needs.*.result, 'failure') }} == true ); then echo 'build failed'; exit 1; else echo 'build complete'; fi
- run: echo 'build complete'

View File

@ -1,71 +1,46 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
name: "CodeQL"
on:
push:
branches: [ 'main' ]
pull_request:
branches: [ 'main' ]
schedule:
- cron: '0 0 * * *' # once in a day at 00:00
workflow_dispatch:
permissions: {}
jobs:
analyze:
permissions:
actions: read # for github/codeql-action/init to get workflow details
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/analyze to upload SARIF results
name: Analyze
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
language: ['actions', 'csharp']
language: ['csharp']
steps:
- name: Configure Pagefile
if: matrix.language == 'csharp'
uses: al-cheb/configure-pagefile-action@a3b6ebd6b634da88790d9c58d4b37a7f4a7b8708 # v1.4
- name: configure Pagefile
uses: al-cheb/configure-pagefile-action@v1.4
with:
minimum-size: 8GB
maximum-size: 32GB
disk-root: "D:"
- name: Checkout repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
filter: 'tree:0'
persist-credentials: false
show-progress: false
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.30.0
uses: github/codeql-action/init@v3
with:
build-mode: none
languages: ${{ matrix.language }}
- name: Setup dotnet
uses: actions/setup-dotnet@v4
- name: dotnet pack OpenTelemetry.proj
run: dotnet pack OpenTelemetry.proj --configuration Release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.30.0
with:
category: '/language:${{ matrix.language }}'
codeql:
if: ${{ !cancelled() }}
needs: [ analyze ]
runs-on: ubuntu-latest
steps:
- name: Report status
shell: bash
env:
SCAN_SUCCESS: ${{ !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }}
run: |
if [ "${SCAN_SUCCESS}" == "true" ]
then
echo 'CodeQL analysis successful'
else
echo 'CodeQL analysis failed'
exit 1
fi
uses: github/codeql-action/analyze@v3

View File

@ -5,33 +5,30 @@ name: Concurrency Tests
on:
workflow_call:
permissions:
contents: read
jobs:
run-concurrency-tests:
strategy:
fail-fast: false # ensures the entire test matrix is run, even if one permutation fails
matrix:
os: [ windows-latest, ubuntu-22.04 ]
os: [ windows-latest, ubuntu-latest ]
version: [ net8.0 ]
project: [ OpenTelemetry.Tests, OpenTelemetry.Api.Tests ]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@v4
- name: Setup dotnet
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
uses: actions/setup-dotnet@v4
- name: Run Coyote Tests
shell: pwsh
run: .\build\scripts\test-threadSafety.ps1 -testProjectName ${{ matrix.project }} -targetFramework ${{ matrix.version }}
run: .\build\test-threadSafety.ps1 -testProjectName ${{ matrix.project }} -targetFramework ${{ matrix.version }}
- name: Publish Artifacts
if: always() && !cancelled()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}-${{ matrix.project }}-${{ matrix.version }}-coyoteoutput
path: '**/*_CoyoteOutput.*'

View File

@ -5,22 +5,16 @@ name: Build docfx
on:
workflow_call:
permissions:
contents: read
jobs:
run-docfx-build:
runs-on: windows-latest
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup dotnet
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
uses: actions/checkout@v4
- name: install docfx
run: dotnet tool install -g docfx
run: choco install docfx -y
- name: run .\build\docfx.cmd
shell: cmd

View File

@ -5,25 +5,22 @@ name: Lint - dotnet format
on:
workflow_call:
permissions:
contents: read
jobs:
run-dotnet-format-stable:
runs-on: windows-latest
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@v4
- name: Setup dotnet
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
uses: actions/setup-dotnet@v4
- name: dotnet restore
run: dotnet restore OpenTelemetry.sln
run: dotnet restore
- name: dotnet format
run: dotnet format OpenTelemetry.sln --no-restore --verify-no-changes # Note: .proj files are currently not supported by dotnet format
run: dotnet format OpenTelemetry.sln --no-restore --verify-no-changes
env:
ExposeExperimentalFeatures: false
@ -32,15 +29,15 @@ jobs:
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@v4
- name: Setup dotnet
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
uses: actions/setup-dotnet@v4
- name: dotnet restore
run: dotnet restore OpenTelemetry.sln
run: dotnet restore
- name: dotnet format
run: dotnet format OpenTelemetry.sln --no-restore --verify-no-changes # Note: .proj files are currently not supported by dotnet format
run: dotnet format OpenTelemetry.sln --no-restore --verify-no-changes
env:
ExposeExperimentalFeatures: true

View File

@ -1,20 +0,0 @@
name: FOSSA scanning
on:
push:
branches:
- main
permissions:
contents: read
jobs:
fossa:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: fossas/fossa-action@3ebcea1862c6ffbd5cf1b4d0bd6b3fe7bd6f2cac # v1.7.0
with:
api-key: ${{secrets.FOSSA_API_KEY}}
team: OpenTelemetry

View File

@ -5,19 +5,16 @@ name: Lint - Markdown
on:
workflow_call:
permissions:
contents: read
jobs:
run-markdownlint:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@v4
- name: run markdownlint
uses: DavidAnson/markdownlint-cli2-action@992badcdf24e3b8eb7e87ff9287fe931bcb00c6e # v20.0.0
uses: DavidAnson/markdownlint-cli2-action@v15.0.0
with:
globs: |
**/*.md

View File

@ -1,47 +0,0 @@
name: OSSF Scorecard
on:
push:
branches:
- main
schedule:
- cron: "24 5 * * 0" # once a week
workflow_dispatch:
permissions: read-all
jobs:
analysis:
runs-on: ubuntu-latest
permissions:
# Needed for Code scanning upload
security-events: write
# Needed for GitHub OIDC token if publish_results is true
id-token: write
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
with:
results_file: results.sarif
results_format: sarif
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable
# uploads of run results in SARIF format to the repository Actions tab.
# https://docs.github.com/en/actions/advanced-guides/storing-workflow-data-as-artifacts
- name: "Upload artifact"
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard (optional).
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.30.0
with:
sarif_file: results.sarif

View File

@ -5,15 +5,12 @@ name: Package Validation
on:
workflow_call:
permissions:
contents: read
jobs:
run-package-validation-stable:
runs-on: windows-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@v4
with:
# Note: By default GitHub only fetches 1 commit. MinVer needs to find
# the version tag which is typically NOT on the first commit so we
@ -21,23 +18,16 @@ jobs:
fetch-depth: 0
- name: Setup dotnet
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
uses: actions/setup-dotnet@v4
- name: dotnet pack
run: dotnet pack ./build/OpenTelemetry.proj --configuration Release /p:EnablePackageValidation=true /p:ExposeExperimentalFeatures=false /p:RunningDotNetPack=true
- name: Publish stable NuGet packages to Artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: packages-stable
path: ./artifacts/package/release
if-no-files-found: error
- name: Pack
run: dotnet pack OpenTelemetry.proj --configuration Release /p:EnablePackageValidation=true /p:ExposeExperimentalFeatures=false
run-package-validation-experimental:
runs-on: windows-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@v4
with:
# Note: By default GitHub only fetches 1 commit. MinVer needs to find
# the version tag which is typically NOT on the first commit so we
@ -45,14 +35,7 @@ jobs:
fetch-depth: 0
- name: Setup dotnet
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
uses: actions/setup-dotnet@v4
- name: dotnet pack
run: dotnet pack ./build/OpenTelemetry.proj --configuration Release /p:EnablePackageValidation=true /p:ExposeExperimentalFeatures=true /p:RunningDotNetPack=true
- name: Publish experimental NuGet packages to Artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: packages-experimental
path: ./artifacts/package/release
if-no-files-found: error
- name: Pack
run: dotnet pack OpenTelemetry.proj --configuration Release /p:EnablePackageValidation=true /p:ExposeExperimentalFeatures=true

View File

@ -1,125 +0,0 @@
name: Complete release
on:
workflow_dispatch:
inputs:
tag:
required: true
description: 'Release tag'
type: string
release:
types:
- published
issue_comment:
types:
- created
permissions:
contents: read
jobs:
automation:
uses: ./.github/workflows/automation.yml
secrets: inherit
push-packages-and-publish-release:
runs-on: ubuntu-22.04
needs: automation
if: |
github.event_name == 'issue_comment'
&& github.event.issue.pull_request
&& github.event.issue.locked == true
&& github.event.comment.user.login != needs.automation.outputs.username
&& contains(github.event.comment.body, '/PushPackages')
&& startsWith(github.event.issue.title, '[release] Prepare release ')
&& github.event.issue.pull_request.merged_at
&& needs.automation.outputs.enabled
env:
GH_TOKEN: ${{ secrets[needs.automation.outputs.token-secret-name] }}
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ secrets[needs.automation.outputs.token-secret-name] }}
ref: ${{ github.event.repository.default_branch }}
- name: Push packages and publish release
shell: pwsh
env:
NUGET_TOKEN: ${{ secrets.NUGET_TOKEN }}
run: |
Import-Module .\build\scripts\post-release.psm1
PushPackagesPublishReleaseUnlockAndPostNoticeOnPrepareReleasePullRequest `
-gitRepository '${{ github.repository }}' `
-pullRequestNumber '${{ github.event.issue.number }}' `
-botUserName '${{ needs.automation.outputs.username }}' `
-commentUserName '${{ github.event.comment.user.login }}' `
-artifactDownloadPath '${{ github.workspace }}/artifacts' `
-pushToNuget '${{ secrets.NUGET_TOKEN != '' }}'
post-release-published:
runs-on: ubuntu-22.04
needs:
- automation
if: |
needs.automation.outputs.enabled
&& (github.event_name == 'release' || github.event_name == 'workflow_dispatch')
env:
GH_TOKEN: ${{ secrets[needs.automation.outputs.token-secret-name] }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
# Note: By default GitHub only fetches 1 commit. We need all the tags
# for this work.
fetch-depth: 0
ref: ${{ github.event.repository.default_branch }}
token: ${{ secrets[needs.automation.outputs.token-secret-name] }}
- name: Setup dotnet
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
- name: Create GitHub Pull Request to update stable build version in props
if: |
(github.ref_type == 'tag' && startsWith(github.ref_name, 'core-') && !contains(github.ref_name, '-alpha') && !contains(github.ref_name, '-beta') && !contains(github.ref_name, '-rc'))
|| (inputs.tag && startsWith(inputs.tag, 'core-') && !contains(inputs.tag, '-alpha') && !contains(inputs.tag, '-beta') && !contains(inputs.tag, '-rc'))
shell: pwsh
run: |
Import-Module .\build\scripts\post-release.psm1
CreateStableVersionUpdatePullRequest `
-gitRepository '${{ github.repository }}' `
-tag '${{ inputs.tag || github.ref_name }}' `
-targetBranch '${{ github.event.repository.default_branch }}' `
-gitUserName '${{ needs.automation.outputs.username }}' `
-gitUserEmail '${{ needs.automation.outputs.email }}'
- name: Invoke core version update workflow in opentelemetry-dotnet-contrib repository
if: vars.CONTRIB_REPO
shell: pwsh
run: |
Import-Module .\build\scripts\post-release.psm1
InvokeCoreVersionUpdateWorkflowInRemoteRepository `
-remoteGitRepository '${{ vars.CONTRIB_REPO }}' `
-tag '${{ inputs.tag || github.ref_name }}'
- name: Post notice when release is published
shell: pwsh
run: |
Import-Module .\build\scripts\post-release.psm1
TryPostReleasePublishedNoticeOnPrepareReleasePullRequest `
-gitRepository '${{ github.repository }}' `
-botUserName '${{ needs.automation.outputs.username }}' `
-tag '${{ inputs.tag || github.ref_name }}'

View File

@ -1,214 +0,0 @@
name: Prepare for a release
on:
workflow_dispatch:
inputs:
tag-prefix:
type: choice
options:
- core-
- coreunstable-
description: 'Release tag prefix'
required: true
version:
type: string
description: 'Release version'
required: true
pull_request:
types:
- closed
issue_comment:
types:
- created
permissions:
contents: read
jobs:
automation:
uses: ./.github/workflows/automation.yml
secrets: inherit
prepare-release-pr:
runs-on: ubuntu-22.04
needs: automation
if: github.event_name == 'workflow_dispatch' && needs.automation.outputs.enabled
env:
GH_TOKEN: ${{ secrets[needs.automation.outputs.token-secret-name] }}
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ secrets[needs.automation.outputs.token-secret-name] }}
- name: Create GitHub Pull Request to prepare release
shell: pwsh
run: |
Import-Module .\build\scripts\prepare-release.psm1
CreatePullRequestToUpdateChangelogsAndPublicApis `
-gitRepository '${{ github.repository }}' `
-minVerTagPrefix '${{ inputs.tag-prefix }}' `
-version '${{ inputs.version }}' `
-requestedByUserName '${{ github.event.sender.login }}' `
-targetBranch '${{ github.ref_name }}' `
-gitUserName '${{ needs.automation.outputs.username }}' `
-gitUserEmail '${{ needs.automation.outputs.email }}'
lock-pr-and-post-notice-to-create-release-tag:
runs-on: ubuntu-22.04
needs: automation
if: |
github.event_name == 'pull_request'
&& github.event.action == 'closed'
&& github.event.pull_request.user.login == needs.automation.outputs.username
&& github.event.pull_request.merged == true
&& startsWith(github.event.pull_request.title, '[release] Prepare release ')
&& needs.automation.outputs.enabled
env:
GH_TOKEN: ${{ secrets[needs.automation.outputs.token-secret-name] }}
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ secrets[needs.automation.outputs.token-secret-name] }}
- name: Lock GitHub Pull Request to prepare release
shell: pwsh
run: |
Import-Module .\build\scripts\prepare-release.psm1
LockPullRequestAndPostNoticeToCreateReleaseTag `
-gitRepository '${{ github.repository }}' `
-pullRequestNumber '${{ github.event.pull_request.number }}' `
-botUserName '${{ needs.automation.outputs.username }}'
create-release-tag-pr-post-notice:
runs-on: ubuntu-22.04
needs: automation
if: |
github.event_name == 'issue_comment'
&& github.event.issue.pull_request
&& github.event.issue.locked == true
&& github.event.comment.user.login != needs.automation.outputs.username
&& contains(github.event.comment.body, '/CreateReleaseTag')
&& startsWith(github.event.issue.title, '[release] Prepare release ')
&& github.event.issue.pull_request.merged_at
&& needs.automation.outputs.enabled
env:
GH_TOKEN: ${{ secrets[needs.automation.outputs.token-secret-name] }}
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
# Note: By default GitHub only fetches 1 commit which fails the git tag operation below
fetch-depth: 0
token: ${{ secrets[needs.automation.outputs.token-secret-name] }}
- name: Create release tag
id: create-tag
shell: pwsh
run: |
Import-Module .\build\scripts\prepare-release.psm1
CreateReleaseTagAndPostNoticeOnPullRequest `
-gitRepository '${{ github.repository }}' `
-pullRequestNumber '${{ github.event.issue.number }}' `
-botUserName '${{ needs.automation.outputs.username }}' `
-gitUserName '${{ needs.automation.outputs.username }}' `
-gitUserEmail '${{ needs.automation.outputs.email }}'
update-changelog-release-dates-on-prepare-pr-post-notice:
runs-on: ubuntu-22.04
needs: automation
if: |
github.event_name == 'issue_comment'
&& github.event.issue.pull_request
&& github.event.issue.state == 'open'
&& github.event.comment.user.login != needs.automation.outputs.username
&& contains(github.event.comment.body, '/UpdateReleaseDates')
&& startsWith(github.event.issue.title, '[release] Prepare release ')
&& github.event.issue.pull_request.merged_at == null
&& needs.automation.outputs.enabled
env:
GH_TOKEN: ${{ secrets[needs.automation.outputs.token-secret-name] }}
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
# Note: By default GitHub only fetches 1 commit which fails the git tag operation below
fetch-depth: 0
token: ${{ secrets[needs.automation.outputs.token-secret-name] }}
- name: Update release date
shell: pwsh
run: |
Import-Module .\build\scripts\prepare-release.psm1
UpdateChangelogReleaseDatesAndPostNoticeOnPullRequest `
-gitRepository '${{ github.repository }}' `
-pullRequestNumber '${{ github.event.issue.number }}' `
-botUserName '${{ needs.automation.outputs.username }}' `
-commentUserName '${{ github.event.comment.user.login }}' `
-gitUserName '${{ needs.automation.outputs.username }}' `
-gitUserEmail '${{ needs.automation.outputs.email }}'
update-releasenotes-on-prepare-pr-post-notice:
runs-on: ubuntu-22.04
needs: automation
if: |
github.event_name == 'issue_comment'
&& github.event.issue.pull_request
&& github.event.issue.state == 'open'
&& github.event.comment.user.login != needs.automation.outputs.username
&& contains(github.event.comment.body, '/UpdateReleaseNotes')
&& startsWith(github.event.issue.title, '[release] Prepare release ')
&& github.event.issue.pull_request.merged_at == null
&& needs.automation.outputs.enabled
env:
GH_TOKEN: ${{ secrets[needs.automation.outputs.token-secret-name] }}
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
# Note: By default GitHub only fetches 1 commit which fails the git tag operation below
fetch-depth: 0
token: ${{ secrets[needs.automation.outputs.token-secret-name] }}
- name: Update release notes
env:
COMMENT_BODY: ${{ github.event.comment.body }}
shell: pwsh
run: |
Import-Module .\build\scripts\prepare-release.psm1
UpdateReleaseNotesAndPostNoticeOnPullRequest `
-gitRepository '${{ github.repository }}' `
-pullRequestNumber '${{ github.event.issue.number }}' `
-botUserName '${{ needs.automation.outputs.username }}' `
-commentUserName '${{ github.event.comment.user.login }}' `
-commentBody $Env:COMMENT_BODY `
-gitUserName '${{ needs.automation.outputs.username }}' `
-gitUserEmail '${{ needs.automation.outputs.email }}'

View File

@ -8,140 +8,43 @@
name: Build, pack, and publish to MyGet
on:
workflow_dispatch:
push:
tags:
- 'core-*'
- 'coreunstable-*'
release:
types: [published]
schedule:
- cron: '0 0 * * *' # once in a day at 00:00
permissions:
contents: read
jobs:
automation:
uses: ./.github/workflows/automation.yml
secrets: inherit
build-pack-publish:
runs-on: windows-latest
permissions:
contents: read
id-token: write
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COSIGN_YES: "yes"
outputs:
artifact-url: ${{ steps.upload-artifacts.outputs.artifact-url }}
artifact-id: ${{ steps.upload-artifacts.outputs.artifact-id }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@v4
with:
# Note: By default GitHub only fetches 1 commit. MinVer needs to find
# the version tag which is typically NOT on the first commit so we
# retrieve them all.
fetch-depth: 0
ref: ${{ github.ref || 'main' }}
- name: Setup dotnet
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
- name: Install Cosign
uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
with:
cosign-release: v2.5.3
uses: actions/setup-dotnet@v4
- name: dotnet restore
run: dotnet restore ./build/OpenTelemetry.proj -p:RunningDotNetPack=true
run: dotnet restore OpenTelemetry.proj -p:RunningDotNetPack=true
- name: dotnet build
run: dotnet build ./build/OpenTelemetry.proj --configuration Release --no-restore -p:Deterministic=true -p:BuildNumber=${{ github.run_number }} -p:RunningDotNetPack=true
- name: Sign DLLs with Cosign Keyless
shell: pwsh
run: |
$projectFiles = Get-ChildItem -Path src/*/*.csproj -File
foreach ($projectFile in $projectFiles) {
$projectName = [System.IO.Path]::GetFileNameWithoutExtension($projectFile)
Get-ChildItem -Path artifacts/bin/$projectName/release_*/$projectName.dll -File | ForEach-Object {
$fileFullPath = $_.FullName
Write-Host "Signing $fileFullPath"
cosign.exe sign-blob $fileFullPath --yes --output-signature $fileFullPath-keyless.sig --output-certificate $fileFullPath-keyless.pem
}
}
run: dotnet build OpenTelemetry.proj --configuration Release --no-restore -p:Deterministic=true -p:BuildNumber=${{ github.run_number }} -p:RunningDotNetPack=true
- name: dotnet pack
run: dotnet pack ./build/OpenTelemetry.proj --configuration Release --no-restore --no-build -p:PackTag=${{ github.ref_type == 'tag' && github.ref_name || '' }}
run: dotnet pack OpenTelemetry.proj --configuration Release --no-restore --no-build
- name: Publish Artifacts
id: upload-artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@v4
with:
name: ${{ github.ref_name }}-packages
path: ./artifacts/package/release
if-no-files-found: error
path: '**/bin/**/*.*nupkg'
- name: Publish MyGet
env:
MYGET_TOKEN_EXISTS: ${{ secrets.MYGET_TOKEN != '' }}
if: env.MYGET_TOKEN_EXISTS == 'true' # Skip MyGet publish if run on a fork without the secret
run: |
nuget setApiKey ${{ secrets.MYGET_TOKEN }} -Source https://www.myget.org/F/opentelemetry/api/v2/package
nuget push ./artifacts/package/release/*.nupkg -Source https://www.myget.org/F/opentelemetry/api/v2/package
post-build:
runs-on: ubuntu-22.04
needs:
- automation
- build-pack-publish
if: needs.automation.outputs.enabled && github.event_name == 'push'
env:
GH_TOKEN: ${{ secrets[needs.automation.outputs.token-secret-name] }}
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ secrets[needs.automation.outputs.token-secret-name] }}
- name: Download Artifacts
run: |
curl \
-H "Accept: application/vnd.github+json" \
-H "Authorization: token ${{ github.token }}" \
-L \
-o '${{ github.workspace }}/artifacts/${{ github.ref_name }}-packages.zip' \
--create-dirs \
"https://api.github.com/repos/${{ github.repository }}/actions/artifacts/${{ needs.build-pack-publish.outputs.artifact-id }}/zip"
- name: Create GitHub Release draft
shell: pwsh
run: |
Import-Module .\build\scripts\post-release.psm1
CreateDraftRelease `
-gitRepository '${{ github.repository }}' `
-tag '${{ github.ref_name }}' `
-releaseFiles '${{ github.workspace }}/artifacts/${{ github.ref_name }}-packages.zip#Packages'
- name: Post notice when packages are ready
shell: pwsh
run: |
Import-Module .\build\scripts\post-release.psm1
TryPostPackagesReadyNoticeOnPrepareReleasePullRequest `
-gitRepository '${{ github.repository }}' `
-tag '${{ github.ref_name }}' `
-tagSha '${{ github.sha }}' `
-packagesUrl '${{ needs.build-pack-publish.outputs.artifact-url }}' `
-botUserName '${{ needs.automation.outputs.username }}'
nuget push **/bin/**/*.nupkg -Source https://www.myget.org/F/opentelemetry/api/v2/package

View File

@ -5,16 +5,13 @@ name: Lint - Spelling & Encoding
on:
workflow_call:
permissions:
contents: read
jobs:
run-misspell:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@v4
- name: install misspell
run: |
@ -25,11 +22,11 @@ jobs:
run: ./bin/misspell -error .
run-sanitycheck:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: check out code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@v4
- name: detect non-ASCII encoding and trailing space
run: python3 ./build/scripts/sanitycheck.py
run: python3 ./build/sanitycheck.py

View File

@ -1,32 +1,21 @@
# Syntax: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions
# Github Actions Stale: https://github.com/actions/stale
name: "Manage stale issues and pull requests"
name: "Close stale pull requests"
on:
schedule:
- cron: "12 3 * * *" # arbitrary time not to DDOS GitHub
permissions:
contents: read
jobs:
stale:
permissions:
issues: write # for actions/stale to close stale issues
pull-requests: write # for actions/stale to close stale PRs
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
- uses: actions/stale@v9
with:
stale-issue-message: 'This issue was marked stale due to lack of activity and will be closed in 7 days. Commenting will instruct the bot to automatically remove the label. This bot runs once per day.'
close-issue-message: 'Closed as inactive. Feel free to reopen if this issue is still a concern.'
stale-pr-message: 'This PR was marked stale due to lack of activity and will be closed in 7 days. Commenting or pushing will instruct the bot to automatically remove the label. This bot runs once per day.'
stale-pr-message: 'This PR was marked stale due to lack of activity and will be closed in 7 days. Commenting or Pushing will instruct the bot to automatically remove the label. This bot runs once per day.'
close-pr-message: 'Closed as inactive. Feel free to reopen if this PR is still being worked on.'
operations-per-run: 400
days-before-pr-stale: 7
days-before-issue-stale: 300
days-before-issue-stale: -1
days-before-pr-close: 7
days-before-issue-close: 7
exempt-all-issue-milestones: true
exempt-issue-labels: 'keep-open,needs-triage'
exempt-pr-labels: 'keep-open'
days-before-issue-close: -1

View File

@ -5,25 +5,23 @@ name: Publish & Verify AOT Compatibility
on:
workflow_call:
permissions:
contents: read
jobs:
run-verify-aot-compat:
strategy:
fail-fast: false # ensures the entire test matrix is run, even if one permutation fails
matrix:
os: [ ubuntu-22.04, windows-latest ]
version: [ net8.0, net9.0 ]
os: [ ubuntu-latest ]
version: [ net8.0 ]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@v4
- name: Setup dotnet
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
uses: actions/setup-dotnet@v4
- name: publish AOT testApp, assert static analysis warning count, and run the app
shell: pwsh
run: .\build\scripts\test-aot-compatibility.ps1 ${{ matrix.version }}
run: .\build\test-aot-compatibility.ps1 ${{ matrix.version }}

4
.gitignore vendored
View File

@ -21,7 +21,6 @@
x64/
x86/
bld/
[Aa]rtifacts/
[Bb]in/
[Oo]bj/
[Ll]og/
@ -352,6 +351,3 @@ tempo-data/
# Coyote Rewrite Files
rewrite.coyote.json
# Test results
TestResults/

View File

@ -1,15 +1,7 @@
# Default state for all rules
default: true
# MD013/line-length : Line length : https://github.com/DavidAnson/markdownlint/blob/v0.32.1/doc/md013.md
# allow long lines for tables and code blocks
MD013:
code_blocks: false
tables: false
# MD033/no-inline-html : Inline HTML : https://github.com/DavidAnson/markdownlint/blob/v0.32.1/doc/md033.md
MD033:
# Allowed elements
allowed_elements: [ 'details', 'summary' ]
# MD059/link-text-should-be-descriptive : Inline HTML : https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md059.md
MD059: false

View File

@ -10,39 +10,16 @@ for a summary description of past meetings. To request edit access, join the
meeting or get in touch on
[Slack](https://cloud-native.slack.com/archives/C01N3BC2W7Q).
Anyone may contribute but there are benefits of being a member of our community.
See the [community membership
Even though, anybody can contribute, there are benefits of being a member of our
community. See to the [community membership
document](https://github.com/open-telemetry/community/blob/main/community-membership.md)
on how to become a
[**Member**](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#member),
[**Triager**](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#triager),
[**Approver**](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver),
[**Member**](https://github.com/open-telemetry/community/blob/main/community-membership.md#member),
[**Approver**](https://github.com/open-telemetry/community/blob/main/community-membership.md#approver)
and
[**Maintainer**](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#maintainer).
[**Maintainer**](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer).
## Give feedback
We are always looking for your feedback.
You can do this by [submitting a GitHub issue](https://github.com/open-telemetry/opentelemetry-dotnet/issues/new).
You may also prefer writing on [#otel-dotnet Slack channel](https://cloud-native.slack.com/archives/C01N3BC2W7Q).
### Report a bug
Reporting bugs is an important contribution. Please make sure to include:
* Expected and actual behavior;
* OpenTelemetry, OS, and .NET versions you are using;
* Steps to reproduce;
* [Minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example).
### Request a feature
If you would like to work on something that is not listed as an issue
(e.g. a new feature or enhancement) please create an issue and describe your proposal.
## Find a buddy and get started quickly
## Find a Buddy and Get Started Quickly
If you are looking for someone to help you find a starting point and be a
resource for your first contribution, join our Slack channel and find a buddy!
@ -57,24 +34,17 @@ resource for your first contribution, join our Slack channel and find a buddy!
Your OpenTelemetry buddy is your resource to talk to directly on all aspects of
contributing to OpenTelemetry: providing context, reviewing PRs, and helping
those get merged. Buddies will not be available 24/7, but are committed to
responding during their normal working hours.
those get merged. Buddies will not be available 24/7, but is committed to
responding during their normal contribution hours.
## Development Environment
You can contribute to this project from a Windows, macOS, or Linux machine.
You can contribute to this project from a Windows, macOS or Linux machine.
On all platforms, the minimum requirements are:
* Git client and command line tools
* [.NET SDK (latest stable version)](https://dotnet.microsoft.com/download)
> [!NOTE]
> At times a pre-release version of the .NET SDK may be required to build code
in this repository. Check
[global.json](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/global.json)
to verify the current required version.
* Git client and command line tools.
* .NET 8.0
### Linux or MacOS
@ -89,97 +59,42 @@ of Windows.
* Visual Studio 2022+ or Visual Studio Code
* .NET Framework 4.6.2+
## Public API validation
### Public API
It is critical to **NOT** make breaking changes to public APIs which have been
released in stable builds. We also strive to keep a minimal public API surface.
This repository is using
[Microsoft.CodeAnalysis.PublicApiAnalyzers](https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)
and [Package
validation](https://learn.microsoft.com/dotnet/fundamentals/apicompat/package-validation/overview)
to validate public APIs.
It is critical to keep public API surface small and clean. This repository is
using `Microsoft.CodeAnalysis.PublicApiAnalyzers` to validate the public APIs.
This analyzer will check if you changed a public property/method so the change
will be easily spotted in pull request. It will also ensure that OpenTelemetry
doesn't expose APIs outside of the library primary concerns like a generic
helper methods.
* `Microsoft.CodeAnalysis.PublicApiAnalyzers` will validate public API
changes/additions against a set of "public API files" which capture the
shipped/unshipped public APIs. These files must be maintained manually (not
recommended) or by using tooling/code fixes built into the package (see below
for details).
#### How to enable and configure
Public API files are also used to perform public API reviews by repo
approvers/maintainers before releasing stable builds.
* Create a folder in your project called `.publicApi` with the frameworks that
as folders you target.
* Create two files called `PublicAPI.Shipped.txt` and `PublicAPI.Unshipped.txt`
in each framework that you target.
* Add the following lines to your csproj:
* `Package validation` will validate public API changes/additions against
previously released NuGet packages.
```xml
<ItemGroup>
<AdditionalFiles Include=".publicApi\$(TargetFramework)\PublicAPI.Shipped.txt" />
<AdditionalFiles Include=".publicApi\$(TargetFramework)\PublicAPI.Unshipped.txt" />
</ItemGroup>
```
This is performed automatically by the build/CI
[package-validation](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/.github/workflows/package-validation.yml)
workflow.
By default package validation is **NOT** run for local builds. To enable
package validation in local builds set the `EnablePackageValidation` property
to `true` in
[Common.prod.props](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/build/Common.prod.props)
(please do not check in this change).
### Working with Microsoft.CodeAnalysis.PublicApiAnalyzers
#### Update public API files when writing code
[IntelliSense](https://docs.microsoft.com/visualstudio/ide/using-intellisense)
will [suggest
modifications](https://github.com/dotnet/roslyn-analyzers/issues/3322#issuecomment-591031429)
to the `PublicAPI.Unshipped.txt` file when you make changes. After reviewing
these changes, ensure they are reflected across all targeted frameworks. You can
do this by:
* Using the "Fix all occurrences in Project" feature in Visual Studio.
* Manually cycling through each framework using Visual Studio's target framework
dropdown (in the upper right corner) and applying the IntelliSense
suggestions.
> [!IMPORTANT]
> Do **NOT** modify `PublicAPI.Shipped.txt` files. New features and bug fixes
**SHOULD** only require changes to `PublicAPI.Unshipped.txt` files. If you
have to modify a "shipped" file it likely means you made a mistake and broke a
stable API. Typically only maintainers modify the `PublicAPI.Shipped.txt` file
while performing stable releases. If you need help reach out to an approver or
maintainer on Slack or open a draft PR.
#### Enable public API validation in new projects
1. If you are **NOT** using experimental APIs:
* If your API is the same across all target frameworks:
* You only need two files: `.publicApi/PublicAPI.Shipped.txt` and
`.publicApi/PublicAPI.Unshipped.txt`.
* If your APIs differ between target frameworks:
* Place the shared APIs in `.publicApi/PublicAPI.Shipped.txt` and
`.publicApi/PublicAPI.Unshipped.txt`.
* Create framework-specific files for API differences (e.g.,
`.publicApi/net462/PublicAPI.Shipped.txt` and
`.publicApi/net462/PublicAPI.Unshipped.txt`).
2. If you are using experimental APIs:
* Follow the rules above, but create an additional layer in your folder
structure:
* For stable APIs: `.publicApi/Stable/*`.
* For experimental APIs: `.publicApi/Experimental/*`.
* The `Experimental` folder should contain APIs that are public only in
pre-release builds. Typically the `Experimental` folder only contains
`PublicAPI.Unshipped.txt` files as experimental APIs are never shipped
stable.
Example folder structure can be found
[here](https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry.Api/.publicApi).
* Use
[IntelliSense](https://docs.microsoft.com/visualstudio/ide/using-intellisense)
to update the publicApi files.
## Pull Requests
### How to create pull requests
### How to Send Pull Requests
Everyone is welcome to contribute code to `opentelemetry-dotnet` via GitHub pull
requests (PRs).
To create a new PR, fork the project on GitHub and clone the upstream repo:
To create a new PR, fork the project in GitHub and clone the upstream repo:
```sh
git clone https://github.com/open-telemetry/opentelemetry-dotnet.git
@ -210,7 +125,7 @@ If you made changes to the Markdown documents (`*.md` files), install the latest
markdownlint .
```
Check out a new branch, make modifications, and push the branch to your fork:
Check out a new branch, make modifications and push the branch to your fork:
```sh
$ git checkout -b feature
@ -221,26 +136,20 @@ $ git push fork feature
Open a pull request against the main `opentelemetry-dotnet` repo.
#### Tips and best practices for pull requests
### How to Receive Comments
* If the PR is not ready for review, please mark it as
[`draft`](https://github.blog/2019-02-14-introducing-draft-pull-requests/).
* Make sure CLA is signed and all required CI checks are clear.
* Submit small, focused PRs addressing a single concern/issue.
* Submit small, focused PRs addressing a single
concern/issue.
* Make sure the PR title reflects the contribution.
* Write a summary that helps understand the change.
* Include usage examples in the summary, where applicable.
* Include benchmarks (before/after) in the summary, for contributions that are
performance enhancements.
* We are open to bot generated PRs or AI/LLM assisted PRs. Actually, we are
using
[dependabot](https://docs.github.com/en/code-security/dependabot/dependabot-security-updates/configuring-dependabot-security-updates)
to automate the security updates. However, if you use bots to generate spam
PRs (e.g. incorrect, noisy, non-improvements, unintelligible, trying to sell
your product, etc.), we might close the PR right away with a warning, and if
you keep doing so, we might block your user account.
### How to get pull requests merged
### How to Get PRs Merged
A PR is considered to be **ready to merge** when:
@ -248,21 +157,18 @@ A PR is considered to be **ready to merge** when:
[Approvers](https://github.com/open-telemetry/community/blob/main/community-membership.md#approver).
/
[Maintainers](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer).
* Major feedback/comments are resolved.
* Major feedbacks are resolved.
* It has been open for review for at least one working day. This gives people
reasonable time to review.
* Trivial change (typo, cosmetic, doc, etc.) doesn't have to wait for one day.
* Urgent fix can take exception as long as it has been actively communicated.
* Trivial change (typo, cosmetic, doc, etc.) doesn't have to wait for one day.
* Urgent fix can take exception as long as it has been actively communicated.
Any maintainer can merge PRs once they are **ready to merge** however
maintainers might decide to wait on merging changes until there are more
approvals and/or dicussion, or based on other factors such as release timing and
risk to users. For example if a stable release is planned and a new change is
introduced adding public API(s) or behavioral changes it might be held until the
next alpha/beta release.
Any Maintainer can merge the PR once it is **ready to merge**. Note, that some
PRs may not be merged immediately if the repo is in the process of a release and
the maintainers decided to defer the PR to the next release train.
If a PR has become stuck (e.g. there is a lot of debate and people couldn't
agree on the direction), the owner should try to get people aligned by:
If a PR has been stuck (e.g. there are lots of debates and people couldn't agree
on each other), the owner should try to get people aligned by:
* Consolidating the perspectives and putting a summary in the PR. It is
recommended to add a link into the PR description, which points to a comment
@ -277,7 +183,7 @@ agree on the direction), the owner should try to get people aligned by:
the owner should bring it to the OpenTelemetry .NET SIG
[meeting](README.md#contributing).
## Design choices
## Design Choices
As with other OpenTelemetry clients, opentelemetry-dotnet follows the
[opentelemetry-specification](https://github.com/open-telemetry/opentelemetry-specification).
@ -285,7 +191,7 @@ As with other OpenTelemetry clients, opentelemetry-dotnet follows the
It's especially valuable to read through the [library
guidelines](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/library-guidelines.md).
### Focus on capabilities not structural compliance
### Focus on Capabilities, Not Structure Compliance
OpenTelemetry is an evolving specification, one where the desires and use cases
are clear, but the method to satisfy those uses cases are not.
@ -299,10 +205,10 @@ than conform to specific API names or argument patterns in the spec.
For a deeper discussion, see [this spec
issue](https://github.com/open-telemetry/opentelemetry-specification/issues/165).
## Style guide
## Style Guide
This project includes a [`.editorconfig`](./.editorconfig) file which is
supported by all the IDEs/editors mentioned above. It works with the IDE/editor
supported by all the IDEs/editor mentioned above. It works with the IDE/editor
only and does not affect the actual build of the project.
This repository also includes StyleCop ruleset files under the `./build` folder.
@ -323,11 +229,31 @@ types](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-type
* Pass [static
analysis](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/overview).
New projects MUST enable static analysis by specifying
`<AnalysisLevel>latest-all</AnalysisLevel>` in the project file (`.csproj`).
> [!NOTE]
> There are other project-level features enabled automatically via
[Common.props](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/build/Common.props)
new projects must NOT manually override these settings.
## New code
New code files MUST enable [nullable reference
types](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/nullable-reference-types)
manually in projects where it is not automatically enabled project-wide. This is
done by specifying `#nullable enable` towards the top of the file (usually after
the copyright header). We are currently working towards enabling nullable
context in every project by updating code as it is worked on, this requirement
is to make sure the surface area of code needing updates is shrinking and not
expanding.
> [!NOTE]
> The first time a project is updated to use nullable context in public APIs
some housekeeping needs to be done in public API definitions (`.publicApi`
folder). This can be done automatically via a code fix offered by the public API
analyzer.
## License requirements
OpenTelemetry .NET is licensed under the [Apache License, Version

View File

@ -1,6 +0,0 @@
<Project>
<PropertyGroup>
<ArtifactsPath>$([System.IO.Path]::Combine('$(MSBuildThisFileDirectory)', 'artifacts'))</ArtifactsPath>
<UseArtifactsOutput>true</UseArtifactsOutput>
</PropertyGroup>
</Project>

View File

@ -1,19 +1,7 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<OTelLatestStableVer>1.12.0</OTelLatestStableVer>
<!--
This is typically the latest annual release of .NET. Use this wherever
possible and only deviate (use a specific version) when a package has a
more specific patch which must be reference directly.
-->
<LatestRuntimeOutOfBandVer>9.0.0</LatestRuntimeOutOfBandVer>
<!-- Mitigate https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-43485. -->
<SystemTextEncodingsWebOutOfBandMinimumCoreAppVer>8.0.0</SystemTextEncodingsWebOutOfBandMinimumCoreAppVer>
<SystemTextJsonOutOfBandMinimumCoreAppVer>8.0.5</SystemTextJsonOutOfBandMinimumCoreAppVer>
<OTelLatestStableVer>1.7.0</OTelLatestStableVer>
</PropertyGroup>
<!--
@ -22,6 +10,13 @@
vulnerability in the NuGet packages that are published from this repository.
-->
<ItemGroup>
<PackageVersion Include="Google.Protobuf" Version="[3.22.5,4.0)" />
<PackageVersion Include="Grpc" Version="[2.44.0,3.0)" />
<PackageVersion Include="Grpc.Net.Client" Version="[2.52.0,3.0)" />
<PackageVersion Include="Microsoft.AspNetCore.Http.Abstractions" Version="[2.1.1,6.0)" />
<PackageVersion Include="Microsoft.AspNetCore.Http.Features" Version="[2.1.1,6.0)" />
<PackageVersion Include="Microsoft.CSharp" Version="[4.7.0]" />
<!--
Typically, for the Microsoft.Extensions.* packages relating to DI Abstractions, Hosting Abstractions, and Logging,
the latest stable version should be used because:
@ -31,98 +26,89 @@
3) Since version 3.1.0, the .NET runtime team is holding a high bar for backward compatibility on
these packages even during major version bumps, so compatibility is not a concern here.
-->
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(LatestRuntimeOutOfBandVer)" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Abstractions" Version="$(LatestRuntimeOutOfBandVer)" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(LatestRuntimeOutOfBandVer)" />
<PackageVersion Include="Microsoft.Extensions.Logging.Configuration" Version="$(LatestRuntimeOutOfBandVer)" />
<!--
OTel packages always point to latest stable release.
-->
<PackageVersion Include="OpenTelemetry" Version="[$(OTelLatestStableVer),2.0)" />
<PackageVersion Include="OpenTelemetry.Api" Version="[$(OTelLatestStableVer),2.0)" />
<PackageVersion Include="OpenTelemetry.Api.ProviderBuilderExtensions" Version="[$(OTelLatestStableVer),2.0)" />
<PackageVersion Include="OpenTelemetry.Exporter.InMemory" Version="[$(OTelLatestStableVer),2.0)" />
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="[$(OTelLatestStableVer),2.0)" />
<PackageVersion Include="OpenTelemetry.Extensions.Propagators" Version="[$(OTelLatestStableVer),2.0)" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Abstractions" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Configuration" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.0" />
<PackageVersion Include="OpenTelemetry" Version="$(OTelLatestStableVer)" />
<PackageVersion Include="OpenTelemetry.Api" Version="$(OTelLatestStableVer)" />
<PackageVersion Include="OpenTelemetry.Api.ProviderBuilderExtensions" Version="$(OTelLatestStableVer)" />
<PackageVersion Include="OpenTelemetry.Exporter.InMemory" Version="$(OTelLatestStableVer)" />
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="$(OTelLatestStableVer)" />
<PackageVersion Include="OpenTelemetry.Extensions.Propagators" Version="$(OTelLatestStableVer)" />
<PackageVersion Include="OpenTracing" Version="[0.12.1,0.13)" />
<!--
Typically, the latest stable version of System.Diagnostics.DiagnosticSource should be used here because:
1) Each major version bump will likely have some new OpenTelemetry capabilities (e.g. .NET 6 introduced Meter
API, .NET 7 added UpDownCounter, .NET 8 added Meter/Instrument level attributes support, .NET 9 added
Advice/Hint API, etc.).
1) Each major version bump will have some new OpenTelemetry API capabilities (e.g. .NET 6 introduced Meter
API, .NET 7 added UpDownCounter, .NET 8 is adding Meter/Instrument level attributes support, .NET 9 might
add Advice/Hint API) that the OpenTelemetry components rely on.
2) Each minor version bump is normally security hotfixes or critical bug fixes.
3) The .NET runtime team provides extra backward compatibility guarantee to System.Diagnostics.DiagnosticSource
even during major version bumps, so compatibility is not a concern here.
-->
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="$(LatestRuntimeOutOfBandVer)" />
</ItemGroup>
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="8.0.0" />
<ItemGroup>
<!--
Note: See TargetFrameworksRequiringSystemTextJsonDirectReference for the
list of targets where System.Text.Json direct reference is applied.
-->
<!--
We use conservative versions of these packages for older runtimes where
an upgrade might introduce breaking changes. For example see:
https://devblogs.microsoft.com/dotnet/system-text-json-in-dotnet-7/#breaking-changes.
-->
<!-- A conservative version of System.Text.Encodings.Web must be used here since there is no backward compatibility guarantee during major version bumps. -->
<PackageVersion Include="System.Text.Encodings.Web" Version="4.7.2" />
<!-- A conservative version of System.Text.Json must be used here since there is no backward compatibility guarantee during major version bumps. -->
<PackageVersion Include="System.Text.Json" Version="4.7.2" />
<!-- Newer NETCoreApp runtimes need to be redirected to safe versions. -->
<PackageVersion Update="System.Text.Encodings.Web" Version="$(SystemTextEncodingsWebOutOfBandMinimumCoreAppVer)" Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'" />
<PackageVersion Update="System.Text.Json" Version="$(SystemTextJsonOutOfBandMinimumCoreAppVer)" Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'" />
<!-- A conservative version of System.Threading.Tasks.Extensions must be used here since there is no backward compatibility guarantee during major version bumps. -->
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
</ItemGroup>
<!--
This section covers packages that are **not** directly referenced by the NuGet packages published from this repository.
These packages are referenced as "PrivateAssets" or used in tests/examples.
For example, these packages are used in the tests, examples or referenced as "PrivateAssets", but not in the NuGet packages themselves.
-->
<!-- 'net8.0' is the default `TargetFramework`. Use `VersionOverride` in the project to override the package versions from a different `TargetFramework` -->
<ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="0.15.2" />
<PackageVersion Include="BenchmarkDotNet" Version="[0.13.10,0.14)" />
<PackageVersion Include="CommandLineParser" Version="[2.9.1,3.0)" />
<PackageVersion Include="GitHubActionsTestLogger" Version="2.4.1" />
<PackageVersion Include="Grpc.AspNetCore" Version="[2.59.0,3.0)" />
<PackageVersion Include="Grpc.AspNetCore.Server" Version="[2.59.0, 3.0)" />
<PackageVersion Include="Grpc.Tools" Version="[2.59.0,3.0)" />
<PackageVersion Include="Google.Protobuf" Version="[3.22.5,4.0)" />
<PackageVersion Include="Grpc" Version="[2.44.0,3.0)" />
<PackageVersion Include="Grpc.Net.Client" Version="[2.52.0,3.0)" />
<PackageVersion Include="JunitXml.TestLogger" Version="6.1.0" />
<PackageVersion Include="Microsoft.CSharp" Version="[4.7.0]" />
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="[3.11.0-beta1.23525.2]" />
<PackageVersion Include="Microsoft.Coyote" Version="1.7.11" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="$(LatestRuntimeOutOfBandVer)" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="$(LatestRuntimeOutOfBandVer)" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="$(LatestRuntimeOutOfBandVer)" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="$(LatestRuntimeOutOfBandVer)" />
<PackageVersion Include="Microsoft.Extensions.Telemetry.Abstractions" Version="[9.0.0,)" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.1.3" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="[8.0.0,)" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="[8.0.0,)" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="[8.0.0,)" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="[8.0.0,)" />
<PackageVersion Include="Microsoft.Extensions.Telemetry.Abstractions" Version="[8.2.0,)" />
<PackageVersion Include="Microsoft.NETFramework.ReferenceAssemblies" Version="[1.0.3,2.0)" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="[17.13.0,18.0.0)" />
<PackageVersion Include="MinVer" Version="[5.0.0,6.0)" />
<PackageVersion Include="NuGet.Versioning" Version="6.11.0" />
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="[1.9.0,2.0)" />
<PackageVersion Include="OpenTelemetry.Instrumentation.GrpcNetClient" Version="[1.9.0-beta.1,2.0)" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="[1.9.0,2.0)" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="[1.9.0,2.0)" />
<PackageVersion Include="RabbitMQ.Client" Version="[6.8.1,7.0)" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="[17.8.0,18.0.0)" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="[1.1.1,2.0)" />
<PackageVersion Include="MinVer" Version="[4.3.0,5.0)" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="[1.5.1,2.0)" />
<PackageVersion Include="RabbitMQ.Client" Version="[6.6.0,7.0)" />
<PackageVersion Include="StyleCop.Analyzers" Version="[1.2.0-beta.556,2.0)" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="[6.7.3,)" />
<PackageVersion Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" />
<PackageVersion Include="xunit" Version="[2.9.3,3.0)" />
<PackageVersion Include="xunit.runner.visualstudio" Version="[2.8.2,3.0)" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="[6.5.0,)" />
<PackageVersion Include="Testcontainers.MsSql" Version="3.6.0" />
<PackageVersion Include="Testcontainers.SqlEdge" Version="3.6.0" />
<PackageVersion Include="xunit" Version="[2.6.2,3.0)" />
<PackageVersion Include="xunit.runner.visualstudio" Version="[2.5.4,3.0)" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="6.0.21" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.21" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.21" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="7.0.9" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.9" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="7.0.9" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="8.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="8.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="9.0.0" />
</ItemGroup>
</Project>

View File

@ -3,14 +3,19 @@
<packageSources>
<clear />
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
<add key="dotnet8" value="https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet8/nuget/v3/index.json" />
</packageSources>
<!-- Define mappings by adding package patterns beneath the target source. -->
<!-- *.Tools packages will be restored from ".Net Core Tools", everything else from nuget.org. -->
<packageSourceMapping>
<!-- key value for <packageSource> should match key values from <packageSources> element -->
<packageSource key="NuGet">
<package pattern="*" />
</packageSource>
<packageSource key="dotnet8">
<package pattern="Microsoft.CodeAnalysis.PublicApiAnalyzers" />
</packageSource>
</packageSourceMapping>
<disabledPackageSources />

View File

@ -1,18 +1,19 @@
<Project>
<PropertyGroup>
<RepoRoot>$([System.IO.Directory]::GetParent($(MSBuildThisFileDirectory)).Parent.FullName)</RepoRoot>
</PropertyGroup>
<ItemGroup>
<SolutionProjects Include="$(RepoRoot)\**\*.csproj" />
<PackProjects Include="$(RepoRoot)\src\**\*.csproj" />
<TestProjects Include="$(RepoRoot)\test\**\*.csproj" />
<SolutionProjects Include="**\*.csproj" />
<PackProjects Include="src\**\*.csproj" />
<TestProjects Include="test\**\*.csproj" />
<!-- Not pack SemanticConventions project for now -->
<PackProjects Remove="src\OpenTelemetry.SemanticConventions\OpenTelemetry.SemanticConventions.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(RunningDotNetPack)' == 'true'">
<!-- Skip building these projects when publish packages workflow runs -->
<SolutionProjects Remove="$(RepoRoot)\docs\**\*.csproj" />
<SolutionProjects Remove="$(RepoRoot)\examples\**\*.csproj" />
<!-- Skip building these projects when publish packages workflow runs as
these projects need to depend upon instrumentation libraries taking a
project reference instead of package reference on API/SDK -->
<SolutionProjects Remove="docs\**\**\*.csproj" />
<SolutionProjects Remove="examples\**\*.csproj" />
<SolutionProjects Remove="@(TestProjects)" />
</ItemGroup>

View File

@ -12,12 +12,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.dockerignore = .dockerignore
.editorconfig = .editorconfig
.gitignore = .gitignore
.github\workflows\ci-concurrency.yml = .github\workflows\ci-concurrency.yml
CONTRIBUTING.md = CONTRIBUTING.md
global.json = global.json
LICENSE.TXT = LICENSE.TXT
NuGet.config = NuGet.config
OpenTelemetry.proj = OpenTelemetry.proj
README.md = README.md
RELEASENOTES.md = RELEASENOTES.md
THIRD-PARTY-NOTICES.TXT = THIRD-PARTY-NOTICES.TXT
VERSIONING.md = VERSIONING.md
EndProjectSection
@ -27,21 +28,23 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{7CB2F02E
build\Common.nonprod.props = build\Common.nonprod.props
build\Common.prod.props = build\Common.prod.props
build\Common.props = build\Common.props
build\Common.targets = build\Common.targets
build\debug.snk = build\debug.snk
Directory.Packages.props = Directory.Packages.props
build\docfx.cmd = build\docfx.cmd
build\docker-compose.net6.0.yml = build\docker-compose.net6.0.yml
build\docker-compose.net7.0.yml = build\docker-compose.net7.0.yml
build\docker-compose.net8.0.yml = build\docker-compose.net8.0.yml
build\docker-compose.net9.0.yml = build\docker-compose.net9.0.yml
build\finalize-publicapi.ps1 = build\finalize-publicapi.ps1
build\GlobalAttrExclusions.txt = build\GlobalAttrExclusions.txt
build\opentelemetry-icon-color.png = build\opentelemetry-icon-color.png
build\OpenTelemetry.prod.loose.ruleset = build\OpenTelemetry.prod.loose.ruleset
build\OpenTelemetry.prod.ruleset = build\OpenTelemetry.prod.ruleset
build\OpenTelemetry.proj = build\OpenTelemetry.proj
build\OpenTelemetry.test.ruleset = build\OpenTelemetry.test.ruleset
build\process-codecoverage.ps1 = build\process-codecoverage.ps1
build\RELEASING.md = build\RELEASING.md
build\stylecop.json = build\stylecop.json
build\UnstableCoreLibraries.proj = build\UnstableCoreLibraries.proj
build\test-aot-compatibility.ps1 = build\test-aot-compatibility.ps1
build\test-threadSafety.ps1 = build\test-threadSafety.ps1
build\xunit.runner.json = build\xunit.runner.json
EndProjectSection
EndProject
@ -49,6 +52,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Zipk
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Api", "src\OpenTelemetry.Api\OpenTelemetry.Api.csproj", "{99F8A331-05E9-45A5-89BA-4C54E825E5B2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.AspNetCore", "src\OpenTelemetry.Instrumentation.AspNetCore\OpenTelemetry.Instrumentation.AspNetCore.csproj", "{752D2182-A351-41D8-99EE-DD363D7D5B43}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.AspNetCore.Tests", "test\OpenTelemetry.Instrumentation.AspNetCore.Tests\OpenTelemetry.Instrumentation.AspNetCore.Tests.csproj", "{2A47F6A8-63E5-4237-8046-94CAF321E797}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testdata", "testdata", "{77C7929A-2EED-4AA6-8705-B5C443C8AA0F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{E359BB2B-9AEC-497D-B321-7DF2450C3B8E}"
@ -73,20 +80,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{F1D0
ProjectSection(SolutionItems) = preProject
.github\codecov.yml = .github\codecov.yml
.github\CODEOWNERS = .github\CODEOWNERS
.github\dependabot.yml = .github\dependabot.yml
.github\PULL_REQUEST_TEMPLATE.md = .github\PULL_REQUEST_TEMPLATE.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ISSUE_TEMPLATE", "ISSUE_TEMPLATE", "{A533C800-3DC3-4D04-90A7-0CE7A1E6BDB3}"
ProjectSection(SolutionItems) = preProject
.github\ISSUE_TEMPLATE\bug_report.yml = .github\ISSUE_TEMPLATE\bug_report.yml
.github\ISSUE_TEMPLATE\feature_request.yml = .github\ISSUE_TEMPLATE\feature_request.yml
.github\ISSUE_TEMPLATE\bug_report.md = .github\ISSUE_TEMPLATE\bug_report.md
.github\ISSUE_TEMPLATE\feature_request.md = .github\ISSUE_TEMPLATE\feature_request.md
.github\ISSUE_TEMPLATE\question.md = .github\ISSUE_TEMPLATE\question.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{E69578EB-B456-4062-A645-877CD964528B}"
ProjectSection(SolutionItems) = preProject
.github\workflows\add-labels.yml = .github\workflows\add-labels.yml
.github\workflows\automation.yml = .github\workflows\automation.yml
.github\workflows\ci.yml = .github\workflows\ci.yml
.github\workflows\codeql-analysis.yml = .github\workflows\codeql-analysis.yml
.github\workflows\Component.BuildTest.yml = .github\workflows\Component.BuildTest.yml
@ -95,8 +100,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
.github\workflows\dotnet-format.yml = .github\workflows\dotnet-format.yml
.github\workflows\markdownlint.yml = .github\workflows\markdownlint.yml
.github\workflows\package-validation.yml = .github\workflows\package-validation.yml
.github\workflows\post-release.yml = .github\workflows\post-release.yml
.github\workflows\prepare-release.yml = .github\workflows\prepare-release.yml
.github\workflows\publish-packages-1.0.yml = .github\workflows\publish-packages-1.0.yml
.github\workflows\sanitycheck.yml = .github\workflows\sanitycheck.yml
.github\workflows\stale.yml = .github\workflows\stale.yml
@ -113,29 +116,36 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{D2E73927-5
ProjectSection(SolutionItems) = preProject
test\Directory.Build.props = test\Directory.Build.props
test\Directory.Build.targets = test\Directory.Build.targets
test\Directory.Packages.props = test\Directory.Packages.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.Grpc.Tests", "test\OpenTelemetry.Instrumentation.Grpc.Tests\OpenTelemetry.Instrumentation.Grpc.Tests.csproj", "{305E9DFD-E73B-4A28-8769-795C25551020}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples.Console", "examples\Console\Examples.Console.csproj", "{FF3E6E08-E8E4-4523-B526-847CD989279F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples.AspNetCore", "examples\AspNetCore\Examples.AspNetCore.csproj", "{0935622B-9377-4056-8343-AE6ECDC274CF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "test\Benchmarks\Benchmarks.csproj", "{DE9130A4-F30A-49D7-8834-41DE3021218B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.SqlClient.Tests", "test\OpenTelemetry.Instrumentation.SqlClient.Tests\OpenTelemetry.Instrumentation.SqlClient.Tests.csproj", "{0C606039-BE0A-4EE6-B8F7-F75B41E52CB8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.SqlClient", "src\OpenTelemetry.Instrumentation.SqlClient\OpenTelemetry.Instrumentation.SqlClient.csproj", "{41C30DC1-8C57-4E14-A83A-7635A3C7960B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.Http.Tests", "test\OpenTelemetry.Instrumentation.Http.Tests\OpenTelemetry.Instrumentation.Http.Tests.csproj", "{DE9EB7D8-9CC5-4073-90B3-9FBF685B3305}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.Http", "src\OpenTelemetry.Instrumentation.Http\OpenTelemetry.Instrumentation.Http.csproj", "{412C64D1-43D6-4E4C-8AD8-E20E63B415BD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.GrpcNetClient", "src\OpenTelemetry.Instrumentation.GrpcNetClient\OpenTelemetry.Instrumentation.GrpcNetClient.csproj", "{0246BFC4-8AAF-45E1-A127-DB43D6E345BB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{7C87CAF9-79D7-4C26-9FFB-F3F1FB6911F1}"
ProjectSection(SolutionItems) = preProject
docs\README.md = docs\README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{2C7DD1DA-C229-4D9E-9AF0-BCD5CD3E4948}"
ProjectSection(SolutionItems) = preProject
examples\Directory.Build.props = examples\Directory.Build.props
examples\Directory.Build.targets = examples\Directory.Build.targets
examples\Directory.Packages.props = examples\Directory.Packages.props
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "trace", "trace", "{5B7FB835-3FFF-4BC2-99C5-A5B5FAE3C818}"
ProjectSection(SolutionItems) = preProject
docs\trace\README.md = docs\trace\README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "metrics", "metrics", "{3277B1C0-BDFE-4460-9B0D-D9A661FB48DB}"
ProjectSection(SolutionItems) = preProject
@ -200,6 +210,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Tests.Stress"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "getting-started-prometheus-grafana", "docs\metrics\getting-started-prometheus-grafana\getting-started-prometheus-grafana.csproj", "{41B784AA-3301-4126-AF9F-1D59BD04B0BF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.SemanticConventions", "src\OpenTelemetry.SemanticConventions\OpenTelemetry.SemanticConventions.csproj", "{D4519DF6-CC72-4AC4-A851-E21383098D11}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "customizing-the-sdk", "docs\logs\customizing-the-sdk\customizing-the-sdk.csproj", "{6C7A1595-36D6-4229-BBB5-5A6B5791791D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.Propagators", "src\OpenTelemetry.Extensions.Propagators\OpenTelemetry.Extensions.Propagators.csproj", "{E91B2E40-E428-43B3-8A43-09709F0E69E4}"
@ -249,18 +261,31 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A49299FB-C5CD-4E0E-B7E1-B7867BBD67CC}"
ProjectSection(SolutionItems) = preProject
src\Shared\ActivityHelperExtensions.cs = src\Shared\ActivityHelperExtensions.cs
src\Shared\AssemblyVersionExtensions.cs = src\Shared\AssemblyVersionExtensions.cs
src\Shared\ActivityInstrumentationHelper.cs = src\Shared\ActivityInstrumentationHelper.cs
src\Shared\DiagnosticDefinitions.cs = src\Shared\DiagnosticDefinitions.cs
src\Shared\ExceptionExtensions.cs = src\Shared\ExceptionExtensions.cs
src\Shared\Guard.cs = src\Shared\Guard.cs
src\Shared\MathHelper.cs = src\Shared\MathHelper.cs
src\Shared\PeerServiceResolver.cs = src\Shared\PeerServiceResolver.cs
src\Shared\PeriodicExportingMetricReaderHelper.cs = src\Shared\PeriodicExportingMetricReaderHelper.cs
src\Shared\PooledList.cs = src\Shared\PooledList.cs
src\Shared\RequestMethodHelper.cs = src\Shared\RequestMethodHelper.cs
src\Shared\ResourceSemanticConventions.cs = src\Shared\ResourceSemanticConventions.cs
src\Shared\SemanticConventions.cs = src\Shared\SemanticConventions.cs
src\Shared\SpanAttributeConstants.cs = src\Shared\SpanAttributeConstants.cs
src\Shared\SpanHelper.cs = src\Shared\SpanHelper.cs
src\Shared\StatusHelper.cs = src\Shared\StatusHelper.cs
src\Shared\ThreadSafeRandom.cs = src\Shared\ThreadSafeRandom.cs
src\Shared\TagAndValueTransformer.cs = src\Shared\TagAndValueTransformer.cs
src\Shared\TagTransformer.cs = src\Shared\TagTransformer.cs
src\Shared\TagTransformerJsonHelper.cs = src\Shared\TagTransformerJsonHelper.cs
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DiagnosticSourceInstrumentation", "DiagnosticSourceInstrumentation", "{28F3EC79-660C-4659-8B73-F90DC1173316}"
ProjectSection(SolutionItems) = preProject
src\Shared\DiagnosticSourceInstrumentation\DiagnosticSourceListener.cs = src\Shared\DiagnosticSourceInstrumentation\DiagnosticSourceListener.cs
src\Shared\DiagnosticSourceInstrumentation\DiagnosticSourceSubscriber.cs = src\Shared\DiagnosticSourceInstrumentation\DiagnosticSourceSubscriber.cs
src\Shared\DiagnosticSourceInstrumentation\ListenerHandler.cs = src\Shared\DiagnosticSourceInstrumentation\ListenerHandler.cs
src\Shared\DiagnosticSourceInstrumentation\PropertyFetcher.cs = src\Shared\DiagnosticSourceInstrumentation\PropertyFetcher.cs
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EnvironmentVariables", "EnvironmentVariables", "{6D4B4FB2-0A8A-4044-948B-C063FD340439}"
@ -272,16 +297,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EnvironmentVariables", "Env
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Options", "Options", "{494902DD-C63F-48E0-BED3-B58EFB4051C8}"
ProjectSection(SolutionItems) = preProject
src\Shared\Options\ConfigurationExtensions.cs = src\Shared\Options\ConfigurationExtensions.cs
src\Shared\Options\DelegatingOptionsFactory.cs = src\Shared\Options\DelegatingOptionsFactory.cs
src\Shared\Options\DelegatingOptionsFactoryServiceCollectionExtensions.cs = src\Shared\Options\DelegatingOptionsFactoryServiceCollectionExtensions.cs
src\Shared\Options\SingletonOptionsManager.cs = src\Shared\Options\SingletonOptionsManager.cs
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shims", "Shims", "{A0CB9A10-F22D-4E66-A449-74B3D0361A9C}"
ProjectSection(SolutionItems) = preProject
src\Shared\Shims\IsExternalInit.cs = src\Shared\Shims\IsExternalInit.cs
src\Shared\Shims\Lock.cs = src\Shared\Shims\Lock.cs
src\Shared\Shims\NullableAttributes.cs = src\Shared\Shims\NullableAttributes.cs
src\Shared\Shims\UnconditionalSuppressMessageAttribute.cs = src\Shared\Shims\UnconditionalSuppressMessageAttribute.cs
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Api.Tests", "test\OpenTelemetry.Api.Tests\OpenTelemetry.Api.Tests.csproj", "{777C04B8-1BD5-43D7-B3CD-D2189DFABCF3}"
@ -304,7 +328,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "experimental-apis", "experi
ProjectSection(SolutionItems) = preProject
docs\diagnostics\experimental-apis\OTEL1000.md = docs\diagnostics\experimental-apis\OTEL1000.md
docs\diagnostics\experimental-apis\OTEL1001.md = docs\diagnostics\experimental-apis\OTEL1001.md
docs\diagnostics\experimental-apis\OTEL1004.md = docs\diagnostics\experimental-apis\OTEL1004.md
docs\diagnostics\experimental-apis\OTEL1002.md = docs\diagnostics\experimental-apis\OTEL1002.md
docs\diagnostics\experimental-apis\OTEL1003.md = docs\diagnostics\experimental-apis\OTEL1003.md
docs\diagnostics\experimental-apis\README.md = docs\diagnostics\experimental-apis\README.md
EndProjectSection
EndProject
@ -317,38 +342,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "extending-the-sdk", "docs\r
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dedicated-pipeline", "docs\logs\dedicated-pipeline\dedicated-pipeline.csproj", "{19545B37-8518-4BDD-AD49-00C031FB3C2A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Configuration", "Configuration", "{87A20A76-D524-4AAC-AF92-8725BFED0415}"
ProjectSection(SolutionItems) = preProject
src\Shared\Configuration\IConfigurationExtensionsLogger.cs = src\Shared\Configuration\IConfigurationExtensionsLogger.cs
src\Shared\Configuration\OpenTelemetryConfigurationExtensions.cs = src\Shared\Configuration\OpenTelemetryConfigurationExtensions.cs
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TagWriter", "TagWriter", "{993E65E5-E71B-40FD-871C-60A9EBD59724}"
ProjectSection(SolutionItems) = preProject
src\Shared\TagWriter\ArrayTagWriter.cs = src\Shared\TagWriter\ArrayTagWriter.cs
src\Shared\TagWriter\JsonStringArrayTagWriter.cs = src\Shared\TagWriter\JsonStringArrayTagWriter.cs
src\Shared\TagWriter\TagWriter.cs = src\Shared\TagWriter\TagWriter.cs
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{44982E0D-C8C6-42DC-9F8F-714981F27CE6}"
ProjectSection(SolutionItems) = preProject
build\scripts\add-labels.psm1 = build\scripts\add-labels.psm1
build\scripts\finalize-publicapi.ps1 = build\scripts\finalize-publicapi.ps1
build\scripts\post-release.psm1 = build\scripts\post-release.psm1
build\scripts\prepare-release.psm1 = build\scripts\prepare-release.psm1
build\scripts\sanitycheck.py = build\scripts\sanitycheck.py
build\scripts\test-aot-compatibility.ps1 = build\scripts\test-aot-compatibility.ps1
build\scripts\test-threadSafety.ps1 = build\scripts\test-threadSafety.ps1
build\scripts\update-changelogs.ps1 = build\scripts\update-changelogs.ps1
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "exemplars", "docs\metrics\exemplars\exemplars.csproj", "{79C12C80-B27B-41FB-AE79-A3BB74CFA782}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Proto", "Proto", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
ProjectSection(SolutionItems) = preProject
src\Shared\Proto\README.md = src\Shared\Proto\README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -371,6 +364,14 @@ Global
{99F8A331-05E9-45A5-89BA-4C54E825E5B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{99F8A331-05E9-45A5-89BA-4C54E825E5B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{99F8A331-05E9-45A5-89BA-4C54E825E5B2}.Release|Any CPU.Build.0 = Release|Any CPU
{752D2182-A351-41D8-99EE-DD363D7D5B43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{752D2182-A351-41D8-99EE-DD363D7D5B43}.Debug|Any CPU.Build.0 = Debug|Any CPU
{752D2182-A351-41D8-99EE-DD363D7D5B43}.Release|Any CPU.ActiveCfg = Release|Any CPU
{752D2182-A351-41D8-99EE-DD363D7D5B43}.Release|Any CPU.Build.0 = Release|Any CPU
{2A47F6A8-63E5-4237-8046-94CAF321E797}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2A47F6A8-63E5-4237-8046-94CAF321E797}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A47F6A8-63E5-4237-8046-94CAF321E797}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A47F6A8-63E5-4237-8046-94CAF321E797}.Release|Any CPU.Build.0 = Release|Any CPU
{AAC408FE-40EF-4479-97D9-697F2C1A0B28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AAC408FE-40EF-4479-97D9-697F2C1A0B28}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AAC408FE-40EF-4479-97D9-697F2C1A0B28}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -403,6 +404,10 @@ Global
{7C4026CA-6434-4762-8B77-D657EAEE1325}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C4026CA-6434-4762-8B77-D657EAEE1325}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7C4026CA-6434-4762-8B77-D657EAEE1325}.Release|Any CPU.Build.0 = Release|Any CPU
{305E9DFD-E73B-4A28-8769-795C25551020}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{305E9DFD-E73B-4A28-8769-795C25551020}.Debug|Any CPU.Build.0 = Debug|Any CPU
{305E9DFD-E73B-4A28-8769-795C25551020}.Release|Any CPU.ActiveCfg = Release|Any CPU
{305E9DFD-E73B-4A28-8769-795C25551020}.Release|Any CPU.Build.0 = Release|Any CPU
{FF3E6E08-E8E4-4523-B526-847CD989279F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FF3E6E08-E8E4-4523-B526-847CD989279F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF3E6E08-E8E4-4523-B526-847CD989279F}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -415,6 +420,26 @@ Global
{DE9130A4-F30A-49D7-8834-41DE3021218B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE9130A4-F30A-49D7-8834-41DE3021218B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE9130A4-F30A-49D7-8834-41DE3021218B}.Release|Any CPU.Build.0 = Release|Any CPU
{0C606039-BE0A-4EE6-B8F7-F75B41E52CB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0C606039-BE0A-4EE6-B8F7-F75B41E52CB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0C606039-BE0A-4EE6-B8F7-F75B41E52CB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0C606039-BE0A-4EE6-B8F7-F75B41E52CB8}.Release|Any CPU.Build.0 = Release|Any CPU
{41C30DC1-8C57-4E14-A83A-7635A3C7960B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{41C30DC1-8C57-4E14-A83A-7635A3C7960B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{41C30DC1-8C57-4E14-A83A-7635A3C7960B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{41C30DC1-8C57-4E14-A83A-7635A3C7960B}.Release|Any CPU.Build.0 = Release|Any CPU
{DE9EB7D8-9CC5-4073-90B3-9FBF685B3305}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE9EB7D8-9CC5-4073-90B3-9FBF685B3305}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE9EB7D8-9CC5-4073-90B3-9FBF685B3305}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE9EB7D8-9CC5-4073-90B3-9FBF685B3305}.Release|Any CPU.Build.0 = Release|Any CPU
{412C64D1-43D6-4E4C-8AD8-E20E63B415BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{412C64D1-43D6-4E4C-8AD8-E20E63B415BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{412C64D1-43D6-4E4C-8AD8-E20E63B415BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{412C64D1-43D6-4E4C-8AD8-E20E63B415BD}.Release|Any CPU.Build.0 = Release|Any CPU
{0246BFC4-8AAF-45E1-A127-DB43D6E345BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0246BFC4-8AAF-45E1-A127-DB43D6E345BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0246BFC4-8AAF-45E1-A127-DB43D6E345BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0246BFC4-8AAF-45E1-A127-DB43D6E345BB}.Release|Any CPU.Build.0 = Release|Any CPU
{07336602-860B-4975-95DD-405D19C00901}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{07336602-860B-4975-95DD-405D19C00901}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07336602-860B-4975-95DD-405D19C00901}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -491,6 +516,10 @@ Global
{41B784AA-3301-4126-AF9F-1D59BD04B0BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{41B784AA-3301-4126-AF9F-1D59BD04B0BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{41B784AA-3301-4126-AF9F-1D59BD04B0BF}.Release|Any CPU.Build.0 = Release|Any CPU
{D4519DF6-CC72-4AC4-A851-E21383098D11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D4519DF6-CC72-4AC4-A851-E21383098D11}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4519DF6-CC72-4AC4-A851-E21383098D11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4519DF6-CC72-4AC4-A851-E21383098D11}.Release|Any CPU.Build.0 = Release|Any CPU
{6C7A1595-36D6-4229-BBB5-5A6B5791791D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6C7A1595-36D6-4229-BBB5-5A6B5791791D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6C7A1595-36D6-4229-BBB5-5A6B5791791D}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -603,10 +632,6 @@ Global
{19545B37-8518-4BDD-AD49-00C031FB3C2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19545B37-8518-4BDD-AD49-00C031FB3C2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19545B37-8518-4BDD-AD49-00C031FB3C2A}.Release|Any CPU.Build.0 = Release|Any CPU
{79C12C80-B27B-41FB-AE79-A3BB74CFA782}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{79C12C80-B27B-41FB-AE79-A3BB74CFA782}.Debug|Any CPU.Build.0 = Debug|Any CPU
{79C12C80-B27B-41FB-AE79-A3BB74CFA782}.Release|Any CPU.ActiveCfg = Release|Any CPU
{79C12C80-B27B-41FB-AE79-A3BB74CFA782}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -650,6 +675,7 @@ Global
{800DB925-6014-4136-AC01-3356CF7CADD3} = {5B7FB835-3FFF-4BC2-99C5-A5B5FAE3C818}
{9C99621C-343E-479C-A943-332DB6129B71} = {5B7FB835-3FFF-4BC2-99C5-A5B5FAE3C818}
{62AF4BD3-DCAE-4D44-AA5B-991C1071166B} = {5B7FB835-3FFF-4BC2-99C5-A5B5FAE3C818}
{28F3EC79-660C-4659-8B73-F90DC1173316} = {A49299FB-C5CD-4E0E-B7E1-B7867BBD67CC}
{6D4B4FB2-0A8A-4044-948B-C063FD340439} = {A49299FB-C5CD-4E0E-B7E1-B7867BBD67CC}
{494902DD-C63F-48E0-BED3-B58EFB4051C8} = {A49299FB-C5CD-4E0E-B7E1-B7867BBD67CC}
{A0CB9A10-F22D-4E66-A449-74B3D0361A9C} = {A49299FB-C5CD-4E0E-B7E1-B7867BBD67CC}
@ -661,11 +687,6 @@ Global
{A115CE4C-71A8-4B95-96A5-C1DF46FD94C2} = {7C87CAF9-79D7-4C26-9FFB-F3F1FB6911F1}
{7BE494FC-4B0D-4340-A62A-9C9F3E7389FE} = {A115CE4C-71A8-4B95-96A5-C1DF46FD94C2}
{19545B37-8518-4BDD-AD49-00C031FB3C2A} = {3862190B-E2C5-418E-AFDC-DB281FB5C705}
{87A20A76-D524-4AAC-AF92-8725BFED0415} = {A49299FB-C5CD-4E0E-B7E1-B7867BBD67CC}
{993E65E5-E71B-40FD-871C-60A9EBD59724} = {A49299FB-C5CD-4E0E-B7E1-B7867BBD67CC}
{44982E0D-C8C6-42DC-9F8F-714981F27CE6} = {7CB2F02E-03FA-4FFF-89A5-C51F107623FD}
{79C12C80-B27B-41FB-AE79-A3BB74CFA782} = {3277B1C0-BDFE-4460-9B0D-D9A661FB48DB}
{02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {A49299FB-C5CD-4E0E-B7E1-B7867BBD67CC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521}

273
README.md
View File

@ -6,32 +6,9 @@
[![NuGet](https://img.shields.io/nuget/dt/OpenTelemetry.svg)](https://www.nuget.org/profiles/OpenTelemetry)
[![Build](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/ci.yml)
[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/open-telemetry/opentelemetry-dotnet/badge)](https://scorecard.dev/viewer/?uri=github.com/open-telemetry/opentelemetry-dotnet)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/10017/badge)](https://www.bestpractices.dev/projects/10017)
[![FOSSA License Status](https://app.fossa.com/api/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-dotnet.svg?type=shield&issueType=license)](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-dotnet?ref=badge_shield&issueType=license)
[![FOSSA Security Status](https://app.fossa.com/api/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-dotnet.svg?type=shield&issueType=security)](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-dotnet?ref=badge_shield&issueType=security)
The .NET [OpenTelemetry](https://opentelemetry.io/) client.
The .NET [OpenTelemetry](https://opentelemetry.io/) implementation.
<details>
<summary>Table of Contents</summary>
* [Supported .NET versions](#supported-net-versions)
* [Project status](#project-status)
* [Getting started](#getting-started)
* [Getting started with Logging](#getting-started-with-logging)
* [Getting started with Metrics](#getting-started-with-metrics)
* [Getting started with Tracing](#getting-started-with-tracing)
* [Repository structure](#repository-structure)
* [Troubleshooting](#troubleshooting)
* [Extensibility](#extensibility)
* [Releases](#releases)
* [Contributing](#contributing)
* [References](#references)
</details>
## Supported .NET versions
## Supported .NET Versions
Packages shipped from this repository generally support all the officially
supported versions of [.NET](https://dotnet.microsoft.com/download/dotnet) and
@ -40,88 +17,50 @@ older Windows-based .NET implementation), except `.NET Framework 3.5`.
Any exceptions to this are noted in the individual `README.md`
files.
## Project status
## Project Status
**Stable** across all 3 signals (`Logs`, `Metrics`, and `Traces`).
**Stable** across all 3 signals i.e. `Logs`, `Metrics`, and `Traces`.
> [!CAUTION]
> Certain components, marked as
[pre-release](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/VERSIONING.md#pre-releases),
are still work in progress and can undergo breaking changes before stable
release. Check the individual `README.md` file for each component to understand its
current state.
See [Spec Compliance
Matrix](https://github.com/open-telemetry/opentelemetry-specification/blob/main/spec-compliance-matrix.md)
to understand which portions of the specification has been implemented in this
repo.
To understand which portions of the [OpenTelemetry
Specification](https://github.com/open-telemetry/opentelemetry-specification)
have been implemented in OpenTelemetry .NET see: [Spec Compliance
Matrix](https://github.com/open-telemetry/opentelemetry-specification/blob/main/spec-compliance-matrix.md).
## Getting started
## Getting Started
If you are new here, please read the getting started docs:
### Getting started with Logging
* [Logs](./docs/logs/README.md): [ASP.NET
Core](./docs/logs/getting-started-aspnetcore/README.md) |
[Console](./docs/logs/getting-started-console/README.md)
* [Metrics](./docs/metrics/README.md): [ASP.NET
Core](./docs/metrics/getting-started-aspnetcore/README.md) |
[Console](./docs/metrics/getting-started-console/README.md)
* [Traces](./docs/trace/README.md): [ASP.NET
Core](./docs/trace/getting-started-aspnetcore/README.md) |
[Console](./docs/trace/getting-started-console/README.md)
If you are new to
[logging](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/README.md),
it is recommended to first follow the [getting started in 5 minutes - ASP.NET
Core Application](./docs/logs/getting-started-aspnetcore/README.md) guide or
the [getting started in 5 minutes - Console
Application](./docs/logs/getting-started-console/README.md) guide to get up
and running.
For general information and best practices see: [OpenTelemetry .NET
Logs](./docs/logs/README.md). For a more detailed explanation of SDK logging
features see: [Customizing OpenTelemetry .NET SDK for
Logs](./docs/logs/customizing-the-sdk/README.md).
### Getting started with Metrics
If you are new to
[metrics](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/README.md),
it is recommended to first follow the [getting started in 5 minutes - ASP.NET
Core Application](./docs/metrics/getting-started-aspnetcore/README.md) guide
or the [getting started in 5 minutes - Console
Application](./docs/metrics/getting-started-console/README.md) guide to get
up and running.
For general information and best practices see: [OpenTelemetry .NET
Metrics](./docs/metrics/README.md). For a more detailed explanation of SDK
metric features see: [Customizing OpenTelemetry .NET SDK for
Metrics](./docs/metrics/customizing-the-sdk/README.md).
### Getting started with Tracing
If you are new to
[traces](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/README.md),
it is recommended to first follow the [getting started in 5 minutes - ASP.NET
Core Application](./docs/trace/getting-started-aspnetcore/README.md) guide
or the [getting started in 5 minutes - Console
Application](./docs/trace/getting-started-console/README.md) guide to get up
and running.
For general information and best practices see: [OpenTelemetry .NET
Traces](./docs/trace/README.md). For a more detailed explanation of SDK tracing
features see: [Customizing OpenTelemetry .NET SDK for
Tracing](./docs/trace/customizing-the-sdk/README.md).
## Repository structure
This repository includes only what is defined in the [OpenTelemetry
Specification](https://github.com/open-telemetry/opentelemetry-specification)
and is shipped as separate packages through
[NuGet](https://www.nuget.org/profiles/OpenTelemetry). Each component has an
individual `README.md` and `CHANGELOG.md` file which covers the instructions on
how to install and get started, and details about the individual changes made
(respectively). To find all the available components, please take a look at the
`src` folder.
This repository includes multiple installable components, available on
[NuGet](https://www.nuget.org/profiles/OpenTelemetry). Each component has its
individual `README.md` file, which covers the instruction on how to install and
how to get started. To find all the available components, please take a look at
the `src` folder.
Here are the most commonly used components:
* [OpenTelemetry API](./src/OpenTelemetry.Api/README.md)
* [OpenTelemetry SDK](./src/OpenTelemetry/README.md)
* [OpenTelemetry Hosting
Extensions](./src/OpenTelemetry.Extensions.Hosting/README.md)
* [OpenTelemetry .NET API](./src/OpenTelemetry.Api/README.md)
* [OpenTelemetry .NET SDK](./src/OpenTelemetry/README.md)
Here are the [instrumentation
libraries](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/glossary.md#instrumentation-library):
* [ASP.NET Core](./src/OpenTelemetry.Instrumentation.AspNetCore/README.md)
* gRPC client:
[Grpc.Net.Client](./src/OpenTelemetry.Instrumentation.GrpcNetClient/README.md)
* HTTP clients: [System.Net.Http.HttpClient and
System.Net.HttpWebRequest](./src/OpenTelemetry.Instrumentation.Http/README.md)
* SQL clients: [Microsoft.Data.SqlClient and
System.Data.SqlClient](./src/OpenTelemetry.Instrumentation.SqlClient/README.md)
Here are the [exporter
libraries](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/glossary.md#exporter-library):
@ -134,19 +73,15 @@ libraries](https://github.com/open-telemetry/opentelemetry-specification/blob/ma
* [Prometheus HttpListener](./src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md)
* [Zipkin](./src/OpenTelemetry.Exporter.Zipkin/README.md)
Additional packages including [instrumentation
libraries](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/glossary.md#instrumentation-library),
exporters, resource detectors, and extensions can be found in the
[opentelemetry-dotnet-contrib
repository](https://github.com/open-telemetry/opentelemetry-dotnet-contrib)
and/or the [OpenTelemetry
registry](https://opentelemetry.io/ecosystem/registry/?language=dotnet).
See the [OpenTelemetry registry](https://opentelemetry.io/registry/?s=net) and
[OpenTelemetry .NET Contrib
repo](https://github.com/open-telemetry/opentelemetry-dotnet-contrib) for more
components.
## Troubleshooting
For general instructions see:
[Troubleshooting](./src/OpenTelemetry/README.md#troubleshooting). Additionally
`README.md` files for individual components may contain more detailed
See [Troubleshooting](./src/OpenTelemetry/README.md#troubleshooting).
Additionally check readme file for the individual components for any additional
troubleshooting information.
## Extensibility
@ -158,7 +93,7 @@ extension scenarios:
library](./docs/trace/extending-the-sdk/README.md#instrumentation-library).
* Building a custom exporter for
[logs](./docs/logs/extending-the-sdk/README.md#exporter),
[metrics](./docs/metrics/extending-the-sdk/README.md#exporter), and
[metrics](./docs/metrics/extending-the-sdk/README.md#exporter) and
[traces](./docs/trace/extending-the-sdk/README.md#exporter).
* Building a custom processor for
[logs](./docs/logs/extending-the-sdk/README.md#processor) and
@ -166,64 +101,14 @@ extension scenarios:
* Building a custom sampler for
[traces](./docs/trace/extending-the-sdk/README.md#sampler).
## Releases
For details about upcoming planned releases see:
[Milestones](https://github.com/open-telemetry/opentelemetry-dotnet/milestones).
The dates and features described in issues and milestones are estimates and
subject to change.
For highlights and annoucements for stable releases see: [Release
Notes](./RELEASENOTES.md).
To access packages, source code, and/or view a list of changes for all
components in a release see:
[Releases](https://github.com/open-telemetry/opentelemetry-dotnet/releases).
Nightly builds from this repo are published to [MyGet](https://www.myget.org),
and can be installed using the
`https://www.myget.org/F/opentelemetry/api/v3/index.json` source.
### Digital signing
Starting with the `1.10.0` release the DLLs included in the packages pushed to
NuGet are digitally signed using [Sigstore](https://www.sigstore.dev/). Within
each NuGet package the digital signature and its corresponding certificate file
are placed alongside the shipped DLL(s) in the `/lib` folder. When a project
targets multiple frameworks each target outputs a dedicated DLL and signing
artifacts into a sub folder based on the
[TFM](https://learn.microsoft.com/dotnet/standard/frameworks).
The digitial signature and certificate files share the same name prefix as the
DLL to ensure easy identification and association.
To verify the integrity of a DLL inside a NuGet package use the
[cosign](https://github.com/sigstore/cosign) tool from Sigstore:
```bash
cosign verify-blob \
--signature OpenTelemetry.dll-keyless.sig \
--certificate OpenTelemetry.dll-keyless.pem.cer \
--certificate-identity "https://github.com/open-telemetry/opentelemetry-dotnet/.github/workflows/publish-packages-1.0.yml@refs/tags/core-1.10.0-rc.1" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
OpenTelemetry.dll
```
> [!NOTE]
> A successful verification outputs `Verify OK`.
For more verification options please refer to the [cosign
documentation](https://github.com/sigstore/cosign/blob/main/doc/cosign_verify-blob.md).
## Contributing
For information about contributing to the project see:
[CONTRIBUTING.md](CONTRIBUTING.md).
See [CONTRIBUTING.md](CONTRIBUTING.md)
We meet weekly on Tuesdays, and the time of the meeting alternates between 9AM
PT and 4PM PT. The meeting is subject to change depending on contributors'
availability. Check the [OpenTelemetry community
calendar](https://github.com/open-telemetry/community?tab=readme-ov-file#calendar)
calendar](https://calendar.google.com/calendar/embed?src=google.com_b79e3e90j7bbsa2n2p5an5lf60%40group.calendar.google.com)
for specific dates and for Zoom meeting links.
Meeting notes are available as a public [Google
@ -236,60 +121,58 @@ regardless of your experience level. Whether you're a seasoned OpenTelemetry
developer, just starting your journey, or simply curious about the work we do,
you're more than welcome to participate!
### Maintainers
[Maintainers](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer)
([@open-telemetry/dotnet-maintainers](https://github.com/orgs/open-telemetry/teams/dotnet-maintainers)):
* [Alan West](https://github.com/alanwest), New Relic
* [Rajkumar Rangaraj](https://github.com/rajkumar-rangaraj), Microsoft
* [Mikel Blanchard](https://github.com/CodeBlanch), Microsoft
* [Utkarsh Umesan Pillai](https://github.com/utpilla), Microsoft
For more information about the maintainer role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#maintainer).
### Approvers
[Approvers](https://github.com/open-telemetry/community/blob/main/community-membership.md#approver)
([@open-telemetry/dotnet-approvers](https://github.com/orgs/open-telemetry/teams/dotnet-approvers)):
* [Cijo Thomas](https://github.com/cijothomas), Microsoft
* [Martin Costello](https://github.com/martincostello), Grafana Labs
* [Mikel Blanchard](https://github.com/CodeBlanch), Microsoft
* [Piotr Kie&#x142;kowicz](https://github.com/Kielek), Splunk
* [Reiley Yang](https://github.com/reyang), Microsoft
* [Vishwesh Bankwar](https://github.com/vishweshbankwar), Microsoft
For more information about the approver role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver).
### Triagers
[Triagers](https://github.com/open-telemetry/community/blob/main/community-membership.md#triager)
([@open-telemetry/dotnet-triagers](https://github.com/orgs/open-telemetry/teams/dotnet-triagers)):
* [Martin Thwaites](https://github.com/martinjt), Honeycomb
* [Timothy "Mothra" Lee](https://github.com/TimothyMothra)
For more information about the triager role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#triager).
### Emeritus Maintainers
* [Mike Goldsmith](https://github.com/MikeGoldsmith)
* [Sergey Kanzhelev](https://github.com/SergeyKanzhelev)
* [Utkarsh Umesan Pillai](https://github.com/utpilla)
For more information about the emeritus role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#emeritus-maintainerapprovertriager).
### Emeritus Approvers
[Emeritus
Maintainer/Approver/Triager](https://github.com/open-telemetry/community/blob/main/community-membership.md#emeritus-maintainerapprovertriager):
* [Bruno Garcia](https://github.com/bruno-garcia)
* [Eddy Nakamura](https://github.com/eddynaka)
* [Liudmila Molkova](https://github.com/lmolkova)
* [Mike Goldsmith](https://github.com/MikeGoldsmith)
* [Paulo Janotti](https://github.com/pjanotti)
* [Reiley Yang](https://github.com/reyang)
* [Robert Paj&#x105;k](https://github.com/pellared)
* [Vishwesh Bankwar](https://github.com/vishweshbankwar)
For more information about the emeritus role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#emeritus-maintainerapprovertriager).
### Emeritus Triagers
* [Sergey Kanzhelev](https://github.com/SergeyKanzhelev)
* [Victor Lu](https://github.com/victlu)
For more information about the emeritus role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#emeritus-maintainerapprovertriager).
### Thanks to all the people who have contributed
[![contributors](https://contributors-img.web.app/image?repo=open-telemetry/opentelemetry-dotnet)](https://github.com/open-telemetry/opentelemetry-dotnet/graphs/contributors)
## References
## Release Schedule
* [OpenTelemetry Project](https://opentelemetry.io/)
* [OpenTelemetry Specification](https://github.com/open-telemetry/opentelemetry-specification)
See the [project
milestones](https://github.com/open-telemetry/opentelemetry-dotnet/milestones)
for details on upcoming releases. The dates and features described in issues and
milestones are estimates, and subject to change.
See the [release
notes](https://github.com/open-telemetry/opentelemetry-dotnet/releases) for
existing releases.
> [!CAUTION]
> Certain components, marked as
[pre-release](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/VERSIONING.md#pre-releases),
are still work in progress and can undergo breaking changes before stable
release. Check the individual `README.md` file for each component to understand its
current state.
Daily builds from this repo are published to MyGet, and can be installed from
[this source](https://www.myget.org/F/opentelemetry/api/v3/index.json).

View File

@ -1,133 +0,0 @@
# Release Notes
This file contains highlights and announcements covering all components.
For more details see `CHANGELOG.md` files maintained in the root source
directory of each individual package.
## 1.12.0
Release details: [1.12.0](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/core-1.12.0)
* **Breaking Change**: `OpenTelemetry.Exporter.OpenTelemetryProtocol` now
defaults to using OTLP/HTTP instead of OTLP/gRPC when targeting .NET Framework
and .NET Standard. This change may cause telemetry export to fail unless
appropriate adjustments are made. Explicitly setting OTLP/gRPC may result in a
`NotSupportedException` unless further configuration is applied. See
[#6209](https://github.com/open-telemetry/opentelemetry-dotnet/issues/6209) for
full details and mitigation guidance. [#6229](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6229)
## 1.11.1
Release details: [1.11.1](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/core-1.11.1)
* Fixed a bug preventing `OpenTelemetry.Exporter.OpenTelemetryProtocol` from
exporting telemetry on .NET Framework.
## 1.11.0
Release details: [1.11.0](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/core-1.11.0)
* `OpenTelemetry.Exporter.OpenTelemetryProtocol` no longer depends on the
`Google.Protobuf`, `Grpc`, or `Grpc.Net.Client` packages. Serialization and
transmission of outgoing data is now performed manually to improve the overall
performance.
## 1.10.0
Release details: [1.10.0](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/core-1.10.0)
* Bumped the package versions of `System.Diagnostic.DiagnosticSource` and other
Microsoft.Extensions.* packages to `9.0.0`.
* Added support for new APIs introduced in `System.Diagnostics.DiagnosticSource`
`9.0.0`:
* [InstrumentAdvice&lt;T&gt;](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics.instrumentadvice-1)
For details see: [Explicit bucket histogram
aggregation](./docs/metrics/customizing-the-sdk/README.md#explicit-bucket-histogram-aggregation).
* [Gauge&lt;T&gt;](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics.gauge-1)
* [ActivitySource.Tags](https://learn.microsoft.com/dotnet/api/system.diagnostics.activitysource.tags)
(supported in OtlpExporter & ConsoleExporter)
* Experimental features promoted to stable:
* `CardinalityLimit` can now be managed for individual metrics via the View
API. For details see: [Changing cardinality limit for a
Metric](./docs/metrics/customizing-the-sdk/README.md#changing-the-cardinality-limit-for-a-metric).
* The [overflow
attribute](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#overflow-attribute)
(`otel.metric.overflow`) behavior is now enabled by default. The
`OTEL_DOTNET_EXPERIMENTAL_METRICS_EMIT_OVERFLOW_ATTRIBUTE` environment
variable is no longer required. For details see: [Cardinality
Limits](./docs/metrics/README.md#cardinality-limits).
* The MetricPoint reclaim behavior is now enabled by default when Delta
aggregation temporality is used. The
`OTEL_DOTNET_EXPERIMENTAL_METRICS_RECLAIM_UNUSED_METRIC_POINTS` environment
variable is no longer required. For details see: [Cardinality
Limits](./docs/metrics/README.md#cardinality-limits).
* Added `OpenTelemetrySdk.Create` API for configuring OpenTelemetry .NET signals
(logging, tracing, and metrics) via a single builder. This new API simplifies
bootstrap and teardown, and supports cross-cutting extensions targeting
`IOpenTelemetryBuilder`.
* Removed out of support `net6.0` target and added `net9.0` target.
## 1.9.0
Release details: [1.9.0](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/core-1.9.0)
* `Exemplars` are now part of the stable API! For details see: [customizing
exemplars
collection](https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/docs/metrics/customizing-the-sdk#exemplars).
* `WithLogging` is now part of the stable API! Logging, Metrics, and Tracing can
now all be configured using the `With` style and the builders finally have
parity in their APIs.
## 1.8.0
Release details: [1.8.0](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/core-1.8.0)
* `TracerProvider` sampler can now be configured via the `OTEL_TRACES_SAMPLER` &
`OTEL_TRACES_SAMPLER_ARG` envvars.
* A new `UseOtlpExporter` cross-cutting extension has been added to register the
`OtlpExporter` and enable all signals in a single call.
* `exception.type`, `exception.message`, `exception.stacktrace` will now
automatically be included by the `OtlpLogExporter` when logging exceptions.
Previously an experimental environment variable had to be set.
## 1.7.0
Release details: [1.7.0](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/core-1.7.0)
* Bumped the package versions of System.Diagnostic.DiagnosticSource and other
Microsoft.Extensions.* packages to `8.0.0`.
* Added `net8.0` targets to all the components.
* OTLP Exporter
* Updated to use `ILogger` `CategoryName` as the instrumentation scope for
logs.
* Added named options support for OTLP Log Exporter.
* Added support for instrumentation scope attributes in metrics.
* Added support under an experimental flag to emit log exception attributes.
* Added support under an experimental flag to emit log eventId and eventName.
attributes.
* Added support for the
[IMetricsBuilder](https://learn.microsoft.com/dotnet/api/microsoft.extensions.diagnostics.metrics.imetricsbuilder)
API.
* Added an experimental opt-in metrics feature to reclaim unused MetricPoints
which enables a higher number of unique dimension combinations to be emitted.
See [reclaim unused metric
points](https://github.com/open-telemetry/opentelemetry-dotnet/blob/32c64d04defb5c92d056fd8817638151168b10da/docs/metrics/README.md#cardinality-limits)
for more details.

View File

@ -29,20 +29,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
License notice for gRPC for .NET (https://github.com/grpc/grpc-dotnet)
----------------------------------------------------------------------------------------------
Copyright 2019 The gRPC Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -56,9 +56,9 @@ without corresponding changes here will result in build breaks - this helps
catch any unintended changes to public API from being shipped accidentally. This
also helps reviewers quickly understand if a given PR is proposing public API
changes. For example,
[this](https://github.com/open-telemetry/opentelemetry-dotnet/tree/master/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/.publicApi)
[this](https://github.com/open-telemetry/opentelemetry-dotnet/tree/master/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi)
shows the public APIs, per target framework for the
`OpenTelemetry.Exporter.OpenTelemetryProtocol` package.
`OpenTelemetry.Instrumentation.AspNetCore` package.
APIs which are released as part of stable packages will be listed in the
"Shipped.txt" file, and those APIs which are released as part of

View File

@ -2,13 +2,13 @@
<Import Project=".\Common.props" />
<PropertyGroup>
<NoWarn>$(NoWarn),CS1574,CS1591</NoWarn>
<NoWarn>$(NoWarn),1574,1591</NoWarn>
<IsPackable>false</IsPackable>
<CodeAnalysisRuleSet>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), 'OpenTelemetry.sln'))\build\OpenTelemetry.test.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup>
<DefaultTargetFrameworkForExampleApps>net9.0</DefaultTargetFrameworkForExampleApps>
<DefaultTargetFrameworkForExampleApps>net8.0</DefaultTargetFrameworkForExampleApps>
</PropertyGroup>
<PropertyGroup Condition="$(MSBuildProjectName.EndsWith('.Tests'))">
@ -21,18 +21,6 @@
</Content>
</ItemGroup>
<ItemGroup Condition="'$(IsTestProject)' == 'true'">
<PackageReference Include="GitHubActionsTestLogger" />
<PackageReference Include="JunitXml.TestLogger" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" PrivateAssets="All" />
</ItemGroup>
<ItemGroup Condition="'$(IsTestProject)' == 'true'">
<Compile Include="$(RepoRoot)\test\Shared\StrongNameTests.cs" Link="StrongNameTests.cs" />
</ItemGroup>
<PropertyGroup>
<!-- Running unit tests from VSCode does not work with .NET SDK 6.0.200 without ProduceReferenceAssemblyInOutDir -->
<!-- Related breaking change: https://docs.microsoft.com/en-us/dotnet/core/compatibility/sdk/6.0/write-reference-assemblies-to-obj -->
@ -56,24 +44,4 @@
<Message Importance="high" Text="Skipping test execution for '$(TargetPath)' because it does not contain the '$(TargetFramework)' target." Condition="'$(_SkipTests)' == 'true'" />
</Target>
<Target Name="ResolveExposedExperimentalFeatures" BeforeTargets="CoreCompile">
<!-- Note: What this does is look for $(ProjectReferenceName).BuildFlags.txt
files for all the dependencies of the project being compiled. If
ExposeExperimentalFeatures=true is found in those files we set compiler
constants for each project where experimental features were exposed.
Example:
OPENTELEMETRY_EXPORTER_INMEMORY_EXPERIMENTAL_FEATURES_EXPOSED;OPENTELEMETRY_EXPERIMENTAL_FEATURES_EXPOSED;OPENTELEMETRY_API_EXPERIMENTAL_FEATURES_EXPOSED;OPENTELEMETRY_API_PROVIDERBUILDEREXTENSIONS_EXPERIMENTAL_FEATURES_EXPOSED
-->
<ItemGroup>
<DependenciesWithExposedExperimentalFeatures
Include="@(_ResolvedProjectReferencePaths->'%(Filename)')"
Condition="$([System.IO.File]::Exists('%(RootDir)%(Directory)%(Filename).BuildFlags.txt')) AND $([System.IO.File]::ReadAllText('%(RootDir)%(Directory)%(Filename).BuildFlags.txt').Contains('ExposeExperimentalFeatures=true'))" />
<CompilerConstantsForDependenciesWithExposedExperimentalFeatures Include="@(DependenciesWithExposedExperimentalFeatures->'$([System.String]::Copy('%(DependenciesWithExposedExperimentalFeatures.Identity)').ToUpper().Replace('.', '_'))_EXPERIMENTAL_FEATURES_EXPOSED')" />
</ItemGroup>
<PropertyGroup Condition="'@(CompilerConstantsForDependenciesWithExposedExperimentalFeatures)' != ''">
<DefineConstants>$(DefineConstants);@(CompilerConstantsForDependenciesWithExposedExperimentalFeatures)</DefineConstants>
</PropertyGroup>
</Target>
</Project>

View File

@ -3,9 +3,6 @@
<PropertyGroup>
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)/OpenTelemetry.prod.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Label="BuildFlags">
<ExposeExperimentalFeatures Condition="'$(ExposeExperimentalFeatures)' == ''">true</ExposeExperimentalFeatures>
<EnablePackageValidation Condition="'$(EnablePackageValidation)' == ''">false</EnablePackageValidation>
</PropertyGroup>
@ -18,15 +15,13 @@
<PackageProjectUrl>https://opentelemetry.io</PackageProjectUrl>
<Authors>OpenTelemetry Authors</Authors>
<Copyright>Copyright The OpenTelemetry Authors</Copyright>
<PackageOutputPath Condition="$(Build_ArtifactStagingDirectory) != ''">$(Build_ArtifactStagingDirectory)</PackageOutputPath>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackagePrimaryLicenseFile>$(RepoRoot)\LICENSE.TXT</PackagePrimaryLicenseFile>
<PackageThirdPartyNoticesFile>$(RepoRoot)\THIRD-PARTY-NOTICES.TXT</PackageThirdPartyNoticesFile>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageChangelogFile>CHANGELOG.md</PackageChangelogFile>
<PackageReleaseNotesFile>$(RepoRoot)\RELEASENOTES.md</PackageReleaseNotesFile>
</PropertyGroup>
<PropertyGroup Label="SourceLinkProperties">
@ -37,34 +32,18 @@
<ItemGroup>
<PackageReference Include="MinVer" PrivateAssets="All" Condition="'$(IntegrationBuild)' != 'true'" />
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Condition="'$(IntegrationBuild)' != 'true'" />
<PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)opentelemetry-icon-color.png" Pack="true" PackagePath="\" />
<SourceRoot Condition="'$(Deterministic)'=='true'" Include="$(MSBuildThisFileDirectory)/" />
<None Include="$(IntermediateOutputPath)$(ProjectName).BuildFlags.txt"
Link="$(ProjectName).BuildFlags.txt"
CopyToOutputDirectory="PreserveNewest"
Visible="false" />
<!-- Note: This includes all the PublicApiAnalyzers files in projects to make editing easier in the IDE -->
<None Include=".publicApi\**\PublicAPI.*.txt" />
</ItemGroup>
<Target Name="IncludeSigningSignaturesInPackages" BeforeTargets="_GetTargetFrameworksOutput">
<!-- Note: This target adds any signatures found to nuget packages -->
<ItemGroup>
<SignatureFiles Include="$(RepoRoot)\src\$(MSBuildProjectName)\bin\$(Configuration)\*\$(MSBuildProjectName).dll-keyless.sig" />
<Content Include="@(SignatureFiles)" Link="%(RecursiveDir)%(Filename)%(Extension)" PackagePath="lib" />
<CertificateFiles Include="$(RepoRoot)\src\$(MSBuildProjectName)\bin\$(Configuration)\*\$(MSBuildProjectName).dll-keyless.pem" />
<Content Include="@(CertificateFiles)" Link="%(RecursiveDir)%(Filename)%(Extension)" PackagePath="lib" />
</ItemGroup>
<Message Importance="high" Text="**IncludeSignaturesInPackagesDebug** SignatureFiles: @(SignatureFiles)" />
<Message Importance="high" Text="**IncludeCertificatesInPackagesDebug** SignatureFiles: @(CertificateFiles)" />
</Target>
<Target Name="AssemblyVersionTarget" AfterTargets="MinVer" Condition="'$(MinVerVersion)' != '' AND '$(BuildNumber)' != ''">
<Target Name="AssemblyVersionTarget" AfterTargets="MinVer" Condition="'$(MinVerVersion)'!='' AND '$(BuildNumber)' != ''">
<!-- Note: $(BuildNumber) is typically only set for builds initiated by the
publish workflow. The goal here is to set the assembly FileVersion and
resolve ExposeExperimentalFeatures based on the version MinVer resolved from
@ -75,10 +54,6 @@
<ExposeExperimentalFeatures Condition="'$(MinVerPreRelease)' == ''">false</ExposeExperimentalFeatures>
</PropertyGroup>
<Error
Condition="'$(MinVerTagPrefix)' == 'coreunstable-' AND ('$(MinVerPreRelease)' == '' OR $(MinVerPreRelease.StartsWith('rc')))"
Text="Unstable core packages cannot be released stable or as release candidates." />
<!-- Note: The '$(TargetFramework)' != '' check here is to reduce log spam
in builds like dotnet pack which fire MinVer but don't resolve the actual
TargetFramework -->
@ -88,72 +63,6 @@
Text="**AssemblyVersionDebug** TargetFramework: $(TargetFramework), MinVerVersion: $(MinVerVersion), BuildNumber: $(BuildNumber), FileVersion: $(FileVersion), ExposeExperimentalFeatures: $(ExposeExperimentalFeatures)" />
</Target>
<Target Name="EnsurePackageValidationBaselineVersion"
BeforeTargets="RunPackageValidation"
Condition="'$(DisablePackageBaselineValidation)' != 'true' AND '$(PackageValidationBaselineVersion)' == '' AND '$(MinVerTagPrefix)' != 'coreunstable-'">
<Error Text="Cannot perform package validation without a baseline package version." />
</Target>
<Target Name="IncludeReadmeAndReleaseNotesInPackages" BeforeTargets="_GetTargetFrameworksOutput">
<!-- Note: This target runs during pack to convert relative links in
markdowns into github permalinks which will work when rendered on Nuget. -->
<Exec
Command="git rev-parse HEAD"
ConsoleToMsBuild="True"
IgnoreExitCode="True"
StandardOutputImportance="low">
<Output PropertyName="GitCommitConsoleOutput" TaskParameter="ConsoleOutput"/>
<Output PropertyName="GitCommitExitCode" TaskParameter="ExitCode"/>
</Exec>
<Exec
Command="git remote get-url origin"
ConsoleToMsBuild="True"
IgnoreExitCode="True"
StandardOutputImportance="low">
<Output PropertyName="GitOriginConsoleOutput" TaskParameter="ConsoleOutput"/>
<Output PropertyName="GitOriginExitCode" TaskParameter="ExitCode"/>
</Exec>
<PropertyGroup>
<MarkdownCommentRegex>\[([^]]+?)\]\(\.(.+?)\)</MarkdownCommentRegex>
<GitHubRepoUrl>$(GitOriginConsoleOutput.Replace('.git',''))</GitHubRepoUrl>
<GitHubPermalinkUrl Condition="'$(PackTag)' != ''">$(GitHubRepoUrl)/blob/$(PackTag)</GitHubPermalinkUrl>
<GitHubPermalinkUrl Condition="'$(PackTag)' == ''">$(GitHubRepoUrl)/blob/$(GitCommitConsoleOutput)</GitHubPermalinkUrl>
</PropertyGroup>
<Message Importance="high" Text="**GitInformationDebug** GitCommitConsoleOutput: $(GitCommitConsoleOutput), GitCommitExitCode: $(GitCommitExitCode), GitOriginConsoleOutput: $(GitOriginConsoleOutput), GitOriginExitCode: $(GitOriginExitCode), GitHubPermalinkUrl: $(GitHubPermalinkUrl)" />
<ItemGroup>
<PackageMarkdownFiles Include="README.md" />
</ItemGroup>
<ItemGroup>
<PackageMarkdownFiles Update="@(PackageMarkdownFiles)" Path="$([MSBuild]::ValueOrDefault('%(FullPath)','').Replace('$(RepoRoot)', '').Replace('%(FileName)%(Extension)', ''))" />
</ItemGroup>
<WriteLinesToFile
File="$(IntermediateOutputPath)%(PackageMarkdownFiles.Filename)%(PackageMarkdownFiles.Extension)"
Lines="$([System.Text.RegularExpressions.Regex]::Replace($([System.IO.File]::ReadAllText(%(PackageMarkdownFiles.FullPath))), '$(MarkdownCommentRegex)', '[$1]($(GitHubPermalinkUrl)%(PackageMarkdownFiles.Path).$2)').Replace('\', '/'))"
Overwrite="true"
Encoding="UTF-8"/>
<PropertyGroup>
<_PackageReleaseNotesFilePath>$([System.IO.Path]::GetFullPath('$(PackageReleaseNotesFile)').Replace('$(RepoRoot)', '').Replace('\', '/'))</_PackageReleaseNotesFilePath>
<_PackageChangelogFilePath>$([System.IO.Path]::GetFullPath('$(PackageChangelogFile)').Replace('$(RepoRoot)', '').Replace('\', '/'))</_PackageChangelogFilePath>
<PackageReleaseNotes>
For highlights and announcements see: $(GitHubPermalinkUrl)$(_PackageReleaseNotesFilePath).
For detailed changes see: $(GitHubPermalinkUrl)$(_PackageChangelogFilePath).
</PackageReleaseNotes>
</PropertyGroup>
<ItemGroup>
<Content Include="$(IntermediateOutputPath)*.md" PackagePath="/" />
</ItemGroup>
</Target>
<Target Name="ResolveExposeExperimentalFeatures" BeforeTargets="CoreCompile" DependsOnTargets="AssemblyVersionTarget">
<!-- Note: This runs for all builds. The goal here is to set the
EXPOSE_EXPERIMENTAL_FEATURES compiler constant if
@ -163,14 +72,9 @@
<DefineConstants>$(DefineConstants);EXPOSE_EXPERIMENTAL_FEATURES</DefineConstants>
</PropertyGroup>
<!-- Note: We write a file into the output dir which captures the state of
ExposeExperimentalFeatures for the current compilation. This is used by
consuming projects (tests, benchmarks, examples, etc) to add compiler
constants which can be used to detect experimental APIs -->
<WriteLinesToFile
File="$(IntermediateOutputPath)$(ProjectName).BuildFlags.txt"
Lines="ExposeExperimentalFeatures=$(ExposeExperimentalFeatures)"
Overwrite="true"/>
<ItemGroup Condition="'$(ExposeExperimentalFeatures)' != 'true'">
<Compile Remove="@(Compile)" Condition="'%(Compile.RequiresExposedExperimentalFeatures)' == 'true'" />
</ItemGroup>
<!-- Note: This selects the correct PublicApiAnalyzers files based on $(ExposeExperimentalFeatures) -->
<ItemGroup>

View File

@ -4,24 +4,15 @@
<SignAssembly>true</SignAssembly>
<RepoRoot>$([System.IO.Directory]::GetParent($(MSBuildThisFileDirectory)).Parent.FullName)</RepoRoot>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)debug.snk</AssemblyOriginatorKeyFile>
<DefineConstants>$(DefineConstants);SIGNED</DefineConstants>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<NuGetAudit>true</NuGetAudit>
<NuGetAuditMode>all</NuGetAuditMode>
<NuGetAuditLevel>low</NuGetAuditLevel>
<!-- Suppress warnings for repo code using experimental features -->
<NoWarn>$(NoWarn);OTEL1000;OTEL1001;OTEL1002;OTEL1004</NoWarn>
<AnalysisLevel>latest-All</AnalysisLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(SignAssembly)' == 'true' ">
<StrongNamePublicKey>002400000480000094000000060200000024000052534131000400000100010051C1562A090FB0C9F391012A32198B5E5D9A60E9B80FA2D7B434C9E5CCB7259BD606E66F9660676AFC6692B8CDC6793D190904551D2103B7B22FA636DCBB8208839785BA402EA08FC00C8F1500CCEF28BBF599AA64FFB1E1D5DC1BF3420A3777BADFE697856E9D52070A50C3EA5821C80BEF17CA3ACFFA28F89DD413F096F898</StrongNamePublicKey>
</PropertyGroup>
<PropertyGroup Label="BuildFlags">
<RunningDotNetPack Condition="'$(RunningDotNetPack)' == ''">false</RunningDotNetPack>
<NoWarn>$(NoWarn);OTEL1000;OTEL1001;OTEL1002;OTEL1003</NoWarn>
<!--temporarily disable. See 3958-->
<!--<AnalysisLevel>latest-All</AnalysisLevel>-->
</PropertyGroup>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
@ -30,19 +21,20 @@
<NetFrameworkSupportedVersions>net481;net48;net472;net471;net47;net462</NetFrameworkSupportedVersions>
<!-- production TFMs -->
<TargetFrameworksForLibraries>net9.0;net8.0;netstandard2.0;$(NetFrameworkMinimumSupportedVersion)</TargetFrameworksForLibraries>
<TargetFrameworksForLibrariesExtended>net9.0;net8.0;netstandard2.1;netstandard2.0;$(NetFrameworkMinimumSupportedVersion)</TargetFrameworksForLibrariesExtended>
<TargetFrameworksForPrometheusAspNetCore>net9.0;net8.0</TargetFrameworksForPrometheusAspNetCore>
<TargetFrameworksRequiringSystemTextJsonDirectReference>net8.0;netstandard2.1;netstandard2.0;$(NetFrameworkMinimumSupportedVersion)</TargetFrameworksRequiringSystemTextJsonDirectReference>
<TargetFrameworksForLibraries>net8.0;net6.0;netstandard2.0;$(NetFrameworkMinimumSupportedVersion)</TargetFrameworksForLibraries>
<TargetFrameworksForLibrariesExtended>net8.0;net6.0;netstandard2.1;netstandard2.0;$(NetFrameworkMinimumSupportedVersion)</TargetFrameworksForLibrariesExtended>
<TargetFrameworksForAspNetCoreInstrumentation>net8.0;net7.0;net6.0;netstandard2.0</TargetFrameworksForAspNetCoreInstrumentation>
<TargetFrameworksForGrpcNetClientInstrumentation>net8.0;net6.0;netstandard2.1;netstandard2.0</TargetFrameworksForGrpcNetClientInstrumentation>
<TargetFrameworksForPrometheusAspNetCore>net8.0;net6.0</TargetFrameworksForPrometheusAspNetCore>
<!-- non-production TFMs -->
<TargetFrameworksForAspNetCoreTests>net9.0;net8.0</TargetFrameworksForAspNetCoreTests>
<TargetFrameworksForAotCompatibilityTests>net9.0;net8.0</TargetFrameworksForAotCompatibilityTests>
<TargetFrameworksForDocs>net9.0;net8.0</TargetFrameworksForDocs>
<TargetFrameworksForAspNetCoreTests>net8.0;net7.0;net6.0</TargetFrameworksForAspNetCoreTests>
<TargetFrameworksForAotCompatibilityTests>net8.0</TargetFrameworksForAotCompatibilityTests>
<TargetFrameworksForDocs>net8.0;net7.0;net6.0</TargetFrameworksForDocs>
<TargetFrameworksForDocs Condition="$(OS) == 'Windows_NT' And '$(UsingMicrosoftNETSdkWeb)' != 'True'">
$(TargetFrameworksForDocs);$(NetFrameworkSupportedVersions)
</TargetFrameworksForDocs>
<TargetFrameworksForTests>net9.0;net8.0</TargetFrameworksForTests>
<TargetFrameworksForTests>net8.0;net7.0;net6.0</TargetFrameworksForTests>
<TargetFrameworksForTests Condition="$(OS) == 'Windows_NT'">
$(TargetFrameworksForTests);$(NetFrameworkMinimumSupportedVersion)
</TargetFrameworksForTests>
@ -67,11 +59,20 @@
<PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" Condition="'$(SkipAnalysis)'!='true'" />
</ItemGroup>
<ItemGroup Condition="'$(IncludeInstrumentationHelpers)'=='true'">
<ItemGroup Condition="'$(IncludeDiagnosticSourceInstrumentationHelpers)'=='true'">
<Compile Include="$(RepoRoot)\src\Shared\ActivityInstrumentationHelper.cs" Link="Includes\ActivityInstrumentationHelper.cs" />
<Compile Include="$(RepoRoot)\src\Shared\DiagnosticSourceInstrumentation\DiagnosticSourceListener.cs" Link="Includes\DiagnosticSourceListener.cs" />
<Compile Include="$(RepoRoot)\src\Shared\DiagnosticSourceInstrumentation\DiagnosticSourceSubscriber.cs" Link="Includes\DiagnosticSourceSubscriber.cs" />
<Compile Include="$(RepoRoot)\src\Shared\DiagnosticSourceInstrumentation\ListenerHandler.cs" Link="Includes\ListenerHandler.cs" />
<Compile Include="$(RepoRoot)\src\Shared\DiagnosticSourceInstrumentation\PropertyFetcher.cs" Link="Includes\PropertyFetcher.cs" />
</ItemGroup>
<ItemGroup Condition="'$(IncludeInstrumentationHelpers)'=='true' Or '$(IncludeDiagnosticSourceInstrumentationHelpers)'=='true'">
<Compile Include="$(RepoRoot)\src\Shared\ActivityHelperExtensions.cs" Link="Includes\ActivityHelperExtensions.cs" />
<Compile Include="$(RepoRoot)\src\Shared\ExceptionExtensions.cs" Link="Includes\ExceptionExtensions.cs" />
<Compile Include="$(RepoRoot)\src\Shared\SemanticConventions.cs" Link="Includes\SemanticConventions.cs" />
<Compile Include="$(RepoRoot)\src\Shared\SpanAttributeConstants.cs" Link="Includes\SpanAttributeConstants.cs" />
<Compile Include="$(RepoRoot)\src\Shared\SpanHelper.cs" Link="Includes\SpanHelper.cs" />
<Compile Include="$(RepoRoot)\src\Shared\StatusHelper.cs" Link="Includes\StatusHelper.cs" />
</ItemGroup>

View File

@ -1,12 +0,0 @@
<Project>
<ItemGroup Condition="'$(ReferenceSystemTextJsonPackages)' == 'true' AND $(TargetFrameworksRequiringSystemTextJsonDirectReference.Contains('$(TargetFramework)'))">
<!-- Note: System.Text.Encodings.Web is referenced on NET Framework & NET
Standard targets because System.Text.Json v4.7.2 uses
System.Text.Encodings.Web >= v4.7.1 but System.Text.Encodings.Web needs to
be at v4.7.2 to be safe. -->
<PackageReference Include="System.Text.Encodings.Web" Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'" />
<PackageReference Include="System.Text.Json" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,18 @@
<Project>
<ItemGroup>
<SolutionProjects Include="..\**\OpenTelemetry.Instrumentation*.csproj" />
<TestProjects Include="..\test\**\OpenTelemetry.Instrumentation*.csproj" />
</ItemGroup>
<Target Name="Build">
<MSBuild Projects="@(SolutionProjects)" Targets="Build" ContinueOnError="ErrorAndStop" />
</Target>
<Target Name="Restore">
<MSBuild Projects="@(SolutionProjects)" Targets="Restore" ContinueOnError="ErrorAndStop" />
</Target>
<Target Name="VSTest">
<MSBuild Projects="@(TestProjects)" Targets="VSTest" ContinueOnError="ErrorAndStop" />
</Target>
</Project>

View File

@ -1,218 +1,141 @@
# Release process
**Note: Approvers (collaborators) can perform much of the release process but
Maintainers (admins) are needed to merge PRs and for the push to NuGet.**
Only for Maintainers.
1. Decide the component(s) and tag name (version name) to be released. We use
1. Decide the tag name (version name) to be released. e.g. 1.4.0-beta.1,
1.0.0-rc9.7 etc.
2. Run the following PowerShell from the root of the repo to get combined
changelog (to be used later).
```powershell
$changelogs = Get-ChildItem -Path . -Recurse -Filter changelog.md
foreach ($changelog in $changelogs)
{
Add-Content -Path .\combinedchangelog.md -Value "**$($changelog.Directory.Name)**"
$lines = Get-Content -Path $changelog.FullName
$started = $false
$ended = $false
foreach ($line in $lines)
{
if($line -like "## Unreleased" -and $started -ne $true)
{
$started = $true
}
elseif($line -like "## *" -and $started -eq $true)
{
$ended = $true
break
}
else
{
if ($started -eq $true)
{
Add-Content -Path .\combinedchangelog.md $line
}
}
}
}
```
This generates combined changelog to be used in GitHub release. Once
contents of combined changelog is saved somewhere, delete the file.
3. Run the following PowerShell script from the root of the repo. This updates
all the changelog to have release date for the current version being
released. Replace the version with actual version. In the script below,
replace `1.4.0-beta.1` with the tag name chosen for the package in Step 1.
```powershell
$changelogs = Get-ChildItem -Path . -Recurse -Filter changelog.md
foreach ($changelog in $changelogs)
{
(Get-Content -Path $changelog.FullName) -replace "Unreleased", "Unreleased
## 1.4.0-beta.1
Released $(Get-Date -UFormat '%Y-%b-%d')" | Set-Content -Path $changelog.FullName
}
```
4. Normalize PublicApi files (Stable Release Only): Run the PowerShell script
`.\build\finalize-publicapi.ps1`. This will merge the contents of
Unshipped.txt into the Shipped.txt.
5. Submit PR with the above changes, and get it merged.
6. Tag Git with version to be released. We use
[MinVer](https://github.com/adamralph/minver) to do versioning, which
produces version numbers based on git tags.
Notes:
Note: If releasing only core components, only add and push the tag prefixed
with `core-`. For example:
* There are different categories of packages. Check the project file for
what you want to release and look for `MinVerTagPrefix`.
```sh
git tag -a core-1.4.0-beta.1 -m "1.4.0-beta.1 of all core components"
git push origin core-1.4.0-beta.1
```
* `core-`: Core packages. These packages are defined\goverened by the
OpenTelemetry Specification or are part of fundamental infrastructure
and have released stable versions. They may be released as `alpha`,
`beta`, `rc`, or stable.
If releasing only non-core components, only add and push the tags without
prefix. For example:
* `OpenTelemetry.Api` - Defined by spec (API)
* `OpenTelemetry.Api.ProviderBuilderExtensions` - Fundamental
infrastructure
* `OpenTelemetry` - Defined by spec (SDK)
* `OpenTelemetry.Exporter.Console` - Defined by spec
* `OpenTelemetry.Exporter.InMemory` - Defined by spec
* `OpenTelemetry.Exporter.OpenTelemetryProtocol` - Defined by spec
* `OpenTelemetry.Exporter.Zipkin` - Defined by spec
* `OpenTelemetry.Extensions.Hosting` - Fundamental infrastructure
* `OpenTelemetry.Extensions.Propagators` - Defined by spec
```sh
git tag -a 1.0.0-rc9.7 -m "1.0.0-rc9.7 of all non-core components"
git push origin 1.0.0-rc9.7
```
* `coreunstable-`: Core unstable packages. These packages are
defined\goverened by the OpenTelemetry Specification or are part of
fundamental infrastructure but have not released stable versions. As
of the `1.9.0` release cycle they may only be released as `alpha` or
`beta`.
If releasing only a particular non-core component which has a dedicated
MinverTagPrefix such as AspNetCore instrumentation, only add and push the
tag with that particular prefix. For example:
* `OpenTelemetry.Exporter.Prometheus.AspNetCore` - Defined by spec
(experimental)
* `OpenTelemetry.Exporter.Prometheus.HttpListener` - Defined by spec
(experimental)
* `OpenTelemetry.Shims.OpenTracing` - Defined by spec (stable but
incomplete implementation)
```sh
git tag -a Instrumentation.AspNetCore-1.6.0 -m "1.6.0 of AspNetCore instrumentation library"
git push origin Instrumentation.AspNetCore-1.6.0
```
* As of the `1.9.0` release cycle core unstable packages always depend on
the stable versions of core packages. Before releasing a non-core
component ensure the `OTelLatestStableVer` property in
`Directory.Packages.props` has been updated to the latest stable core
version.
If releasing multiple kinds of components, push both tags for each of them.
2. Run the [Prepare for a
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/prepare-release.yml)
workflow. Specify the `tag-prefix` and the `version` for the release. Make
sure to run the workflow on the branch being released. This is typically
`main` but could be some other branch for hotfix (eg `main-1.8.0`). The
workflow will open a PR to update `CHANGELOG.md` files for the projects
being released. If a stable version is specified as the `version` parameter,
the workflow will also merge the contents of any detected
`PublicAPI.Unshipped.txt` files in the `.publicApi` folder into the
corresponding `PublicAPI.Shipped.txt` files for the projects being released.
7. Go to the [list of
tags](https://github.com/open-telemetry/opentelemetry-dotnet/tags)
and find the tag created for the core components. Click the three
dots next to the tag and choose `Create release`.
* Give the release a name based on the tags created
(e.g., `1.4.0-beta.1 / 1.0.0-rc9.7`).
* Paste the contents of combined changelog from Step 2.
* Check "This is a pre-release" if applicable.
* Click "Publish release". This will kick off the [Pack and publish to
MyGet workflow](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/publish-packages-1.0.yml).
<details>
<summary>Instructions for preparing for a release manually</summary>
8. Validate using MyGet packages. Basic sanity checks :)
* Update CHANGELOG files
9. From the above build, get the artifacts from the drop, which has all the
NuGet packages.
Run the PowerShell script `.\build\scripts\update-changelogs.ps1
-minVerTagPrefix [MinVerTagPrefix] -version [Version]`. Where
`[MinVerTagPrefix]` is the tag prefix (eg `core-`) for the components
being released and `[Version]` is the version being released (eg
`1.9.0`). This will update `CHANGELOG.md` files for the projects being
released.
10. Copy all the NuGet files and symbols into a local folder. If only releasing
core packages, only copy them over.
* **Stable releases only**: Normalize PublicApi files
11. Download latest [nuget.exe](https://www.nuget.org/downloads) into the same
folder from Step 9.
Run the PowerShell script `.\build\scripts\finalize-publicapi.ps1
-minVerTagPrefix [MinVerTagPrefix]`. Where `[MinVerTagPrefix]` is the tag
prefix (eg `core-`) for the components being released. This will merge
the contents of any detected `PublicAPI.Unshipped.txt` files in the
`.publicApi` folder into the corresponding `PublicAPI.Shipped.txt` files
for the projects being released.
</details
12. Obtain the API key from nuget.org (Only maintainers have access)
3. For stable releases, use the `/UpdateReleaseNotes` command on the PR opened
by [Prepare for a
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/prepare-release.yml)
workflow in step 2 to update [Release Notes](../RELEASENOTES.md) with any
big or interesting new features.
13. Run the following commands from PowerShell from local folder used in Step 9:
* The `/UpdateReleaseDates` command may also be used to update dates in
`CHANGELOG.md` files. This is useful when the PR is opened a few days
before the planned release date to review public API changes.
```powershell
.\nuget.exe setApiKey <actual api key>
4. :stop_sign: The PR opened by [Prepare for a
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/prepare-release.yml)
workflow in step 2 has to be merged.
get-childitem -Recurse | where {$_.extension -eq ".nupkg"} | foreach ($_) {.\nuget.exe push $_.fullname -Source https://api.nuget.org/v3/index.json}
```
5. Once the PR opened by [Prepare for a
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/prepare-release.yml)
workflow in step 2 has been merged a trigger will automatically add a
comment and lock the PR. Post a comment with "/CreateReleaseTag" in the
body. This will tell the [Prepare for a
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/prepare-release.yml)
workflow to push the tag for the merge commit of the PR which will trigger
the [Build, pack, and publish to
MyGet](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/publish-packages-1.0.yml)
workflow.
14. Packages would be available in nuget.org in few minutes. Validate that the
package is uploaded.
<details>
<summary>Instructions for pushing tags manually</summary>
15. Delete the API key generated in Step 11.
Note: In the below examples `git push origin` is used. If running in a fork,
add the main repo as `upstream` and use `git push upstream` instead. Pushing
a tag to `origin` in a fork pushes the tag to the fork.
16. Update the OpenTelemetry.io document
[here](https://github.com/open-telemetry/opentelemetry.io/tree/main/content/en/docs/net)
by sending a Pull Request.
* If releasing core components, add and push the tag prefixed with `core-`.
For example:
```sh
git tag -a core-1.4.0-beta.1 -m "1.4.0-beta.1 of all core components"
git push origin core-1.4.0-beta.1
```
* If releasing core unstable components, push the tag prefixed with
`coreunstable-`. For example:
```sh
git tag -a coreunstable-1.9.0-beta.1 -m "1.9.0-beta.1 of all core unstable components"
git push origin coreunstable-1.9.0-beta.1
```
Pushing the tag will kick off the [Build, pack, and publish to
MyGet](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/publish-packages-1.0.yml)
workflow.
</details>
6. :stop_sign: Wait for the [Build, pack, and publish to
MyGet](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/publish-packages-1.0.yml)
workflow to complete. When complete a trigger will automatically add a
comment on the PR opened by [Prepare for a
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/prepare-release.yml)
workflow in step 2. Use MyGet or download the packages using the provided
link to validate locally everything works. After validation has been
performed have a maintainer post a comment with "/PushPackages" in the body.
This will trigger the [Complete
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/prepare-release.yml)
workflow to push the packages to NuGet and publish the draft release created
by the [Build, pack, and publish to
MyGet](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/publish-packages-1.0.yml)
workflow. Comments will automatically be added on the PR opened by [Prepare
for a
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/prepare-release.yml)
workflow in step 2 as the process is run and the PR will be unlocked.
<details>
<summary>Instructions for pushing packages to NuGet manually</summary>
1. The [Build, pack, and publish to
MyGet](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/publish-packages-1.0.yml)
workflow pushes the packages to MyGet and attaches them as artifacts on
the workflow run.
2. Validate locally everything works using the packages pushed to MyGet or
downloaded from the drop attached to the workflow run. Basic sanity
checks :)
3. Download the artifacts from the drop attached to the workflow run. The
artifacts archive (`.zip`) contains all the NuGet packages (`.nupkg`) and
symbols (`.snupkg`) from the build which were pushed to MyGet.
4. Extract the artifacts from the archive (`.zip`) into a local folder.
5. Download latest [nuget.exe](https://www.nuget.org/downloads) into the
same folder from step 4.
6. Create or regenerate an API key from nuget.org (only maintainers have
access). When creating API keys make sure it is set to expire in 1 day or
less.
7. Run the following commands from PowerShell from local folder used in step
4:
```powershell
.\nuget.exe setApiKey <actual api key>
get-childitem -Recurse | where {$_.extension -eq ".nupkg"} | foreach ($_) {.\nuget.exe push $_.fullname -Source https://api.nuget.org/v3/index.json}
```
8. Validate that the package(s) are uploaded. Packages are available
immediately to maintainers on nuget.org but aren't publicly visible until
scanning completes. This process usually takes a few minutes.
9. Open the
[Releases](https://github.com/open-telemetry/opentelemetry-dotnet/releases)
page on the GitHub repository. The [Build, pack, and publish to
MyGet](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/publish-packages-1.0.yml)
workflow creates a draft release for the tag which was pushed. Edit the
draft Release and click `Publish release`.
</details>
7. If a new stable version of the core packages was released, a PR should have
been automatically created by the [Complete
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/post-release.yml)
workflow to update the `OTelLatestStableVer` property in
`Directory.Packages.props` to the just released stable version. Merge that
PR once the build passes (this requires the packages be available on NuGet).
8. The [Complete
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/post-release.yml)
workflow should have invoked the [Core version
update](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/actions/workflows/core-version-update.yml)
workflow on the
[opentelemetry-dotnet-contrib](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/)
repository which opens a PR to update dependencies. Verify this PR was
opened successfully.
9. For stable releases post an announcement in the [Slack
channel](https://cloud-native.slack.com/archives/C01N3BC2W7Q) announcing the
release and link to the release notes.
17. If a new stable version of the core packages were released, update
`OTelLatestStableVer` in Directory.Packages.props to the just released
stable version.

View File

@ -1,27 +0,0 @@
<Project>
<PropertyGroup>
<RepoRoot>$([System.IO.Directory]::GetParent($(MSBuildThisFileDirectory)).Parent.FullName)</RepoRoot>
</PropertyGroup>
<ItemGroup>
<SolutionProjects Include="$(RepoRoot)\**\OpenTelemetry.Exporter.Prometheus.AspNetCore*.csproj" />
<SolutionProjects Include="$(RepoRoot)\**\OpenTelemetry.Exporter.Prometheus.HttpListener*.csproj" />
<SolutionProjects Include="$(RepoRoot)\**\OpenTelemetry.Shims.OpenTracing*.csproj" />
<TestProjects Include="$(RepoRoot)\test\**\OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests.csproj" />
<TestProjects Include="$(RepoRoot)\test\**\OpenTelemetry.Exporter.Prometheus.HttpListener.Tests.csproj" />
<TestProjects Include="$(RepoRoot)\test\**\OpenTelemetry.Shims.OpenTracing.Tests.csproj" />
</ItemGroup>
<Target Name="Build">
<MSBuild Projects="@(SolutionProjects)" Targets="Build" ContinueOnError="ErrorAndStop" />
</Target>
<Target Name="Restore">
<MSBuild Projects="@(SolutionProjects)" Targets="Restore" ContinueOnError="ErrorAndStop" />
</Target>
<Target Name="VSTest">
<MSBuild Projects="@(TestProjects)" Targets="VSTest" ContinueOnError="ErrorAndStop" />
</Target>
</Project>

View File

@ -0,0 +1,9 @@
version: '3.7'
services:
tests:
build:
args:
PUBLISH_FRAMEWORK: net6.0
TEST_SDK_VERSION: "6.0"
BUILD_SDK_VERSION: "8.0"

View File

@ -0,0 +1,9 @@
version: '3.7'
services:
tests:
build:
args:
PUBLISH_FRAMEWORK: net7.0
TEST_SDK_VERSION: "7.0"
BUILD_SDK_VERSION: "8.0"

View File

@ -1,7 +1,9 @@
version: '3.7'
services:
tests:
build:
args:
PUBLISH_FRAMEWORK: net8.0
TEST_SDK_VERSION: "8.0"
BUILD_SDK_VERSION: "9.0"
BUILD_SDK_VERSION: "8.0"

View File

@ -1,7 +0,0 @@
services:
tests:
build:
args:
PUBLISH_FRAMEWORK: net9.0
TEST_SDK_VERSION: "9.0"
BUILD_SDK_VERSION: "9.0"

View File

@ -0,0 +1,31 @@
# After every stable release, all PublicApi text files (Shipped & Unshipped) should be merged.
$path = "src\*\.publicApi\**\";
$directory = Split-Path -Path $PSScriptRoot -Parent;
$searchPath = Join-Path -Path $directory -ChildPath $path;
Write-Host "Search Directory: $searchPath";
Write-Host "";
Get-ChildItem -Path $searchPath -Recurse -Filter *.Shipped.txt |
ForEach-Object {
Write-Host $_.FullName;
[string]$shipped = $_.FullName;
[string]$unshipped = $shipped -replace ".shipped.txt", ".Unshipped.txt";
if (Test-Path $unshipped) {
Write-Host $unshipped;
Get-Content $shipped, $unshipped | # get contents of both text files
Where-Object {$_ -ne ""} | # filter empty lines
Sort-Object | # sort lines
Get-Unique | # filter duplicates
Set-Content $shipped; # write to shipped.txt
Clear-Content $unshipped; # empty unshipped.txt
Write-Host "...MERGED and SORTED";
}
Write-Host "";
}

View File

@ -1,148 +0,0 @@
function AddLabelsOnIssuesForPackageFoundInBody {
param(
[Parameter(Mandatory=$true)][int]$issueNumber,
[Parameter(Mandatory=$true)][string]$issueBody
)
$match = [regex]::Match($issueBody, '^[#]+ Package\s*(OpenTelemetry(?:\.\w+)*)')
if ($match.Success -eq $false)
{
Return
}
gh issue edit $issueNumber --add-label $("pkg:" + $match.Groups[1].Value)
}
Export-ModuleMember -Function AddLabelsOnIssuesForPackageFoundInBody
function AddLabelsOnPullRequestsBasedOnFilesChanged {
param(
[Parameter(Mandatory=$true)][int]$pullRequestNumber,
[Parameter(Mandatory=$true)][string]$labelPackagePrefix # 'pkg:' on main repo, 'comp:' on contrib repo
)
# Note: This function is intended to work on main repo and on contrib. Please
# keep them in sync.
$repoLabels = gh label list --json name,id -L 200 | ConvertFrom-Json
$filesChangedOnPullRequest = gh pr diff $pullRequestNumber --name-only
$labelsOnPullRequest = (gh pr view $pullRequestNumber --json labels | ConvertFrom-Json).labels
$visitedProjects = New-Object System.Collections.Generic.HashSet[string]
$labelsToAdd = New-Object System.Collections.Generic.HashSet[string]
$labelsToRemove = New-Object System.Collections.Generic.HashSet[string]
# Note: perf label may be added but it is kind of a guess so we don't remove
# it automatically in order to also allow manual inclusion after reviewing files
$managedLabels = 'infra', 'documentation', 'dependencies'
$rootInfraFiles = 'global.json', 'NuGet.config', 'codeowners'
$documentationFiles = 'readme.md', 'contributing.md', 'releasing.md', 'versioning.md', 'releasenotes.md'
foreach ($fileChanged in $filesChangedOnPullRequest)
{
$fileChanged = $fileChanged.ToLower()
$fullFileName = [System.IO.Path]::GetFileName($fileChanged)
$fileName = [System.IO.Path]::GetFileNameWithoutExtension($fileChanged)
$fileExtension = [System.IO.Path]::GetExtension($fileChanged)
if ($fileChanged.StartsWith('src/') -or $fileChanged.StartsWith('test/'))
{
$match = [regex]::Match($fileChanged, '^(?:(?:src)|(?:test))\/(.*?)\/.+$')
if ($match.Success -eq $false)
{
continue
}
$rawProjectName = $match.Groups[1].Value
if ($rawProjectName.Contains(".benchmarks") -or $rawProjectName.Contains(".stress"))
{
$added = $labelsToAdd.Add("perf")
}
$projectName = $rawProjectName.Replace(".tests", "").Replace(".benchmarks", "").Replace(".stress", "")
if ($visitedProjects.Contains($projectName))
{
continue
}
$added = $visitedProjects.Add($projectName);
foreach ($repoLabel in $repoLabels)
{
if ($repoLabel.name.StartsWith($labelPackagePrefix))
{
$package = $repoLabel.name.Substring($labelPackagePrefix.Length).ToLower()
if ($package.StartsWith('opentelemetry') -eq $false)
{
# Note: On contrib labels don't have "OpenTelemetry." prefix
$package = 'opentelemetry.' + $package
}
if ($package -eq $projectName)
{
$added = $labelsToAdd.Add($repoLabel.name)
break
}
}
}
}
if ($documentationFiles.Contains($fullFileName) -or
$fileChanged.StartsWith('docs/') -or
$fileChanged.StartsWith('examples/'))
{
$added = $labelsToAdd.Add("documentation")
}
if ($fileChanged.StartsWith('build/') -or
$fileChanged.StartsWith('.github/') -or
$rootInfraFiles.Contains($fullFileName) -or
$fileExtension -eq ".props" -or
$fileExtension -eq ".targets" -or
$fileChanged.StartsWith('test/openTelemetry.aotcompatibility'))
{
$added = $labelsToAdd.Add("infra")
}
if ($fileChanged.StartsWith('test/benchmarks'))
{
$added = $labelsToAdd.Add("perf")
}
if ($fullFileName -eq 'directory.packages.props')
{
$added = $labelsToAdd.Add("dependencies")
}
}
foreach ($labelOnPullRequest in $labelsOnPullRequest)
{
if ($labelsToAdd.Contains($labelOnPullRequest.name))
{
$removed = $labelsToAdd.Remove($labelOnPullRequest.name)
}
elseif ($labelOnPullRequest.name.StartsWith($labelPackagePrefix) -or
$managedLabels.Contains($labelOnPullRequest.name))
{
$added = $labelsToRemove.Add($labelOnPullRequest.name)
}
}
if ($labelsToAdd.Count -gt 0)
{
foreach ($label in $labelsToAdd)
{
gh pr edit $pullRequestNumber --add-label $label
}
}
if ($labelsToRemove.Count -gt 0)
{
foreach ($label in $labelsToRemove)
{
gh pr edit $pullRequestNumber --remove-label $label
}
}
}
Export-ModuleMember -Function AddLabelsOnPullRequestsBasedOnFilesChanged

View File

@ -1,39 +0,0 @@
param(
[Parameter(Mandatory=$true)][string]$minVerTagPrefix
)
# For stable releases "Unshipped" PublicApi text files are merged into "Shipped" versions.
$projectDirs = Get-ChildItem -Path src/**/*.csproj | Select-String "<MinVerTagPrefix>$minVerTagPrefix</MinVerTagPrefix>" -List | Select Path | Split-Path -Parent
$path = "\.publicApi\**\PublicAPI.Shipped.txt";
foreach ($projectDir in $projectDirs) {
$searchPath = Join-Path -Path $projectDir -ChildPath $path;
Write-Host "Search glob: $searchPath";
Get-ChildItem -Path $searchPath -Recurse |
ForEach-Object {
Write-Host "Shipped: $_";
[string]$shipped = $_.FullName;
[string]$unshipped = $shipped -replace ".shipped.txt", ".Unshipped.txt";
if (Test-Path $unshipped) {
Write-Host "Unshipped: $unshipped";
Get-Content $shipped, $unshipped | # get contents of both text files
Where-Object {$_ -ne ""} | # filter empty lines
Sort-Object | # sort lines
Get-Unique | # filter duplicates
Set-Content $shipped; # write to shipped.txt
Clear-Content $unshipped; # empty unshipped.txt
Write-Host "...MERGED and SORTED";
}
Write-Host "";
}
}

View File

@ -1,598 +0,0 @@
function CreateDraftRelease {
param(
[Parameter(Mandatory=$true)][string]$gitRepository,
[Parameter(Mandatory=$true)][string]$tag,
[Parameter()][string]$releaseFiles
)
$match = [regex]::Match($tag, '^(.*?-)(.*)$')
if ($match.Success -eq $false)
{
throw 'Could not parse prefix or version from tag'
}
$tagPrefix = $match.Groups[1].Value
$version = $match.Groups[2].Value
$isPrerelease = $version -match '-alpha' -or $version -match '-beta' -or $version -match '-rc'
$projects = @(Get-ChildItem -Path src/**/*.csproj | Select-String "<MinVerTagPrefix>$tagPrefix</MinVerTagPrefix>" -List | Select Path)
if ($projects.Length -eq 0)
{
throw 'No projects found with MinVerTagPrefix matching prefix from tag'
}
$notes = ''
$previousVersion = ''
foreach ($project in $projects)
{
$projectName = [System.IO.Path]::GetFileNameWithoutExtension($project.Path)
$changelogContent = Get-Content -Path "src/$projectName/CHANGELOG.md"
$started = $false
$content = ""
foreach ($line in $changelogContent)
{
if ($line -like "## $version" -and $started -ne $true)
{
$started = $true
}
elseif ($line -like "Released *" -and $started -eq $true)
{
continue
}
elseif ($line -like "## *" -and $started -eq $true)
{
$match = [regex]::Match($line, '^##\s*(.*)$')
if ($match.Success -eq $true)
{
$previousVersion = $match.Groups[1].Value
}
break
}
else
{
if ($started -eq $true -and ([string]::IsNullOrWhitespace($line) -eq $false -or $content.Length -gt 0))
{
$content += " " + $line + "`r`n"
}
}
}
if ([string]::IsNullOrWhitespace($content) -eq $true)
{
$content = " No notable changes."
}
$content = $content.trimend()
$notes +=
@"
* NuGet: [$projectName v$version](https://www.nuget.org/packages/$projectName/$version)
$content
See [CHANGELOG](https://github.com/$gitRepository/blob/$tag/src/$projectName/CHANGELOG.md) for details.
"@
}
if ($isPrerelease -eq $true)
{
$notes =
@"
The following changes are from the previous release [$previousVersion](https://github.com/$gitRepository/releases/tag/$tagPrefix$previousVersion).
"@ + $notes
gh release create $tag $releaseFiles `
--title $tag `
--verify-tag `
--notes $notes `
--prerelease `
--draft
}
else
{
$notes =
@"
For highlights and announcements pertaining to this release see: [Release Notes > $version](https://github.com/$gitRepository/blob/main/RELEASENOTES.md#$($version.Replace('.',''))).
The following changes are from the previous release [$previousVersion](https://github.com/$gitRepository/releases/tag/$tagPrefix$previousVersion).
"@ + $notes
gh release create $tag $releaseFiles `
--title $tag `
--verify-tag `
--notes $notes `
--latest `
--draft
}
}
Export-ModuleMember -Function CreateDraftRelease
function TryPostPackagesReadyNoticeOnPrepareReleasePullRequest {
param(
[Parameter(Mandatory=$true)][string]$gitRepository,
[Parameter(Mandatory=$true)][string]$tag,
[Parameter(Mandatory=$true)][string]$tagSha,
[Parameter(Mandatory=$true)][string]$packagesUrl,
[Parameter(Mandatory=$true)][string]$botUserName
)
$prListResponse = gh pr list --search $tagSha --state merged --json number,author,title,comments | ConvertFrom-Json
if ($prListResponse.Length -eq 0)
{
Write-Host 'No prepare release PR found for tag & commit skipping post notice'
return
}
foreach ($pr in $prListResponse)
{
if ($pr.author.login -ne $botUserName -or $pr.title -ne "[release] Prepare release $tag")
{
continue
}
$foundComment = $false
foreach ($comment in $pr.comments)
{
if ($comment.author.login -eq $botUserName -and $comment.body.StartsWith("I just pushed the [$tag]"))
{
$foundComment = $true
break
}
}
if ($foundComment -eq $false)
{
continue
}
$body =
@"
The packages for [$tag](https://github.com/$gitRepository/releases/tag/$tag) are now available: $packagesUrl.
Once these packages have been validated have a maintainer post a comment with "/PushPackages" in the body if you would like me to push to NuGet.
"@
$pullRequestNumber = $pr.number
gh pr comment $pullRequestNumber --body $body
return
}
Write-Host 'No prepare release PR found matched author and title with a valid comment'
}
Export-ModuleMember -Function TryPostPackagesReadyNoticeOnPrepareReleasePullRequest
function PushPackagesPublishReleaseUnlockAndPostNoticeOnPrepareReleasePullRequest {
param(
[Parameter(Mandatory=$true)][string]$gitRepository,
[Parameter(Mandatory=$true)][string]$pullRequestNumber,
[Parameter(Mandatory=$true)][string]$botUserName,
[Parameter(Mandatory=$true)][string]$commentUserName,
[Parameter(Mandatory=$true)][string]$artifactDownloadPath,
[Parameter(Mandatory=$true)][string]$pushToNuget
)
$prViewResponse = gh pr view $pullRequestNumber --json author,title,comments | ConvertFrom-Json
if ($prViewResponse.author.login -ne $botUserName)
{
throw 'PR author was unexpected'
}
$match = [regex]::Match($prViewResponse.title, '^\[release\] Prepare release (.*)$')
if ($match.Success -eq $false)
{
throw 'Could not parse tag from PR title'
}
$tag = $match.Groups[1].Value
$commentUserPermission = gh api "repos/$gitRepository/collaborators/$commentUserName/permission" | ConvertFrom-Json
if ($commentUserPermission.permission -ne 'admin')
{
gh pr comment $pullRequestNumber `
--body "I'm sorry @$commentUserName but you don't have permission to push packages. Only maintainers can push to NuGet."
return
}
$foundComment = $false
$packagesUrl = ''
foreach ($comment in $prViewResponse.comments)
{
if ($comment.author.login -eq $botUserName -and $comment.body.StartsWith("The packages for [$tag](https://github.com/$gitRepository/releases/tag/$tag) are now available:"))
{
$foundComment = $true
break
}
}
if ($foundComment -eq $false)
{
throw 'Could not find package push comment on pr'
}
gh release download $tag `
-p "$tag-packages.zip" `
-D "$artifactDownloadPath"
Expand-Archive -LiteralPath "$artifactDownloadPath/$tag-packages.zip" -DestinationPath "$artifactDownloadPath\"
if ($pushToNuget -eq 'true')
{
gh pr comment $pullRequestNumber `
--body "I am uploading the packages for ``$tag`` to NuGet and then I will publish the release."
nuget push "$artifactDownloadPath/**/*.nupkg" -Source https://api.nuget.org/v3/index.json -ApiKey "$env:NUGET_TOKEN" -SymbolApiKey "$env:NUGET_TOKEN"
if ($LASTEXITCODE -gt 0)
{
gh pr comment $pullRequestNumber `
--body "Something went wrong uploading the packages for ``$tag`` to NuGet."
throw 'nuget push failure'
}
}
else {
gh pr comment $pullRequestNumber `
--body "I am publishing the release without uploading the packages to NuGet because a token wasn't configured."
}
gh release edit $tag --draft=false
gh pr unlock $pullRequestNumber
}
Export-ModuleMember -Function PushPackagesPublishReleaseUnlockAndPostNoticeOnPrepareReleasePullRequest
function CreateStableVersionUpdatePullRequest {
param(
[Parameter(Mandatory=$true)][string]$gitRepository,
[Parameter(Mandatory=$true)][string]$tag,
[Parameter()][string]$targetBranch="main",
[Parameter()][string]$lineEnding="`n",
[Parameter()][string]$gitUserName,
[Parameter()][string]$gitUserEmail
)
$match = [regex]::Match($tag, '.*?-(.*)')
if ($match.Success -eq $false)
{
throw 'Could not parse version from tag'
}
$version = $match.Groups[1].Value
$branch="release/post-stable-${tag}-update"
if ([string]::IsNullOrEmpty($gitUserName) -eq $false)
{
git config user.name $gitUserName
}
if ([string]::IsNullOrEmpty($gitUserEmail) -eq $false)
{
git config user.email $gitUserEmail
}
git switch --create $branch origin/$targetBranch --no-track 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git switch failure'
}
$projectsAndDependenciesBefore = GetCoreDependenciesForProjects
(Get-Content Directory.Packages.props) `
-replace '<OTelLatestStableVer>.*<\/OTelLatestStableVer>', "<OTelLatestStableVer>$version</OTelLatestStableVer>" |
Set-Content Directory.Packages.props
$projectsAndDependenciesAfter = GetCoreDependenciesForProjects
$changedProjects = @{}
$projectsAndDependenciesBefore.GetEnumerator() | ForEach-Object {
$projectDir = $_.Key
$projectDependenciesBefore = $_.Value
$projectDependenciesAfter = $projectsAndDependenciesAfter[$projectDir]
$projectDependenciesBefore.GetEnumerator() | ForEach-Object {
$packageName = $_.Key
$packageVersionBefore = $_.Value
if ($projectDependenciesAfter[$packageName] -ne $packageVersionBefore)
{
$changedProjects[$projectDir] = $true
}
}
}
git add Directory.Packages.props 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git add failure'
}
git commit -m "Update OTelLatestStableVer in Directory.Packages.props to $version." 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git commit failure'
}
git push -u origin $branch 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git push failure'
}
$body =
@"
Note: This PR was opened automatically by the [post-release workflow](https://github.com/$gitRepository/actions/workflows/post-release.yml).
Merge once packages are available on NuGet and the build passes.
## Changes
* Sets ``OTelLatestStableVer`` in ``Directory.Packages.props`` to ``$version``.
"@
$createPullRequestResponse = gh pr create `
--title "[release] Core stable release $version updates" `
--body $body `
--base $targetBranch `
--head $branch `
--label release
Write-Host $createPullRequestResponse
$match = [regex]::Match($createPullRequestResponse, "\/pull\/(.*)$")
if ($match.Success -eq $false)
{
throw 'Could not parse pull request number from gh pr create response'
}
$pullRequestNumber = $match.Groups[1].Value
if ($changedProjects.Count -eq 0)
{
Return
}
$entry = @"
* Updated OpenTelemetry core component version(s) to ``$version``.
([#$pullRequestNumber](https://github.com/$gitRepository/pull/$pullRequestNumber))
"@
$lastLineBlank = $true
$changelogFilesUpdated = 0
foreach ($projectDir in $changedProjects.Keys)
{
$path = Join-Path -Path $projectDir -ChildPath "CHANGELOG.md"
if ([System.IO.File]::Exists($path) -eq $false)
{
Write-Host "No CHANGELOG found in $projectDir"
continue
}
$changelogContent = Get-Content -Path $path
$started = $false
$isRemoving = $false
$content = ""
foreach ($line in $changelogContent)
{
if ($line -like "## Unreleased" -and $started -ne $true)
{
$started = $true
}
elseif ($line -like "## *" -and $started -eq $true)
{
if ($lastLineBlank -eq $false)
{
$content += $lineEnding
}
$content += $entry
$started = $false
$isRemoving = $false
}
elseif ($started -eq $true -and ($line -like '*Update* OpenTelemetry SDK version to*' -or $line -like '*Updated OpenTelemetry core component version(s) to*'))
{
$isRemoving = $true
continue
}
if ($line.StartsWith('* '))
{
if ($isRemoving -eq $true)
{
$isRemoving = $false
}
if ($lastLineBlank -eq $false)
{
$content += $lineEnding
}
}
if ($isRemoving -eq $true)
{
continue
}
$content += $line + $lineEnding
$lastLineBlank = [string]::IsNullOrWhitespace($line)
}
if ($started -eq $true)
{
# Note: If we never wrote the entry it means the file ended in the unreleased section
if ($lastLineBlank -eq $false)
{
$content += $lineEnding
}
$content += $entry
}
Set-Content -Path $path -Value $content.TrimEnd()
git add $path 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git add failure'
}
$changelogFilesUpdated++
}
if ($changelogFilesUpdated -gt 0)
{
git commit -m "Update CHANGELOGs for projects using OTelLatestStableVer." 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git commit failure'
}
git push -u origin $branch 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git push failure'
}
}
}
Export-ModuleMember -Function CreateStableVersionUpdatePullRequest
function GetCoreDependenciesForProjects {
$projects = @(Get-ChildItem -Path 'src/*/*.csproj')
$projectsAndDependencies = @{}
foreach ($project in $projects)
{
# Note: dotnet restore may fail if the core packages aren't available yet but that is fine, we just want to generate project.assets.json for these projects.
$output = dotnet restore $project -p:RunningDotNetPack=true
$projectDir = $project | Split-Path -Parent
$content = (Get-Content "$projectDir/obj/project.assets.json" -Raw)
$projectDependencies = @{}
$matches = [regex]::Matches($content, '"(OpenTelemetry(?:.*))?": {[\S\s]*?"target": "Package",[\S\s]*?"version": "(.*)"[\S\s]*?}')
foreach ($match in $matches)
{
$packageName = $match.Groups[1].Value
$packageVersion = $match.Groups[2].Value
if ($packageName -eq 'OpenTelemetry' -or
$packageName -eq 'OpenTelemetry.Api' -or
$packageName -eq 'OpenTelemetry.Api.ProviderBuilderExtensions' -or
$packageName -eq 'OpenTelemetry.Extensions.Hosting' -or
$packageName -eq 'OpenTelemetry.Extensions.Propagators')
{
$projectDependencies[$packageName.ToString()] = $packageVersion.ToString()
}
}
$projectsAndDependencies[$projectDir.ToString()] = $projectDependencies
}
return $projectsAndDependencies
}
function InvokeCoreVersionUpdateWorkflowInRemoteRepository {
param(
[Parameter(Mandatory=$true)][string]$remoteGitRepository,
[Parameter(Mandatory=$true)][string]$tag,
[Parameter()][string]$targetBranch="main"
)
$match = [regex]::Match($tag, '^(.*?-)(.*)$')
if ($match.Success -eq $false)
{
throw 'Could not parse prefix or version from tag'
}
gh workflow run "core-version-update.yml" `
--repo $remoteGitRepository `
--ref $targetBranch `
--field "tag=$tag"
}
Export-ModuleMember -Function InvokeCoreVersionUpdateWorkflowInRemoteRepository
function TryPostReleasePublishedNoticeOnPrepareReleasePullRequest {
param(
[Parameter(Mandatory=$true)][string]$gitRepository,
[Parameter(Mandatory=$true)][string]$botUserName,
[Parameter(Mandatory=$true)][string]$tag
)
$tagSha = git rev-list -n 1 $tag 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git rev-list failure'
}
$prListResponse = gh pr list --search $tagSha --state merged --json number,author,title,comments | ConvertFrom-Json
if ($prListResponse.Length -eq 0)
{
Write-Host 'No prepare release PR found for tag & commit skipping post notice'
return
}
foreach ($pr in $prListResponse)
{
if ($pr.author.login -ne $botUserName -or $pr.title -ne "[release] Prepare release $tag")
{
continue
}
$foundComment = $false
foreach ($comment in $pr.comments)
{
if ($comment.author.login -eq $botUserName -and $comment.body.StartsWith("The packages for [$tag](https://github.com/$gitRepository/releases/tag/$tag) are now available:"))
{
$foundComment = $true
break
}
}
if ($foundComment -eq $false)
{
continue
}
$body =
@"
The release [$tag](https://github.com/$gitRepository/releases/tag/$tag) has been published and packages should be available on NuGet momentarily.
Have a nice day!
"@
$pullRequestNumber = $pr.number
gh pr comment $pullRequestNumber --body $body
return
}
Write-Host 'No prepare release PR found matched author and title with a valid comment'
}
Export-ModuleMember -Function TryPostReleasePublishedNoticeOnPrepareReleasePullRequest

View File

@ -1,463 +0,0 @@
function CreatePullRequestToUpdateChangelogsAndPublicApis {
param(
[Parameter(Mandatory=$true)][string]$gitRepository,
[Parameter(Mandatory=$true)][string]$minVerTagPrefix,
[Parameter(Mandatory=$true)][string]$version,
[Parameter(Mandatory=$true)][string]$requestedByUserName,
[Parameter()][string]$targetBranch="main",
[Parameter()][string]$gitUserName,
[Parameter()][string]$gitUserEmail
)
$match = [regex]::Match($version, '^(\d+\.\d+\.\d+)(?:-((?:alpha)|(?:beta)|(?:rc))\.(\d+))?$')
if ($match.Success -eq $false)
{
throw 'Input version did not match expected format'
}
$isPrerelease = $version -match '-alpha' -or $version -match '-beta' -or $version -match '-rc'
$tag="${minVerTagPrefix}${version}"
$branch="release/prepare-${tag}-release"
if ([string]::IsNullOrEmpty($gitUserName) -eq $false)
{
git config user.name $gitUserName
}
if ([string]::IsNullOrEmpty($gitUserEmail) -eq $false)
{
git config user.email $gitUserEmail
}
git switch --create $branch 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git switch failure'
}
$body =
@"
Note: This PR was opened automatically by the [prepare release workflow](https://github.com/$gitRepository/actions/workflows/prepare-release.yml).
Requested by: @$requestedByUserName
## Changes
* CHANGELOG files updated for projects being released.
"@
# Update CHANGELOGs
& ./build/scripts/update-changelogs.ps1 -minVerTagPrefix $minVerTagPrefix -version $version
# Update publicApi files for stable releases
if ($isPrerelease -ne $true)
{
& ./build/scripts/finalize-publicapi.ps1 -minVerTagPrefix $minVerTagPrefix
$body += "`r`n* Public API files updated for projects being released (only performed for stable releases)."
}
$body +=
@"
## Commands
``/UpdateReleaseDates``: Use to update release dates in CHANGELOGs before merging [``approvers``, ``maintainers``]
"@
if ($minVerTagPrefix -eq 'core-' -and $isPrerelease -ne $true)
{
$body +=
@"
``/UpdateReleaseNotes``: Use to update ``RELEASENOTES.md`` before merging [``approvers``, ``maintainers``]
"@
}
$body +=
@"
``/CreateReleaseTag``: Use after merging to push the release tag and trigger the job to create packages [``approvers``, ``maintainers``]
``/PushPackages``: Use after the created packages have been validated to push to NuGet [``maintainers``]
"@
git commit -a -m "Prepare repo to release $tag." 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git commit failure'
}
git push -u origin $branch 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git push failure'
}
$createPullRequestResponse = gh pr create `
--title "[release] Prepare release $tag" `
--body $body `
--base $targetBranch `
--head $branch `
--label release
Write-Host $createPullRequestResponse
$match = [regex]::Match($createPullRequestResponse, "\/pull\/(.*)$")
if ($match.Success -eq $false)
{
throw 'Could not parse pull request number from gh pr create response'
}
$pullRequestNumber = $match.Groups[1].Value
if ($minVerTagPrefix -eq 'core-' -and $isPrerelease -ne $true)
{
$found = Select-String -Path "RELEASENOTES.md" -Pattern "## $version" -Quiet
if ($found -eq $false)
{
$body =
@"
I noticed this PR is releasing a stable version of core packages but there isn't any content in ``RELEASENOTES.md`` for the version being released.
It is important to update ``RELEASENOTES.md`` before creating the release tag because a permalink will become part of the package(s).
Post a comment with "/UpdateReleaseNotes" in the body if you would like me to update release notes.
Note: In the comment everything below "/UpdateReleaseNotes" will be added to ``RELEASENOTES.md`` for the version being released. If something is already there it will be replaced.
"@
gh pr comment $pullRequestNumber --body $body
}
}
}
Export-ModuleMember -Function CreatePullRequestToUpdateChangelogsAndPublicApis
function LockPullRequestAndPostNoticeToCreateReleaseTag {
param(
[Parameter(Mandatory=$true)][string]$gitRepository,
[Parameter(Mandatory=$true)][string]$pullRequestNumber,
[Parameter(Mandatory=$true)][string]$botUserName
)
$prViewResponse = gh pr view $pullRequestNumber --json mergeCommit,author,title | ConvertFrom-Json
if ($prViewResponse.author.login -ne $botUserName)
{
throw 'PR author was unexpected'
}
$match = [regex]::Match($prViewResponse.title, '^\[release\] Prepare release (.*)$')
if ($match.Success -eq $false)
{
throw 'Could not parse tag from PR title'
}
$tag = $match.Groups[1].Value
$commit = $prViewResponse.mergeCommit.oid
if ([string]::IsNullOrEmpty($commit) -eq $true)
{
throw 'Could not find merge commit'
}
$body =
@"
I noticed this PR was merged.
Post a comment with "/CreateReleaseTag" in the body if you would like me to create the release tag ``$tag`` for [the merge commit](https://github.com/$gitRepository/commit/$commit) which will trigger the package workflow.
"@
gh pr comment $pullRequestNumber --body $body
gh pr lock $pullRequestNumber
}
Export-ModuleMember -Function LockPullRequestAndPostNoticeToCreateReleaseTag
function CreateReleaseTagAndPostNoticeOnPullRequest {
param(
[Parameter(Mandatory=$true)][string]$gitRepository,
[Parameter(Mandatory=$true)][string]$pullRequestNumber,
[Parameter(Mandatory=$true)][string]$botUserName,
[Parameter()][string]$gitUserName,
[Parameter()][string]$gitUserEmail
)
$prViewResponse = gh pr view $pullRequestNumber --json mergeCommit,author,title | ConvertFrom-Json
if ($prViewResponse.author.login -ne $botUserName)
{
throw 'PR author was unexpected'
}
$match = [regex]::Match($prViewResponse.title, '^\[release\] Prepare release (.*)$')
if ($match.Success -eq $false)
{
throw 'Could not parse tag from PR title'
}
$tag = $match.Groups[1].Value
$commit = $prViewResponse.mergeCommit.oid
if ([string]::IsNullOrEmpty($commit) -eq $true)
{
throw 'Could not find merge commit'
}
if ([string]::IsNullOrEmpty($gitUserName) -eq $false)
{
git config user.name $gitUserName
}
if ([string]::IsNullOrEmpty($gitUserEmail) -eq $false)
{
git config user.email $gitUserEmail
}
git tag -a $tag -m "$tag" $commit 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git tag failure'
}
git push origin $tag 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git push failure'
}
$body =
@"
I just pushed the [$tag](https://github.com/$gitRepository/releases/tag/$tag) tag.
The [package workflow](https://github.com/$gitRepository/actions/workflows/publish-packages-1.0.yml) should begin momentarily.
"@
gh pr comment $pullRequestNumber --body $body
}
Export-ModuleMember -Function CreateReleaseTagAndPostNoticeOnPullRequest
function UpdateChangelogReleaseDatesAndPostNoticeOnPullRequest {
param(
[Parameter(Mandatory=$true)][string]$gitRepository,
[Parameter(Mandatory=$true)][string]$pullRequestNumber,
[Parameter(Mandatory=$true)][string]$botUserName,
[Parameter(Mandatory=$true)][string]$commentUserName,
[Parameter()][string]$gitUserName,
[Parameter()][string]$gitUserEmail
)
$prViewResponse = gh pr view $pullRequestNumber --json headRefName,author,title | ConvertFrom-Json
if ($prViewResponse.author.login -ne $botUserName)
{
throw 'PR author was unexpected'
}
$match = [regex]::Match($prViewResponse.title, '^\[release\] Prepare release (.*)$')
if ($match.Success -eq $false)
{
throw 'Could not parse tag from PR title'
}
$tag = $match.Groups[1].Value
$match = [regex]::Match($tag, '^(.*?-)(.*)$')
if ($match.Success -eq $false)
{
throw 'Could not parse prefix or version from tag'
}
$tagPrefix = $match.Groups[1].Value
$version = $match.Groups[2].Value
$commentUserPermission = gh api "repos/$gitRepository/collaborators/$commentUserName/permission" | ConvertFrom-Json
if ($commentUserPermission.permission -ne 'admin' -and $commentUserPermission.permission -ne 'write')
{
gh pr comment $pullRequestNumber `
--body "I'm sorry @$commentUserName but you don't have permission to update this PR. Only maintainers and approvers can update this PR."
return
}
if ([string]::IsNullOrEmpty($gitUserName) -eq $false)
{
git config user.name $gitUserName
}
if ([string]::IsNullOrEmpty($gitUserEmail) -eq $false)
{
git config user.email $gitUserEmail
}
git switch $prViewResponse.headRefName 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git switch failure'
}
$updatedFiles = 0
$newHeader =
@"
## $version
Released $(Get-Date -UFormat '%Y-%b-%d')
"@
$projectDirs = Get-ChildItem -Path src/**/*.csproj | Select-String "<MinVerTagPrefix>$tagPrefix</MinVerTagPrefix>" -List | Select Path | Split-Path -Parent
foreach ($projectDir in $projectDirs)
{
$content = (Get-Content "$projectDir/CHANGELOG.md" -Raw)
$newContent = $content -replace "## $version\s*Released .*", $newHeader
if ($content -ne $newContent)
{
$updatedFiles++
Set-Content -Path "$projectDir/CHANGELOG.md" $newContent.Trim()
}
}
if ($updatedFiles -eq 0)
{
gh pr comment $pullRequestNumber --body "All of the CHANGELOG files have valid release dates."
return
}
git commit -a -m "Update CHANGELOG release dates for $tag." 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git commit failure'
}
git push -u origin $prViewResponse.headRefName 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git push failure'
}
gh pr comment $pullRequestNumber --body "I updated the CHANGELOG release dates."
}
Export-ModuleMember -Function UpdateChangelogReleaseDatesAndPostNoticeOnPullRequest
function UpdateReleaseNotesAndPostNoticeOnPullRequest {
param(
[Parameter(Mandatory=$true)][string]$gitRepository,
[Parameter(Mandatory=$true)][string]$pullRequestNumber,
[Parameter(Mandatory=$true)][string]$botUserName,
[Parameter(Mandatory=$true)][string]$commentUserName,
[Parameter(Mandatory=$true)][string]$commentBody,
[Parameter()][string]$gitUserName,
[Parameter()][string]$gitUserEmail
)
$prViewResponse = gh pr view $pullRequestNumber --json headRefName,author,title | ConvertFrom-Json
if ($prViewResponse.author.login -ne $botUserName)
{
throw 'PR author was unexpected'
}
$match = [regex]::Match($prViewResponse.title, '^\[release\] Prepare release (.*)$')
if ($match.Success -eq $false)
{
throw 'Could not parse tag from PR title'
}
$tag = $match.Groups[1].Value
$match = [regex]::Match($tag, '^(.*?-)(.*)$')
if ($match.Success -eq $false)
{
throw 'Could not parse prefix or version from tag'
}
$tagPrefix = $match.Groups[1].Value
$version = $match.Groups[2].Value
$isPrerelease = $version -match '-alpha' -or $version -match '-beta' -or $version -match '-rc'
$commentUserPermission = gh api "repos/$gitRepository/collaborators/$commentUserName/permission" | ConvertFrom-Json
if ($commentUserPermission.permission -ne 'admin' -and $commentUserPermission.permission -ne 'write')
{
gh pr comment $pullRequestNumber `
--body "I'm sorry @$commentUserName but you don't have permission to update this PR. Only maintainers and approvers can update this PR."
return
}
if ($tagPrefix -ne 'core-' -or $isPrerelease -eq $true)
{
gh pr comment $pullRequestNumber `
--body "I'm sorry @$commentUserName but we don't typically add release notes for prereleases or unstable packages."
return
}
if ([string]::IsNullOrEmpty($gitUserName) -eq $false)
{
git config user.name $gitUserName
}
if ([string]::IsNullOrEmpty($gitUserEmail) -eq $false)
{
git config user.email $gitUserEmail
}
git switch $prViewResponse.headRefName 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git switch failure'
}
$releaseNotesContent = (Get-Content -Path "RELEASENOTES.md" -Raw)
$match = [regex]::Match($commentBody, '[\w\W\s]*\/UpdateReleaseNotes.*$([\w\W\s]*)', [Text.RegularExpressions.RegexOptions]::Multiline)
if ($match.Success -eq $false)
{
throw 'Could not find release notes content'
}
$content = $match.Groups[1].Value.Trim() -replace "`r`n", "`n"
$body =
@"
## $version
Release details: [$version](https://github.com/$gitRepository/releases/tag/$tagPrefix$version)
$content
##
"@
$match = [regex]::Match($releaseNotesContent, "(## $version[\w\W\s]*?)##", [Text.RegularExpressions.RegexOptions]::Multiline)
if ($match.Success -eq $true)
{
$content = [regex]::Replace($releaseNotesContent, "(## $version[\w\W\s]*?)##", $body, [Text.RegularExpressions.RegexOptions]::Multiline)
Set-Content -Path "RELEASENOTES.md" -Value $content.TrimEnd()
}
else {
$match = [regex]::Match($releaseNotesContent, '(# Release Notes[\w\W\s]*?)##', [Text.RegularExpressions.RegexOptions]::Multiline)
if ($match.Success -eq $false)
{
throw 'Could not find release notes header'
}
$body = $match.Groups[1].Value + $body
$content = [regex]::Replace($releaseNotesContent, '(# Release Notes[\w\W\s]*?)##', $body, [Text.RegularExpressions.RegexOptions]::Multiline)
Set-Content -Path "RELEASENOTES.md" -Value $content.TrimEnd()
}
git commit -a -m "Update RELEASENOTES for $tag." 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git commit failure'
}
git push -u origin $prViewResponse.headRefName 2>&1 | % ToString
if ($LASTEXITCODE -gt 0)
{
throw 'git push failure'
}
gh pr comment $pullRequestNumber --body "I updated ``RELEASENOTES.md``."
}
Export-ModuleMember -Function UpdateReleaseNotesAndPostNoticeOnPullRequest

View File

@ -1,49 +0,0 @@
param([string]$targetNetFramework)
$rootDirectory = Get-Location
$publishOutput = dotnet publish $rootDirectory/test/OpenTelemetry.AotCompatibility.TestApp/OpenTelemetry.AotCompatibility.TestApp.csproj --framework $targetNetFramework -nodeReuse:false /p:UseSharedCompilation=false /p:ExposeExperimentalFeatures=true
$actualWarningCount = 0
foreach ($line in $($publishOutput -split "`r`n"))
{
if (($line -like "*analysis warning IL*") -or ($line -like "*analysis error IL*"))
{
Write-Host $line
$actualWarningCount += 1
}
}
Write-Host "Actual warning count is:", $actualWarningCount
$expectedWarningCount = 0
if ($LastExitCode -ne 0)
{
Write-Host "There was an error while publishing AotCompatibility Test App. LastExitCode is:", $LastExitCode
Write-Host $publishOutput
}
$app = $IsWindows ? "./OpenTelemetry.AotCompatibility.TestApp.exe" : "./OpenTelemetry.AotCompatibility.TestApp"
Push-Location $rootDirectory/artifacts/publish/OpenTelemetry.AotCompatibility.TestApp/release_$targetNetFramework
Write-Host "Executing test App..."
$app
Write-Host "Finished executing test App"
if ($LastExitCode -ne 0)
{
Write-Host "There was an error while executing AotCompatibility Test App. LastExitCode is:", $LastExitCode
}
Pop-Location
$testPassed = 0
if ($actualWarningCount -ne $expectedWarningCount)
{
$testPassed = 1
Write-Host "Actual warning count:", $actualWarningCount, "is not as expected. Expected warning count is:", $expectedWarningCount
}
Exit $testPassed

View File

@ -1,20 +0,0 @@
param(
[Parameter(Mandatory=$true)][string]$minVerTagPrefix,
[Parameter(Mandatory=$true)][string]$version
)
$projectDirs = Get-ChildItem -Path src/**/*.csproj | Select-String "<MinVerTagPrefix>$minVerTagPrefix</MinVerTagPrefix>" -List | Select Path | Split-Path -Parent
$content = "Unreleased
## $version
Released $(Get-Date -UFormat '%Y-%b-%d')"
foreach ($projectDir in $projectDirs) {
$path = Join-Path -Path $projectDir -ChildPath "CHANGELOG.md"
Write-Host "Updating $path"
(Get-Content -Path $path) -replace "Unreleased", $content | Set-Content -Path $path
}

View File

@ -0,0 +1,41 @@
param([string]$targetNetFramework)
$rootDirectory = Split-Path $PSScriptRoot -Parent
$publishOutput = dotnet publish $rootDirectory/test/OpenTelemetry.AotCompatibility.TestApp/OpenTelemetry.AotCompatibility.TestApp.csproj -nodeReuse:false /p:UseSharedCompilation=false /p:ExposeExperimentalFeatures=true
$actualWarningCount = 0
foreach ($line in $($publishOutput -split "`r`n"))
{
if ($line -like "*analysis warning IL*")
{
Write-Host $line
$actualWarningCount += 1
}
}
pushd $rootDirectory/test/OpenTelemetry.AotCompatibility.TestApp/bin/Release/$targetNetFramework/linux-x64
Write-Host "Executing test App..."
./OpenTelemetry.AotCompatibility.TestApp
Write-Host "Finished executing test App"
if ($LastExitCode -ne 0)
{
Write-Host "There was an error while executing AotCompatibility Test App. LastExitCode is:", $LastExitCode
}
popd
Write-Host "Actual warning count is:", $actualWarningCount
$expectedWarningCount = 0
$testPassed = 0
if ($actualWarningCount -ne $expectedWarningCount)
{
$testPassed = 1
Write-Host "Actual warning count:", actualWarningCount, "is not as expected. Expected warning count is:", $expectedWarningCount
}
Exit $testPassed

View File

@ -1,32 +1,22 @@
param(
[Parameter()][string]$coyoteVersion="1.7.11",
[Parameter()][string]$coyoteVersion="1.7.10",
[Parameter(Mandatory=$true)][string]$testProjectName,
[Parameter(Mandatory=$true)][string]$targetFramework,
[Parameter()][string]$categoryName="CoyoteConcurrencyTests",
[Parameter()][string]$configuration="Release"
)
$ErrorActionPreference = "Stop"
$env:OTEL_RUN_COYOTE_TESTS = 'true'
$rootDirectory = Get-Location
$rootDirectory = Split-Path $PSScriptRoot -Parent
Write-Host "Install Coyote CLI."
dotnet tool install --global Microsoft.Coyote.CLI --version $coyoteVersion
if ($LASTEXITCODE -ne 0) {
throw "Microsoft.Coyote.CLI installation failed with exit code $LASTEXITCODE"
}
dotnet tool install --global Microsoft.Coyote.CLI
Write-Host "Build $testProjectName project."
dotnet build "$rootDirectory/test/$testProjectName/$testProjectName.csproj" --configuration $configuration
if ($LASTEXITCODE -ne 0) {
throw "dotnet build failed with exit code $LASTEXITCODE"
}
$artifactsPath = Join-Path $rootDirectory "artifacts/bin/$testProjectName/$($configuration.ToLowerInvariant())_$targetFramework"
$artifactsPath = Join-Path $rootDirectory "test/$testProjectName/bin/$configuration/$targetFramework"
Write-Host "Generate Coyote rewriting options JSON file."
$assemblies = Get-ChildItem $artifactsPath -Filter OpenTelemetry*.dll | ForEach-Object {$_.Name}
@ -39,13 +29,6 @@ $RewriteOptionsJson | ConvertTo-Json -Compress | Set-Content -Path "$rootDirecto
Write-Host "Run Coyote rewrite."
coyote rewrite "$rootDirectory/test/$testProjectName/rewrite.coyote.json"
if ($LASTEXITCODE -ne 0) {
throw "coyote rewrite failed with exit code $LASTEXITCODE"
}
Write-Host "Execute re-written binary."
dotnet test "$artifactsPath/$testProjectName.dll" --framework $targetFramework --filter CategoryName=$categoryName
if ($LASTEXITCODE -ne 0) {
throw "dotnet test failed with exit code $LASTEXITCODE"
}

View File

@ -1,11 +1,8 @@
<Project>
<Import Project="$([System.IO.Path]::Combine($(MSBuildThisFileDirectory), '..', 'Directory.Build.props'))" />
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), 'OpenTelemetry.sln'))\build\Common.nonprod.props" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>$(TargetFrameworksForDocs)</TargetFrameworks>
<!-- Opt-out of Artifacts Output for docs as there are duplicated project names -->
<UseArtifactsOutput>false</UseArtifactsOutput>
</PropertyGroup>
</Project>

View File

@ -1,134 +0,0 @@
# OpenTelemetry .NET SDK
## Initialize the SDK
There are two different common initialization styles supported by OpenTelemetry.
### Initialize the SDK using a host
Users building applications based on
[Microsoft.Extensions.Hosting](https://www.nuget.org/packages/Microsoft.Extensions.Hosting)
should utilize the
[OpenTelemetry.Extensions.Hosting](../src/OpenTelemetry.Extensions.Hosting/README.md)
package to initialize OpenTelemetry. This style provides a deep integration
between the host infrastructure (`IServiceCollection`, `IServiceProvider`,
`IConfiguration`, etc.) and OpenTelemetry.
[AspNetCore](https://learn.microsoft.com/aspnet/core/fundamentals/host/web-host)
applications are the most common to use the hosting model but there is also a
[Generic Host](https://learn.microsoft.com/dotnet/core/extensions/generic-host)
which may be used in console, service, and worker applications.
> [!NOTE]
> When using `OpenTelemetry.Extensions.Hosting` only a single pipeline will be
> created for each configured signal (logging, metrics, and/or tracing). Users
> who need more granular control can create additional pipelines using the
> manual style below.
First install the
[OpenTelemetry.Extensions.Hosting](../src/OpenTelemetry.Extensions.Hosting/README.md)
package.
Second call the `AddOpenTelemetry` extension using the host
`IServiceCollection`:
```csharp
var builder = WebApplication.CreateBuilder(args);
// Clear the default logging providers added by the host
builder.Logging.ClearProviders();
// Initialize OpenTelemetry
builder.Services.AddOpenTelemetry()
.ConfigureResource(resource => /* Resource configuration goes here */)
.WithLogging(logging => /* Logging configuration goes here */)
.WithMetrics(metrics => /* Metrics configuration goes here */)
.WithTracing(tracing => /* Tracing configuration goes here */));
```
> [!NOTE]
> Calling `WithLogging` automatically registers the OpenTelemetry
> `ILoggerProvider` and enables `ILogger` integration.
### Initialize the SDK manually
Users running on .NET Framework or running without a host may initialize
OpenTelemetry manually.
> [!IMPORTANT]
> When initializing OpenTelemetry manually make sure to ALWAYS dispose the SDK
> and/or providers when the application is shutting down. Disposing
> OpenTelemetry gives the SDK a chance to flush any telemetry held in memory.
> Skipping this step may result in data loss.
First install the [OpenTelemetry SDK](../src/OpenTelemetry/README.md) package or
an exporter package such as
[OpenTelemetry.Exporter.OpenTelemetryProtocol](../src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md).
Exporter packages typically reference the SDK and will make it available via
transitive reference.
Second use one of the following initialization APIs (depending on the SDK
version being used):
#### Using 1.10.0 or newer
The `OpenTelemetrySdk.Create` API can be used to initialize all signals off a
single root builder and supports cross-cutting extensions such as
`ConfigureResource` which configures a `Resource` to be used by all enabled
signals. An `OpenTelemetrySdk` instance is returned which may be used to access
providers for each signal. Calling `Dispose` on the returned instance will
gracefully shutdown the SDK and flush any telemetry held in memory.
> [!NOTE]
> When calling `OpenTelemetrySdk.Create` a dedicated `IServiceCollection` and
> `IServiceProvider` will be created for the SDK and shared by all signals. An
> `IConfiguration` is created automatically from environment variables.
```csharp
using OpenTelemetry;
var sdk = OpenTelemetrySdk.Create(builder => builder
.ConfigureResource(resource => /* Resource configuration goes here */)
.WithLogging(logging => /* Logging configuration goes here */)
.WithMetrics(metrics => /* Metrics configuration goes here */)
.WithTracing(tracing => /* Tracing configuration goes here */));
// During application shutdown
sdk.Dispose();
```
To obtain an `ILogger` instance for emitting logs when using the
`OpenTelemetrySdk.Create` API call the `GetLoggerFactory` extension method using
the returned `OpenTelemetrySdk` instance:
```csharp
var logger = sdk.GetLoggerFactory().CreateLogger<Program>();
logger.LogInformation("Application started");
```
#### Using 1.9.0 or older
The following shows how to create providers for each individual signal. Each
provider is independent and must be managed and disposed explicitly. There is no
mechanism using this style to perform cross-cutting actions across signals.
```csharp
using Microsoft.Extensions.Logging;
using OpenTelemetry;
var tracerProvider = Sdk.CreateTracerProviderBuilder()
/* Tracing configuration goes here */
.Build();
var meterProvider = Sdk.CreateMeterProviderBuilder()
/* Metrics configuration goes here */
.Build();
var loggerFactory = LoggerFactory.Create(builder => builder
.AddOpenTelemetry(options => /* Logging configuration goes here */));
// During application shutdown
tracerProvider.Dispose();
meterProvider.Dispose();
loggerFactory.Dispose();
```

View File

@ -4,17 +4,11 @@
This is an Experimental API diagnostic covering the following APIs:
* `ILoggingBuilder.UseOpenTelemetry`
Experimental APIs may be changed or removed in the future.
The following portions of `OTEL1000` were released stable in `1.9.0` and are no
longer considered experimental:
* `LoggerProviderBuilder`
* `LoggerProvider`
* `IDeferredLoggerProviderBuilder`
* `OpenTelemetryBuilder.WithLogging`
Experimental APIs may be changed or removed in the future.
## Details

View File

@ -9,7 +9,6 @@ This is an Experimental API diagnostic covering the following APIs:
* `LogRecordAttributeList`
* `LogRecordData`
* `LogRecordSeverity`
* `Sdk.CreateLoggerProviderBuilder`
Experimental APIs may be changed or removed in the future.

View File

@ -0,0 +1,30 @@
# OpenTelemetry .NET Diagnostic: OTEL1002
## Overview
This is an Experimental API diagnostic covering the following APIs:
* `AlwaysOnExemplarFilter`
* `AlwaysOffExemplarFilter`
* `Exemplar`
* `ExemplarFilter`
* `MeterProviderBuilder.SetExemplarFilter` extension method
* `TraceBasedExemplarFilter`
Experimental APIs may be changed or removed in the future.
## Details
The OpenTelemetry Specification defines an [Exemplar
API](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#exemplar)
in the Metrics SDK.
From the specification:
> Exemplars are example data points for aggregated data. They provide specific
> context to otherwise general aggregations. Exemplars allow correlation between
> aggregated metric data and the original API calls where measurements are
> recorded.
We are exposing these APIs experimentally until the specification declares them
stable.

View File

@ -0,0 +1,47 @@
# OpenTelemetry .NET Diagnostic: OTEL1003
## Overview
This is an Experimental API diagnostic covering the following API:
* `MetricStreamConfiguration.CardinalityLimit.get`
* `MetricStreamConfiguration.CardinalityLimit.set`
Experimental APIs may be changed or removed in the future.
## Details
From the specification:
> The cardinality limit for an aggregation is defined in one of three ways:
>
> 1. A view with criteria matching the instrument an aggregation is created for
> has an `aggregation_cardinality_limit` value defined for the stream, that
> value SHOULD be used.
> 2. If there is no matching view, but the `MetricReader` defines a default
> cardinality limit value based on the instrument an aggregation is created
> for, that value SHOULD be used.
> 3. If none of the previous values are defined, the default value of 2000
> SHOULD be used.
We are exposing these APIs experimentally until the specification declares them
stable.
### Setting cardinality limit for a specific Metric via the View API
The OpenTelemetry Specification defines the [cardinality
limit](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#cardinality-limits)
of a metric can be set by the matching view.
```csharp
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddView(
instrumentName: "MyFruitCounter",
new MetricStreamConfiguration { CardinalityLimit = 10 })
.Build();
```
### Setting cardinality limit for a specific MetricReader
[This is not currently supported by OpenTelemetry
.NET.](https://github.com/open-telemetry/opentelemetry-dotnet/issues/5331)

View File

@ -1,62 +0,0 @@
# OpenTelemetry .NET Diagnostic: OTEL1004
## Overview
This is an Experimental API diagnostic covering the following APIs:
* `ExemplarReservoir`
* `FixedSizeExemplarReservoir`
* `ExemplarMeasurement<T>`
* `MetricStreamConfiguration.ExemplarReservoirFactory.get`
* `MetricStreamConfiguration.ExemplarReservoirFactory.set`
Experimental APIs may be changed or removed in the future.
## Details
The OpenTelemetry Specification defines an [ExemplarReservoir
API](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#exemplarreservoir)
and a mechanism for configuring `ExemplarReservoir` via the [View
API](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#stream-configuration)
in the Metrics SDK.
From the specification:
> The SDK MUST provide a mechanism for SDK users to provide their own
> ExemplarReservoir implementation. This extension MUST be configurable on a
> metric View, although individual reservoirs MUST still be instantiated per
> metric-timeseries...
We are exposing these APIs experimentally for the following reasons:
* `FixedSizeExemplarReservoir` is not part of the spec. It is meant to help
custom reservoir authors and takes care of correctly creating & updating
`struct Exemplar`s (managing tag filtering when views are used), handles
`Exemplar` collection, and ensures all operations are safe to be called
concurrency (spec requirement). We want to see if this is helpful and meets
the needs of users.
* There is currently no way to use
`MetricStreamConfiguration.ExemplarReservoirFactory` to switch a metric to a
different built-in reservoir (`AlignedHistogramBucketExemplarReservoir` or
`SimpleFixedSizeExemplarReservoir`). This is something supported by the spec
but we want to understand the use cases and needs before exposing these types.
Also it seems the default reservoirs may change.
* There is currently no way to get access to the bucket index inside a reservoir
when a measurement is recorded against a histogram with explicit bounds. The
spec says the reservoir should calculate this given the
definition/configuration of the bounds but the SDK has already done this
computation. It seems unncessarily complicated to expose the configuration and
wasteful to do the work twice. We want to understand the types of algorithms
which users will want to implement before exposing something.
**TL;DR** We want to gather feedback on the usability of the API and for the
need(s) in general for custom reservoirs before exposing a stable API.
## Provide feedback
Please provide feedback on [this
issue](https://github.com/open-telemetry/opentelemetry-dotnet/issues/5629) if
you need stable support for custom `ExemplarReservoir`s. The feedback will help
inform decisions about what to expose stable and when.

View File

@ -27,11 +27,17 @@ Description: Logs Bridge API
Details: [OTEL1001](./OTEL1001.md)
### OTEL1004
### OTEL1002
Description: ExemplarReservoir Support
Description: Metrics Exemplar Support
Details: [OTEL1004](./OTEL1004.md)
Details: [OTEL1002](./OTEL1002.md)
### OTEL1003
Description: MetricStreamConfiguration CardinalityLimit Support
Details: [OTEL1003](./OTEL1003.md)
## Inactive
@ -45,18 +51,4 @@ Experimental APIs which have been released stable or removed:
removed add details for alternative solution or reasoning.
-->
### OTEL1002
Description: Metrics Exemplar Support
Details: [OTEL1002](https://github.com/open-telemetry/opentelemetry-dotnet/blob/b8ea807bae1a5d9b0f3d6d23b1e1e10f5e096a25/docs/diagnostics/experimental-apis/OTEL1002.md)
Released stable: `1.9.0`
### OTEL1003
Description: MetricStreamConfiguration CardinalityLimit Support
Details: [OTEL1003](https://github.com/open-telemetry/opentelemetry-dotnet/blob/9f41eadf03f3dcc5e76c686b61fb39849f046312/docs/diagnostics/experimental-apis/OTEL1003.md)
Released stable: `1.10.0`
None

View File

@ -1,5 +1,6 @@
# OpenTelemetry .NET Logs
<!-- markdownlint-disable MD033 -->
<details>
<summary>Table of Contents</summary>
@ -14,6 +15,7 @@
* [Log Redaction](#log-redaction)
</details>
<!-- markdownlint-enable MD033 -->
## Best Practices
@ -25,17 +27,33 @@ OpenTelemetry .NET:
* [Getting Started - Console Application](./getting-started-console/README.md)
* [Logging with Complex Objects](./complex-objects/README.md)
## Logging API
## Structured Logging
### ILogger
:heavy_check_mark: You should use structured logging.
.NET supports high performance, structured logging via the
[`Microsoft.Extensions.Logging.ILogger`](https://docs.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger)
interface (including
[`ILogger<TCategoryName>`](https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger-1))
to help monitor application behavior and diagnose issues.
* Structured logging is more efficient than unstructured logging.
* Filtering and redaction can happen on individual key-value pairs instead of
the entire log message.
* Storage and indexing are more efficient.
* Structured logging makes it easier to manage and consume logs.
#### Package Version
:stop_sign: You should avoid string interpolation.
> [!WARNING]
> The following code has bad performance due to [string
interpolation](https://learn.microsoft.com/dotnet/csharp/tutorials/string-interpolation):
```csharp
var food = "tomato";
var price = 2.99;
logger.LogInformation($"Hello from {food} {price}.");
```
Refer to the [logging performance
benchmark](../../test/Benchmarks/Logs/LogBenchmarks.cs) for more details.
## Package Version
:heavy_check_mark: You should always use the
[`ILogger`](https://docs.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger)
@ -53,6 +71,16 @@ package, regardless of the .NET runtime version being used:
backward compatibility on `Microsoft.Extensions.Logging` even during major
version bumps, so compatibility is not a concern here.
## Logging API
### ILogger
.NET supports high performance, structured logging via the
[`Microsoft.Extensions.Logging.ILogger`](https://docs.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger)
interface (including
[`ILogger<TCategoryName>`](https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger-1))
to help monitor application behavior and diagnose issues.
#### Get Logger
In order to use the `ILogger` interface, you need to first get a logger. How to
@ -99,38 +127,7 @@ are not super expensive, they still come with CPU and memory cost, and are meant
to be reused throughout the application. Refer to the [logging performance
benchmark](../../test/Benchmarks/Logs/LogBenchmarks.cs) for more details.
#### Write log messages
:heavy_check_mark: You should use structured logging.
* Structured logging is more efficient than unstructured logging.
* Filtering and redaction can happen on individual key-value pairs instead of
the entire log message.
* Storage and indexing are more efficient.
* Structured logging makes it easier to manage and consume logs.
```csharp
var food = "tomato";
var price = 2.99;
logger.LogInformation("Hello from {food} {price}.", food, price);
```
:stop_sign: You should avoid string interpolation.
> [!WARNING]
> The following code has bad performance due to [string
interpolation](https://learn.microsoft.com/dotnet/csharp/tutorials/string-interpolation):
```csharp
var food = "tomato";
var price = 2.99;
logger.LogInformation($"Hello from {food} {price}.");
```
Refer to the [logging performance
benchmark](../../test/Benchmarks/Logs/LogBenchmarks.cs) for more details.
#### Use Logger
:heavy_check_mark: You should use [compile-time logging source
generation](https://docs.microsoft.com/dotnet/core/extensions/logger-message-generator)
@ -182,156 +179,6 @@ logger.LogInformation("Hello from {food} {price}.", food, price);
Refer to the [logging performance
benchmark](../../test/Benchmarks/Logs/LogBenchmarks.cs) for more details.
:heavy_check_mark: You should hold a high bar while using
[`ILogger.IsEnabled`](https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger.isenabled).
The logging API is highly optimized for the scenario where most loggers are
**disabled** for certain log levels. Making an extra call to `IsEnabled` before
logging will not give you any performance gain.
> [!WARNING]
> The `logger.IsEnabled(LogLevel.Information)` call in the following code is not
going to give any performance gain. Refer to the [logging performance
benchmark](../../test/Benchmarks/Logs/LogBenchmarks.cs) for more details.
```csharp
var food = "tomato";
var price = 2.99;
if (logger.IsEnabled(LogLevel.Information)) // do not do this, there is no perf gain
{
logger.SayHello(food, price);
}
internal static partial class LoggerExtensions
{
[LoggerMessage(Level = LogLevel.Information, Message = "Hello from {food} {price}.")]
public static partial void SayHello(this ILogger logger, string food, double price);
}
```
`IsEnabled` can give performance benefits when it is expensive to evaluate the
arguments. For example, in the following code the `Database.GetFoodPrice`
invocation will be skipped if the logger is not enabled:
```csharp
if (logger.IsEnabled(LogLevel.Information))
{
logger.SayHello(food, Database.GetFoodPrice(food));
}
```
Although `IsEnabled` can give some performance benefits in the above scenario,
for most users it can cause more problems. For example, the performance of the
code is now depending on which logger is being enabled, not to mention the
argument evaluation might have significant side effects that are now depending
on the logging configuration.
:heavy_check_mark: You should use a dedicated parameter to log exceptions when
using the compile-time source generator.
```csharp
var food = "tomato";
var price = 2.99;
try
{
// Execute some logic
logger.SayHello(food, price);
}
catch (Exception ex)
{
logger.SayHelloFailure(ex, food, price);
}
internal static partial class LoggerExtensions
{
[LoggerMessage(Level = LogLevel.Information, Message = "Hello from {food} {price}.")]
public static partial void SayHello(this ILogger logger, string food, double price);
[LoggerMessage(Level = LogLevel.Error, Message = "Could not say hello from {food} {price}.")]
public static partial void SayHelloFailure(this ILogger logger, Exception exception, string food, double price);
}
```
> [!NOTE]
> When using the compile-time source generator the first `Exception` parameter
> detected is automatically given special handling. It **SHOULD NOT** be part of
> the message template. For details see: [Log method
> anatomy](https://learn.microsoft.com/dotnet/core/extensions/logger-message-generator#log-method-anatomy).
:heavy_check_mark: You should use the dedicated overloads to log exceptions when
using the logging extensions methods.
```csharp
var food = "tomato";
var price = 2.99;
try
{
// Execute some logic
logger.LogInformation("Hello from {food} {price}.", food, price);
}
catch (Exception ex)
{
logger.LogError(ex, "Could not say hello from {food} {price}.", food, price);
}
```
:stop_sign: You should avoid adding exception details into the message template.
You want to use the correct `Exception` APIs because the OpenTelemetry
Specification [defines dedicated
attributes](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/exceptions/exceptions-logs.md)
for `Exception` details. The following examples show what **NOT** to do. In
these cases the details won't be lost, but the dedicated attributes also won't
be added.
```csharp
var food = "tomato";
var price = 2.99;
try
{
// Execute some logic
logger.SayHello(food, price);
}
catch (Exception ex)
{
logger.SayHelloFailure(food, price, ex.Message);
}
internal static partial class LoggerExtensions
{
[LoggerMessage(Level = LogLevel.Information, Message = "Hello from {food} {price}.")]
public static partial void SayHello(this ILogger logger, string food, double price);
// BAD - Exception should not be part of the message template. Use the dedicated parameter.
[LoggerMessage(Level = LogLevel.Error, Message = "Could not say hello from {food} {price} {message}.")]
public static partial void SayHelloFailure(this ILogger logger, string food, double price, string message);
}
```
```csharp
var food = "tomato";
var price = 2.99;
try
{
// Execute some logic
logger.LogInformation("Hello from {food} {price}.", food, price);
}
catch (Exception ex)
{
// BAD - Exception should not be part of the message template. Use the dedicated parameter.
logger.LogError("Could not say hello from {food} {price} {message}.", food, price, ex.Message);
}
```
## LoggerFactory
In many cases, you can use [ILogger](#ilogger) without having to interact with

View File

@ -1,9 +1,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
namespace ComplexObjects;
internal struct FoodRecallNotice
public class FoodRecallNotice
{
public string? BrandName { get; set; }

View File

@ -1,7 +1,6 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
using ComplexObjects;
using Microsoft.Extensions.Logging;
using OpenTelemetry.Logs;
@ -35,5 +34,5 @@ internal static partial class LoggerExtensions
[LoggerMessage(LogLevel.Critical)]
public static partial void FoodRecallNotice(
this ILogger logger,
[LogProperties(OmitReferenceName = true)] in FoodRecallNotice foodRecallNotice);
[LogProperties(OmitReferenceName = true)] FoodRecallNotice foodRecallNotice);
}

View File

@ -30,12 +30,16 @@ dotnet add package Microsoft.Extensions.Telemetry.Abstractions
Define a new complex data type, as shown in [FoodRecallNotice.cs](./FoodRecallNotice.cs):
```csharp
public struct FoodRecallNotice
public class FoodRecallNotice
{
public string? BrandName { get; set; }
public string? ProductDescription { get; set; }
public string? ProductType { get; set; }
public string? RecallReasonDescription { get; set; }
public string? CompanyName { get; set; }
}
```
@ -50,7 +54,7 @@ internal static partial class LoggerExtensions
[LoggerMessage(LogLevel.Critical)]
public static partial void FoodRecallNotice(
this ILogger logger,
[LogProperties(OmitReferenceName = true)] in FoodRecallNotice foodRecallNotice);
[LogProperties(OmitReferenceName = true)] FoodRecallNotice foodRecallNotice);
}
```

View File

@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Telemetry.Abstractions" />

View File

@ -7,9 +7,7 @@ using OpenTelemetry;
using OpenTelemetry.Logs;
using OpenTelemetry.Trace;
namespace Correlation;
internal sealed class Program
public class Program
{
private static readonly ActivitySource MyActivitySource = new("MyCompany.MyProduct.MyLibrary");

View File

@ -14,10 +14,9 @@ TODO
### IncludeScopes
Log
[scope](https://docs.microsoft.com/dotnet/core/extensions/logging#log-scopes) is
an `ILogger` concept that can group a set of logical operations and attach data
to each log created as part of a set.
A "[scope](https://docs.microsoft.com/dotnet/core/extensions/logging#log-scopes)"
is an `ILogger` concept that can group a set of logical operations and attach
data to each log created as part of a set.
`IncludeScopes` is off by default. Setting this to `true` will include all
scopes with the exported `LogRecord`. Consult the individual `Exporter`
@ -25,14 +24,6 @@ docs to learn more about how scopes will be processed.
See [Program.cs](Program.cs) for an example.
> [!NOTE]
> When using [`ILogger.BeginScope<TState>(TState
state)`](https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger.beginscope),
it is highly recommended to use `IReadOnlyList<KeyValue<string, object?>>` or
`List<KeyValuePair<string, object?>>` as the `TState` for the best performance.
When performance is not a critical requirement,
`IEnumerable<KeyValuePair<string, object?>>` can be used.
### IncludeFormattedMessage
`IncludeFormattedMessage` indicates if the `LogRecord.FormattedMessage` will be

View File

@ -6,30 +6,25 @@ using OpenTelemetry.Logs;
namespace DedicatedLogging;
internal static class DedicatedLoggingServiceCollectionExtensions
public static class DedicatedLoggingServiceCollectionExtensions
{
public static IServiceCollection AddDedicatedLogging(
this IServiceCollection services,
IConfiguration configuration,
Action<LoggerProviderBuilder> configureOpenTelemetry)
Action<OpenTelemetryLoggerOptions> configureOpenTelemetry)
{
ArgumentNullException.ThrowIfNull(configureOpenTelemetry);
services.TryAddSingleton(_ =>
services.TryAddSingleton(sp =>
{
var services = new ServiceCollection();
services.AddLogging(builder =>
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConfiguration(configuration);
builder.AddOpenTelemetry();
builder.AddOpenTelemetry(configureOpenTelemetry);
});
services.ConfigureOpenTelemetryLoggerProvider(configureOpenTelemetry);
var sp = services.BuildServiceProvider();
return new DedicatedLoggerFactory(sp);
return new DedicatedLoggerFactory(loggerFactory);
});
services.TryAdd(ServiceDescriptor.Singleton(typeof(IDedicatedLogger<>), typeof(DedicatedLogger<>)));
@ -59,13 +54,11 @@ internal static class DedicatedLoggingServiceCollectionExtensions
private sealed class DedicatedLoggerFactory : ILoggerFactory
{
private readonly ServiceProvider serviceProvider;
private readonly ILoggerFactory innerLoggerFactory;
public DedicatedLoggerFactory(ServiceProvider serviceProvider)
public DedicatedLoggerFactory(ILoggerFactory loggerFactory)
{
this.serviceProvider = serviceProvider;
this.innerLoggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
this.innerLoggerFactory = loggerFactory;
}
public void AddProvider(ILoggerProvider provider)
@ -75,6 +68,6 @@ internal static class DedicatedLoggingServiceCollectionExtensions
=> this.innerLoggerFactory.CreateLogger(categoryName);
public void Dispose()
=> this.serviceProvider.Dispose();
=> this.innerLoggerFactory.Dispose();
}
}

View File

@ -3,10 +3,10 @@
namespace DedicatedLogging;
internal interface IDedicatedLogger : ILogger
public interface IDedicatedLogger : ILogger
{
}
internal interface IDedicatedLogger<out TCategoryName> : IDedicatedLogger
public interface IDedicatedLogger<out TCategoryName> : IDedicatedLogger
{
}

View File

@ -8,19 +8,18 @@ var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Services.AddOpenTelemetry()
.WithLogging(logging =>
{
// Set up primary pipeline for common app logs
logging.AddConsoleExporter();
});
builder.Logging.AddOpenTelemetry(options =>
{
// Set up primary pipeline for common app logs
options.AddConsoleExporter();
});
builder.Services.AddDedicatedLogging(
builder.Configuration.GetSection("DedicatedLogging"), // Bind configuration for dedicated logging pipeline
logging =>
options =>
{
// Set up secondary pipeline for dedicated logs
logging.AddConsoleExporter();
options.AddConsoleExporter();
});
var app = builder.Build();

View File

@ -1,8 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<NoWarn>$(NoWarn);CA1812;CA2213</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Console\OpenTelemetry.Exporter.Console.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Extensions.Hosting\OpenTelemetry.Extensions.Hosting.csproj" />

View File

@ -5,7 +5,7 @@ using System.Text;
using OpenTelemetry;
using OpenTelemetry.Logs;
internal sealed class MyExporter : BaseExporter<LogRecord>
internal class MyExporter : BaseExporter<LogRecord>
{
private readonly string name;
@ -59,7 +59,6 @@ internal sealed class MyExporter : BaseExporter<LogRecord>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
Console.WriteLine($"{this.name}.Dispose({disposing})");
}
}

View File

@ -4,7 +4,7 @@
using OpenTelemetry;
using OpenTelemetry.Logs;
internal sealed class MyProcessor : BaseProcessor<LogRecord>
internal class MyProcessor : BaseProcessor<LogRecord>
{
private readonly string name;
@ -32,7 +32,6 @@ internal sealed class MyProcessor : BaseProcessor<LogRecord>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
Console.WriteLine($"{this.name}.Dispose({disposing})");
}
}

View File

@ -6,7 +6,7 @@ using OpenTelemetry;
namespace ExtendingTheSdk;
internal sealed class Program
public class Program
{
public static void Main()
{
@ -29,16 +29,16 @@ internal sealed class Program
// logger.LogInformation($"Hello from potato {0.99}.");
// structured log with template
logger.LogInformation("Hello from {Name} {Price}.", "tomato", 2.99);
logger.LogInformation("Hello from {name} {price}.", "tomato", 2.99);
// structured log with strong type
logger.LogInformation("{Food}", new Food { Name = "artichoke", Price = 3.99 });
logger.LogInformation("{food}", new Food { Name = "artichoke", Price = 3.99 });
// structured log with anonymous type
logger.LogInformation("{Food}", new { Name = "pumpkin", Price = 5.99 });
logger.LogInformation("{food}", new { Name = "pumpkin", Price = 5.99 });
// structured log with general type
logger.LogInformation("{Food}", new Dictionary<string, object>
logger.LogInformation("{food}", new Dictionary<string, object>
{
["Name"] = "truffle",
["Price"] = 299.99,
@ -48,11 +48,11 @@ internal sealed class Program
using (logger.BeginScope("[operation]"))
using (logger.BeginScope("[hardware]"))
{
logger.LogError("{Name} is broken.", "refrigerator");
logger.LogError("{name} is broken.", "refrigerator");
}
// message will be redacted by MyRedactionProcessor
logger.LogInformation("OpenTelemetry {SensitiveString}.", "<secret>");
logger.LogInformation("OpenTelemetry {sensitiveString}.", "<secret>");
}
internal struct Food

View File

@ -1,8 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<NoWarn>$(NoWarn);CA2000;CA1848;CA1510;CA1305</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry\OpenTelemetry.csproj" />
</ItemGroup>

View File

@ -6,21 +6,25 @@ using OpenTelemetry.Resources;
var builder = WebApplication.CreateBuilder(args);
// For instructional purposes only, disable the default .NET logging providers.
// We remove the console logging provider in this demo to use the verbose
// OpenTelemetry console exporter instead. For most development and production
// scenarios the default console provider works well and there is no need to
// Remove default providers and add OpenTelemetry logging provider.
// For instructional purposes only, disable the default .NET console logging provider to
// use the verbose OpenTelemetry console exporter instead. For most development
// and production scenarios the default console provider works well and there is no need to
// clear these providers.
builder.Logging.ClearProviders();
// Add OpenTelemetry logging provider by calling the WithLogging extension.
builder.Services.AddOpenTelemetry()
.ConfigureResource(r => r.AddService(builder.Environment.ApplicationName))
.WithLogging(logging => logging
/* Note: ConsoleExporter is used for demo purpose only. In production
environment, ConsoleExporter should be replaced with other exporters
(e.g. OTLP Exporter). */
.AddConsoleExporter());
builder.Logging.AddOpenTelemetry(logging =>
{
var resourceBuilder = ResourceBuilder
.CreateDefault()
.AddService(builder.Environment.ApplicationName);
logging.SetResourceBuilder(resourceBuilder)
// ConsoleExporter is used for demo purpose only.
// In production environment, ConsoleExporter should be replaced with other exporters (e.g. OTLP Exporter).
.AddConsoleExporter();
});
var app = builder.Build();

View File

@ -15,18 +15,18 @@ internal sealed class MyRedactionProcessor : BaseProcessor<LogRecord>
}
}
internal sealed class MyClassWithRedactionEnumerator : IReadOnlyList<KeyValuePair<string, object?>>
internal sealed class MyClassWithRedactionEnumerator : IReadOnlyList<KeyValuePair<string, object>>
{
private readonly IReadOnlyList<KeyValuePair<string, object?>> state;
private readonly IReadOnlyList<KeyValuePair<string, object>> state;
public MyClassWithRedactionEnumerator(IReadOnlyList<KeyValuePair<string, object?>> state)
public MyClassWithRedactionEnumerator(IReadOnlyList<KeyValuePair<string, object>> state)
{
this.state = state;
}
public int Count => this.state.Count;
public KeyValuePair<string, object?> this[int index]
public KeyValuePair<string, object> this[int index]
{
get
{
@ -34,14 +34,14 @@ internal sealed class MyRedactionProcessor : BaseProcessor<LogRecord>
var entryVal = item.Value?.ToString();
if (entryVal != null && entryVal.Contains("<secret>"))
{
return new KeyValuePair<string, object?>(item.Key, "newRedactedValueHere");
return new KeyValuePair<string, object>(item.Key, "newRedactedValueHere");
}
return item;
}
}
public IEnumerator<KeyValuePair<string, object?>> GetEnumerator()
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
for (var i = 0; i < this.Count; i++)
{

View File

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<NoWarn>$(NoWarn);CA2213;CA1812;CA1307</NoWarn>
<!-- this is temporary. will remove in future PR. -->
<Nullable>disable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Console\OpenTelemetry.Exporter.Console.csproj" />
</ItemGroup>

View File

@ -1,5 +1,6 @@
# OpenTelemetry .NET Metrics
<!-- markdownlint-disable MD033 -->
<details>
<summary>Table of Contents</summary>
@ -10,15 +11,14 @@
* [Instruments](#instruments)
* [MeterProvider Management](#meterprovider-management)
* [Memory Management](#memory-management)
* [Example](#example)
* [Pre-Aggregation](#pre-aggregation)
* [Cardinality Limits](#cardinality-limits)
* [Memory Preallocation](#memory-preallocation)
* [Metrics Correlation](#metrics-correlation)
* [Metrics Enrichment](#metrics-enrichment)
* [Common issues that lead to missing metrics](#common-issues-that-lead-to-missing-metrics)
</details>
<!-- markdownlint-enable MD033 -->
## Best Practices
@ -45,9 +45,6 @@ package, regardless of the .NET runtime version being used:
* The .NET runtime team is holding a high bar for backward compatibility on
`System.Diagnostics.DiagnosticSource` even during major version bumps, so
compatibility is not a concern here.
* Refer to the [.NET official
document](https://learn.microsoft.com/dotnet/core/diagnostics/compare-metric-apis#systemdiagnosticsmetrics)
for more information about `System.Diagnostics.Metrics`.
## Metrics API
@ -59,7 +56,7 @@ too frequently. `Meter` is fairly expensive and meant to be reused throughout
the application. For most applications, it can be modeled as static readonly
field (e.g. [Program.cs](./getting-started-console/Program.cs)) or singleton via
dependency injection (e.g.
[InstrumentationSource.cs](../../examples/AspNetCore/InstrumentationSource.cs)).
[Instrumentation.cs](../../examples/AspNetCore/Instrumentation.cs)).
:heavy_check_mark: You should use dot-separated
[UpperCamelCase](https://en.wikipedia.org/wiki/Camel_case) as the
@ -88,7 +85,7 @@ static readonly Meter MyMeter = new("MyCompany.MyProduct.MyLibrary", "1.0");
| [Asynchronous Gauge](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#asynchronous-gauge) | [`ObservableGauge<T>`](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics.observablegauge-1) |
| [Asynchronous UpDownCounter](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#asynchronous-updowncounter) | [`ObservableUpDownCounter<T>`](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics.observableupdowncounter-1) |
| [Counter](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#counter) | [`Counter<T>`](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics.counter-1) |
| [Gauge](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#gauge) | [`Gauge<T>`](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics.gauge-1) |
| [Gauge](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#gauge) (experimental) | N/A |
| [Histogram](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#histogram) | [`Histogram<T>`](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics.histogram-1) |
| [UpDownCounter](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#updowncounter) | [`UpDownCounter<T>`](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics.updowncounter-1) |
@ -97,7 +94,7 @@ frequently. Instruments are fairly expensive and meant to be reused throughout
the application. For most applications, instruments can be modeled as static
readonly fields (e.g. [Program.cs](./getting-started-console/Program.cs)) or
singleton via dependency injection (e.g.
[InstrumentationSource.cs](../../examples/AspNetCore/InstrumentationSource.cs)).
[Instrumentation.cs](../../examples/AspNetCore/Instrumentation.cs)).
:stop_sign: You should avoid invalid instrument names.
@ -129,7 +126,7 @@ There are two different ways of passing tags to an instrument API:
* Pass the tags directly to the instrument API:
```csharp
counter.Add(100, new("Key1", "Value1"), new("Key2", "Value2"));
counter.Add(100, ("Key1", "Value1"), ("Key2", "Value2"));
```
* Use
@ -388,25 +385,37 @@ and the `MetricStreamConfiguration.CardinalityLimit` setting. Refer to this
[doc](../../docs/metrics/customizing-the-sdk/README.md#changing-the-cardinality-limit-for-a-metric)
for more information.
As of `1.10.0` once a metric has reached the cardinality limit, any new
measurement that could not be independently aggregated will be automatically
Given a metric, once the cardinality limit is reached, any new measurement which
cannot be independently aggregated because of the limit will be dropped or
aggregated using the [overflow
attribute](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#overflow-attribute).
attribute](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#overflow-attribute)
(if enabled). When NOT using the overflow attribute feature a warning is written
to the [self-diagnostic log](../../src/OpenTelemetry/README.md#self-diagnostics)
the first time an overflow is detected for a given metric.
> [!NOTE]
> In SDK versions `1.6.0` - `1.9.0` the overflow attribute was an experimental
feature that could be enabled by setting the environment variable
`OTEL_DOTNET_EXPERIMENTAL_METRICS_EMIT_OVERFLOW_ATTRIBUTE=true`.
> Overflow attribute was introduced in OpenTelemetry .NET
[1.6.0-rc.1](../../src/OpenTelemetry/CHANGELOG.md#160-rc1). It is currently an
experimental feature which can be turned on by setting the environment
variable `OTEL_DOTNET_EXPERIMENTAL_METRICS_EMIT_OVERFLOW_ATTRIBUTE=true`. Once
the [OpenTelemetry
Specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#overflow-attribute)
become stable, this feature will be turned on by default.
As of `1.10.0` when [Delta Aggregation
When [Delta Aggregation
Temporality](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md#temporality)
is used, it is possible to choose a smaller cardinality limit because the SDK
will reclaim unused metric points.
is used, it is possible to choose a smaller cardinality limit by allowing the
SDK to reclaim unused metric points.
> [!NOTE]
> In SDK versions `1.7.0` - `1.9.0`, metric point reclaim was an experimental
feature that could be enabled by setting the environment variable
`OTEL_DOTNET_EXPERIMENTAL_METRICS_RECLAIM_UNUSED_METRIC_POINTS=true`.
> Reclaim unused metric points feature was introduced in OpenTelemetry .NET
[1.7.0-alpha.1](../../src/OpenTelemetry/CHANGELOG.md#170-alpha1). It is
currently an experimental feature which can be turned on by setting the
environment variable
`OTEL_DOTNET_EXPERIMENTAL_METRICS_RECLAIM_UNUSED_METRIC_POINTS=true`. Once the
[OpenTelemetry
Specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#overflow-attribute)
become stable, this feature will be turned on by default.
### Memory Preallocation

View File

@ -8,7 +8,7 @@ using OpenTelemetry.Resources;
namespace CustomizingTheSdk;
internal static class Program
public class Program
{
private static readonly Meter Meter1 = new("CompanyA.ProductA.Library1", "1.0");
private static readonly Meter Meter2 = new("CompanyA.ProductB.Library2", "1.0");
@ -29,22 +29,28 @@ internal static class Program
.AddView(instrumentName: "MyCounter", name: "MyCounterRenamed")
// Change Histogram boundaries using the Explicit Bucket Histogram aggregation.
.AddView(instrumentName: "MyHistogram", new ExplicitBucketHistogramConfiguration() { Boundaries = [10.0, 20.0] })
.AddView(instrumentName: "MyHistogram", new ExplicitBucketHistogramConfiguration() { Boundaries = new double[] { 10, 20 } })
// Change Histogram to use the Base2 Exponential Bucket Histogram aggregation.
.AddView(instrumentName: "MyExponentialBucketHistogram", new Base2ExponentialBucketHistogramConfiguration())
// For the instrument "MyCounterCustomTags", aggregate with only the keys "tag1", "tag2".
.AddView(instrumentName: "MyCounterCustomTags", new MetricStreamConfiguration() { TagKeys = ["tag1", "tag2"] })
.AddView(instrumentName: "MyCounterCustomTags", new MetricStreamConfiguration() { TagKeys = new string[] { "tag1", "tag2" } })
// Drop the instrument "MyCounterDrop".
.AddView(instrumentName: "MyCounterDrop", MetricStreamConfiguration.Drop)
// Configure the Explicit Bucket Histogram aggregation with custom boundaries and new name.
.AddView(instrumentName: "histogramWithMultipleAggregations", new ExplicitBucketHistogramConfiguration() { Boundaries = [10.0, 20.0], Name = "MyHistogramWithExplicitHistogram" })
// Advanced selection criteria and config via Func<Instrument, MetricStreamConfiguration>
.AddView((instrument) =>
{
if (instrument.Meter.Name.Equals("CompanyA.ProductB.Library2") &&
instrument.GetType().Name.Contains("Histogram"))
{
return new ExplicitBucketHistogramConfiguration() { Boundaries = new double[] { 10, 20 } };
}
// Use Base2 Exponential Bucket Histogram aggregation and new name.
.AddView(instrumentName: "histogramWithMultipleAggregations", new Base2ExponentialBucketHistogramConfiguration() { Name = "MyHistogramWithBase2ExponentialBucketHistogram" })
return null;
})
// An instrument which does not match any views
// gets processed with default behavior. (SDK default)
@ -76,12 +82,6 @@ internal static class Program
exponentialBucketHistogram.Record(random.Next(1, 1000), new("tag1", "value1"), new("tag2", "value2"));
}
var histogramWithMultipleAggregations = Meter1.CreateHistogram<long>("histogramWithMultipleAggregations");
for (int i = 0; i < 20000; i++)
{
histogramWithMultipleAggregations.Record(random.Next(1, 1000), new("tag1", "value1"), new("tag2", "value2"));
}
var counterCustomTags = Meter1.CreateCounter<long>("MyCounterCustomTags");
for (int i = 0; i < 20000; i++)
{

View File

@ -115,9 +115,14 @@ name starts with "Abc.".
A
[View](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#view)
provides the ability to customize the metrics that are output by the SDK.
Following sections explains how to use `AddView` method that takes the
instrument name as the first parameter, the `View` configuration is then applied
to the matching instrument name.
Following sections explains how to use this feature. Each section has two code
snippets. The first one uses an overload of `AddView` method that takes in the
name of the instrument as the first parameter. The `View` configuration is then
applied to the matching instrument name. The second code snippet shows how to
use an advanced selection criteria to achieve the same results. This requires
the user to provide a `Func<Instrument, MetricStreamConfiguration>` which offers
more flexibility in filtering the instruments to which the `View` should be
applied.
#### Rename an instrument
@ -131,6 +136,20 @@ own the instrument to create it with a different name.
.AddView(instrumentName: "MyCounter", name: "MyCounterRenamed")
```
```csharp
// Advanced selection criteria and config via Func<Instrument, MetricStreamConfiguration>
.AddView((instrument) =>
{
if (instrument.Meter.Name == "CompanyA.ProductB.LibraryC" &&
instrument.Name == "MyCounter")
{
return new MetricStreamConfiguration() { Name = "MyCounterRenamed" };
}
return null;
})
```
#### Drop an instrument
When using `AddMeter` to add a Meter to the provider, all the instruments from
@ -143,6 +162,20 @@ then it is recommended to simply not add that `Meter` using `AddMeter`.
.AddView(instrumentName: "MyCounterDrop", MetricStreamConfiguration.Drop)
```
```csharp
// Advanced selection criteria and config via Func<Instrument, MetricStreamConfiguration>
.AddView((instrument) =>
{
if (instrument.Meter.Name == "CompanyA.ProductB.LibraryC" &&
instrument.Name == "MyCounterDrop")
{
return MetricStreamConfiguration.Drop;
}
return null;
})
```
#### Select specific tags
When recording a measurement from an instrument, all the tags that were provided
@ -186,6 +219,23 @@ with the metric are of interest to you.
...
```
```csharp
// Advanced selection criteria and config via Func<Instrument, MetricStreamConfiguration>
.AddView((instrument) =>
{
if (instrument.Meter.Name == "CompanyA.ProductB.LibraryC" &&
instrument.Name == "MyFruitCounter")
{
return new MetricStreamConfiguration
{
TagKeys = new string[] { "name" },
};
}
return null;
})
```
#### Configuring the aggregation of a Histogram
There are two types of
@ -200,56 +250,47 @@ used.
##### Explicit bucket histogram aggregation
By default, the [OpenTelemetry
Specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.14.0/specification/metrics/sdk.md#explicit-bucket-histogram-aggregation)
defines explicit buckets (aka boundaries) for Histograms as: `[ 0, 5, 10, 25,
50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000 ]`.
By default, the boundaries used for a Histogram are [`{ 0, 5, 10, 25, 50, 75,
100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000}`](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.14.0/specification/metrics/sdk.md#explicit-bucket-histogram-aggregation).
Views can be used to provide custom boundaries for a Histogram. The measurements
are then aggregated using the custom boundaries provided instead of the the
default boundaries. This requires the use of
`ExplicitBucketHistogramConfiguration`.
###### Customizing explicit buckets when using histogram aggregation
```csharp
// Change Histogram boundaries to count measurements under the following buckets:
// (-inf, 10]
// (10, 20]
// (20, +inf)
.AddView(
instrumentName: "MyHistogram",
new ExplicitBucketHistogramConfiguration { Boundaries = new double[] { 10, 20 } })
There are two mechanisms available to configure explicit buckets when using
histogram aggregation:
// If you provide an empty `double` array as `Boundaries` to the `ExplicitBucketHistogramConfiguration`,
// the SDK will only export the sum, count, min and max for the measurements.
// There are no buckets exported in this case.
.AddView(
instrumentName: "MyHistogram",
new ExplicitBucketHistogramConfiguration { Boundaries = Array.Empty<double>() })
```
* View API - Part of the OpenTelemetry .NET SDK.
* Advice API - Part of the `System.Diagnostics.DiagnosticSource` package
starting with version `9.0.0`.
```csharp
// Advanced selection criteria and config via Func<Instrument, MetricStreamConfiguration>
.AddView((instrument) =>
{
if (instrument.Meter.Name == "CompanyA.ProductB.LibraryC" &&
instrument.Name == "MyHistogram")
{
// `ExplicitBucketHistogramConfiguration` is a child class of `MetricStreamConfiguration`
return new ExplicitBucketHistogramConfiguration
{
Boundaries = new double[] { 10, 20 },
};
}
> [!IMPORTANT]
> When both the View API and Advice API are used, the View API takes precedence.
If explicit buckets are not provided by either the View API or the Advice API
then the SDK defaults apply.
* View API
Views can be used to provide custom explicit buckets for a Histogram. This
requires the use of `ExplicitBucketHistogramConfiguration`.
```csharp
// Change Histogram boundaries to count measurements under the following buckets:
// (-inf, 10]
// (10, 20]
// (20, +inf)
.AddView(
instrumentName: "MyHistogram",
new ExplicitBucketHistogramConfiguration { Boundaries = new double[] { 10, 20 } })
// If you provide an empty `double` array as `Boundaries` to the `ExplicitBucketHistogramConfiguration`,
// the SDK will only export the sum, count, min and max for the measurements.
// There are no buckets exported in this case.
.AddView(
instrumentName: "MyHistogram",
new ExplicitBucketHistogramConfiguration { Boundaries = Array.Empty<double>() })
```
* Advice API
Starting with the `1.10.0` SDK, explicit buckets for a Histogram may be provided
by instrumentation authors when the instrument is created. This is generally
recommended to be used by library authors when the SDK defaults don't match the
required granularity for the histogram being emitted.
See: [Using Advice to customize Histogram
instruments](https://learn.microsoft.com/dotnet/core/diagnostics/metrics-instrumentation#using-advice-to-customize-histogram-instruments).
return null;
})
```
##### Base2 exponential bucket histogram aggregation
@ -266,94 +307,20 @@ within the maximum number of buckets defined by `MaxSize`. The default
`MaxSize` is 160 buckets and the default `MaxScale` is 20.
```csharp
// Change the maximum number of buckets for "MyHistogram"
// Change the maximum number of buckets
.AddView(
instrumentName: "MyHistogram",
new Base2ExponentialBucketHistogramConfiguration { MaxSize = 40 })
```
#### Produce multiple metrics from single instrument
When an instrument matches multiple views, it can generate multiple metrics. For
instance, if an instrument is matched by two different view configurations, it
will result in two separate metrics being produced from that single instrument.
Below is an example demonstrating how to leverage this capability to create two
independent metrics from a single instrument. In this example, a histogram
instrument is used to report measurements, and views are configured to produce
two metrics : one aggregated using `ExplicitBucketHistogramConfiguration` and the
other using `Base2ExponentialBucketHistogramConfiguration`.
```csharp
var histogramWithMultipleAggregations = meter.CreateHistogram<long>("HistogramWithMultipleAggregations");
// Configure the Explicit Bucket Histogram aggregation with custom boundaries and new name.
.AddView(instrumentName: "HistogramWithMultipleAggregations", new ExplicitBucketHistogramConfiguration() { Boundaries = new double[] { 10, 20 }, Name = "MyHistogramWithExplicitHistogram" })
// Use Base2 Exponential Bucket Histogram aggregation and new name.
.AddView(instrumentName: "HistogramWithMultipleAggregations", new Base2ExponentialBucketHistogramConfiguration() { Name = "MyHistogramWithBase2ExponentialBucketHistogram" })
// Both views rename the metric to avoid name conflicts. However, in this case,
// renaming one would be sufficient.
// This measurement will be aggregated into two separate metrics.
histogramWithMultipleAggregations.Record(10, new("tag1", "value1"), new("tag2", "value2"));
```
When using views that produce multiple metrics from single instrument, it's
crucial to rename the metric to prevent conflicts. In the event of conflict,
OpenTelemetry will emit an internal warning but will still export both metrics.
The impact of this behavior depends on the backend or receiver being used. You
can refer to [OpenTelemetry's
specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md#opentelemetry-protocol-data-model-consumer-recommendations)
for more details.
Below example is showing the *BAD* practice. DO NOT FOLLOW it.
```csharp
var histogram = meter.CreateHistogram<long>("MyHistogram");
// Configure a view to aggregate based only on the "location" tag.
.AddView(instrumentName: "MyHistogram", metricStreamConfiguration: new MetricStreamConfiguration
{
TagKeys = new string[] { "location" },
})
// Configure another view to aggregate based only on the "status" tag.
.AddView(instrumentName: "MyHistogram", metricStreamConfiguration: new MetricStreamConfiguration
{
TagKeys = new string[] { "status" },
})
// The measurement below will be aggregated into two metric streams, but both will have the same name.
// OpenTelemetry will issue a warning about this conflict and pass both streams to the exporter.
// However, this may cause issues depending on the backend.
histogram.Record(10, new("location", "seattle"), new("status", "OK"));
```
The modified version, avoiding name conflict is shown below:
```csharp
var histogram = meter.CreateHistogram<long>("MyHistogram");
// Configure a view to aggregate based only on the "location" tag,
// and rename the metric.
.AddView(instrumentName: "MyHistogram", metricStreamConfiguration: new MetricStreamConfiguration
{
Name = "MyHistogramWithLocation",
TagKeys = new string[] { "location" },
})
// Configure a view to aggregate based only on the "status" tag,
// and rename the metric.
.AddView(instrumentName: "MyHistogram", metricStreamConfiguration: new MetricStreamConfiguration
{
Name = "MyHistogramWithStatus",
TagKeys = new string[] { "status" },
})
// The measurement below will be aggregated into two separate metrics, "MyHistogramWithLocation"
// and "MyHistogramWithStatus".
histogram.Record(10, new("location", "seattle"), new("status", "OK"));
// Configure all histogram instruments to use the Base2 Exponential Histogram aggregation
.AddView((instrument) =>
{
return instrument.GetType().GetGenericTypeDefinition() == typeof(Histogram<>)
? new Base2ExponentialBucketHistogramConfiguration()
: null;
})
```
> [!NOTE]
@ -362,28 +329,6 @@ by using Views.
See [Program.cs](./Program.cs) for a complete example.
#### Change the ExemplarReservoir
> [!NOTE]
> `MetricStreamConfiguration.ExemplarReservoirFactory` is an experimental API only
available in pre-release builds. For details see:
[OTEL1004](../../diagnostics/experimental-apis/OTEL1004.md).
To set the [ExemplarReservoir](#exemplarreservoir) for an instrument, use the
`MetricStreamConfiguration.ExemplarReservoirFactory` property on the View API:
> [!IMPORTANT]
> Setting `MetricStreamConfiguration.ExemplarReservoirFactory` alone will NOT
enable `Exemplar`s for an instrument. An [ExemplarFilter](#exemplarfilter)
MUST also be used.
```csharp
// Use MyCustomExemplarReservoir for "MyFruitCounter"
.AddView(
instrumentName: "MyFruitCounter",
new MetricStreamConfiguration { ExemplarReservoirFactory = () => new MyCustomExemplarReservoir() })
```
### Changing maximum Metric Streams
Every instrument results in the creation of a single Metric stream. With Views,
@ -409,7 +354,7 @@ Counter<long> MyFruitCounter = MyMeter.CreateCounter<long>("MyFruitCounter");
Counter<long> AnotherFruitCounter = MyMeter.CreateCounter<long>("AnotherFruitCounter");
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("MyCompany.MyProduct.MyLibrary")
.AddMeter("*")
.AddConsoleExporter()
.SetMaxMetricStreams(1) // The default value is 1000
.Build();
@ -422,30 +367,16 @@ MyFruitCounter.Add(1, new("name", "apple"), new("color", "red"));
AnotherFruitCounter.Add(1, new("name", "apple"), new("color", "red"));
```
### Changing the cardinality limit for a MeterProvider
To set the default [cardinality limit](../README.md#cardinality-limits) for all
metrics managed by a given `MeterProvider`, use the
`MeterProviderBuilder.SetMaxMetricPointsPerMetricStream` extension:
> [!CAUTION]
> `MeterProviderBuilder.SetMaxMetricPointsPerMetricStream` is marked `Obsolete`
in stable builds since 1.10.0 and has been replaced by
`MetricStreamConfiguration.CardinalityLimit`.
```csharp
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("MyCompany.MyProduct.MyLibrary")
.SetMaxMetricPointsPerMetricStream(4000) // Note: The default value is 2000
.AddConsoleExporter()
.Build();
```
### Changing the cardinality limit for a Metric
To set the [cardinality limit](../README.md#cardinality-limits) for an
individual metric, use the `MetricStreamConfiguration.CardinalityLimit` property
on the View API:
individual metric, use `MetricStreamConfiguration.CardinalityLimit` setting on
the View API:
> [!NOTE]
> `MetricStreamConfiguration.CardinalityLimit` is an experimental API only
available in pre-release builds. For details see:
[OTEL1003](../../diagnostics/experimental-apis/OTEL1003.md).
```csharp
var meterProvider = Sdk.CreateMeterProviderBuilder()
@ -479,30 +410,19 @@ tutorial](../exemplars/README.md) demonstrates how to use exemplars to achieve
correlation from metrics to traces, which is one of the primary use cases for
exemplars.
#### Default behavior
Exemplars in OpenTelemetry .NET are **off by default**
(`ExemplarFilterType.AlwaysOff`). The [OpenTelemetry
Specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#exemplarfilter)
recommends Exemplars collection should be on by default
(`ExemplarFilterType.TraceBased`) however there is a performance cost associated
with Exemplars so OpenTelemetry .NET has taken a more conservative stance for
its default behavior.
#### ExemplarFilter
`ExemplarFilter` determines which measurements are offered to the configured
`ExemplarReservoir`, which makes the final decision about whether or not the
offered measurement gets recorded as an `Exemplar`. Generally `ExemplarFilter`
is a mechanism to control the overhead associated with the offering and
recording of `Exemplar`s.
is a mechanism to control the overhead associated with `Exemplar` offering.
OpenTelemetry SDK comes with the following `ExemplarFilter`s (defined on
OpenTelemetry SDK comes with the following `ExemplarFilters` (defined on
`ExemplarFilterType`):
* (Default behavior) `AlwaysOff`: Makes no measurements eligible for becoming an
`Exemplar`. Using this disables `Exemplar` collection and avoids all
performance costs associated with `Exemplar`s.
* `AlwaysOff`: Makes no measurements eligible for becoming an `Exemplar`. Using
this is as good as turning off the `Exemplar` feature and is the current
default.
* `AlwaysOn`: Makes all measurements eligible for becoming an `Exemplar`.
* `TraceBased`: Makes those measurements eligible for becoming an `Exemplar`
which are recorded in the context of a sampled `Activity` (span).
@ -510,9 +430,6 @@ OpenTelemetry SDK comes with the following `ExemplarFilter`s (defined on
The `SetExemplarFilter` extension method on `MeterProviderBuilder` can be used
to set the desired `ExemplarFilterType` and enable `Exemplar` collection:
> [!NOTE]
> The `SetExemplarFilter` API was added in the `1.9.0` release.
```csharp
using OpenTelemetry;
using OpenTelemetry.Metrics;
@ -523,24 +440,6 @@ using var meterProvider = Sdk.CreateMeterProviderBuilder()
.Build();
```
It is also possible to configure the `ExemplarFilter` by using following
environmental variables:
> [!NOTE]
> Programmatically calling `SetExemplarFilter` will override any defaults set
using environment variables or configuration.
| Environment variable | Description | Notes |
| -------------------------- | -------------------------------------------------- |-------|
| `OTEL_METRICS_EXEMPLAR_FILTER` | Sets the default `ExemplarFilter` to use for all metrics. | Added in `1.9.0` |
| `OTEL_DOTNET_EXPERIMENTAL_METRICS_EXEMPLAR_FILTER_HISTOGRAMS` | Sets the default `ExemplarFilter` to use for histogram metrics. If set `OTEL_DOTNET_EXPERIMENTAL_METRICS_EXEMPLAR_FILTER_HISTOGRAMS` takes precedence over `OTEL_METRICS_EXEMPLAR_FILTER` for histogram metrics. | Experimental key (may be removed or changed in the future). Added in `1.9.0` |
Allowed values:
* `always_off`: Equivalent to `ExemplarFilterType.AlwaysOff`
* `always_on`: Equivalent to `ExemplarFilterType.AlwaysOn`
* `trace_based`: Equivalent to `ExemplarFilterType.TraceBased`
#### ExemplarReservoir
`ExemplarReservoir` receives the measurements sampled by the `ExemplarFilter`
@ -548,24 +447,19 @@ and is responsible for recording `Exemplar`s. The following are the default
reservoirs:
* `AlignedHistogramBucketExemplarReservoir` is the default reservoir used for
Histograms with buckets, and it stores at most one `Exemplar` per histogram
bucket. The `Exemplar` stored is the last measurement recorded - i.e. any new
Histograms with buckets, and it stores at most one exemplar per histogram
bucket. The exemplar stored is the last measurement recorded - i.e. any new
measurement overwrites the previous one in that bucket.
* `SimpleFixedSizeExemplarReservoir` is the default reservoir used for all
metrics except histograms with buckets. It has a fixed reservoir pool, and
metrics except Histograms with buckets. It has a fixed reservoir pool, and
implements the equivalent of [naive
reservoir](https://en.wikipedia.org/wiki/Reservoir_sampling). The reservoir pool
size (currently defaulting to 1) determines the maximum number of `Exemplar`s
stored. Exponential histograms use a `SimpleFixedSizeExemplarReservoir` with a
pool size equal to the number of buckets up to a max of `20`.
size (currently defaulting to 1) determines the maximum number of exemplars
stored.
See [Change the ExemplarReservoir](#change-the-exemplarreservoir) for details on
how to use the View API to change `ExemplarReservoir`s for an instrument.
See [Building your own
ExemplarReservoir](../extending-the-sdk/README.md#exemplarreservoir) for details
on how to implement custom `ExemplarReservoir`s.
> [!NOTE]
> Currently there is no ability to change or configure `ExemplarReservoir`.
### Instrumentation

View File

@ -1,8 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<NoWarn>$(NoWarn);CA5394</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Console\OpenTelemetry.Exporter.Console.csproj" />
</ItemGroup>

View File

@ -1,68 +0,0 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
using System.Diagnostics;
using System.Diagnostics.Metrics;
using OpenTelemetry;
using OpenTelemetry.Exporter;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
namespace Exemplars;
internal static class Program
{
private static readonly ActivitySource MyActivitySource = new("OpenTelemetry.Demo.Exemplar");
private static readonly Meter MyMeter = new("OpenTelemetry.Demo.Exemplar");
private static readonly Histogram<double> MyHistogram = MyMeter.CreateHistogram<double>("MyHistogram");
public static void Main()
{
var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("OpenTelemetry.Demo.Exemplar")
.AddOtlpExporter()
.Build();
var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("OpenTelemetry.Demo.Exemplar")
.SetExemplarFilter(ExemplarFilterType.TraceBased)
.AddOtlpExporter((exporterOptions, metricReaderOptions) =>
{
exporterOptions.Endpoint = new Uri("http://localhost:9090/api/v1/otlp/v1/metrics");
exporterOptions.Protocol = OtlpExportProtocol.HttpProtobuf;
metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = 1000;
})
.Build();
var random = new Random();
Console.WriteLine("Press any key to exit");
while (!Console.KeyAvailable)
{
using (var parent = MyActivitySource.StartActivity("Parent Operation"))
{
parent?.SetTag("key1", "value1");
parent?.SetTag("key2", "value2");
using (var child = MyActivitySource.StartActivity("Child Operation"))
{
child?.SetTag("key3", "value3");
child?.SetTag("key4", "value4");
MyHistogram.Record(random.NextDouble() * 100, new("tag1", "value1"), new("tag2", "value2"));
}
}
Thread.Sleep(300);
}
// Dispose meter provider before the application ends.
// This will flush the remaining metrics and shutdown the metrics pipeline.
meterProvider.Dispose();
// Dispose tracer provider before the application ends.
// This will flush the remaining spans and shutdown the tracing pipeline.
tracerProvider.Dispose();
}
}

View File

@ -1,166 +1,99 @@
# Using Exemplars in OpenTelemetry .NET
<details>
<summary>Table of Contents</summary>
Exemplars are example data points for aggregated data. They provide specific
context to otherwise general aggregations. One common use case is to gain
ability to correlate metrics to traces (and logs). While OpenTelemetry .NET
supports Exemplars, it is only useful if the telemetry backend also supports the
capabilities. This tutorial uses well known open source backends to demonstrate
the concept. The following are the components involved:
* [Install and run Jaeger](#install-and-run-jaeger)
* [Install and run Prometheus](#install-and-run-prometheus)
* [Install and configure Grafana](#install-and-configure-grafana)
* [Export metrics and traces from the
application](#export-metrics-and-traces-from-the-application)
* [Use exemplars to navigate from metrics to
traces](#use-exemplars-to-navigate-from-metrics-to-traces)
* [Learn more](#learn-more)
* Test App - We use existing example app from the repo. This app is already
instrumented with OpenTelemetry for logs, metrics and traces, and is configured
to export them to the configured OTLP end point.
* OpenTelemetry Collector - An instance of collector is run, which receives
telemetry from the above app using OTLP. The collector then exports metrics to
Prometheus, traces to Tempo.
* Prometheus - Prometheus is used as the Metric backend.
* Tempo - Tempo is used as the Tracing backend.
* Grafana - UI to query metrics from Prometheus, traces from Tempo, and to
navigate between metrics and traces using Exemplar.
</details>
All these components except the test app require additional configuration to
enable Exemplar feature. To make it easy for users, these components are
pre-configured to enable Exemplars, and a docker-compose is provided to spun
them all up, in the required configurations.
[Exemplars](../customizing-the-sdk/README.md#exemplars) are example data points
for aggregated data. They provide specific context to otherwise general
aggregations. One common use case is to gain ability to correlate metrics to
traces (and logs). While OpenTelemetry .NET supports Exemplars, it is only
useful if the telemetry backend also supports the capabilities. This tutorial
uses well known open-source backends to demonstrate the concept. The following
components are involved:
## Pre-requisite
* [Program.cs](./Program.cs) - this application is instrumented with
OpenTelemetry, it sends metrics to Prometheus, and traces to Jaeger.
* [Prometheus](#install-and-run-prometheus) - Prometheus is used as the metrics
backend.
* [Jaeger](#install-and-run-jaeger) - Jaeger is used as the distributed tracing
backend.
* [Grafana](#install-and-configure-grafana) - UI to query metrics from
Prometheus, traces from Jaeger, and to navigate between metrics and traces
using Exemplars.
Install docker: <https://docs.docker.com/get-docker/>
## Install and run Jaeger
## Setup
Download the [latest binary distribution
archive](https://www.jaegertracing.io/download/) of Jaeger.
As mentioned in the intro, this tutorial uses OTel Collector, Prometheus, Tempo,
and Grafana, and they must be up and running before proceeding. The following
spins all of them with the correct configurations to support Exemplars.
After finished downloading, extract it to a local location that's easy to
access. Run the `jaeger-all-in-one(.exe)` executable:
Navigate to current directory and run the following:
```sh
./jaeger-all-in-one --collector.otlp.enabled
docker-compose up -d
```
## Install and run Prometheus
If the above step succeeds, all dependencies would be spun up and ready now. To
test, navigate to Grafana running at: `http://localhost:3000/`.
Follow the [first steps](https://prometheus.io/docs/introduction/first_steps/)
to download the [latest release](https://prometheus.io/download/) of Prometheus.
## Run test app
After finished downloading, extract it to a local location that's easy to
access. Run the `prometheus(.exe)` server executable with feature flags
[exemplars
storage](https://prometheus.io/docs/prometheus/latest/feature_flags/#exemplars-storage)
and
[otlp-receiver](https://prometheus.io/docs/prometheus/latest/feature_flags/#otlp-receiver)
enabled:
Now that the required dependencies are ready, lets run the demo app.
This tutorial is using the existing ASP.NET Core app from the repo.
Navigate to [Example Asp.Net Core App](../../../examples/AspNetCore/Program.cs)
directory and run the following command:
```sh
./prometheus --enable-feature=exemplar-storage --web.enable-otlp-receiver
```
## Install and configure Grafana
Follow the operating system specific instructions to [download and install
Grafana](https://grafana.com/docs/grafana/latest/setup-grafana/installation/#supported-operating-systems).
After installation, start the standalone Grafana server (`grafana-server.exe` or
`./bin/grafana-server`, depending on the operating system). Then, use a
[supported web
browser](https://grafana.com/docs/grafana/latest/setup-grafana/installation/#supported-web-browsers)
to navigate to [http://localhost:3000/](http://localhost:3000/).
Follow the instructions in the Grafana getting started
[doc](https://grafana.com/docs/grafana/latest/getting-started/getting-started/#step-2-log-in)
to log in.
After successfully logging in, hover on the Configuration icon
on the panel at the left hand side, and click on Plugins.
Find and click on the Jaeger plugin. Next click on `Create a Jaeger data source`
button. Make the following changes:
1. Set "URL" to `http://localhost:16686/`.
2. At the bottom of the page click `Save & test` to ensure the data source is
working.
![Add Jaeger data
source](https://github.com/open-telemetry/opentelemetry-dotnet/assets/17327289/8356dc1d-dad2-4c82-9936-9a84b51d12fa)
Find and click on the Prometheus plugin. Next click on
`Create a Prometheus data source` button. Make the following changes:
1. Set "URL" to `http://localhost:9090`.
2. Under the "Exemplars" section, enable "Internal link", set "Data source" to
`Jaeger`, and set "Label name" to `trace_id`.
3. At the bottom of the page click `Save & test` to ensure the data source is
working.
![Add Prometheus data
source](https://github.com/open-telemetry/opentelemetry-dotnet/assets/17327289/a137c4ac-dfd7-4d24-8811-208f66e67e37)
## Export metrics and traces from the application
Create a new console application and run it:
```sh
dotnet new console --output exemplars
cd exemplars
dotnet run
```
Add reference to [OTLP
Exporter](../../../src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md):
Once the application is running, navigate to
[http://localhost:5000/weatherforecast]("http://localhost:5000/weatherforecast")
from a web browser. You may use the following Powershell script to generate load
to the application.
```sh
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
```powershell
while($true)
{
Invoke-WebRequest http://localhost:5000/weatherforecast
Start-Sleep -Milliseconds 500
}
```
Now copy the code from [Program.cs](./Program.cs) and run the application again.
The application will start sending metrics to Prometheus and traces to Jaeger.
## Use Exemplars to navigate from Metrics to Traces
The application is configured with trace-based exemplar filter, which enables
the OpenTelemetry SDK to attach exemplars to metrics:
The application sends metrics (with exemplars), and traces to the OTel
Collector, which export metrics and traces to Prometheus and Tempo
respectively.
```csharp
var meterProvider = Sdk.CreateMeterProviderBuilder()
...
.SetExemplarFilter(ExemplarFilterType.TraceBased)
...
```
For more details about the `SetExemplarFilter` API see: [Customizing
OpenTelemetry .NET SDK for Metrics >
ExemplarFilter](../customizing-the-sdk/README.md#exemplarfilter).
## Use exemplars to navigate from metrics to traces
Please wait for 2 minutes before continuing so that enough data is generated
and exported.
Open Grafana, select Explore, and select Prometheus as the source. Select the
metric named `MyHistogram_bucket`, and plot the chart. Toggle on the "Exemplars"
option from the UI and hit refresh.
metric named "http_server_duration_bucket", and plot the chart. Toggle on the
"Exemplar" option from the UI and hit refresh.
![Enable
Exemplars](https://github.com/open-telemetry/opentelemetry-dotnet/assets/17327289/bc461c6d-a0b9-49b7-a91d-94b07c3f417f)
![Enable Exemplar](https://user-images.githubusercontent.com/16979322/218627781-9886f837-11ae-4d52-94d3-f1821503209c.png)
The Exemplars appear as special "diamond shaped dots" along with the metric
charts in the UI. Select any exemplar to see the exemplar data, which includes
charts in the UI. Select any Exemplar to see the exemplar data, which includes
the timestamp when the measurement was recorded, the raw value, and trace
context when the recording was done. The "trace_id" enables jumping to the
tracing backed (Jaeger in this case). Click on the "Query with Jaeger" button
next to the "trace_id" field to open the corresponding trace in Jaeger.
tracing backed (tempo). Click on the "Query with Tempo" button next to the
"trace_id" field to open the corresponding `Trace` in Tempo.
![Navigate to trace with
exemplar](https://github.com/open-telemetry/opentelemetry-dotnet/assets/17327289/56bb5297-f744-41f3-bc35-8596392b8673)
![Navigate to trace with exemplar](https://user-images.githubusercontent.com/16979322/218629999-1d1cd6ba-2385-4683-975a-d4797df8361a.png)
## Learn more
## References
* [Exemplar
specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#exemplar)
* [What is Prometheus?](https://prometheus.io/docs/introduction/overview/)
* [Prometheus now supports OpenTelemetry
Metrics](https://horovits.medium.com/prometheus-now-supports-opentelemetry-metrics-83f85878e46a)
* [Jaeger Tracing](https://www.jaegertracing.io/)
* [Grafana support for
Prometheus](https://prometheus.io/docs/visualization/grafana/#creating-a-prometheus-graph)
* [Exemplar specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#exemplar)
* [Exemplars in Prometheus](https://prometheus.io/docs/prometheus/latest/feature_flags/#exemplars-storage)
* [Exemplars in Grafana](https://grafana.com/docs/grafana/latest/fundamentals/exemplars/)
* [Tempo](https://github.com/grafana/tempo)

View File

@ -1,8 +1,9 @@
version: "3"
services:
# OTEL Collector to receive logs, metrics and traces from the application
otel-collector:
image: otel/opentelemetry-collector:0.111.0
image: otel/opentelemetry-collector:0.70.0
command: [ "--config=/etc/otel-collector.yaml" ]
volumes:
- ./otel-collector.yaml:/etc/otel-collector.yaml

View File

@ -1,9 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<NoWarn>$(NoWarn);CA5394</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj" />
</ItemGroup>
</Project>

View File

@ -2,13 +2,11 @@ receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
exporters:
debug:
verbosity: detailed
logging:
loglevel: debug
prometheus:
endpoint: ":9201"
send_timestamps: true
@ -23,10 +21,10 @@ service:
pipelines:
traces:
receivers: [otlp]
exporters: [debug, otlp]
exporters: [logging,otlp]
metrics:
receivers: [otlp]
exporters: [debug, prometheus]
exporters: [logging,prometheus]
logs:
receivers: [otlp]
exporters: [debug]
exporters: [logging]

View File

@ -6,9 +6,7 @@ distributor:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
grpc:
endpoint: 0.0.0.0:4317
storage:
trace:

Some files were not shown because too many files have changed in this diff Show More