├── OSSMETADATA
├── smoke-tests
├── collector
│ ├── data-results
│ │ └── .gitkeep
│ └── otel-collector-config.yaml
├── docker-compose.yml
├── smoke-sdk-grpc.bats
├── smoke-sdk-http.bats
└── test_helpers
│ └── utilities.bash
├── .github
├── CODEOWNERS
├── workflows
│ ├── apply-labels.yml
│ ├── add-to-project-v2.yml
│ ├── stale.yml
│ └── validate-pr-title.yml
├── ISSUE_TEMPLATE
│ ├── question-discussion.md
│ ├── feature_request.md
│ ├── security-vulnerability-report.md
│ └── bug_report.md
├── release.yml
├── PULL_REQUEST_TEMPLATE.md
└── dependabot.yml
├── examples
├── aspnetcore
│ ├── .dockerignore
│ ├── my-web-app.png
│ ├── appsettings.Development.json
│ ├── Dockerfile
│ ├── WeatherForecast.cs
│ ├── appsettings.json
│ ├── aspnetcore.csproj
│ ├── Properties
│ │ └── launchSettings.json
│ ├── README.md
│ ├── Program.cs
│ └── Controllers
│ │ └── WeatherForecastController.cs
├── aspnetcore-fsharp
│ ├── my-web-app.png
│ ├── appsettings.json
│ ├── aspnetcore-fsharp.fsproj
│ ├── README.md
│ ├── Program.fs
│ └── Routing.fs
├── console
│ ├── appsettings.json
│ ├── console.csproj
│ ├── Program.cs
│ └── README.md
└── aspnetcore-redis
│ ├── my-web-app-with-redis.png
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ ├── WeatherForecast.cs
│ ├── aspnetcoreredis.csproj
│ ├── Properties
│ └── launchSettings.json
│ ├── Program.cs
│ ├── README.md
│ └── Controllers
│ └── WeatherForecastController.cs
├── honeycomb.png
├── Honeycomb.OpenTelemetry.snk.gpg
├── CONTRIBUTING.md
├── SUPPORT.md
├── CODE_OF_CONDUCT.md
├── DEVELOPMENT.md
├── Directory.build.props
├── NOTICE
├── src
├── Honeycomb.OpenTelemetry
│ ├── BaggageSpanProcessor.cs
│ ├── WebApplicationBuilderExtensions.cs
│ ├── DeterministicSampler.cs
│ ├── Honeycomb.OpenTelemetry.csproj
│ ├── MeterProviderBuilderExtensions.cs
│ ├── EnvironmentOptions.cs
│ ├── ConsoleTraceLinkExporter.cs
│ ├── ResourceBuilderExtensions.cs
│ ├── TracerProviderBuilderExtensions.cs
│ └── HoneycombOptions.cs
├── Honeycomb.OpenTelemetry.Instrumentation.AspNetCore
│ ├── Honeycomb.OpenTelemetry.Instrumentation.AspNetCore.csproj
│ └── TracerProviderBuilderExtensions.cs
└── Honeycomb.OpenTelemetry.CommonInstrumentations
│ ├── TracerProviderBuilderExtensions.cs
│ └── Honeycomb.OpenTelemetry.CommonInstrumentations.csproj
├── test
└── Honeycomb.OpenTelemetry.Tests
│ ├── appsettings.test.json
│ ├── Honeycomb.OpenTelemetry.Tests.csproj
│ ├── HoneycombOptionsExtensionsTests.cs
│ ├── EnvironmentOptionsTests.cs
│ ├── DeterministicSamplerTests.cs
│ └── HoneycombOptionsTests.cs
├── .vscode
├── launch.json
└── tasks.json
├── RELEASING.md
├── SECURITY.md
├── Makefile
├── README.md
├── .circleci
└── config.yml
├── .editorconfig
├── .gitignore
├── honeycomb-opentelemetry.sln
├── LICENSE
└── CHANGELOG.md
/OSSMETADATA:
--------------------------------------------------------------------------------
1 | osslifecycle=archived
2 |
--------------------------------------------------------------------------------
/smoke-tests/collector/data-results/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @honeycombio/pipeline-team
2 |
--------------------------------------------------------------------------------
/examples/aspnetcore/.dockerignore:
--------------------------------------------------------------------------------
1 | **/bin/
2 | **/obj/
--------------------------------------------------------------------------------
/honeycomb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/honeycombio/honeycomb-opentelemetry-dotnet/HEAD/honeycomb.png
--------------------------------------------------------------------------------
/Honeycomb.OpenTelemetry.snk.gpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/honeycombio/honeycomb-opentelemetry-dotnet/HEAD/Honeycomb.OpenTelemetry.snk.gpg
--------------------------------------------------------------------------------
/examples/aspnetcore/my-web-app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/honeycombio/honeycomb-opentelemetry-dotnet/HEAD/examples/aspnetcore/my-web-app.png
--------------------------------------------------------------------------------
/examples/aspnetcore-fsharp/my-web-app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/honeycombio/honeycomb-opentelemetry-dotnet/HEAD/examples/aspnetcore-fsharp/my-web-app.png
--------------------------------------------------------------------------------
/examples/console/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Honeycomb": {
3 | "ServiceName": "my-console-app",
4 | "ApiKey": "",
5 | "Dataset": ""
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/examples/aspnetcore-redis/my-web-app-with-redis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/honeycombio/honeycomb-opentelemetry-dotnet/HEAD/examples/aspnetcore-redis/my-web-app-with-redis.png
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guide
2 |
3 | Please see our [general guide for OSS lifecycle and practices.](https://github.com/honeycombio/home/blob/main/honeycomb-oss-lifecycle-and-practices.md)
4 |
--------------------------------------------------------------------------------
/SUPPORT.md:
--------------------------------------------------------------------------------
1 | # How to Get Help
2 |
3 | This project uses GitHub issues to track bugs, feature requests, and questions about using the project. Please search for existing issues before filing a new one.
4 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct
2 |
3 | This project has adopted the Honeycomb User Community Code of Conduct to clarify expected behavior in our community.
4 |
5 | https://www.honeycomb.io/honeycomb-user-community-code-of-conduct/
--------------------------------------------------------------------------------
/examples/aspnetcore/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/examples/aspnetcore-redis/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/.github/workflows/apply-labels.yml:
--------------------------------------------------------------------------------
1 | name: Apply project labels
2 | on: [issues, pull_request_target, label]
3 | jobs:
4 | apply-labels:
5 | runs-on: ubuntu-latest
6 | name: Apply common project labels
7 | steps:
8 | - uses: honeycombio/oss-management-actions/labels@v1
9 | with:
10 | github-token: ${{ secrets.GITHUB_TOKEN }}
11 |
--------------------------------------------------------------------------------
/examples/aspnetcore/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
2 | WORKDIR /app
3 | COPY . ./
4 | RUN dotnet publish -c release -f net6.0 -o /out
5 |
6 | # final stage/image
7 | FROM mcr.microsoft.com/dotnet/sdk:6.0
8 | WORKDIR /app
9 | COPY --from=build /out ./
10 |
11 | ENV ASPNETCORE_URLS=http://+:5001
12 | EXPOSE 5001
13 | ENTRYPOINT ["dotnet", "aspnetcore.dll"]
--------------------------------------------------------------------------------
/examples/aspnetcore/WeatherForecast.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace aspnetcore
4 | {
5 | public class WeatherForecast
6 | {
7 | public DateTime Date { get; set; }
8 |
9 | public int TemperatureC { get; set; }
10 |
11 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
12 |
13 | public string Summary { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/aspnetcore-redis/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*",
10 | "Honeycomb": {
11 | "ServiceName": "aspnetcore-redis-example",
12 | "ApiKey": "{apikey}",
13 | "Debug": true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/aspnetcore-redis/WeatherForecast.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace aspnetcoreredis
4 | {
5 | public class WeatherForecast
6 | {
7 | public DateTime Date { get; set; }
8 |
9 | public int TemperatureC { get; set; }
10 |
11 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
12 |
13 | public string Summary { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/aspnetcore/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*",
10 | "Honeycomb": {
11 | "ServiceName": "aspnetcore-example",
12 | "ApiKey": "{apikey}",
13 | "MetricsDataset": "aspnetcore-example-metrics",
14 | "Debug": true
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question-discussion.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Question/Discussion
3 | about: General question about how things work or a discussion
4 | title: ''
5 | labels: 'type: discussion'
6 | assignees: ''
7 |
8 | ---
9 |
10 |
15 |
--------------------------------------------------------------------------------
/examples/aspnetcore-fsharp/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*",
10 | "Honeycomb": {
11 | "ServiceName": "aspnetcore-fsharp-example",
12 | "ApiKey": "{apikey}",
13 | "MetricsDataset": "aspnetcore-fsharp-example-metrics",
14 | "Debug": true
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.github/workflows/add-to-project-v2.yml:
--------------------------------------------------------------------------------
1 | name: Add to project
2 | on:
3 | issues:
4 | types: [opened]
5 | pull_request_target:
6 | types: [opened]
7 | jobs:
8 | add-to-project:
9 | runs-on: ubuntu-latest
10 | name: Add issues and PRs to project
11 | steps:
12 | - uses: actions/add-to-project@main
13 | with:
14 | project-url: https://github.com/orgs/honeycombio/projects/27
15 | github-token: ${{ secrets.GHPROJECTS_TOKEN }}
16 |
--------------------------------------------------------------------------------
/DEVELOPMENT.md:
--------------------------------------------------------------------------------
1 | ## Building & Testing
2 |
3 | ### Using local packages with other projects
4 |
5 | To share this project with another local project you will need to build and store the distributable nuget package in a local nuget source directory. The following makefile target creates a local nuget source, builds and publishes the packages.
6 |
7 | `make publish_local`
8 |
9 | After the command has run, you can add the package to another project using the normal add package command:
10 |
11 | `dotnet add package Honeycomb.OpenTelemetry`
12 |
--------------------------------------------------------------------------------
/Directory.build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 | true
5 | true
6 |
7 |
8 |
9 | true
10 | $(MSBuildThisFileDirectory)Honeycomb.OpenTelemetry.snk
11 |
12 |
--------------------------------------------------------------------------------
/examples/console/console.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.github/release.yml:
--------------------------------------------------------------------------------
1 | # .github/release.yml
2 |
3 | changelog:
4 | exclude:
5 | labels:
6 | - no-changelog
7 | categories:
8 | - title: 💥 Breaking Changes 💥
9 | labels:
10 | - "version: bump major"
11 | - breaking-change
12 | - title: 💡 Enhancements
13 | labels:
14 | - "type: enhancement"
15 | - title: 🐛 Fixes
16 | labels:
17 | - "type: bug"
18 | - title: 🛠 Maintenance
19 | labels:
20 | - "type: maintenance"
21 | - "type: dependencies"
22 | - "type: documentation"
23 | - title: 🤷 Other Changes
24 | labels:
25 | - "*"
26 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016-Present Honeycomb, Hound Technology, Inc. All Rights Reserved.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: 'type: enhancement'
6 | assignees: ''
7 |
8 | ---
9 |
10 |
15 |
16 | **Is your feature request related to a problem? Please describe.**
17 |
18 |
19 | **Describe the solution you'd like**
20 |
21 |
22 | **Describe alternatives you've considered**
23 |
24 |
25 | **Additional context**
26 |
--------------------------------------------------------------------------------
/smoke-tests/collector/otel-collector-config.yaml:
--------------------------------------------------------------------------------
1 | receivers:
2 | otlp:
3 | protocols:
4 | grpc:
5 | http:
6 |
7 | processors:
8 | batch:
9 |
10 | exporters:
11 | file:
12 | path: /var/lib/data.json
13 | logging:
14 | loglevel: debug
15 |
16 | service:
17 | pipelines:
18 | traces:
19 | receivers: [otlp]
20 | processors: [batch]
21 | exporters: [file, logging]
22 | metrics:
23 | receivers: [otlp]
24 | processors: [batch]
25 | exporters: [file, logging]
26 | logs:
27 | receivers: [otlp]
28 | processors: [batch]
29 | # exporters: [file, logging]
30 | exporters: [logging]
31 |
--------------------------------------------------------------------------------
/src/Honeycomb.OpenTelemetry/BaggageSpanProcessor.cs:
--------------------------------------------------------------------------------
1 | using OpenTelemetry;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 |
5 | namespace Honeycomb.OpenTelemetry
6 | {
7 | ///
8 | /// Span processor that adds fields to every new span
9 | ///
10 | public class BaggageSpanProcessor : BaseProcessor
11 | {
12 | ///
13 | public override void OnStart(Activity activity)
14 | {
15 | foreach (var entry in Baggage.Current)
16 | {
17 | activity.SetTag(entry.Key, entry.Value);
18 | }
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/security-vulnerability-report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Security vulnerability report
3 | about: Let us know if you discover a security vulnerability
4 | title: ''
5 | labels: 'type: security'
6 | assignees: ''
7 |
8 | ---
9 |
10 |
15 | **Versions**
16 |
17 | - .NET runtime & version (eg .NET Core, .NET Framework):
18 | - Honeycomb OpenTelemetry Distribution:
19 |
20 | **Description**
21 |
22 | (Please include any relevant CVE advisory links)
23 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
12 |
13 | ## Which problem is this PR solving?
14 |
15 | -
16 |
17 | ## Short description of the changes
18 |
19 | -
20 |
21 |
--------------------------------------------------------------------------------
/test/Honeycomb.OpenTelemetry.Tests/appsettings.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "Honeycomb": {
3 | "ApiKey": "my-apikey",
4 | "TracesApiKey": "my-traces-apikey",
5 | "MetricsApiKey": "my-metrics-apikey",
6 | "Dataset": "my-dataset",
7 | "TracesDataset": "my-traces-dataset",
8 | "MetricsDataset": "my-metrics-dataset",
9 | "SampleRate": 5,
10 | "Endpoint": "my-endpoint",
11 | "TracesEndpoint": "my-traces-endpoint",
12 | "MetricsEndpoint": "my-metrics-endpoint",
13 | "MeterNames": [
14 | "meter1",
15 | "meter2"
16 | ],
17 | "ServiceName": "my-service",
18 | "ServiceVersion": "my-version",
19 | "EnableLocalVisualizations": true,
20 | "Debug": true
21 | }
22 | }
--------------------------------------------------------------------------------
/examples/aspnetcore/aspnetcore.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | false
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/examples/aspnetcore-redis/aspnetcoreredis.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | false
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Let us know if something is not working as expected
4 | title: ''
5 | labels: 'type: bug'
6 | assignees: ''
7 |
8 | ---
9 |
10 |
17 |
18 | **Versions**
19 |
20 | - .NET runtime & version (eg .NET Core, .NET Framework):
21 | - Honeycomb OpenTelemetry Distribution:
22 |
23 | **Steps to reproduce**
24 |
25 | 1.
26 |
27 | **Additional context**
28 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "nuget" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "monthly"
12 | labels:
13 | - "type: dependencies"
14 | reviewers:
15 | - "honeycombio/pipeline-team"
16 | commit-message:
17 | prefix: "maint"
18 | include: "scope"
19 | ignore:
20 | # We don't target .NET 7 yet and this breaks LTS EFCore
21 | - dependency-name: "Npgsql.OpenTelemetry"
22 | update-types: ["version-update:semver-major"]
23 |
--------------------------------------------------------------------------------
/examples/aspnetcore-fsharp/aspnetcore-fsharp.fsproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | net6.0
6 | aspnetcore_fsharp
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/examples/aspnetcore/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:33487",
8 | "sslPort": 44351
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "swagger",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "aspnetcore": {
21 | "commandName": "Project",
22 | "dotnetRunMessages": "true",
23 | "launchBrowser": true,
24 | "launchUrl": "swagger",
25 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
26 | "environmentVariables": {
27 | "ASPNETCORE_ENVIRONMENT": "Development"
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/examples/aspnetcore-redis/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:33487",
8 | "sslPort": 44351
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "swagger",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "aspnetcoreredis": {
21 | "commandName": "Project",
22 | "dotnetRunMessages": "true",
23 | "launchBrowser": true,
24 | "launchUrl": "swagger",
25 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
26 | "environmentVariables": {
27 | "ASPNETCORE_ENVIRONMENT": "Development"
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/examples/aspnetcore-redis/Program.cs:
--------------------------------------------------------------------------------
1 | using OpenTelemetry.Trace;
2 | using StackExchange.Redis;
3 |
4 | var builder = WebApplication.CreateBuilder(args);
5 | builder.Services.AddControllers();
6 |
7 | var redis = ConnectionMultiplexer.Connect(
8 | new ConfigurationOptions
9 | {
10 | EndPoints = { "localhost:6379" },
11 | AbortOnConnectFail = false, // allow for reconnects if redis is not available
12 | }
13 | );
14 | builder.Services.AddSingleton(redis);
15 |
16 | var honeycombOptions = builder.Configuration.GetHoneycombOptions();
17 |
18 | builder.Services.AddOpenTelemetry().WithTracing(otelBuilder =>
19 | otelBuilder
20 | .AddHoneycomb(honeycombOptions)
21 | .AddAspNetCoreInstrumentationWithBaggage()
22 | .AddRedisInstrumentation(redis)
23 | );
24 |
25 | builder.Services.AddSingleton(TracerProvider.Default.GetTracer(honeycombOptions.ServiceName));
26 |
27 | var app = builder.Build();
28 | app.MapControllers();
29 | await app.RunAsync();
--------------------------------------------------------------------------------
/examples/aspnetcore/README.md:
--------------------------------------------------------------------------------
1 | # Honeycomb.OpenTelemetry ASP.NET Core web example
2 |
3 | This example shows how to use the Honeycomb OpenTelemetry distro with a .NET Core web application.
4 |
5 | ## Using the Example
6 |
7 | - First, set your Honeycomb API key and a service name in the [appsettings.json](appsettings.json) configuration file.
8 | - If you are using Honeycomb Classic, add `TracesDataset`.
9 | - If you are sending Metrics, add `MetricsDataset`.
10 |
11 | Run `dotnet run` to start the app.
12 |
13 | To generate telemetry, navigate to `localhost:5001/weatherforecast`.
14 |
15 | 
16 |
17 | As part of the configuration process, an instance of the Tracer is registed in the services Dependency Injection map that can be be injected into controllers and used to add additional context and create additional spans.
18 |
19 | See [Startup.cs](Startup.cs) for an example of how the `AddHoneycomb` method is called.
20 |
21 | See [WeatherForecastController](Controllers/WeatherForecastController.cs) for an example app being instrumented.
22 |
--------------------------------------------------------------------------------
/examples/aspnetcore/Program.cs:
--------------------------------------------------------------------------------
1 | using OpenTelemetry.Metrics;
2 | using OpenTelemetry.Trace;
3 |
4 | using System.Diagnostics.Metrics;
5 |
6 | var builder = WebApplication.CreateBuilder(args);
7 | builder.Services.AddControllers();
8 |
9 | var honeycombOptions = builder.Configuration.GetHoneycombOptions();
10 |
11 | // Setup OpenTelemetry Tracing
12 | builder.Services.AddOpenTelemetry().WithTracing(otelBuilder =>
13 | otelBuilder
14 | .AddHoneycomb(honeycombOptions)
15 | .AddAspNetCoreInstrumentationWithBaggage()
16 | );
17 |
18 | // Register Tracer so it can be injected into other components (eg Controllers)
19 | builder.Services.AddSingleton(TracerProvider.Default.GetTracer(honeycombOptions.ServiceName));
20 |
21 | // Setup OpenTelemetry Metrics
22 | builder.Services.AddOpenTelemetry().WithMetrics(otelBuilder =>
23 | otelBuilder.AddHoneycomb(honeycombOptions)
24 | );
25 |
26 | // Register Meter so it can be injected into other components (eg controllers)
27 | builder.Services.AddSingleton(new Meter(honeycombOptions.MetricsDataset));
28 |
29 | var app = builder.Build();
30 |
31 | app.MapControllers();
32 | await app.RunAsync();
--------------------------------------------------------------------------------
/examples/aspnetcore-redis/README.md:
--------------------------------------------------------------------------------
1 | # Honeycomb.OpenTelemetry ASP.NET Core with Redis web example
2 |
3 | This example shows how to use the Honeycomb OpenTelemetry distro with a .NET Core web application.
4 | This example also includes automatic instrumentation of Redis.
5 |
6 | ## Using the Example
7 |
8 | - Install Redis and start the service, for example `brew services start redis`
9 | - Set your Honeycomb API key and a service name in the [appsettings.json](appsettings.json) configuration file.
10 | - If you are using Honeycomb Classic, add `TracesDataset`.
11 |
12 | Run `dotnet run` to start the app.
13 |
14 | To generate telemetry, navigate to `localhost:5001/weatherforecast`.
15 |
16 | 
17 |
18 | As part of the configuration process, an instance of the Tracer is registed in the services Dependency Injection map that can be be injected into controllers and used to add additional context and create additional spans.
19 |
20 | See [Startup.cs](Startup.cs) for an example of how the `AddHoneycomb` method is called.
21 |
22 | See [WeatherForecastController](Controllers/WeatherForecastController.cs) for an example app being instrumented.
23 |
--------------------------------------------------------------------------------
/examples/aspnetcore-fsharp/README.md:
--------------------------------------------------------------------------------
1 | # Honeycomb.OpenTelemetry ASP.NET Core web example
2 |
3 | This example shows how to use the Honeycomb OpenTelemetry distro with a .NET Core web application.
4 |
5 | ## Using the Example
6 |
7 | - First, set your Honeycomb API key and a service name in the [appsettings.json](appsettings.json) configuration file.
8 | - If you are using Honeycomb Classic, add `TracesDataset`.
9 | - If you are sending Metrics, add `MetricsDataset`.
10 |
11 | Run `dotnet run` to start the app.
12 |
13 | To generate telemetry, navigate to `localhost:5001/weatherforecast`.
14 |
15 | 
16 |
17 | As part of the configuration process, an instance of the Tracer is registed in the services Dependency Injection map that can be be injected into controllers and used to add additional context and create additional spans.
18 |
19 | See [Program.fs](https://github.com/honeycombio/honeycomb-opentelemetry-dotnet/blob/main/examples/aspnetcore-fsharp/Program.fs#L22) for an example of how the `AddHoneycomb` method is called.
20 |
21 | See [Routing.fs](https://github.com/honeycombio/honeycomb-opentelemetry-dotnet/blob/main/examples/aspnetcore-fsharp/Routing.fs#L38) for an example app being instrumented.
22 |
--------------------------------------------------------------------------------
/smoke-tests/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.0'
2 |
3 | x-env-base: &env_base
4 | HONEYCOMB_API_KEY: bogus_key
5 | HONEYCOMB_DATASET: bogus_dataset
6 | HONEYCOMB_METRICS_DATASET: bogus_dataset
7 | OTEL_SERVICE_NAME: "aspnetcore-example"
8 | DEBUG: "true"
9 |
10 | x-app-base: &app_base
11 | build:
12 | context: ../
13 | dockerfile: ./examples/aspnetcore/Dockerfile
14 | image: honeycomb/aspnetcore
15 | depends_on:
16 | - collector
17 |
18 | services:
19 | collector:
20 | image: otel/opentelemetry-collector:0.52.0
21 | command: ["--config=/etc/otel-collector-config.yaml"]
22 | volumes:
23 | - "./collector/otel-collector-config.yaml:/etc/otel-collector-config.yaml"
24 | - "./collector:/var/lib"
25 |
26 | app-sdk-http:
27 | <<: *app_base
28 | environment:
29 | <<: *env_base
30 | HONEYCOMB_API_ENDPOINT: http://collector:4318
31 | OTEL_EXPORTER_OTLP_PROTOCOL: http/protobuf
32 | ports:
33 | - "127.0.0.1:5001:5001"
34 |
35 | app-sdk-grpc:
36 | <<: *app_base
37 | environment:
38 | <<: *env_base
39 | HONEYCOMB_API_ENDPOINT: http://collector:4317
40 | OTEL_EXPORTER_OTLP_PROTOCOL: grpc
41 | ports:
42 | - "127.0.0.1:5001:5001"
--------------------------------------------------------------------------------
/smoke-tests/smoke-sdk-grpc.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | load test_helpers/utilities
4 |
5 | CONTAINER_NAME="app-sdk-grpc"
6 | OTEL_SERVICE_NAME="aspnetcore-example"
7 | METRICS_DATASET="bogus_dataset"
8 |
9 | setup_file() {
10 | echo "# 🚧" >&3
11 | docker-compose up --build --detach collector ${CONTAINER_NAME}
12 | wait_for_ready_app ${CONTAINER_NAME}
13 | curl --silent "http://localhost:5001/weatherforecast"
14 | wait_for_traces
15 | wait_for_metrics 15
16 | }
17 |
18 | teardown_file() {
19 | cp collector/data.json collector/data-results/data-${CONTAINER_NAME}.json
20 | docker-compose stop ${CONTAINER_NAME}
21 | docker-compose restart collector
22 | wait_for_flush
23 | }
24 |
25 | # TESTS
26 |
27 | @test "Manual instrumentation produces span with name of span" {
28 | result=$(span_names_for ${OTEL_SERVICE_NAME})
29 | assert_equal "$result" '"sleep"'
30 | }
31 |
32 | @test "Manual instrumentation adds custom attribute" {
33 | result=$(span_attributes_for ${OTEL_SERVICE_NAME} | jq "select(.key == \"delay_ms\").value.intValue")
34 | assert_equal "$result" '"100"'
35 | }
36 |
37 | @test "Manual instrumentation produces metrics" {
38 | result=$(metric_names_for ${METRICS_DATASET})
39 | assert_equal "$result" '"sheep"'
40 | }
--------------------------------------------------------------------------------
/smoke-tests/smoke-sdk-http.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | load test_helpers/utilities
4 |
5 | CONTAINER_NAME="app-sdk-http"
6 | OTEL_SERVICE_NAME="aspnetcore-example"
7 | METRICS_DATASET="bogus_dataset"
8 |
9 | setup_file() {
10 | echo "# 🚧" >&3
11 | docker-compose up --build --detach collector ${CONTAINER_NAME}
12 | wait_for_ready_app ${CONTAINER_NAME}
13 | curl --silent "http://localhost:5001/weatherforecast"
14 | wait_for_traces
15 | wait_for_metrics 15
16 | }
17 |
18 | teardown_file() {
19 | cp collector/data.json collector/data-results/data-${CONTAINER_NAME}.json
20 | docker-compose stop ${CONTAINER_NAME}
21 | docker-compose restart collector
22 | wait_for_flush
23 | }
24 |
25 | # TESTS
26 |
27 | @test "Manual instrumentation produces span with name of span" {
28 | result=$(span_names_for ${OTEL_SERVICE_NAME})
29 | assert_equal "$result" '"sleep"'
30 | }
31 |
32 | @test "Manual instrumentation adds custom attribute" {
33 | result=$(span_attributes_for ${OTEL_SERVICE_NAME} | jq "select(.key == \"delay_ms\").value.intValue")
34 | assert_equal "$result" '"100"'
35 | }
36 |
37 | @test "Manual instrumentation produces metrics" {
38 | result=$(metric_names_for ${METRICS_DATASET})
39 | assert_equal "$result" '"sheep"'
40 | }
41 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | // Use IntelliSense to find out which attributes exist for C# debugging
6 | // Use hover for the description of the existing attributes
7 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
8 | "name": ".NET Core Launch (console)",
9 | "type": "coreclr",
10 | "request": "launch",
11 | "preLaunchTask": "build",
12 | // If you have changed target frameworks, make sure to update the program path.
13 | "program": "${workspaceFolder}/test/Honeycomb.OpenTelemetry.Tests/bin/Debug/netcoreapp3.1/Honeycomb.OpenTelemetry.Tests.dll",
14 | "args": [],
15 | "cwd": "${workspaceFolder}/test/Honeycomb.OpenTelemetry.Tests",
16 | // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
17 | "console": "internalConsole",
18 | "stopAtEntry": false
19 | },
20 | {
21 | "name": ".NET Core Attach",
22 | "type": "coreclr",
23 | "request": "attach"
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/test/Honeycomb.OpenTelemetry.Tests/Honeycomb.OpenTelemetry.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | false
6 |
7 |
8 |
9 |
10 |
11 |
12 | runtime; build; native; contentfiles; analyzers; buildtransitive
13 | all
14 |
15 |
16 | runtime; build; native; contentfiles; analyzers; buildtransitive
17 | all
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/RELEASING.md:
--------------------------------------------------------------------------------
1 | # Releasing Process
2 |
3 | - Update `CHANGELOG.md` with the changes since the last release. Consider automating with a command such as these two:
4 | - `git log $(git describe --tags --abbrev=0)..HEAD --no-merges --oneline > new-in-this-release.log`
5 | - `git log --pretty='%C(green)%d%Creset- %s | [%an](https://github.com/)'`
6 | - Update VersionPrefix (and VersionSuffix if necessary) in the `*.csproj` files
7 | - If updating the OTel SDK, update the OTLP version in `HoneycombOptions.cs`
8 | - If updating the OTel SDK, update the OTel version in `README.md`
9 | - Commit changes, push, and open a release preparation pull request for review.
10 | - Once the pull request is merged, fetch the updated `main` branch.
11 | - Apply a tag for the new version on the merged commit (e.g. `git tag -a v1.3.0 -m "v1.3.0"`)
12 | - Note: We only tag the main package (even if changes were made to the instr packages) so the pipeline doesn't double-run
13 | - Push the tag upstream (this will kick off the release pipeline in CI) e.g. `git push origin v1.3.0`
14 | - Ensure that there is a draft GitHub release created as part of CI publish steps (this will also publish to Nuget).
15 | - Click "generate release notes" in Github for full changelog notes and any new contributors
16 | - Publish the Github draft release - if it is a prerelease (e.g. beta) click the prerelease checkbox.
17 |
--------------------------------------------------------------------------------
/.github/workflows/stale.yml:
--------------------------------------------------------------------------------
1 | name: 'Close stale issues and PRs'
2 | on:
3 | schedule:
4 | - cron: '30 1 * * *'
5 |
6 | jobs:
7 | stale:
8 | name: 'Close stale issues and PRs'
9 | runs-on: ubuntu-latest
10 | permissions:
11 | issues: write
12 | pull-requests: write
13 |
14 | steps:
15 | - uses: actions/stale@v4
16 | with:
17 | start-date: '2021-09-01T00:00:00Z'
18 | stale-issue-message: 'Marking this issue as stale because it has been open 14 days with no activity. Please add a comment if this is still an ongoing issue; otherwise this issue will be automatically closed in 7 days.'
19 | stale-pr-message: 'Marking this PR as stale because it has been open 30 days with no activity. Please add a comment if this PR is still relevant; otherwise this PR will be automatically closed in 7 days.'
20 | close-issue-message: 'Closing this issue due to inactivity. Please see our [Honeycomb OSS Lifecyle and Practices](https://github.com/honeycombio/home/blob/main/honeycomb-oss-lifecycle-and-practices.md).'
21 | close-pr-message: 'Closing this PR due to inactivity. Please see our [Honeycomb OSS Lifecyle and Practices](https://github.com/honeycombio/home/blob/main/honeycomb-oss-lifecycle-and-practices.md).'
22 | days-before-issue-stale: 14
23 | days-before-pr-stale: 30
24 | days-before-issue-close: 7
25 | days-before-pr-close: 7
26 | any-of-labels: 'status: info needed,status: revision needed'
27 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | This security policy applies to public projects under the [honeycombio organization][gh-organization] on GitHub.
4 | For security reports involving the services provided at `(ui|ui-eu|api|api-eu).honeycomb.io`, refer to the [Honeycomb Bug Bounty Program][bugbounty] for scope, expectations, and reporting procedures.
5 |
6 | ## Security/Bugfix Versions
7 |
8 | Security and bug fixes are generally provided only for the last minor version.
9 | Fixes are released either as part of the next minor version or as an on-demand patch version.
10 |
11 | Security fixes are given priority and might be enough to cause a new version to be released.
12 |
13 | ## Reporting a Vulnerability
14 |
15 | We encourage responsible disclosure of security vulnerabilities.
16 | If you find something suspicious, we encourage and appreciate your report!
17 |
18 | ### Ways to report
19 |
20 | In order for the vulnerability reports to reach maintainers as soon as possible, the preferred way is to use the "Report a vulnerability" button under the "Security" tab of the associated GitHub project.
21 | This creates a private communication channel between the reporter and the maintainers.
22 |
23 | If you are absolutely unable to or have strong reasons not to use GitHub's vulnerability reporting workflow, please reach out to the Honeycomb security team at [security@honeycomb.io](mailto:security@honeycomb.io).
24 |
25 | [gh-organization]: https://github.com/honeycombio
26 | [bugbounty]: https://www.honeycomb.io/bugbountyprogram
27 |
--------------------------------------------------------------------------------
/src/Honeycomb.OpenTelemetry/WebApplicationBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using Honeycomb.OpenTelemetry;
2 |
3 | namespace Microsoft.Extensions.Configuration
4 | {
5 | ///
6 | /// Extension methods for to help configure Honeycomb with OpenTelemetry.
7 | ///
8 | public static class ConfigurationManagerExtensions
9 | {
10 | ///
11 | /// Attempts to retrieve an instance of used to configure the OpenTelemetry SDK.
12 | ///
13 | public static HoneycombOptions GetHoneycombOptions(this ConfigurationManager builder)
14 | {
15 | return builder
16 | .GetSection(HoneycombOptions.ConfigSectionName)
17 | .Get();
18 | }
19 | }
20 |
21 | ///
22 | /// Extension methods for to help configure Honeycomb with OpenTelemetry.
23 | ///
24 | public static class ConfigurationInterfaceExtensions
25 | {
26 | ///
27 | /// Attempts to retrieve an instance of used to configure the OpenTelemetry SDK.
28 | ///
29 | public static HoneycombOptions GetHoneycombOptions(this IConfiguration configuration)
30 | {
31 | return configuration
32 | .GetSection(HoneycombOptions.ConfigSectionName)
33 | .Get();
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "label": "build",
6 | "command": "dotnet",
7 | "type": "process",
8 | "args": [
9 | "build",
10 | "${workspaceFolder}/test/Honeycomb.OpenTelemetry.Tests/Honeycomb.OpenTelemetry.Tests.csproj",
11 | "/property:GenerateFullPaths=true",
12 | "/consoleloggerparameters:NoSummary"
13 | ],
14 | "problemMatcher": "$msCompile"
15 | },
16 | {
17 | "label": "publish",
18 | "command": "dotnet",
19 | "type": "process",
20 | "args": [
21 | "publish",
22 | "${workspaceFolder}/test/Honeycomb.OpenTelemetry.Tests/Honeycomb.OpenTelemetry.Tests.csproj",
23 | "/property:GenerateFullPaths=true",
24 | "/consoleloggerparameters:NoSummary"
25 | ],
26 | "problemMatcher": "$msCompile"
27 | },
28 | {
29 | "label": "watch",
30 | "command": "dotnet",
31 | "type": "process",
32 | "args": [
33 | "watch",
34 | "run",
35 | "${workspaceFolder}/test/Honeycomb.OpenTelemetry.Tests/Honeycomb.OpenTelemetry.Tests.csproj",
36 | "/property:GenerateFullPaths=true",
37 | "/consoleloggerparameters:NoSummary"
38 | ],
39 | "problemMatcher": "$msCompile"
40 | }
41 | ]
42 | }
--------------------------------------------------------------------------------
/examples/aspnetcore-fsharp/Program.fs:
--------------------------------------------------------------------------------
1 | open System
2 | open System.Diagnostics.Metrics
3 |
4 | open Microsoft.AspNetCore
5 | open Microsoft.AspNetCore.Builder
6 | open Microsoft.Extensions.DependencyInjection
7 | open Microsoft.Extensions.Hosting
8 | open Microsoft.Extensions.Configuration
9 |
10 | open Giraffe
11 | open Giraffe.EndpointRouting
12 |
13 | open OpenTelemetry
14 | open OpenTelemetry.Trace
15 | open OpenTelemetry.Metrics
16 | open Honeycomb.OpenTelemetry
17 |
18 | let configureServices (services: IServiceCollection) (honeycombOptions: HoneycombOptions) =
19 | services
20 | .AddRouting()
21 | .AddGiraffe()
22 | .AddOpenTelemetry()
23 | .WithTracing(fun otelBuilder ->
24 | otelBuilder
25 | .AddHoneycomb(honeycombOptions)
26 | .AddAspNetCoreInstrumentationWithBaggage()
27 | |> ignore)
28 | .WithMetrics(fun otelBuilder ->
29 | otelBuilder.AddHoneycomb(honeycombOptions)
30 | |> ignore)
31 | |> ignore
32 |
33 | let configureApp (appBuilder: IApplicationBuilder) (honeycombOptions: HoneycombOptions) =
34 | let tracer = TracerProvider.Default.GetTracer(honeycombOptions.ServiceName)
35 | let meter = new Meter(honeycombOptions.MetricsDataset)
36 | appBuilder
37 | .UseRouting()
38 | .UseGiraffe(Routing.endpoints tracer meter)
39 | |> ignore
40 |
41 | let args = Environment.GetCommandLineArgs()
42 | let builder = WebApplication.CreateBuilder(args)
43 | let honeycombOptions = builder.Configuration.GetHoneycombOptions();
44 |
45 | configureServices builder.Services honeycombOptions
46 |
47 | let app = builder.Build()
48 | configureApp app honeycombOptions
49 |
50 | app.Run()
--------------------------------------------------------------------------------
/examples/aspnetcore-fsharp/Routing.fs:
--------------------------------------------------------------------------------
1 | module Routing
2 |
3 | open System
4 | open System.Diagnostics.Metrics
5 |
6 | open Microsoft.AspNetCore.Http
7 |
8 | open Giraffe
9 | open Giraffe.EndpointRouting
10 | open OpenTelemetry.Trace
11 |
12 | type WeatherForecast =
13 | { Date: DateTime
14 | TemperatureC: int
15 | Summary: string }
16 |
17 | let private createForecast index (rng: Random) (weatherSummaries: string[]) =
18 | { Date = DateTime.Now.AddDays(index)
19 | TemperatureC = rng.Next(-20,55)
20 | Summary = weatherSummaries[rng.Next(weatherSummaries.Length)] }
21 |
22 | let weatherSummaries =
23 | [|
24 | "Freezing"
25 | "Bracing"
26 | "Chilly"
27 | "Cool"
28 | "Mild"
29 | "Warm"
30 | "Balmy"
31 | "Hot"
32 | "Sweltering"
33 | "Scorching"
34 | |]
35 |
36 | let private weatherForecastHandler (tracer: Tracer) (sheepCounter: Counter) =
37 | fun (next : HttpFunc) (ctx : HttpContext) ->
38 | use forecastSpan = tracer.StartActiveSpan("app.weatherForecast")
39 |
40 | let rng = Random()
41 | let forecast =
42 | [|
43 | for index in 0..4 ->
44 | createForecast index rng weatherSummaries
45 | |]
46 |
47 | forecastSpan.SetAttribute("app.weatherForecast.days", forecast.Length) |> ignore
48 |
49 | sheepCounter.Add(1)
50 |
51 | json forecast next ctx
52 |
53 | let endpoints (tracer: Tracer) (meter: Meter) =
54 | let sheepCounter = meter.CreateCounter("app.sheep")
55 | [
56 | GET [
57 | route "/" (text "Hello World")
58 | route "/weatherforecast" (weatherForecastHandler tracer sheepCounter)
59 | ]
60 | ]
--------------------------------------------------------------------------------
/examples/aspnetcore/Controllers/WeatherForecastController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 | using OpenTelemetry.Trace;
3 | using System.Diagnostics.Metrics;
4 |
5 | namespace aspnetcore.Controllers
6 | {
7 | [ApiController]
8 | [Route("[controller]")]
9 | public class WeatherForecastController : ControllerBase
10 | {
11 | private static readonly string[] Summaries = new[]
12 | {
13 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
14 | };
15 |
16 | private readonly ILogger _logger;
17 | private readonly Tracer _tracer;
18 | private readonly Counter _counter;
19 |
20 | public WeatherForecastController(ILogger logger, Tracer tracer, Meter meter)
21 | {
22 | _logger = logger;
23 | _tracer = tracer;
24 | _counter = meter.CreateCounter("sheep");
25 | }
26 |
27 | [HttpGet]
28 | public async Task> Get()
29 | {
30 | using (var span = _tracer.StartActiveSpan("sleep"))
31 | {
32 | span.SetAttribute("delay_ms", 100);
33 | await Task.Delay(TimeSpan.FromMilliseconds(100));
34 | }
35 |
36 | _counter.Add(1);
37 |
38 | var rng = new Random();
39 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast
40 | {
41 | Date = DateTime.Now.AddDays(index),
42 | TemperatureC = rng.Next(-20, 55),
43 | Summary = Summaries[rng.Next(Summaries.Length)]
44 | })
45 | .ToArray();
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Honeycomb.OpenTelemetry.Instrumentation.AspNetCore/Honeycomb.OpenTelemetry.Instrumentation.AspNetCore.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | true
6 |
7 |
8 | true
9 | true
10 | true
11 | snupkg
12 |
13 |
14 | 0.29.0
15 | beta
16 | Honeycomb.OpenTelemetry.Instrumentation.AspNetCore
17 | Honeycomb
18 | OpenTelemetry AspNetCore instrumentation extensions
19 | https://docs.honeycomb.io/getting-data-in/dotnet/
20 | Apache-2.0
21 | https://github.com/honeycombio/honeycomb-opentelemetry-dotnet/blob/main/CHANGELOG.md
22 | Copyright (c) Honeycomb
23 | opentelemetry honeycomb observability tracing
24 | honeycomb.png
25 | https://github.com/honeycombio/honeycomb-opentelemetry-dotnet
26 | git
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/examples/aspnetcore-redis/Controllers/WeatherForecastController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc;
6 | using Microsoft.Extensions.Logging;
7 | using OpenTelemetry.Trace;
8 | using StackExchange.Redis;
9 |
10 | namespace aspnetcoreredis.Controllers
11 | {
12 | [ApiController]
13 | [Route("[controller]")]
14 | public class WeatherForecastController : ControllerBase
15 | {
16 | private static readonly string[] Summaries = new[]
17 | {
18 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
19 | };
20 |
21 | private readonly ILogger _logger;
22 | private readonly Tracer _tracer;
23 |
24 | private readonly IConnectionMultiplexer _redisConnection;
25 |
26 | public WeatherForecastController(ILogger logger, Tracer tracer, IConnectionMultiplexer redisConnection)
27 | {
28 | _logger = logger;
29 | _tracer = tracer;
30 | _redisConnection = redisConnection;
31 | }
32 |
33 | [HttpGet]
34 | public async Task> Get()
35 | {
36 | using (var span = _tracer.StartActiveSpan("sleep"))
37 | {
38 | span.SetAttribute("delay_ms", 100);
39 | var db = _redisConnection.GetDatabase();
40 | var pong = await db.PingAsync();
41 | await Task.Delay(TimeSpan.FromMilliseconds(100));
42 | }
43 |
44 | var rng = new Random();
45 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast
46 | {
47 | Date = DateTime.Now.AddDays(index),
48 | TemperatureC = rng.Next(-20, 55),
49 | Summary = Summaries[rng.Next(Summaries.Length)]
50 | })
51 | .ToArray();
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # default location for local nuget package source
2 | NUGET_PACKAGES_LOCAL ?= ${HOME}/.nuget/local
3 |
4 | build:
5 | dotnet build
6 |
7 | test: build
8 | dotnet test --no-build
9 |
10 | clean-smoke-tests:
11 | rm -rf ./smoke-tests/collector/data.json
12 | rm -rf ./smoke-tests/collector/data-results/*.json
13 | rm -rf ./smoke-tests/report.*
14 |
15 | clean: clean-smoke-tests
16 | rm -rf ./examples/aspnetcore/bin/*
17 | rm -rf ./examples/aspnetcore/obj/*
18 | rm -rf ./test/Honeycomb.OpenTelemetry.Tests/bin/*
19 | rm -rf ./test/Honeycomb.OpenTelemetry.Tests/obj/*
20 | rm -rf ./src/Honeycomb.OpenTelemetry/bin/*
21 | rm -rf ./src/Honeycomb.OpenTelemetry/obj/*
22 | dotnet clean
23 |
24 |
25 | smoke-tests/collector/data.json:
26 | @echo ""
27 | @echo "+++ Zhuzhing smoke test's Collector data.json"
28 | @touch $@ && chmod o+w $@
29 |
30 | smoke-sdk-grpc: smoke-tests/collector/data.json
31 | @echo ""
32 | @echo "+++ Running gRPC smoke tests."
33 | @echo ""
34 | cd smoke-tests && bats ./smoke-sdk-grpc.bats --report-formatter junit --output ./
35 |
36 | smoke-sdk-http: smoke-tests/collector/data.json
37 | @echo ""
38 | @echo "+++ Running HTTP smoke tests."
39 | @echo ""
40 | cd smoke-tests && bats ./smoke-sdk-http.bats --report-formatter junit --output ./
41 |
42 | smoke-sdk: smoke-sdk-grpc smoke-sdk-http
43 |
44 | smoke: smoke-sdk
45 |
46 | unsmoke:
47 | @echo ""
48 | @echo "+++ Spinning down the smokers."
49 | @echo ""
50 | cd smoke-tests && docker-compose down --volumes
51 |
52 | ## use this for local testing
53 | resmoke: unsmoke smoke
54 |
55 | ${NUGET_PACKAGES_LOCAL}:
56 | @mkdir -p ${NUGET_PACKAGES_LOCAL}
57 |
58 | local_nuget_source_registered: ${NUGET_PACKAGES_LOCAL}
59 | @dotnet nuget list source | grep -q '${NUGET_PACKAGES_LOCAL}' || dotnet nuget add source -n local ${NUGET_PACKAGES_LOCAL}
60 |
61 | publish_local: local_nuget_source_registered
62 | @echo "Publishing nuget package(s) to: ${NUGET_PACKAGES_LOCAL}\n"
63 | @dotnet pack -c release -o ${NUGET_PACKAGES_LOCAL} -p:signed=false
64 |
65 | .PHONY: build test clean smoke unsmoke resmoke local_nuget_source_registered publish_local smoke-sdk-grpc smoke-sdk-http smoke-sdk clean-smoke-tests
66 |
--------------------------------------------------------------------------------
/src/Honeycomb.OpenTelemetry.CommonInstrumentations/TracerProviderBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using Npgsql;
2 | using StackExchange.Redis;
3 |
4 | namespace OpenTelemetry.Trace
5 | {
6 | ///
7 | /// Extension methods to add instrumentation support for many common instrumentation packages.
8 | ///
9 | public static class TracerProviderBuilderExtensions
10 | {
11 | ///
12 | /// Adds support for common instrumentation packages. Refer to documentation for a complete list of included instrumentations.
13 | ///
14 | /// being configured.
15 | /// The instance of to chain the calls.
16 | public static TracerProviderBuilder AddCommonInstrumentations(this TracerProviderBuilder builder)
17 | {
18 | // Only add Redis instrumentation if we can find a Redis connection in DI
19 | if (builder is IDeferredTracerProviderBuilder deferredBuilder)
20 | {
21 | deferredBuilder.Configure((sp, b) =>
22 | {
23 | var connection = sp.GetService(typeof(IConnectionMultiplexer)) as IConnectionMultiplexer;
24 | if (connection != null)
25 | {
26 | b.AddRedisInstrumentation(connection);
27 | }
28 | });
29 | }
30 |
31 | return
32 | builder
33 | #if NET6_0_OR_GREATER
34 | .AddAspNetCoreInstrumentationWithBaggage()
35 | .AddGrpcClientInstrumentation()
36 | #elif NET462_OR_GREATER
37 | .AddAspNetInstrumentation()
38 | #endif
39 | #if NETSTANDARD2_0_OR_GREATER
40 | .AddQuartzInstrumentation()
41 | #endif
42 | .AddHttpClientInstrumentation()
43 | .AddSqlClientInstrumentation()
44 | .AddEntityFrameworkCoreInstrumentation()
45 | .AddMySqlDataInstrumentation()
46 | .AddWcfInstrumentation()
47 | .AddNpgsql();
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/src/Honeycomb.OpenTelemetry.Instrumentation.AspNetCore/TracerProviderBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using OpenTelemetry.Instrumentation.AspNetCore;
2 |
3 | namespace OpenTelemetry.Trace
4 | {
5 | ///
6 | /// Extension methods to simplify registering of ASP.NET Core request instrumentation.
7 | ///
8 | public static class TracerProviderBuilderExtensions
9 | {
10 | ///
11 | /// Enables the incoming requests automatic data collection for ASP.NET Core and adds current trace context baggage as
12 | /// attributes to created spans.
13 | ///
14 | /// being configured.
15 | /// The instance of to chain the calls.
16 | public static TracerProviderBuilder AddAspNetCoreInstrumentationWithBaggage(this TracerProviderBuilder builder)
17 | {
18 | return builder.AddAspNetCoreInstrumentation(options =>
19 | {
20 | options.RecordException = true;
21 | options.EnrichWithBaggage();
22 | }
23 | );
24 | }
25 |
26 | ///
27 | /// Configures the AspNetCore instrumentation to adds current trace context baggage as attributes to created spans.
28 | ///
29 | /// being configured.
30 | public static void EnrichWithBaggage(this AspNetCoreInstrumentationOptions options)
31 | {
32 | options.EnrichWithHttpRequest = (activity, request) =>
33 | {
34 | foreach (var entry in Baggage.Current)
35 | {
36 | activity.SetTag(entry.Key, entry.Value);
37 | }
38 | };
39 | options.EnrichWithHttpResponse = (activity, response) =>
40 | {
41 | foreach (var entry in Baggage.Current)
42 | {
43 | activity.SetTag(entry.Key, entry.Value);
44 | }
45 | };
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/test/Honeycomb.OpenTelemetry.Tests/HoneycombOptionsExtensionsTests.cs:
--------------------------------------------------------------------------------
1 | using Xunit;
2 |
3 | namespace Honeycomb.OpenTelemetry {
4 | public class HoneycombOptionsExtensionsTests
5 | {
6 | private const string ModernApiKey = "6936628e60f4c6157fde46";
7 | private const string ClassicApiKey = "a142c03cf06936628e60f4c6157fde46";
8 |
9 | [Theory]
10 | [InlineData("", "", "x-otlp-version=0.19.0,x-honeycomb-team=")]
11 | [InlineData(ModernApiKey, "", "x-otlp-version=0.19.0,x-honeycomb-team=6936628e60f4c6157fde46")]
12 | [InlineData(ModernApiKey, "dataset", "x-otlp-version=0.19.0,x-honeycomb-team=6936628e60f4c6157fde46")]
13 | [InlineData(ClassicApiKey, "", "x-otlp-version=0.19.0,x-honeycomb-team=a142c03cf06936628e60f4c6157fde46")]
14 | [InlineData(ClassicApiKey, "dataset", "x-otlp-version=0.19.0,x-honeycomb-team=a142c03cf06936628e60f4c6157fde46,x-honeycomb-dataset=dataset")]
15 | public void TracesHeaders(string apikey, string dataset, string expectedHeader) {
16 | var options = new HoneycombOptions
17 | {
18 | TracesApiKey = apikey,
19 | TracesDataset = dataset
20 | };
21 | Assert.Equal(expectedHeader, options.GetTraceHeaders());
22 | }
23 |
24 | [Theory]
25 | [InlineData("", "", "x-otlp-version=0.19.0,x-honeycomb-team=,x-honeycomb-dataset=")]
26 | [InlineData(ModernApiKey, "", "x-otlp-version=0.19.0,x-honeycomb-team=6936628e60f4c6157fde46,x-honeycomb-dataset=")]
27 | [InlineData(ModernApiKey, "dataset", "x-otlp-version=0.19.0,x-honeycomb-team=6936628e60f4c6157fde46,x-honeycomb-dataset=dataset")]
28 | [InlineData(ClassicApiKey, "", "x-otlp-version=0.19.0,x-honeycomb-team=a142c03cf06936628e60f4c6157fde46,x-honeycomb-dataset=")]
29 | [InlineData(ClassicApiKey, "dataset", "x-otlp-version=0.19.0,x-honeycomb-team=a142c03cf06936628e60f4c6157fde46,x-honeycomb-dataset=dataset")]
30 | public void MetricsHeaders(string apikey, string dataset, string expectedHeader) {
31 | var options = new HoneycombOptions
32 | {
33 | MetricsApiKey = apikey,
34 | MetricsDataset = dataset
35 | };
36 | Assert.Equal(expectedHeader, options.GetMetricsHeaders());
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/.github/workflows/validate-pr-title.yml:
--------------------------------------------------------------------------------
1 | name: "Validate PR Title"
2 |
3 | on:
4 | pull_request:
5 | types:
6 | - opened
7 | - edited
8 | - synchronize
9 |
10 | jobs:
11 | main:
12 | name: Validate PR title
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: amannn/action-semantic-pull-request@v5
16 | id: lint_pr_title
17 | name: "🤖 Check PR title follows conventional commit spec"
18 | env:
19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
20 | with:
21 | # Have to specify all types because `maint` and `rel` aren't defaults
22 | types: |
23 | maint
24 | rel
25 | fix
26 | feat
27 | chore
28 | ci
29 | docs
30 | style
31 | refactor
32 | perf
33 | test
34 | ignoreLabels: |
35 | "type: dependencies"
36 | # When the previous steps fails, the workflow would stop. By adding this
37 | # condition you can continue the execution with the populated error message.
38 | - if: always() && (steps.lint_pr_title.outputs.error_message != null)
39 | name: "📝 Add PR comment about using conventional commit spec"
40 | uses: marocchino/sticky-pull-request-comment@v2
41 | with:
42 | header: pr-title-lint-error
43 | message: |
44 | Thank you for contributing to the project! 🎉
45 |
46 | We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted.
47 |
48 | Make sure to prepend with `feat:`, `fix:`, or another option in the list below.
49 |
50 | Once you update the title, this workflow will re-run automatically and validate the updated title.
51 |
52 | Details:
53 |
54 | ```
55 | ${{ steps.lint_pr_title.outputs.error_message }}
56 | ```
57 |
58 | # Delete a previous comment when the issue has been resolved
59 | - if: ${{ steps.lint_pr_title.outputs.error_message == null }}
60 | name: "❌ Delete PR comment after title has been updated"
61 | uses: marocchino/sticky-pull-request-comment@v2
62 | with:
63 | header: pr-title-lint-error
64 | delete: true
65 |
--------------------------------------------------------------------------------
/examples/console/Program.cs:
--------------------------------------------------------------------------------
1 | using OpenTelemetry.Trace;
2 | using Honeycomb.OpenTelemetry;
3 | using OpenTelemetry.Metrics;
4 | using System.Diagnostics.Metrics;
5 | using OpenTelemetry.Resources;
6 | using System.Collections.Generic;
7 |
8 | namespace console
9 | {
10 | class Program
11 | {
12 | static void Main(string[] args)
13 | {
14 | // configure HoneycombOptions
15 | var options = new HoneycombOptions
16 | {
17 | ServiceName = "my-app",
18 | ApiKey = "{apikey}",
19 | TracesDataset = "{traces-dataset}",
20 | MetricsDataset = "{metrics-dataset}", // optional
21 | ResourceBuilder = ResourceBuilder.CreateDefault().AddAttributes(
22 | new Dictionary
23 | {
24 | {"my-attribute", "some-value"}
25 | })
26 | };
27 |
28 | // ------------ TRACES ------------
29 |
30 | // configure OpenTelemetry SDK to send trace data to Honeycomb
31 | // NOTE: the tracer provider should be a long-lived resource, and disposed
32 | // at the end of your app lifecycle to ensure all telemetry is exported
33 | using var tracerProvider = OpenTelemetry.Sdk.CreateTracerProviderBuilder()
34 | .AddHoneycomb(options)
35 | .Build();
36 |
37 | // get an instance of a tracer that can be used to create spans
38 | var tracer = tracerProvider.GetTracer(options.ServiceName);
39 |
40 | // create span to describe some application logic
41 | using var span = tracer.StartActiveSpan("doSomething");
42 | span.SetAttribute("user_id", 123);
43 |
44 | // ------------ METRICS (optional) ------------
45 |
46 | // configure OpenTelemetry SDK to send metric data to Honeycomb
47 | using var meterProvider = OpenTelemetry.Sdk.CreateMeterProviderBuilder()
48 | .AddHoneycomb(options)
49 | .Build();
50 |
51 | // meter name used here must be configured in the OpenTelemetry SDK
52 | // service name is configured by default
53 | // you may configure additional meter names using the Honeycomb options
54 | using var meter = new Meter(options.ServiceName);
55 | Counter counter = meter.CreateCounter("sheep");
56 | counter.Add(1);
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/examples/console/README.md:
--------------------------------------------------------------------------------
1 | # Honeycomb.OpenTelemetry Console example
2 |
3 | This example shows how to use the Honeycomb.OpenTelemetry distro with a .NET console application.
4 |
5 | To run the example, you need to create an instance of HoneycombOptions and pass it into the `AddHoneycomb` function of the OpenTelemetry TraceProviderBuilder. There are a variety of ways to create the options, as shown below.
6 |
7 | ### Manually
8 |
9 | ```csharp
10 | var options = new HoneycombOptions
11 | {
12 | ServiceName = "my-app",
13 | ApiKey = "{apikey}",
14 | Dataset = "{dataset}"
15 | };
16 | ```
17 |
18 | ### Command line arguments
19 |
20 | Create options using command line arguments:
21 |
22 | ```csharp
23 | var options = HoneycombOptionsHelper.GetHoneycombOptions(args);
24 | ```
25 |
26 | Run app with command line arguments:
27 |
28 | `dotnet run --service-name=my-app --honeycomb-apikey={apikey} --honeycomb-dataset={dataset}`
29 |
30 | ### Configuration files
31 |
32 | If you application uses JSON or XML configuration files, you crate an instance of HoneycombOptions to pass to the `AddHoneycomb` function.
33 |
34 | ```json
35 | {
36 | "Honeycomb": {
37 | "ServiceName": "my-app",
38 | "ApiKey": "{apikey}",
39 | "Dataset": "{dataset}"
40 | }
41 | }
42 | ```
43 |
44 | ```xml
45 |
46 | my-app
47 | {apikey}
48 | {dataset}
49 |
50 | ```
51 |
52 | ```csharp
53 | var config = new ConfigurationBuilder().AddJsonFile("{setting-file-name}").Build();
54 | var options = HoneycombOptionsHelper.GetHoneycombOptions(configuration);
55 | var tracerProvider = new TracerProviderBuilder()
56 | .AddHoneycomb(options)
57 | .Build()
58 | ```
59 |
60 | ### Setting Resource Attributes
61 |
62 | You can set additional resource attributes by either using an environment variable or programmatically using HoneycomnOptions when configuring the SDK.
63 |
64 | #### Environment Variable
65 |
66 | You can use `OTEL_RESOURCE_ATTRIBUTES` to set extra resoruce attributes. The value is key value pairs and multiple entries are separated using a comma (`,`).
67 |
68 | For example:
69 |
70 | `export OTEL_RESOURCE_ATTRIBUTES="deployment.environment=dev"`
71 |
72 | #### Programatically using HoneycombOptions
73 |
74 | You can set resource attributes proramatically by creating your own ResourceBuilder and passing adding it to HoneycombOptions.
75 |
76 | ```csharp
77 | var resourceBuilder = ResourceBuilder.CreateDefault().AddAttributes(
78 | new Dictionary
79 | {
80 | {"deployment.environment", "dev"}
81 | });
82 | var tracerProvider = OpenTelemetry.Sdk.CreateTracerProviderBuilder()
83 | .AddHoneycomb(options => options.ResourceBuilder = resourceBuilder)
84 | .Build();
85 | ```
86 |
87 | ### Example
88 |
89 | See [Program.cs](Program.cs) for a complete example.
90 |
--------------------------------------------------------------------------------
/src/Honeycomb.OpenTelemetry/DeterministicSampler.cs:
--------------------------------------------------------------------------------
1 | using OpenTelemetry.Trace;
2 | using System.Collections.Generic;
3 |
4 | namespace Honeycomb.OpenTelemetry
5 | {
6 | ///
7 | /// This Sampler implementation allows for distributed sampling based on a trace ID.
8 | /// It accepts a sample rate N and will deterministically sample 1/N events based
9 | /// on the target field. Hence, two or more processes can decide whether or not to
10 | /// sample related events without communication.
11 | ///
12 | /// - A sample rate of 0 means the Sampler will never sample.
13 | ///
14 | /// - A sampler rate of 1 means the Sampler will always sample.
15 | ///
16 | /// This implementation is based on the implementations (and necessarily needs to
17 | /// be in line with) other Honeycomb SDK implementations.
18 | ///
19 | public class DeterministicSampler : Sampler
20 | {
21 | internal const uint NeverSample = 0;
22 | internal const uint AlwaysSample = 1;
23 | internal const string SampleRateField = "SampleRate";
24 | private const double AlwaysSampleRatio = 1.0;
25 | private const double NeverSameRatio = 0.0;
26 |
27 | private Sampler _innerSampler;
28 | private readonly List> _sampleResultAttributes;
29 |
30 | ///
31 | /// Initializes a new instance of the class.
32 | ///
33 | /// The desired sample rate, expressed as 1/{sampleRate}.
34 | ///
35 | public DeterministicSampler(uint sampleRate)
36 | {
37 | double ratio;
38 | switch(sampleRate)
39 | {
40 | case NeverSample:
41 | ratio = NeverSameRatio;
42 | break;
43 | case AlwaysSample:
44 | ratio = AlwaysSampleRatio;
45 | break;
46 | default:
47 | ratio = AlwaysSampleRatio / sampleRate;
48 | break;
49 | }
50 | _innerSampler = new TraceIdRatioBasedSampler(ratio);
51 | _sampleResultAttributes = new List>
52 | {
53 | new KeyValuePair(SampleRateField, sampleRate)
54 | };
55 | }
56 |
57 | ///
58 | public override SamplingResult ShouldSample(in SamplingParameters samplingParameters)
59 | {
60 | var result = _innerSampler.ShouldSample(samplingParameters);
61 | return new SamplingResult(
62 | result.Decision,
63 | _sampleResultAttributes
64 | );
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Honeycomb.OpenTelemetry/Honeycomb.OpenTelemetry.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0;netstandard2.1;netstandard2.0;net462
5 | true
6 |
7 |
8 | true
9 | true
10 | true
11 | snupkg
12 |
13 |
14 | 1.5.0
15 | Honeycomb.OpenTelemetry
16 | Honeycomb
17 | Honeycomb's OpenTelemetry SDK
18 | https://docs.honeycomb.io/getting-data-in/dotnet/
19 | Apache-2.0
20 | https://github.com/honeycombio/honeycomb-opentelemetry-dotnet/blob/main/CHANGELOG.md
21 | Copyright (c) Honeycomb
22 | opentelemetry honeycomb observability tracing
23 | honeycomb.png
24 | https://github.com/honeycombio/honeycomb-opentelemetry-dotnet
25 | git
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/test/Honeycomb.OpenTelemetry.Tests/EnvironmentOptionsTests.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Xunit;
3 |
4 | namespace Honeycomb.OpenTelemetry
5 | {
6 | public class EnvironmentOptionsTests
7 | {
8 | [Fact]
9 | public void Can_get_options_from_env_vars()
10 | {
11 | var values = new Dictionary
12 | {
13 | {"HONEYCOMB_API_KEY", "my-api-key"},
14 | {"HONEYCOMB_TRACES_API_KEY", "my-traces-api-key"},
15 | {"HONEYCOMB_METRICS_API_KEY", "my-metrics-api-key"},
16 | {"HONEYCOMB_DATASET", "my-dataset"},
17 | {"HONEYCOMB_TRACES_DATASET", "my-traces-dataset"},
18 | {"HONEYCOMB_METRICS_DATASET", "my-metrics-dataset"},
19 | {"HONEYCOMB_API_ENDPOINT", "my-endpoint"},
20 | {"HONEYCOMB_TRACES_ENDPOINT", "my-traces-endpoint"},
21 | {"HONEYCOMB_METRICS_ENDPOINT", "my-metrics-endpoint"},
22 | {"HONEYCOMB_SAMPLE_RATE", "10"},
23 | {"OTEL_SERVICE_NAME", "my-service-name"},
24 | {"SERVICE_VERSION", "my-service-version"},
25 | {"HONEYCOMB_ENABLE_LOCAL_VISUALIZATIONS", "true" },
26 | {"DEBUG", "true"},
27 | {"OTEL_EXPORTER_OTLP_PROTOCOL", "grpc"},
28 | };
29 | var options = new EnvironmentOptions(values);
30 | Assert.Equal("my-api-key", options.ApiKey);
31 | Assert.Equal("my-traces-api-key", options.TracesApiKey);
32 | Assert.Equal("my-metrics-api-key", options.MetricsApiKey);
33 | Assert.Equal("my-dataset", options.Dataset);
34 | Assert.Equal("my-traces-dataset", options.TracesDataset);
35 | Assert.Equal("my-metrics-dataset", options.MetricsDataset);
36 | Assert.Equal("my-endpoint", options.ApiEndpoint);
37 | Assert.Equal("my-traces-endpoint", options.TracesEndpoint);
38 | Assert.Equal("my-metrics-endpoint", options.MetricsEndpoint);
39 | Assert.Equal((uint)10, options.SampleRate);
40 | Assert.Equal("my-service-name", options.ServiceName);
41 | Assert.Equal("my-service-version", options.ServiceVersion);
42 | Assert.True(options.EnableLocalVisualizations);
43 | Assert.True(options.Debug);
44 | Assert.Equal("grpc", options.OtelExporterOtlpProtocol);
45 | }
46 |
47 | [Fact]
48 | public void Optional_args_fall_back_to_defaults()
49 | {
50 | var options = new EnvironmentOptions(new Dictionary());
51 | Assert.Equal((uint)1, options.SampleRate);
52 | Assert.False(options.EnableLocalVisualizations);
53 | }
54 |
55 | [Fact]
56 | public void Sample_rate_returns_default_for_invalid_value()
57 | {
58 | var values = new Dictionary
59 | {
60 | {"HONEYCOMB_SAMPLE_RATE", "invalid"}
61 | };
62 | var options = new EnvironmentOptions(values);
63 | Assert.Equal((uint)1, options.SampleRate);
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Honeycomb OpenTelemetry Distro for .NET
2 |
3 | [](https://github.com/honeycombio/home/blob/main/honeycomb-oss-lifecycle-and-practices.md)
4 | [](https://circleci.com/gh/honeycombio/honeycomb-opentelemetry-dotnet)
5 | [](https://github.com/honeycombio/honeycomb-opentelemetry-dotnet/blob/main/src/Honeycomb.OpenTelemetry/Honeycomb.OpenTelemetry.csproj)
6 | [](https://www.nuget.org/packages/Honeycomb.OpenTelemetry)
7 |
8 | **STATUS**: This project is now archived. See [this issue](https://github.com/honeycombio/honeycomb-opentelemetry-dotnet/issues/378) for more details.
9 |
10 | This is Honeycomb's distribution of OpenTelemetry for .NET.
11 |
12 | Latest release built with:
13 |
14 | - [OpenTelemetry Version 1.6.0](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/core-1.6.0)
15 |
16 | ***NOTE***
17 |
18 | OpenTelemetry .NET SDK versions after 1.6.0 use updated HTTP semantic conventions that result in different telemetry attribute keys and can contribute to unexpected query results in Honeycomb. For this reason, we have decided the Honeycomb OpenTelemetry distro will not take further updates yet.
19 |
20 | Please see our [Migration guide for HTTP semantic conventions](https://docs.honeycomb.io/troubleshoot/product-lifecycle/recommended-migrations/#migrate-to-stabilized-opentelemetry-semantic-conventions) for more details.
21 |
22 | ## Getting Started
23 |
24 | Honeycomb's OpenTelemetry .NET SDK gives you the ability to add manual instrumentation to your applications.
25 |
26 | - [Documentation](https://docs.honeycomb.io/getting-data-in/dotnet/opentelemetry-distro/)
27 | - [Examples](/examples/)
28 |
29 | ## Why would I want to use this?
30 |
31 | - Streamlined configuration for sending data to Honeycomb!
32 | - Easy interop with existing instrumentation with OpenTelemetry!
33 | - Deterministic sampling!
34 | - Multi-span attributes!
35 |
36 | ### Overriding OpenTelemetry SDK Builder options
37 |
38 | The OpenTelemetry SDK uses a builder pattern to set options and currently does not provide a way to know if a particular option has already been set.
39 | This can lead to the same option being set multiple times with the last one wins behaviour.
40 |
41 | For example, the `AddHoneycomb(options)` function configures a Sampler so another call to `SetSampler(sampler)` will override the first sampler.
42 |
43 |
44 | ### HTTP Semantic Conventions
45 |
46 | The semantic conventions for attribute names used in HTTP instrumentation libraries is being updated and could cause distruption for existing users who rely on the existing names.
47 | For this reason, we have locked HTTP instrumentation packages to [1.6.0-beta.3](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/1.6.0-beta.3) which includes the `OTEL_SEMCONV_STABILITY_OPT_IN` environment variable that allows users to opt-in to the new behaviour when they are ready to.
48 |
49 | See this [Migration Guide](https://docs.honeycomb.io/getting-data-in/semconv/migration) for details on how to switch between the old and new attribute keys when using Honeycomb.
50 |
51 | ## License
52 |
53 | [Apache 2.0 License](./LICENSE).
54 |
--------------------------------------------------------------------------------
/src/Honeycomb.OpenTelemetry.CommonInstrumentations/Honeycomb.OpenTelemetry.CommonInstrumentations.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0;netstandard2.1;netstandard2.0;net462
5 | true
6 |
7 |
8 | true
9 | true
10 | true
11 | snupkg
12 |
13 |
14 | 0.29.0
15 | beta
16 | Honeycomb.OpenTelemetry.CommonInstrumentations
17 | Honeycomb
18 | Honeycomb's OpenTelemetry common instrumentations package. Adds support for many common instrumentation libraries for you.
19 | https://docs.honeycomb.io/getting-data-in/dotnet/
20 | Apache-2.0
21 | https://github.com/honeycombio/honeycomb-opentelemetry-dotnet/blob/main/CHANGELOG.md
22 | Copyright (c) Honeycomb
23 | opentelemetry honeycomb observability tracing
24 | honeycomb.png
25 | https://github.com/honeycombio/honeycomb-opentelemetry-dotnet
26 | git
27 |
28 |
29 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/test/Honeycomb.OpenTelemetry.Tests/DeterministicSamplerTests.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics;
3 | using OpenTelemetry.Trace;
4 | using Xunit;
5 |
6 | namespace Honeycomb.OpenTelemetry.Tests
7 | {
8 | public class DeterministicSamplerTests
9 | {
10 | [Fact]
11 | public void NeverSampleRateAlwaysReturnsDropResult()
12 | {
13 | var sampler = new DeterministicSampler(DeterministicSampler.NeverSample);
14 | for (int i = 0; i < 100; i++)
15 | {
16 | var traceID = ActivityTraceId.CreateRandom();
17 | var parameters = new SamplingParameters(
18 | parentContext: default,
19 | traceId: traceID,
20 | name: "Span",
21 | kind: ActivityKind.Client
22 | );
23 |
24 | var result = sampler.ShouldSample(parameters);
25 | Assert.Equal(SamplingDecision.Drop, result.Decision);
26 | }
27 | }
28 |
29 | [Fact]
30 | public void AlwaysSampleRateAlwaysReturnsRecordAndSample()
31 | {
32 | var sampler = new DeterministicSampler(DeterministicSampler.AlwaysSample);
33 | for (int i = 0; i < 100; i++)
34 | {
35 | var traceID = ActivityTraceId.CreateRandom();
36 | var parameters = new SamplingParameters(
37 | parentContext: default,
38 | traceId: traceID,
39 | name: "Span",
40 | kind: ActivityKind.Client
41 | );
42 |
43 | var result = sampler.ShouldSample(parameters);
44 | Assert.Equal(SamplingDecision.RecordAndSample, result.Decision);
45 | }
46 | }
47 |
48 | [Fact]
49 | public void DeterministicSamplerResultVariesBasedOnTraceId()
50 | {
51 | const uint sampleRate = 2;
52 | var sampler = new DeterministicSampler(sampleRate);
53 | var count = 0;
54 | for (int i = 0; i < 100; i++)
55 | {
56 | var activityTraceID = ActivityTraceId.CreateRandom();
57 | var parameters = new SamplingParameters(
58 | parentContext: default,
59 | traceId: activityTraceID,
60 | name: "Span",
61 | kind: ActivityKind.Client
62 | );
63 | var result = sampler.ShouldSample(parameters);
64 | if (result.Decision == SamplingDecision.RecordAndSample) {
65 | count++;
66 | }
67 | }
68 |
69 | Assert.True(count > 25 && count < 75);
70 | }
71 |
72 | [Fact]
73 | public void DeterministicSamplerAddsSampleRateAttribute()
74 | {
75 | for (int i = 0; i < 100; i++)
76 | {
77 | var sampler = new DeterministicSampler((uint) i);
78 | var activityTraceID = ActivityTraceId.CreateRandom();
79 | var parameters = new SamplingParameters(
80 | parentContext: default,
81 | traceId: activityTraceID,
82 | name: "Span",
83 | kind: ActivityKind.Client
84 | );
85 |
86 | var result = sampler.ShouldSample(parameters);
87 | Assert.Collection(result.Attributes,
88 | item => Assert.Equal(new KeyValuePair(DeterministicSampler.SampleRateField, (uint) i), item)
89 | );
90 | }
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/smoke-tests/test_helpers/utilities.bash:
--------------------------------------------------------------------------------
1 | # UTILITY FUNCS
2 |
3 | spans_from_library_named() {
4 | spans_received | jq ".scopeSpans[] | select(.scope.name == \"$1\").spans[]"
5 | }
6 |
7 | metrics_from_library_named() {
8 | metrics_received | jq ".scopeMetrics[] | select(.scope.name == \"$1\").metrics[]"
9 | }
10 |
11 | spans_received() {
12 | jq ".resourceSpans[]?" ./collector/data.json
13 | }
14 |
15 | metrics_received() {
16 | jq ".resourceMetrics[]?" ./collector/data.json
17 | }
18 |
19 | # test span name
20 | span_names_for() {
21 | spans_from_library_named $1 | jq '.name'
22 | }
23 |
24 | # test span attributes
25 | span_attributes_for() {
26 | # $1 - library name
27 |
28 | spans_from_library_named $1 | \
29 | jq ".attributes[]"
30 | }
31 |
32 | # test metric name
33 | metric_names_for() {
34 | metrics_from_library_named $1 | jq '.name'
35 | }
36 |
37 | # Arguments
38 | # $1 - retry limit (default 5); Nth retry sleeps for N seconds
39 | wait_for_metrics() {
40 | echo -n "# ⏳ Waiting for collector to receive metrics" >&3
41 | NEXT_WAIT_TIME=0
42 | MAX_RETRIES=${1:-5}
43 | until [ $NEXT_WAIT_TIME -eq $MAX_RETRIES ] || [ "$(metrics_received)" != "" ]
44 | do
45 | echo -n " ... $(( NEXT_WAIT_TIME++ ))s" >&3
46 | sleep $NEXT_WAIT_TIME
47 | done
48 | echo "" >&3
49 | [ $NEXT_WAIT_TIME -lt $MAX_RETRIES ]
50 | }
51 |
52 | # Arguments
53 | # $1 - retry limit (default 5); Nth retry sleeps for N seconds
54 | wait_for_data() {
55 | echo -n "# ⏳ Waiting for collector to receive data" >&3
56 | NEXT_WAIT_TIME=0
57 | MAX_RETRIES=${1:-5}
58 | until [ $NEXT_WAIT_TIME -eq $MAX_RETRIES ] || [ "$(wc -l ./collector/data.json | awk '{ print $1 }')" -ne 0 ]
59 | do
60 | echo -n " ... $(( NEXT_WAIT_TIME++ ))s" >&3
61 | sleep $NEXT_WAIT_TIME
62 | done
63 | echo "" >&3
64 | [ $NEXT_WAIT_TIME -lt $MAX_RETRIES ]
65 | }
66 |
67 | # Arguments
68 | # $1 - retry limit (default 5); Nth retry sleeps for N seconds
69 | wait_for_traces() {
70 | echo -n "# ⏳ Waiting for collector to receive traces" >&3
71 | NEXT_WAIT_TIME=0
72 | MAX_RETRIES=${1:-5}
73 | until [ $NEXT_WAIT_TIME -eq $MAX_RETRIES ] || [ "$(spans_received)" != "" ]
74 | do
75 | echo -n " ... $(( NEXT_WAIT_TIME++ ))s" >&3
76 | sleep $NEXT_WAIT_TIME
77 | done
78 | echo "" >&3
79 | [ $NEXT_WAIT_TIME -lt $MAX_RETRIES ]
80 | }
81 |
82 | wait_for_flush() {
83 | echo -n "# ⏳ Waiting for collector data flush" >&3
84 | NEXT_WAIT_TIME=0
85 | until [ $NEXT_WAIT_TIME -eq 5 ] || [ "$(wc -l ./collector/data.json | awk '{ print $1 }')" -eq 0 ]
86 | do
87 | echo -n " ... $(( NEXT_WAIT_TIME++ ))s" >&3
88 | sleep $NEXT_WAIT_TIME
89 | done
90 | echo "" >&3
91 | [ $NEXT_WAIT_TIME -lt 5 ]
92 | }
93 |
94 | # Wait loop for one of our example Dotnet apps to be started and ready to receive traffic.
95 | #
96 | # Arguments:
97 | # $1 - the name of the container/service in which the app is running
98 | wait_for_ready_app() {
99 | CONTAINER=${1:?container name is a required parameter}
100 | MAX_RETRIES=10
101 | echo -n "# 🍿 Setting up ${CONTAINER}" >&3
102 | NEXT_WAIT_TIME=0
103 | until [ $NEXT_WAIT_TIME -eq $MAX_RETRIES ] || [[ $(docker-compose logs ${CONTAINER} | grep "Now listening on:") ]]
104 | do
105 | echo -n " ... $(( NEXT_WAIT_TIME++ ))s" >&3
106 | sleep $NEXT_WAIT_TIME
107 | done
108 | echo "" >&3
109 | [ $NEXT_WAIT_TIME -lt $MAX_RETRIES ]
110 | }
111 |
112 | # Fail and display details if the expected and actual values do not
113 | # equal. Details include both values.
114 | #
115 | # Lifted and then drastically simplified from bats-assert * bats-support
116 | assert_equal() {
117 | if [[ $1 != "$2" ]]; then
118 | {
119 | echo
120 | echo "-- 💥 values are not equal 💥 --"
121 | echo "expected : $2"
122 | echo "actual : $1"
123 | echo "--"
124 | echo
125 | } >&2 # output error to STDERR
126 | return 1
127 | fi
128 | }
--------------------------------------------------------------------------------
/src/Honeycomb.OpenTelemetry/MeterProviderBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using Honeycomb.OpenTelemetry;
2 | using OpenTelemetry.Resources;
3 | using System;
4 |
5 | namespace OpenTelemetry.Metrics
6 | {
7 | ///
8 | /// Extension methods to configure to send metrics telemetry data to Honeycomb.
9 | ///
10 | public static class MeterProviderBuilderExtensions
11 | {
12 | ///
13 | /// Configures the to send metrics telemetry data to Honeycomb.
14 | ///
15 | public static MeterProviderBuilder AddHoneycomb(this MeterProviderBuilder builder,
16 | Action configureHoneycombOptions = null)
17 | {
18 | var honeycombOptions = new HoneycombOptions();
19 | configureHoneycombOptions?.Invoke(honeycombOptions);
20 | return builder.AddHoneycomb(honeycombOptions);
21 | }
22 |
23 | ///
24 | /// Configures the to send metrics telemetry data to Honeycomb using an instance of .
25 | ///
26 | public static MeterProviderBuilder AddHoneycomb(this MeterProviderBuilder builder, HoneycombOptions options)
27 | {
28 | if (options is null)
29 | {
30 | options = new HoneycombOptions { };
31 | }
32 |
33 | options.ApplyEnvironmentOptions(new EnvironmentOptions(Environment.GetEnvironmentVariables()));
34 |
35 | // only enable metrics if a metrics dataset is set
36 | if (!string.IsNullOrWhiteSpace(options.MetricsDataset))
37 | {
38 | var metricsApiKey = options.GetMetricsApiKey();
39 | var metricsEndpoint = options.GetMetricsEndpoint();
40 |
41 | if (string.IsNullOrWhiteSpace(metricsApiKey))
42 | {
43 | Console.WriteLine("WARN: missing metrics API key");
44 | }
45 |
46 | builder
47 | .SetResourceBuilder(
48 | ResourceBuilder
49 | .CreateDefault()
50 | .AddHoneycombAttributes()
51 | .AddEnvironmentVariableDetector()
52 | .AddService(serviceName: options.ServiceName, serviceVersion: options.ServiceVersion)
53 | )
54 | .AddHoneycombOtlpExporter(metricsApiKey, options.MetricsDataset, metricsEndpoint);
55 |
56 | builder.AddMeter(options.MetricsDataset);
57 | foreach (var meterName in options.MeterNames)
58 | {
59 | builder.AddMeter(meterName);
60 | }
61 |
62 | if (options.Debug)
63 | {
64 | builder.AddConsoleExporter();
65 | }
66 | }
67 |
68 | return builder;
69 | }
70 |
71 | ///
72 | /// Configures the with an OTLP exporter that sends metrics telemetry to Honeycomb.
73 | ///
74 | public static MeterProviderBuilder AddHoneycombOtlpExporter(this MeterProviderBuilder builder, string apikey, string dataset = null, string endpoint = null)
75 | {
76 | if (string.IsNullOrWhiteSpace(endpoint))
77 | {
78 | endpoint = HoneycombOptions.DefaultEndpoint;
79 | }
80 |
81 | return builder.AddOtlpExporter(otlpOptions =>
82 | {
83 | otlpOptions.Endpoint = new Uri(endpoint);
84 | otlpOptions.Headers = HoneycombOptions.GetMetricsHeaders(apikey, dataset);
85 | });
86 | }
87 | }
88 | }
--------------------------------------------------------------------------------
/src/Honeycomb.OpenTelemetry/EnvironmentOptions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 |
4 | namespace Honeycomb.OpenTelemetry
5 | {
6 | internal class EnvironmentOptions
7 | {
8 | private const string ApiKeyKey = "HONEYCOMB_API_KEY";
9 | private const string TracesApiKeyKey = "HONEYCOMB_TRACES_API_KEY";
10 | private const string MetricsApiKeyKey = "HONEYCOMB_METRICS_API_KEY";
11 | private const string DatasetKey = "HONEYCOMB_DATASET";
12 | private const string TracesDatasetKey = "HONEYCOMB_TRACES_DATASET";
13 | private const string MetricsDatasetKey = "HONEYCOMB_METRICS_DATASET";
14 | private const string ApiEndpointKey = "HONEYCOMB_API_ENDPOINT";
15 | private const string TracesEndpointKey = "HONEYCOMB_TRACES_ENDPOINT";
16 | private const string MetricsEndpointKey = "HONEYCOMB_METRICS_ENDPOINT";
17 | private const string SampleRateKey = "HONEYCOMB_SAMPLE_RATE";
18 | private const string ServiceNameKey = "OTEL_SERVICE_NAME";
19 | private const string ServiceVersionKey = "SERVICE_VERSION";
20 | private const string EnableLocalVisualizationsKey = "HONEYCOMB_ENABLE_LOCAL_VISUALIZATIONS";
21 | private const string DebugKey = "DEBUG";
22 | private const string OtelExporterOtlpProtocolKey = "OTEL_EXPORTER_OTLP_PROTOCOL";
23 | private const uint DefaultSampleRate = 1;
24 | private const string DefaultApiEndpoint = "https://api.honeycomb.io:443";
25 | private readonly IDictionary _environmentService;
26 |
27 | internal EnvironmentOptions() => new EnvironmentOptions(new Dictionary());
28 | internal EnvironmentOptions(IDictionary service)
29 | {
30 | _environmentService = service;
31 | }
32 |
33 | internal string ApiKey => GetEnvironmentVariable(ApiKeyKey);
34 | internal string TracesApiKey => GetEnvironmentVariable(TracesApiKeyKey);
35 | internal string MetricsApiKey => GetEnvironmentVariable(MetricsApiKeyKey);
36 | internal string Dataset => GetEnvironmentVariable(DatasetKey);
37 | internal string TracesDataset => GetEnvironmentVariable(TracesDatasetKey);
38 | internal string MetricsDataset => GetEnvironmentVariable(MetricsDatasetKey);
39 | internal string ApiEndpoint => GetEnvironmentVariable(ApiEndpointKey);
40 | internal string TracesEndpoint => GetEnvironmentVariable(TracesEndpointKey);
41 | internal string MetricsEndpoint => GetEnvironmentVariable(MetricsEndpointKey);
42 | internal string ServiceName => GetEnvironmentVariable(ServiceNameKey);
43 | internal string ServiceVersion => GetEnvironmentVariable(ServiceVersionKey);
44 | internal string EnableLocalVisualizationsValue => GetEnvironmentVariable(EnableLocalVisualizationsKey);
45 | internal bool EnableLocalVisualizations => bool.TryParse(EnableLocalVisualizationsValue, out var enableLocalVisualizations) ? enableLocalVisualizations : false;
46 | internal string DebugValue => GetEnvironmentVariable(DebugKey);
47 | internal bool Debug => bool.TryParse(DebugValue, out var debug) ? debug : false;
48 | internal string SampleRateValue => GetEnvironmentVariable(SampleRateKey);
49 | internal uint SampleRate => uint.TryParse(SampleRateValue, out var sampleRate) ? sampleRate : DefaultSampleRate;
50 | internal string OtelExporterOtlpProtocol => GetEnvironmentVariable(OtelExporterOtlpProtocolKey);
51 | private string GetEnvironmentVariable(string key, string defaultValue = "")
52 | {
53 | var value = _environmentService[key];
54 | if (value is string str && !string.IsNullOrWhiteSpace(str))
55 | {
56 | return str;
57 | }
58 |
59 | return defaultValue;
60 | }
61 |
62 | internal static string GetErrorMessage(string humanKey, string key)
63 | {
64 | return ($"Missing {humanKey}. Specify {key} environment variable, or the associated property in appsettings.json or the command line");
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/src/Honeycomb.OpenTelemetry/ConsoleTraceLinkExporter.cs:
--------------------------------------------------------------------------------
1 | using OpenTelemetry;
2 | using System;
3 | using System.Diagnostics;
4 | using System.Net.Http;
5 | using System.Text.Json;
6 | using System.Text.Json.Serialization;
7 |
8 | namespace Honeycomb.OpenTelemetry
9 | {
10 | ///
11 | /// Writes links to the Honeycomb UI for all root spans to the console
12 | ///
13 | internal class ConsoleTraceLinkExporter : BaseExporter
14 | {
15 | private const string ApiHost = "https://api.honeycomb.io";
16 | private string _apiKey;
17 | private string _serviceName;
18 | private string _teamSlug;
19 | private string _environmentSlug;
20 |
21 | private bool IsEnabled = false;
22 |
23 | ///
24 | /// Initializes the class
25 | ///
26 | /// Settings for Link generation
27 | public ConsoleTraceLinkExporter(HoneycombOptions options)
28 | {
29 | _apiKey = options.ApiKey;
30 | _serviceName = options.ServiceName;
31 | try
32 | {
33 | InitTraceLinkParameters();
34 | }
35 | catch (Exception)
36 | {
37 | Console.WriteLine("WARN: Failed to get data from Honeycomb Auth Endpoint");
38 | }
39 | }
40 |
41 | private void InitTraceLinkParameters()
42 | {
43 | if (string.IsNullOrEmpty(_apiKey))
44 | {
45 | return;
46 | }
47 |
48 | var httpClient = new HttpClient();
49 | httpClient.BaseAddress = new Uri(ApiHost);
50 | httpClient.DefaultRequestHeaders.Add("X-Honeycomb-Team", _apiKey);
51 |
52 | var response = httpClient.GetAsync("/1/auth").GetAwaiter().GetResult();
53 | if (!response.IsSuccessStatusCode)
54 | {
55 | Console.WriteLine("WARN: Didn't get a valid response from Honeycomb");
56 | return;
57 | }
58 |
59 | var responseString = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
60 | var authResponse = JsonSerializer.Deserialize(responseString);
61 | _environmentSlug = authResponse.Environment.Slug;
62 | _teamSlug = authResponse.Team.Slug;
63 | if (string.IsNullOrEmpty(_environmentSlug) ||
64 | string.IsNullOrEmpty(_teamSlug))
65 | {
66 | Console.WriteLine("WARN: Team or Environment wasn't returned");
67 | return;
68 | }
69 | IsEnabled = true;
70 | }
71 |
72 | ///
73 | public override ExportResult Export(in Batch batch)
74 | {
75 | if (!IsEnabled)
76 | {
77 | return ExportResult.Success;
78 | }
79 |
80 | foreach (var activity in batch)
81 | {
82 | if (string.IsNullOrEmpty(activity.ParentId))
83 | {
84 | Console.WriteLine($"Trace for {activity.DisplayName}" + Environment.NewLine +
85 | $"Honeycomb link: {GetTraceLink(activity.TraceId.ToString())}");
86 | }
87 | }
88 | return ExportResult.Success;
89 | }
90 |
91 | private string GetTraceLink(string traceId) =>
92 | _apiKey.Length == 32
93 | ? $"http://ui.honeycomb.io/{_teamSlug}/datasets/{_serviceName}/trace?trace_id={traceId}"
94 | : $"http://ui.honeycomb.io/{_teamSlug}/environments/{_environmentSlug}/datasets/{_serviceName}/trace?trace_id={traceId}";
95 | }
96 |
97 | internal class AuthResponse
98 | {
99 | [JsonPropertyName("environment")]
100 | public HoneycombEnvironment Environment { get; set; }
101 |
102 | [JsonPropertyName("team")]
103 | public Team Team { get; set; }
104 | }
105 | internal class HoneycombEnvironment
106 | {
107 | [JsonPropertyName("slug")]
108 | public string Slug { get; set; }
109 | }
110 |
111 | internal class Team
112 | {
113 | [JsonPropertyName("slug")]
114 | public string Slug { get; set; }
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | orbs:
4 | windows: circleci/windows@5.0.0
5 | bats: circleci/bats@1.0.0
6 |
7 | commands:
8 | setup:
9 | steps:
10 | - checkout
11 | - run:
12 | name: "Generate cache seed"
13 | command: |
14 | Get-ChildItem -Path $HOME\*.csproj -Recurse `
15 | | Sort-Object Name `
16 | | ForEach-Object { Get-Content $_ } `
17 | | Out-File -FilePath .\cache-seed -Append
18 | - restore_cache:
19 | keys:
20 | - dotnet-packages-v1-{{ checksum "cache-seed" }}
21 | - run:
22 | name: "Install project dependencies"
23 | command: dotnet.exe restore
24 | - save_cache:
25 | paths:
26 | - C:\Users\circleci\.nuget\packages
27 | key: dotnet-packages-v1-{{ checksum "cache-seed" }}
28 |
29 | jobs:
30 | test:
31 | executor:
32 | name: windows/default
33 | steps:
34 | - setup
35 | - run:
36 | name: "Run tests"
37 | command: dotnet.exe test --no-restore
38 | package:
39 | executor:
40 | name: windows/default
41 | steps:
42 | - setup
43 | - run:
44 | name: "Create build directory"
45 | command: mkdir -p build
46 | shell: bash.exe
47 | - run:
48 | name: "Import GPG cert"
49 | command: echo $GPG_BASE64 | base64 --decode | gpg.exe --batch --no-tty --import --yes
50 | shell: bash.exe
51 | - run:
52 | name: "Decrypt SNK file"
53 | command: gpg.exe --decrypt --pinentry-mode loopback --passphrase $GPG_PASSPHRASE --output Honeycomb.OpenTelemetry.snk Honeycomb.OpenTelemetry.snk.gpg
54 | shell: bash.exe
55 | - run:
56 | name: "Build release package"
57 | command: dotnet.exe pack --configuration release --output build --no-restore -p:signed=true
58 | - persist_to_workspace:
59 | root: \
60 | paths:
61 | - build\*
62 | - store_artifacts:
63 | path: build
64 |
65 | smoke_test:
66 | machine:
67 | image: ubuntu-2204:2024.01.1
68 | steps:
69 | - checkout
70 | - attach_workspace:
71 | at: ./
72 | - bats/install
73 | - run:
74 | name: What's the BATS?
75 | command: |
76 | which bats
77 | bats --version
78 | - run:
79 | name: Smoke Test
80 | command: make smoke
81 | - store_test_results:
82 | path: ./smoke-tests/
83 | - store_artifacts:
84 | path: ./smoke-tests/report.xml
85 | - store_artifacts:
86 | path: ./smoke-tests/collector/data-results
87 | - run:
88 | name: Extinguish the flames
89 | command: make unsmoke
90 |
91 | publish_github:
92 | docker:
93 | - image: cibuilds/github:0.13.0
94 | steps:
95 | - attach_workspace:
96 | at: ./
97 | - run:
98 | name: "Publishing Release on GitHub"
99 | command: ghr -draft -n ${CIRCLE_TAG} -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} ${CIRCLE_TAG} build/
100 |
101 | publish_nuget:
102 | executor:
103 | name: windows/default
104 | steps:
105 | - attach_workspace:
106 | at: .\
107 | - run:
108 | name: "Publishing to nuget.org"
109 | command: dotnet.exe nuget push "build\*.nupkg" --api-key $env:NUGET_APIKEY --source https://api.nuget.org/v3/index.json
110 |
111 | # Apply this filter to jobs that should always run.
112 | filter_always: &filter_always
113 | filters:
114 | tags:
115 | only: /.*/
116 |
117 | # Apply this filter to release-time jobs that should
118 | # only run when a version tag (v1.2.3) is pushed.
119 | filter_version_tag: &filter_version_tag
120 | filters:
121 | tags:
122 | only: /^v.*/
123 | branches:
124 | ignore: /.*/
125 |
126 | # Apply this filter to jobs that require secrets, which
127 | # are unavailable to PRs from forks and Dependabot.
128 | filter_exclude_forks: &filter_exclude_forks
129 | filters:
130 | tags:
131 | only: /.*/
132 | branches:
133 | ignore: /^(pull|dependabot)\/.*$/
134 |
135 | workflows:
136 | version: 2
137 | nightly:
138 | triggers:
139 | - schedule:
140 | cron: "0 0 * * *"
141 | filters:
142 | branches:
143 | only:
144 | - main
145 | jobs:
146 | - test
147 | - smoke_test:
148 | requires:
149 | - test
150 |
151 | build:
152 | jobs:
153 | - test:
154 | <<: *filter_always
155 | - smoke_test:
156 | requires:
157 | - test
158 | <<: *filter_always
159 | - package:
160 | context: Honeycomb Secrets for Public Repos
161 | requires:
162 | - test
163 | <<: *filter_exclude_forks
164 | - publish_github:
165 | context: Honeycomb Secrets for Public Repos
166 | requires:
167 | - smoke_test
168 | - package
169 | <<: *filter_version_tag
170 | - publish_nuget:
171 | context: Honeycomb Secrets for Public Repos
172 | requires:
173 | - smoke_test
174 | - package
175 | <<: *filter_version_tag
176 |
--------------------------------------------------------------------------------
/src/Honeycomb.OpenTelemetry/ResourceBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using System.Collections.Generic;
4 | using System.Reflection;
5 |
6 | namespace OpenTelemetry.Resources
7 | {
8 | ///
9 | /// Extension methods to configure with Honeycomb distro attributes.
10 | ///
11 | public static class ResourceBuilderExtensions
12 | {
13 | ///
14 | /// Configures the with Honeycomb attributes.
15 | ///
16 | public static ResourceBuilder AddHoneycombAttributes(this ResourceBuilder builder)
17 | {
18 | return builder
19 | .AddAttributes(new List>
20 | {
21 | new KeyValuePair("honeycomb.distro.language", "dotnet"),
22 | new KeyValuePair("honeycomb.distro.version", GetFileVersion()),
23 | new KeyValuePair("honeycomb.distro.runtime_version",
24 | Environment.Version.ToString()),
25 | })
26 | .AddRuntimeResource()
27 | .AddOSResource();
28 | }
29 |
30 | ///
31 | /// Determines process runtime resources and adds them to the .
32 | ///
33 | ///
34 | /// See https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/process/#process-runtimes
35 | ///
36 | private static ResourceBuilder AddRuntimeResource(this ResourceBuilder builder)
37 | {
38 | var frameworkDescription = RuntimeInformation.FrameworkDescription;
39 |
40 | var runtimeName = "unknown";
41 | var runtimeVersion = "unknown";
42 |
43 | if (!frameworkDescription.StartsWith(".NET"))
44 | {
45 | return builder;
46 | }
47 |
48 | if (frameworkDescription.StartsWith(".NET Core"))
49 | {
50 | runtimeName = ".NET Core";
51 | runtimeVersion = frameworkDescription.Substring(".NET Core".Length);
52 | }
53 | else if (frameworkDescription.StartsWith(".NET Framework"))
54 | {
55 | runtimeName = ".NET Framework";
56 | runtimeVersion = frameworkDescription.Substring(".NET Framework".Length);
57 | }
58 | else if (frameworkDescription.StartsWith(".NET Native"))
59 | {
60 | // I doubt we'll ever see a user match this, but it's a valid runtime, so...
61 | runtimeName = ".NET Native";
62 | runtimeVersion = frameworkDescription.Substring(".NET Native".Length);
63 | }
64 | else
65 | {
66 | runtimeName = ".NET";
67 | runtimeVersion = frameworkDescription.Substring(".NET".Length);
68 | }
69 |
70 | return builder
71 | .AddAttributes(new List>
72 | {
73 | new KeyValuePair("process.runtime.name", runtimeName),
74 | new KeyValuePair("process.runtime.version", runtimeVersion)
75 | });
76 | }
77 |
78 | private static ResourceBuilder AddOSResource(this ResourceBuilder builder)
79 | {
80 | var osType = "unknown";
81 | var osName = "unknown";
82 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
83 | {
84 | osType = "windows";
85 | osName = "Windows";
86 | }
87 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
88 | {
89 | osType = "linux";
90 | osName = "Linux";
91 | }
92 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
93 | {
94 | osType = "darwin";
95 | osName = "macOS";
96 | }
97 |
98 | var versionWithPotentialWindowsServicePack = Environment.OSVersion.VersionString.IndexOf(" ") + 1;
99 | return builder
100 | .AddAttributes(new List>
101 | {
102 | new KeyValuePair("os.type", osType),
103 | new KeyValuePair("os.description",
104 | Environment.OSVersion.VersionString),
105 | new KeyValuePair("os.name", osName),
106 | new KeyValuePair("os.version",
107 | Environment.OSVersion.VersionString.Substring(versionWithPotentialWindowsServicePack)),
108 | });
109 | }
110 |
111 | private static string GetFileVersion()
112 | {
113 | var version = typeof(Honeycomb.OpenTelemetry.HoneycombOptions)
114 | .Assembly
115 | .GetCustomAttribute()
116 | .InformationalVersion;
117 |
118 | // AssemblyInformationalVersionAttribute may include the latest commit hash in
119 | // the form `{version_prefix}{version_suffix}+{commit_hash}`.
120 | // We should trim the hash if present to just leave the version prefix and suffix
121 | var i = version.IndexOf("+");
122 | return i > 0
123 | ? version.Substring(0, i)
124 | : version;
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/Honeycomb.OpenTelemetry/TracerProviderBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using Honeycomb.OpenTelemetry;
2 | using Microsoft.Extensions.Configuration;
3 | using OpenTelemetry.Resources;
4 | using System;
5 | using System.Text.Json;
6 |
7 | #if NET462
8 | using System.Collections.Generic;
9 | #endif
10 |
11 | namespace OpenTelemetry.Trace
12 | {
13 | ///
14 | /// Extension methods to configure to send telemetry data to Honeycomb.
15 | ///
16 | public static class TracerProviderBuilderExtensions
17 | {
18 | ///
19 | /// Configures the to send telemetry data to Honeycomb.
20 | ///
21 | /// being configured.
22 | /// Action delegate that configures a .
23 | /// The instance of to chain the calls.
24 | public static TracerProviderBuilder AddHoneycomb(this TracerProviderBuilder builder,
25 | Action configureHoneycombOptions = null)
26 | {
27 | var honeycombOptions = new HoneycombOptions { };
28 | configureHoneycombOptions?.Invoke(honeycombOptions);
29 | return builder.AddHoneycomb(honeycombOptions);
30 | }
31 |
32 | ///
33 | /// Configures the to send telemetry data to Honeycomb.
34 | ///
35 | /// being configured.
36 | /// The to configure with
37 | /// The instance of to chain the calls.
38 | public static TracerProviderBuilder AddHoneycomb(this TracerProviderBuilder builder, IConfiguration configuration)
39 | {
40 | return builder.AddHoneycomb(configuration.GetSection(HoneycombOptions.ConfigSectionName).Get());
41 | }
42 |
43 | ///
44 | /// Configures the to send telemetry data to Honeycomb using an instance of .
45 | ///
46 | public static TracerProviderBuilder AddHoneycomb(this TracerProviderBuilder builder, HoneycombOptions options)
47 | {
48 | if (options is null)
49 | {
50 | options = new HoneycombOptions { };
51 | }
52 |
53 | options.ApplyEnvironmentOptions(new EnvironmentOptions(Environment.GetEnvironmentVariables()));
54 |
55 | var tracesEndpoint = options.GetTracesEndpoint();
56 | var tracesApiKey = options.GetTracesApiKey();
57 | var tracesDataset = options.GetTracesDataset();
58 |
59 | // if serviceName is null, warn and set to default
60 | if (string.IsNullOrWhiteSpace(options.ServiceName))
61 | {
62 | options.ServiceName = HoneycombOptions.SDefaultServiceName;
63 | Console.WriteLine($"WARN: {EnvironmentOptions.GetErrorMessage("service name", "OTEL_SERVICE_NAME")}. If left unset, this will show up in Honeycomb as unknown_service:.");
64 | }
65 |
66 | builder
67 | .AddSource(options.ServiceName)
68 | .SetResourceBuilder(
69 | options.ResourceBuilder
70 | .AddHoneycombAttributes()
71 | .AddService(serviceName: options.ServiceName, serviceVersion: options.ServiceVersion)
72 | .AddEnvironmentVariableDetector()
73 | );
74 |
75 | if (options.AddDeterministicSampler)
76 | {
77 | builder.AddDeterministicSampler(options.SampleRate);
78 | }
79 |
80 | if (options.AddBaggageSpanProcessor)
81 | {
82 | builder.AddBaggageSpanProcessor();
83 | }
84 |
85 | if (!string.IsNullOrWhiteSpace(tracesApiKey))
86 | {
87 | builder.AddHoneycombOtlpExporter(tracesApiKey, tracesDataset, tracesEndpoint);
88 | }
89 | else
90 | {
91 | Console.WriteLine($"WARN: {EnvironmentOptions.GetErrorMessage("API Key", "HONEYCOMB_API_KEY")}.");
92 | }
93 |
94 | if (options.EnableLocalVisualizations)
95 | {
96 | builder.AddProcessor(new SimpleActivityExportProcessor(new ConsoleTraceLinkExporter(options)));
97 | }
98 |
99 | if (options.Debug)
100 | {
101 | builder.AddConsoleExporter();
102 | Console.WriteLine("DEBUG: HoneycombOptions");
103 | Console.WriteLine(JsonSerializer.Serialize(options, new JsonSerializerOptions { WriteIndented = true }));
104 | }
105 |
106 | // heads up: even if dataset is set, it will be ignored
107 | if (!string.IsNullOrWhiteSpace(tracesApiKey) & !HoneycombOptions.IsClassicKey(tracesApiKey) & (!string.IsNullOrWhiteSpace(tracesDataset)))
108 | {
109 | if (!string.IsNullOrWhiteSpace(options.ServiceName))
110 | {
111 | Console.WriteLine($"WARN: Dataset is ignored in favor of service name. Data will be sent to service name: {options.ServiceName}");
112 | }
113 | else
114 | {
115 | // should only get here if missing service name and dataset
116 | Console.WriteLine("WARN: Dataset is ignored in favor of service name.");
117 | }
118 | }
119 |
120 | return builder;
121 | }
122 |
123 | ///
124 | /// Configures the to add the span processor.
125 | ///
126 | public static TracerProviderBuilder AddBaggageSpanProcessor(this TracerProviderBuilder builder)
127 | {
128 | return builder.AddProcessor(new BaggageSpanProcessor());
129 | }
130 |
131 | ///
132 | /// Configures the to add the trace sampler.
133 | ///
134 | public static TracerProviderBuilder AddDeterministicSampler(this TracerProviderBuilder builder, uint sampleRate)
135 | {
136 | return builder.SetSampler(new DeterministicSampler(sampleRate));
137 | }
138 |
139 | ///
140 | /// Configures the with an OTLP exporter that sends trace telemetry to Honeycomb.
141 | ///
142 | public static TracerProviderBuilder AddHoneycombOtlpExporter(this TracerProviderBuilder builder, string apikey, string dataset = null, string endpoint = null)
143 | {
144 | return builder.AddOtlpExporter(otlpOptions =>
145 | {
146 | otlpOptions.Endpoint = new Uri(endpoint);
147 | otlpOptions.Headers = HoneycombOptions.GetTraceHeaders(apikey, dataset);
148 | });
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: https://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | [*]
7 | indent_style = space
8 |
9 | # C# files
10 | [*.cs]
11 |
12 | #### Core EditorConfig Options ####
13 |
14 | # Indentation and spacing
15 | indent_size = 4
16 | indent_style = space
17 | tab_width = 4
18 |
19 | # New line preferences
20 | end_of_line = crlf
21 | insert_final_newline = false
22 |
23 | #### .NET Coding Conventions ####
24 |
25 | # Organize usings
26 | dotnet_separate_import_directive_groups = false
27 | dotnet_sort_system_directives_first = false
28 | file_header_template = unset
29 |
30 | # this. and Me. preferences
31 | dotnet_style_qualification_for_event = false:silent
32 | dotnet_style_qualification_for_field = false:silent
33 | dotnet_style_qualification_for_method = false:silent
34 | dotnet_style_qualification_for_property = false:silent
35 |
36 | # Language keywords vs BCL types preferences
37 | dotnet_style_predefined_type_for_locals_parameters_members = true:silent
38 | dotnet_style_predefined_type_for_member_access = true:silent
39 |
40 | # Parentheses preferences
41 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
42 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
43 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
44 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
45 |
46 | # Modifier preferences
47 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
48 |
49 | # Expression-level preferences
50 | dotnet_style_coalesce_expression = true:suggestion
51 | dotnet_style_collection_initializer = true:suggestion
52 | dotnet_style_explicit_tuple_names = true:suggestion
53 | dotnet_style_null_propagation = true:suggestion
54 | dotnet_style_object_initializer = true:suggestion
55 | dotnet_style_operator_placement_when_wrapping = beginning_of_line
56 | dotnet_style_prefer_auto_properties = true:silent
57 | dotnet_style_prefer_compound_assignment = true:suggestion
58 | dotnet_style_prefer_conditional_expression_over_assignment = true:silent
59 | dotnet_style_prefer_conditional_expression_over_return = true:silent
60 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
61 | dotnet_style_prefer_inferred_tuple_names = true:suggestion
62 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
63 | dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
64 | dotnet_style_prefer_simplified_interpolation = true:suggestion
65 |
66 | # Field preferences
67 | dotnet_style_readonly_field = true:suggestion
68 |
69 | # Parameter preferences
70 | dotnet_code_quality_unused_parameters = all:suggestion
71 |
72 | # Suppression preferences
73 | dotnet_remove_unnecessary_suppression_exclusions = none
74 |
75 | #### C# Coding Conventions ####
76 |
77 | # var preferences
78 | csharp_style_var_elsewhere = false:silent
79 | csharp_style_var_for_built_in_types = false:silent
80 | csharp_style_var_when_type_is_apparent = false:silent
81 |
82 | # Expression-bodied members
83 | csharp_style_expression_bodied_accessors = true:silent
84 | csharp_style_expression_bodied_constructors = false:silent
85 | csharp_style_expression_bodied_indexers = true:silent
86 | csharp_style_expression_bodied_lambdas = true:silent
87 | csharp_style_expression_bodied_local_functions = false:silent
88 | csharp_style_expression_bodied_methods = false:silent
89 | csharp_style_expression_bodied_operators = false:silent
90 | csharp_style_expression_bodied_properties = true:silent
91 |
92 | # Pattern matching preferences
93 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
94 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
95 | csharp_style_prefer_not_pattern = true:suggestion
96 | csharp_style_prefer_pattern_matching = true:silent
97 | csharp_style_prefer_switch_expression = true:suggestion
98 |
99 | # Null-checking preferences
100 | csharp_style_conditional_delegate_call = true:suggestion
101 |
102 | # Modifier preferences
103 | csharp_prefer_static_local_function = true:suggestion
104 | csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent
105 |
106 | # Code-block preferences
107 | csharp_prefer_braces = true:silent
108 | csharp_prefer_simple_using_statement = true:suggestion
109 |
110 | # Expression-level preferences
111 | csharp_prefer_simple_default_expression = true:suggestion
112 | csharp_style_deconstructed_variable_declaration = true:suggestion
113 | csharp_style_inlined_variable_declaration = true:suggestion
114 | csharp_style_pattern_local_over_anonymous_function = true:suggestion
115 | csharp_style_prefer_index_operator = true:suggestion
116 | csharp_style_prefer_range_operator = true:suggestion
117 | csharp_style_throw_expression = true:suggestion
118 | csharp_style_unused_value_assignment_preference = discard_variable:suggestion
119 | csharp_style_unused_value_expression_statement_preference = discard_variable:silent
120 |
121 | #### C# Formatting Rules ####
122 |
123 | # New line preferences
124 | csharp_new_line_before_catch = true
125 | csharp_new_line_before_else = true
126 | csharp_new_line_before_finally = true
127 | csharp_new_line_before_members_in_anonymous_types = true
128 | csharp_new_line_before_members_in_object_initializers = true
129 | csharp_new_line_before_open_brace = all
130 | csharp_new_line_between_query_expression_clauses = true
131 |
132 | # Indentation preferences
133 | csharp_indent_block_contents = true
134 | csharp_indent_braces = false
135 | csharp_indent_case_contents = true
136 | csharp_indent_case_contents_when_block = true
137 | csharp_indent_labels = one_less_than_current
138 | csharp_indent_switch_labels = true
139 |
140 | # Space preferences
141 | csharp_space_after_cast = false
142 | csharp_space_after_colon_in_inheritance_clause = true
143 | csharp_space_after_comma = true
144 | csharp_space_after_dot = false
145 | csharp_space_after_keywords_in_control_flow_statements = true
146 | csharp_space_after_semicolon_in_for_statement = true
147 | csharp_space_around_binary_operators = before_and_after
148 | csharp_space_around_declaration_statements = false
149 | csharp_space_before_colon_in_inheritance_clause = true
150 | csharp_space_before_comma = false
151 | csharp_space_before_dot = false
152 | csharp_space_before_open_square_brackets = false
153 | csharp_space_before_semicolon_in_for_statement = false
154 | csharp_space_between_empty_square_brackets = false
155 | csharp_space_between_method_call_empty_parameter_list_parentheses = false
156 | csharp_space_between_method_call_name_and_opening_parenthesis = false
157 | csharp_space_between_method_call_parameter_list_parentheses = false
158 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
159 | csharp_space_between_method_declaration_name_and_open_parenthesis = false
160 | csharp_space_between_method_declaration_parameter_list_parentheses = false
161 | csharp_space_between_parentheses = false
162 | csharp_space_between_square_brackets = false
163 |
164 | # Wrapping preferences
165 | csharp_preserve_single_line_blocks = true
166 | csharp_preserve_single_line_statements = true
167 |
168 | #### Naming styles ####
169 |
170 | # Naming rules
171 |
172 | dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
173 | dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
174 | dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
175 |
176 | dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
177 | dotnet_naming_rule.types_should_be_pascal_case.symbols = types
178 | dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
179 |
180 | dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
181 | dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
182 | dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
183 |
184 | # Symbol specifications
185 |
186 | dotnet_naming_symbols.interface.applicable_kinds = interface
187 | dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
188 | dotnet_naming_symbols.interface.required_modifiers =
189 |
190 | dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
191 | dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
192 | dotnet_naming_symbols.types.required_modifiers =
193 |
194 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
195 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
196 | dotnet_naming_symbols.non_field_members.required_modifiers =
197 |
198 | # Naming styles
199 |
200 | dotnet_naming_style.pascal_case.required_prefix =
201 | dotnet_naming_style.pascal_case.required_suffix =
202 | dotnet_naming_style.pascal_case.word_separator =
203 | dotnet_naming_style.pascal_case.capitalization = pascal_case
204 |
205 | dotnet_naming_style.begins_with_i.required_prefix = I
206 | dotnet_naming_style.begins_with_i.required_suffix =
207 | dotnet_naming_style.begins_with_i.word_separator =
208 | dotnet_naming_style.begins_with_i.capitalization = pascal_case
209 |
210 | # Xml project files
211 | [*.csproj]
212 | indent_size = 2
213 |
214 | [Makefile]
215 | indent_style = tab
216 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Ll]og/
33 | [Ll]ogs/
34 |
35 | # Visual Studio 2015/2017 cache/options directory
36 | .vs/
37 | # Uncomment if you have tasks that create the project's static files in wwwroot
38 | #wwwroot/
39 |
40 | # Visual Studio 2017 auto generated files
41 | Generated\ Files/
42 |
43 | # MSTest test Results
44 | [Tt]est[Rr]esult*/
45 | [Bb]uild[Ll]og.*
46 |
47 | # NUnit
48 | *.VisualState.xml
49 | TestResult.xml
50 | nunit-*.xml
51 |
52 | # Build Results of an ATL Project
53 | [Dd]ebugPS/
54 | [Rr]eleasePS/
55 | dlldata.c
56 |
57 | # Benchmark Results
58 | BenchmarkDotNet.Artifacts/
59 |
60 | # .NET Core
61 | project.lock.json
62 | project.fragment.lock.json
63 | artifacts/
64 |
65 | # Tye
66 | .tye/
67 |
68 | # ASP.NET Scaffolding
69 | ScaffoldingReadMe.txt
70 |
71 | # StyleCop
72 | StyleCopReport.xml
73 |
74 | # Files built by Visual Studio
75 | *_i.c
76 | *_p.c
77 | *_h.h
78 | *.ilk
79 | *.meta
80 | *.obj
81 | *.iobj
82 | *.pch
83 | *.pdb
84 | *.ipdb
85 | *.pgc
86 | *.pgd
87 | *.rsp
88 | *.sbr
89 | *.tlb
90 | *.tli
91 | *.tlh
92 | *.tmp
93 | *.tmp_proj
94 | *_wpftmp.csproj
95 | *.log
96 | *.vspscc
97 | *.vssscc
98 | .builds
99 | *.pidb
100 | *.svclog
101 | *.scc
102 |
103 | # Chutzpah Test files
104 | _Chutzpah*
105 |
106 | # Visual C++ cache files
107 | ipch/
108 | *.aps
109 | *.ncb
110 | *.opendb
111 | *.opensdf
112 | *.sdf
113 | *.cachefile
114 | *.VC.db
115 | *.VC.VC.opendb
116 |
117 | # Visual Studio profiler
118 | *.psess
119 | *.vsp
120 | *.vspx
121 | *.sap
122 |
123 | # Visual Studio Trace Files
124 | *.e2e
125 |
126 | # TFS 2012 Local Workspace
127 | $tf/
128 |
129 | # Guidance Automation Toolkit
130 | *.gpState
131 |
132 | # ReSharper is a .NET coding add-in
133 | _ReSharper*/
134 | *.[Rr]e[Ss]harper
135 | *.DotSettings.user
136 |
137 | # TeamCity is a build add-in
138 | _TeamCity*
139 |
140 | # DotCover is a Code Coverage Tool
141 | *.dotCover
142 |
143 | # AxoCover is a Code Coverage Tool
144 | .axoCover/*
145 | !.axoCover/settings.json
146 |
147 | # Coverlet is a free, cross platform Code Coverage Tool
148 | coverage*.json
149 | coverage*.xml
150 | coverage*.info
151 |
152 | # Visual Studio code coverage results
153 | *.coverage
154 | *.coveragexml
155 |
156 | # NCrunch
157 | _NCrunch_*
158 | .*crunch*.local.xml
159 | nCrunchTemp_*
160 |
161 | # MightyMoose
162 | *.mm.*
163 | AutoTest.Net/
164 |
165 | # Web workbench (sass)
166 | .sass-cache/
167 |
168 | # Installshield output folder
169 | [Ee]xpress/
170 |
171 | # DocProject is a documentation generator add-in
172 | DocProject/buildhelp/
173 | DocProject/Help/*.HxT
174 | DocProject/Help/*.HxC
175 | DocProject/Help/*.hhc
176 | DocProject/Help/*.hhk
177 | DocProject/Help/*.hhp
178 | DocProject/Help/Html2
179 | DocProject/Help/html
180 |
181 | # Click-Once directory
182 | publish/
183 |
184 | # Publish Web Output
185 | *.[Pp]ublish.xml
186 | *.azurePubxml
187 | # Note: Comment the next line if you want to checkin your web deploy settings,
188 | # but database connection strings (with potential passwords) will be unencrypted
189 | *.pubxml
190 | *.publishproj
191 |
192 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
193 | # checkin your Azure Web App publish settings, but sensitive information contained
194 | # in these scripts will be unencrypted
195 | PublishScripts/
196 |
197 | # NuGet Packages
198 | *.nupkg
199 | # NuGet Symbol Packages
200 | *.snupkg
201 | # The packages folder can be ignored because of Package Restore
202 | **/[Pp]ackages/*
203 | # except build/, which is used as an MSBuild target.
204 | !**/[Pp]ackages/build/
205 | # Uncomment if necessary however generally it will be regenerated when needed
206 | #!**/[Pp]ackages/repositories.config
207 | # NuGet v3's project.json files produces more ignorable files
208 | *.nuget.props
209 | *.nuget.targets
210 |
211 | # Microsoft Azure Build Output
212 | csx/
213 | *.build.csdef
214 |
215 | # Microsoft Azure Emulator
216 | ecf/
217 | rcf/
218 |
219 | # Windows Store app package directories and files
220 | AppPackages/
221 | BundleArtifacts/
222 | Package.StoreAssociation.xml
223 | _pkginfo.txt
224 | *.appx
225 | *.appxbundle
226 | *.appxupload
227 |
228 | # Visual Studio cache files
229 | # files ending in .cache can be ignored
230 | *.[Cc]ache
231 | # but keep track of directories ending in .cache
232 | !?*.[Cc]ache/
233 |
234 | # Others
235 | ClientBin/
236 | ~$*
237 | *~
238 | *.dbmdl
239 | *.dbproj.schemaview
240 | *.jfm
241 | *.pfx
242 | *.publishsettings
243 | orleans.codegen.cs
244 |
245 | # Including strong name files can present a security risk
246 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
247 | *.snk
248 |
249 | # Since there are multiple workflows, uncomment next line to ignore bower_components
250 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
251 | #bower_components/
252 |
253 | # RIA/Silverlight projects
254 | Generated_Code/
255 |
256 | # Backup & report files from converting an old project file
257 | # to a newer Visual Studio version. Backup files are not needed,
258 | # because we have git ;-)
259 | _UpgradeReport_Files/
260 | Backup*/
261 | UpgradeLog*.XML
262 | UpgradeLog*.htm
263 | ServiceFabricBackup/
264 | *.rptproj.bak
265 |
266 | # SQL Server files
267 | *.mdf
268 | *.ldf
269 | *.ndf
270 |
271 | # Business Intelligence projects
272 | *.rdl.data
273 | *.bim.layout
274 | *.bim_*.settings
275 | *.rptproj.rsuser
276 | *- [Bb]ackup.rdl
277 | *- [Bb]ackup ([0-9]).rdl
278 | *- [Bb]ackup ([0-9][0-9]).rdl
279 |
280 | # Microsoft Fakes
281 | FakesAssemblies/
282 |
283 | # GhostDoc plugin setting file
284 | *.GhostDoc.xml
285 |
286 | # Node.js Tools for Visual Studio
287 | .ntvs_analysis.dat
288 | node_modules/
289 |
290 | # Visual Studio 6 build log
291 | *.plg
292 |
293 | # Visual Studio 6 workspace options file
294 | *.opt
295 |
296 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
297 | *.vbw
298 |
299 | # Visual Studio LightSwitch build output
300 | **/*.HTMLClient/GeneratedArtifacts
301 | **/*.DesktopClient/GeneratedArtifacts
302 | **/*.DesktopClient/ModelManifest.xml
303 | **/*.Server/GeneratedArtifacts
304 | **/*.Server/ModelManifest.xml
305 | _Pvt_Extensions
306 |
307 | # Paket dependency manager
308 | .paket/paket.exe
309 | paket-files/
310 |
311 | # FAKE - F# Make
312 | .fake/
313 |
314 | # CodeRush personal settings
315 | .cr/personal
316 |
317 | # Python Tools for Visual Studio (PTVS)
318 | __pycache__/
319 | *.pyc
320 |
321 | # Cake - Uncomment if you are using it
322 | # tools/**
323 | # !tools/packages.config
324 |
325 | # Tabs Studio
326 | *.tss
327 |
328 | # Telerik's JustMock configuration file
329 | *.jmconfig
330 |
331 | # BizTalk build output
332 | *.btp.cs
333 | *.btm.cs
334 | *.odx.cs
335 | *.xsd.cs
336 |
337 | # OpenCover UI analysis results
338 | OpenCover/
339 |
340 | # Azure Stream Analytics local run output
341 | ASALocalRun/
342 |
343 | # MSBuild Binary and Structured Log
344 | *.binlog
345 |
346 | # NVidia Nsight GPU debugger configuration file
347 | *.nvuser
348 |
349 | # MFractors (Xamarin productivity tool) working folder
350 | .mfractor/
351 |
352 | # Local History for Visual Studio
353 | .localhistory/
354 |
355 | # BeatPulse healthcheck temp database
356 | healthchecksdb
357 |
358 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
359 | MigrationBackup/
360 |
361 | # Ionide (cross platform F# VS Code tools) working folder
362 | .ionide/
363 |
364 | # Fody - auto-generated XML schema
365 | FodyWeavers.xsd
366 |
367 | ##
368 | ## Visual studio for Mac
369 | ##
370 |
371 |
372 | # globs
373 | Makefile.in
374 | *.userprefs
375 | *.usertasks
376 | config.make
377 | config.status
378 | aclocal.m4
379 | install-sh
380 | autom4te.cache/
381 | *.tar.gz
382 | tarballs/
383 | test-results/
384 |
385 | # Mac bundle stuff
386 | *.dmg
387 | *.app
388 |
389 | # content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
390 | # General
391 | .DS_Store
392 | .AppleDouble
393 | .LSOverride
394 |
395 | # Icon must end with two \r
396 | Icon
397 |
398 |
399 | # Thumbnails
400 | ._*
401 |
402 | # Files that might appear in the root of a volume
403 | .DocumentRevisions-V100
404 | .fseventsd
405 | .Spotlight-V100
406 | .TemporaryItems
407 | .Trashes
408 | .VolumeIcon.icns
409 | .com.apple.timemachine.donotpresent
410 |
411 | # Directories potentially created on remote AFP share
412 | .AppleDB
413 | .AppleDesktop
414 | Network Trash Folder
415 | Temporary Items
416 | .apdisk
417 |
418 | # content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
419 | # Windows thumbnail cache files
420 | Thumbs.db
421 | ehthumbs.db
422 | ehthumbs_vista.db
423 |
424 | # Dump file
425 | *.stackdump
426 |
427 | # Folder config file
428 | [Dd]esktop.ini
429 |
430 | # Recycle Bin used on file shares
431 | $RECYCLE.BIN/
432 |
433 | # Windows Installer files
434 | *.cab
435 | *.msi
436 | *.msix
437 | *.msm
438 | *.msp
439 |
440 | # Windows shortcuts
441 | *.lnk
442 |
443 | # JetBrains Rider
444 | .idea/
445 | *.sln.iml
446 |
447 | ##
448 | ## Visual Studio Code
449 | ##
450 | .vscode/*
451 | !.vscode/settings.json
452 | !.vscode/tasks.json
453 | !.vscode/launch.json
454 | !.vscode/extensions.json
455 |
456 | ### temporary smoke-test files
457 | smoke-tests/collector/data.json
458 | smoke-tests/collector/data-results/*.json
459 | smoke-tests/report.xml
460 | smoke-tests/report.html
461 |
462 | # asdf local tools versions file
463 | .tool-versions
--------------------------------------------------------------------------------
/honeycomb-opentelemetry.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.4.32916.344
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3E7EDB35-637A-402C-ABA6-EF8E4C55C051}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Honeycomb.OpenTelemetry", "src\Honeycomb.OpenTelemetry\Honeycomb.OpenTelemetry.csproj", "{061494E1-D5D7-479E-BE88-FE0E2F94D9F5}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{B622C013-E4C5-4632-A263-B652C38D2E27}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Honeycomb.OpenTelemetry.Tests", "test\Honeycomb.OpenTelemetry.Tests\Honeycomb.OpenTelemetry.Tests.csproj", "{DE41D67B-F18B-4EAD-A1AC-D7AAB1DEB55E}"
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{B2B54384-A507-44F4-B611-039F7CC27AC0}"
15 | EndProject
16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "console", "examples\console\console.csproj", "{DC70B54C-4F4E-4826-A41B-99E976E9475A}"
17 | EndProject
18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "aspnetcore", "examples\aspnetcore\aspnetcore.csproj", "{37D377D0-7C5A-4F44-B535-C9DA60FDB723}"
19 | EndProject
20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "aspnetcoreredis", "examples\aspnetcore-redis\aspnetcoreredis.csproj", "{41B05546-CC58-4546-AC73-2497F7CD8FD8}"
21 | EndProject
22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Honeycomb.OpenTelemetry.Instrumentation.AspNetCore", "src\Honeycomb.OpenTelemetry.Instrumentation.AspNetCore\Honeycomb.OpenTelemetry.Instrumentation.AspNetCore.csproj", "{DB772676-A314-44DC-8EBD-971FBE6953B9}"
23 | EndProject
24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Honeycomb.OpenTelemetry.CommonInstrumentations", "src\Honeycomb.OpenTelemetry.CommonInstrumentations\Honeycomb.OpenTelemetry.CommonInstrumentations.csproj", "{CA34C8B5-6C46-41C5-8931-AAFAD732DF5F}"
25 | EndProject
26 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "aspnetcore-fsharp", "examples\aspnetcore-fsharp\aspnetcore-fsharp.fsproj", "{72DF2078-62A4-4529-B439-BFFF4AD4C6B9}"
27 | EndProject
28 | Global
29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
30 | Debug|Any CPU = Debug|Any CPU
31 | Debug|x64 = Debug|x64
32 | Debug|x86 = Debug|x86
33 | Release|Any CPU = Release|Any CPU
34 | Release|x64 = Release|x64
35 | Release|x86 = Release|x86
36 | EndGlobalSection
37 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
38 | {061494E1-D5D7-479E-BE88-FE0E2F94D9F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {061494E1-D5D7-479E-BE88-FE0E2F94D9F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {061494E1-D5D7-479E-BE88-FE0E2F94D9F5}.Debug|x64.ActiveCfg = Debug|Any CPU
41 | {061494E1-D5D7-479E-BE88-FE0E2F94D9F5}.Debug|x64.Build.0 = Debug|Any CPU
42 | {061494E1-D5D7-479E-BE88-FE0E2F94D9F5}.Debug|x86.ActiveCfg = Debug|Any CPU
43 | {061494E1-D5D7-479E-BE88-FE0E2F94D9F5}.Debug|x86.Build.0 = Debug|Any CPU
44 | {061494E1-D5D7-479E-BE88-FE0E2F94D9F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {061494E1-D5D7-479E-BE88-FE0E2F94D9F5}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {061494E1-D5D7-479E-BE88-FE0E2F94D9F5}.Release|x64.ActiveCfg = Release|Any CPU
47 | {061494E1-D5D7-479E-BE88-FE0E2F94D9F5}.Release|x64.Build.0 = Release|Any CPU
48 | {061494E1-D5D7-479E-BE88-FE0E2F94D9F5}.Release|x86.ActiveCfg = Release|Any CPU
49 | {061494E1-D5D7-479E-BE88-FE0E2F94D9F5}.Release|x86.Build.0 = Release|Any CPU
50 | {DE41D67B-F18B-4EAD-A1AC-D7AAB1DEB55E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51 | {DE41D67B-F18B-4EAD-A1AC-D7AAB1DEB55E}.Debug|Any CPU.Build.0 = Debug|Any CPU
52 | {DE41D67B-F18B-4EAD-A1AC-D7AAB1DEB55E}.Debug|x64.ActiveCfg = Debug|Any CPU
53 | {DE41D67B-F18B-4EAD-A1AC-D7AAB1DEB55E}.Debug|x64.Build.0 = Debug|Any CPU
54 | {DE41D67B-F18B-4EAD-A1AC-D7AAB1DEB55E}.Debug|x86.ActiveCfg = Debug|Any CPU
55 | {DE41D67B-F18B-4EAD-A1AC-D7AAB1DEB55E}.Debug|x86.Build.0 = Debug|Any CPU
56 | {DE41D67B-F18B-4EAD-A1AC-D7AAB1DEB55E}.Release|Any CPU.ActiveCfg = Release|Any CPU
57 | {DE41D67B-F18B-4EAD-A1AC-D7AAB1DEB55E}.Release|Any CPU.Build.0 = Release|Any CPU
58 | {DE41D67B-F18B-4EAD-A1AC-D7AAB1DEB55E}.Release|x64.ActiveCfg = Release|Any CPU
59 | {DE41D67B-F18B-4EAD-A1AC-D7AAB1DEB55E}.Release|x64.Build.0 = Release|Any CPU
60 | {DE41D67B-F18B-4EAD-A1AC-D7AAB1DEB55E}.Release|x86.ActiveCfg = Release|Any CPU
61 | {DE41D67B-F18B-4EAD-A1AC-D7AAB1DEB55E}.Release|x86.Build.0 = Release|Any CPU
62 | {DC70B54C-4F4E-4826-A41B-99E976E9475A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
63 | {DC70B54C-4F4E-4826-A41B-99E976E9475A}.Debug|Any CPU.Build.0 = Debug|Any CPU
64 | {DC70B54C-4F4E-4826-A41B-99E976E9475A}.Debug|x64.ActiveCfg = Debug|Any CPU
65 | {DC70B54C-4F4E-4826-A41B-99E976E9475A}.Debug|x64.Build.0 = Debug|Any CPU
66 | {DC70B54C-4F4E-4826-A41B-99E976E9475A}.Debug|x86.ActiveCfg = Debug|Any CPU
67 | {DC70B54C-4F4E-4826-A41B-99E976E9475A}.Debug|x86.Build.0 = Debug|Any CPU
68 | {DC70B54C-4F4E-4826-A41B-99E976E9475A}.Release|Any CPU.ActiveCfg = Release|Any CPU
69 | {DC70B54C-4F4E-4826-A41B-99E976E9475A}.Release|Any CPU.Build.0 = Release|Any CPU
70 | {DC70B54C-4F4E-4826-A41B-99E976E9475A}.Release|x64.ActiveCfg = Release|Any CPU
71 | {DC70B54C-4F4E-4826-A41B-99E976E9475A}.Release|x64.Build.0 = Release|Any CPU
72 | {DC70B54C-4F4E-4826-A41B-99E976E9475A}.Release|x86.ActiveCfg = Release|Any CPU
73 | {DC70B54C-4F4E-4826-A41B-99E976E9475A}.Release|x86.Build.0 = Release|Any CPU
74 | {37D377D0-7C5A-4F44-B535-C9DA60FDB723}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
75 | {37D377D0-7C5A-4F44-B535-C9DA60FDB723}.Debug|Any CPU.Build.0 = Debug|Any CPU
76 | {37D377D0-7C5A-4F44-B535-C9DA60FDB723}.Debug|x64.ActiveCfg = Debug|Any CPU
77 | {37D377D0-7C5A-4F44-B535-C9DA60FDB723}.Debug|x64.Build.0 = Debug|Any CPU
78 | {37D377D0-7C5A-4F44-B535-C9DA60FDB723}.Debug|x86.ActiveCfg = Debug|Any CPU
79 | {37D377D0-7C5A-4F44-B535-C9DA60FDB723}.Debug|x86.Build.0 = Debug|Any CPU
80 | {37D377D0-7C5A-4F44-B535-C9DA60FDB723}.Release|Any CPU.ActiveCfg = Release|Any CPU
81 | {37D377D0-7C5A-4F44-B535-C9DA60FDB723}.Release|Any CPU.Build.0 = Release|Any CPU
82 | {37D377D0-7C5A-4F44-B535-C9DA60FDB723}.Release|x64.ActiveCfg = Release|Any CPU
83 | {37D377D0-7C5A-4F44-B535-C9DA60FDB723}.Release|x64.Build.0 = Release|Any CPU
84 | {37D377D0-7C5A-4F44-B535-C9DA60FDB723}.Release|x86.ActiveCfg = Release|Any CPU
85 | {37D377D0-7C5A-4F44-B535-C9DA60FDB723}.Release|x86.Build.0 = Release|Any CPU
86 | {41B05546-CC58-4546-AC73-2497F7CD8FD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
87 | {41B05546-CC58-4546-AC73-2497F7CD8FD8}.Debug|Any CPU.Build.0 = Debug|Any CPU
88 | {41B05546-CC58-4546-AC73-2497F7CD8FD8}.Debug|x64.ActiveCfg = Debug|Any CPU
89 | {41B05546-CC58-4546-AC73-2497F7CD8FD8}.Debug|x64.Build.0 = Debug|Any CPU
90 | {41B05546-CC58-4546-AC73-2497F7CD8FD8}.Debug|x86.ActiveCfg = Debug|Any CPU
91 | {41B05546-CC58-4546-AC73-2497F7CD8FD8}.Debug|x86.Build.0 = Debug|Any CPU
92 | {41B05546-CC58-4546-AC73-2497F7CD8FD8}.Release|Any CPU.ActiveCfg = Release|Any CPU
93 | {41B05546-CC58-4546-AC73-2497F7CD8FD8}.Release|Any CPU.Build.0 = Release|Any CPU
94 | {41B05546-CC58-4546-AC73-2497F7CD8FD8}.Release|x64.ActiveCfg = Release|Any CPU
95 | {41B05546-CC58-4546-AC73-2497F7CD8FD8}.Release|x64.Build.0 = Release|Any CPU
96 | {41B05546-CC58-4546-AC73-2497F7CD8FD8}.Release|x86.ActiveCfg = Release|Any CPU
97 | {41B05546-CC58-4546-AC73-2497F7CD8FD8}.Release|x86.Build.0 = Release|Any CPU
98 | {DB772676-A314-44DC-8EBD-971FBE6953B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
99 | {DB772676-A314-44DC-8EBD-971FBE6953B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
100 | {DB772676-A314-44DC-8EBD-971FBE6953B9}.Debug|x64.ActiveCfg = Debug|Any CPU
101 | {DB772676-A314-44DC-8EBD-971FBE6953B9}.Debug|x64.Build.0 = Debug|Any CPU
102 | {DB772676-A314-44DC-8EBD-971FBE6953B9}.Debug|x86.ActiveCfg = Debug|Any CPU
103 | {DB772676-A314-44DC-8EBD-971FBE6953B9}.Debug|x86.Build.0 = Debug|Any CPU
104 | {DB772676-A314-44DC-8EBD-971FBE6953B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
105 | {DB772676-A314-44DC-8EBD-971FBE6953B9}.Release|Any CPU.Build.0 = Release|Any CPU
106 | {DB772676-A314-44DC-8EBD-971FBE6953B9}.Release|x64.ActiveCfg = Release|Any CPU
107 | {DB772676-A314-44DC-8EBD-971FBE6953B9}.Release|x64.Build.0 = Release|Any CPU
108 | {DB772676-A314-44DC-8EBD-971FBE6953B9}.Release|x86.ActiveCfg = Release|Any CPU
109 | {DB772676-A314-44DC-8EBD-971FBE6953B9}.Release|x86.Build.0 = Release|Any CPU
110 | {CA34C8B5-6C46-41C5-8931-AAFAD732DF5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
111 | {CA34C8B5-6C46-41C5-8931-AAFAD732DF5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
112 | {CA34C8B5-6C46-41C5-8931-AAFAD732DF5F}.Debug|x64.ActiveCfg = Debug|Any CPU
113 | {CA34C8B5-6C46-41C5-8931-AAFAD732DF5F}.Debug|x64.Build.0 = Debug|Any CPU
114 | {CA34C8B5-6C46-41C5-8931-AAFAD732DF5F}.Debug|x86.ActiveCfg = Debug|Any CPU
115 | {CA34C8B5-6C46-41C5-8931-AAFAD732DF5F}.Debug|x86.Build.0 = Debug|Any CPU
116 | {CA34C8B5-6C46-41C5-8931-AAFAD732DF5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
117 | {CA34C8B5-6C46-41C5-8931-AAFAD732DF5F}.Release|Any CPU.Build.0 = Release|Any CPU
118 | {CA34C8B5-6C46-41C5-8931-AAFAD732DF5F}.Release|x64.ActiveCfg = Release|Any CPU
119 | {CA34C8B5-6C46-41C5-8931-AAFAD732DF5F}.Release|x64.Build.0 = Release|Any CPU
120 | {CA34C8B5-6C46-41C5-8931-AAFAD732DF5F}.Release|x86.ActiveCfg = Release|Any CPU
121 | {CA34C8B5-6C46-41C5-8931-AAFAD732DF5F}.Release|x86.Build.0 = Release|Any CPU
122 | {72DF2078-62A4-4529-B439-BFFF4AD4C6B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
123 | {72DF2078-62A4-4529-B439-BFFF4AD4C6B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
124 | {72DF2078-62A4-4529-B439-BFFF4AD4C6B9}.Debug|x64.ActiveCfg = Debug|Any CPU
125 | {72DF2078-62A4-4529-B439-BFFF4AD4C6B9}.Debug|x64.Build.0 = Debug|Any CPU
126 | {72DF2078-62A4-4529-B439-BFFF4AD4C6B9}.Debug|x86.ActiveCfg = Debug|Any CPU
127 | {72DF2078-62A4-4529-B439-BFFF4AD4C6B9}.Debug|x86.Build.0 = Debug|Any CPU
128 | {72DF2078-62A4-4529-B439-BFFF4AD4C6B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
129 | {72DF2078-62A4-4529-B439-BFFF4AD4C6B9}.Release|Any CPU.Build.0 = Release|Any CPU
130 | {72DF2078-62A4-4529-B439-BFFF4AD4C6B9}.Release|x64.ActiveCfg = Release|Any CPU
131 | {72DF2078-62A4-4529-B439-BFFF4AD4C6B9}.Release|x64.Build.0 = Release|Any CPU
132 | {72DF2078-62A4-4529-B439-BFFF4AD4C6B9}.Release|x86.ActiveCfg = Release|Any CPU
133 | {72DF2078-62A4-4529-B439-BFFF4AD4C6B9}.Release|x86.Build.0 = Release|Any CPU
134 | EndGlobalSection
135 | GlobalSection(SolutionProperties) = preSolution
136 | HideSolutionNode = FALSE
137 | EndGlobalSection
138 | GlobalSection(NestedProjects) = preSolution
139 | {061494E1-D5D7-479E-BE88-FE0E2F94D9F5} = {3E7EDB35-637A-402C-ABA6-EF8E4C55C051}
140 | {DE41D67B-F18B-4EAD-A1AC-D7AAB1DEB55E} = {B622C013-E4C5-4632-A263-B652C38D2E27}
141 | {DC70B54C-4F4E-4826-A41B-99E976E9475A} = {B2B54384-A507-44F4-B611-039F7CC27AC0}
142 | {37D377D0-7C5A-4F44-B535-C9DA60FDB723} = {B2B54384-A507-44F4-B611-039F7CC27AC0}
143 | {41B05546-CC58-4546-AC73-2497F7CD8FD8} = {B2B54384-A507-44F4-B611-039F7CC27AC0}
144 | {DB772676-A314-44DC-8EBD-971FBE6953B9} = {3E7EDB35-637A-402C-ABA6-EF8E4C55C051}
145 | {CA34C8B5-6C46-41C5-8931-AAFAD732DF5F} = {3E7EDB35-637A-402C-ABA6-EF8E4C55C051}
146 | {72DF2078-62A4-4529-B439-BFFF4AD4C6B9} = {B2B54384-A507-44F4-B611-039F7CC27AC0}
147 | EndGlobalSection
148 | GlobalSection(ExtensibilityGlobals) = postSolution
149 | SolutionGuid = {AFD90899-B909-432A-BBAA-BBC662E19E7C}
150 | EndGlobalSection
151 | EndGlobal
152 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/src/Honeycomb.OpenTelemetry/HoneycombOptions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using OpenTelemetry.Resources;
3 | using OpenTelemetry.Trace;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Diagnostics.Metrics;
7 | using System.Text.RegularExpressions;
8 |
9 | namespace Honeycomb.OpenTelemetry
10 | {
11 | ///
12 | /// Configuration options used to configure to send telemetry data to Honeycomb.
13 | ///
14 | public class HoneycombOptions
15 | {
16 | private const string OtlpVersion = "0.19.0";
17 | private const string OtelExporterOtlpProtocolHttpProtobuf = "http/protobuf";
18 | private const string OtelExporterOtlpProtocolHttpJson = "http/json";
19 | private const string OtelExporterOtlpProtocolGrpc = "grpc";
20 | private const string OtelExporterHttpTracesPath = "/v1/traces";
21 | private const string OtelExporterHttpMetricsPath = "/v1/metrics";
22 | private const string ClassicKeyRegex = "^[a-f0-9]*$";
23 | private const string IngestClassicKeyRegex = "^hc[a-z]ic_[a-z0-9]*$";
24 | private bool isHttp = false;
25 |
26 | ///
27 | /// Default service name if service name is not provided.
28 | ///
29 | internal static readonly string SDefaultServiceName = $"unknown_service:{System.Diagnostics.Process.GetCurrentProcess().ProcessName}";
30 | internal static readonly string SDefaultServiceVersion = "unknown_service_version";
31 |
32 | ///
33 | /// Name of the Honeycomb section of IConfiguration
34 | ///
35 | public const string ConfigSectionName = "Honeycomb";
36 |
37 | ///
38 | /// Default API endpoint.
39 | ///
40 | public const string DefaultEndpoint = "https://api.honeycomb.io:443";
41 |
42 | ///
43 | /// Default sample rate - sample everything.
44 | ///
45 | public const uint DefaultSampleRate = 1;
46 |
47 | ///
48 | /// API key used to send telemetry data to Honeycomb.
49 | ///
50 | ///
51 | public string ApiKey { get; set; }
52 |
53 | ///
54 | /// Returns whether the provided API key is a classic key.
55 | ///
56 | ///
57 | /// Classic configuration keys have 32 characters and classic ingest keys have 64 characters.
58 | ///
59 | internal static bool IsClassicKey(string apikey)
60 | {
61 | if (String.IsNullOrEmpty(apikey))
62 | {
63 | return false;
64 | }
65 | else if (apikey.Length == 32)
66 | {
67 | return Regex.Match(apikey, ClassicKeyRegex).Success;
68 | }
69 | else if (apikey.Length == 64)
70 | {
71 | return Regex.Match(apikey, IngestClassicKeyRegex).Success;
72 | }
73 | return false;
74 | }
75 |
76 | ///
77 | /// Write links to honeycomb traces as they come in
78 | ///
79 | public bool EnableLocalVisualizations { get; set; } = false;
80 |
81 | ///
82 | /// API key used to send trace telemetry data to Honeycomb. Defaults to .
83 | ///
84 | public string TracesApiKey { get; set; }
85 |
86 | ///
87 | /// API key used to send metrics telemetry data to Honeycomb. Defaults to .
88 | ///
89 | public string MetricsApiKey { get; set; }
90 |
91 | ///
92 | /// Honeycomb dataset to store telemetry data.
93 | ///
94 | ///
95 | public string Dataset { get; set; }
96 |
97 | ///
98 | /// Honeycomb dataset to store trace telemetry data. Defaults to .
99 | ///
100 | public string TracesDataset { get; set; }
101 |
102 | ///
103 | /// Honeycomb dataset to store metrics telemetry data. Defaults to "null".
104 | ///
105 | /// Required to enable metrics.
106 | ///
107 | public string MetricsDataset { get; set; }
108 |
109 | ///
110 | /// API endpoint to send telemetry data. Defaults to .
111 | ///
112 | public string Endpoint { get; set; } = DefaultEndpoint;
113 |
114 | ///
115 | /// API endpoint to send telemetry data. Defaults to .
116 | ///
117 | public string TracesEndpoint { get; set; }
118 |
119 | ///
120 | /// API endpoint to send telemetry data. Defaults to .
121 | ///
122 | public string MetricsEndpoint { get; set; }
123 |
124 | ///
125 | /// Sample rate for sending telemetry data. Defaults to .
126 | ///
127 | /// See for more details on how sampling is applied.
128 | ///
129 | public uint SampleRate { get; set; } = DefaultSampleRate;
130 |
131 | ///
132 | /// Service name used to identify application. Defaults to unknown_process:processname.
133 | ///
134 | public string ServiceName { get; set; } = SDefaultServiceName;
135 |
136 | ///
137 | /// Service version. Defaults to application assembly information version.
138 | ///
139 | public string ServiceVersion { get; set; } = SDefaultServiceVersion;
140 |
141 | ///
142 | /// (Optional) Additional names for generating metrics.
143 | /// is configured as a meter name by default.
144 | ///
145 | public List MeterNames { get; set; } = new List();
146 |
147 | ///
148 | /// The to use to add Resource attributes to.
149 | /// A custom ResouceBuilder can be used to set additional resources and then passed here to add
150 | /// Honeycomb attributes.
151 | ///
152 | public ResourceBuilder ResourceBuilder { get; set; } = ResourceBuilder.CreateDefault();
153 |
154 | ///
155 | /// Determines whether the is added when configuring a .
156 | ///
157 | public bool AddBaggageSpanProcessor { get; set; } = true;
158 |
159 | ///
160 | /// Determines whether the sampler is added when configuring a .
161 | ///
162 | public bool AddDeterministicSampler { get; set; } = true;
163 |
164 | ///
165 | /// If set to true, enables the console span exporter for local debugging.
166 | ///
167 | public bool Debug { get; set; } = false;
168 |
169 | ///
170 | /// Applies environment variable option overrides.
171 | ///
172 | internal void ApplyEnvironmentOptions(EnvironmentOptions environmentOptions)
173 | {
174 | if (!string.IsNullOrWhiteSpace(environmentOptions.ApiKey))
175 | {
176 | ApiKey = environmentOptions.ApiKey;
177 | }
178 |
179 | if (!string.IsNullOrWhiteSpace(environmentOptions.TracesApiKey))
180 | {
181 | TracesApiKey = environmentOptions.TracesApiKey;
182 | }
183 |
184 | if (!string.IsNullOrWhiteSpace(environmentOptions.MetricsApiKey))
185 | {
186 | MetricsApiKey = environmentOptions.MetricsApiKey;
187 | }
188 |
189 | if (!string.IsNullOrWhiteSpace(environmentOptions.ApiEndpoint))
190 | {
191 | Endpoint = environmentOptions.ApiEndpoint;
192 | }
193 |
194 | if (!string.IsNullOrWhiteSpace(environmentOptions.Dataset))
195 | {
196 | Dataset = environmentOptions.Dataset;
197 | }
198 |
199 | if (!string.IsNullOrWhiteSpace(environmentOptions.TracesDataset))
200 | {
201 | TracesDataset = environmentOptions.TracesDataset;
202 | }
203 |
204 | if (!string.IsNullOrWhiteSpace(environmentOptions.MetricsDataset))
205 | {
206 | MetricsDataset = environmentOptions.MetricsDataset;
207 | }
208 |
209 | if (!string.IsNullOrWhiteSpace(environmentOptions.TracesEndpoint))
210 | {
211 | TracesEndpoint = environmentOptions.TracesEndpoint;
212 | }
213 |
214 | if (!string.IsNullOrWhiteSpace(environmentOptions.MetricsEndpoint))
215 | {
216 | MetricsEndpoint = environmentOptions.MetricsEndpoint;
217 | }
218 |
219 | if (!string.IsNullOrWhiteSpace(environmentOptions.ServiceName))
220 | {
221 | ServiceName = environmentOptions.ServiceName;
222 | }
223 |
224 | if (!string.IsNullOrWhiteSpace(environmentOptions.ServiceVersion))
225 | {
226 | ServiceVersion = environmentOptions.ServiceVersion;
227 | }
228 |
229 | if (!string.IsNullOrWhiteSpace(environmentOptions.EnableLocalVisualizationsValue))
230 | {
231 | EnableLocalVisualizations = environmentOptions.EnableLocalVisualizations;
232 | }
233 |
234 | if (!string.IsNullOrWhiteSpace(environmentOptions.DebugValue))
235 | {
236 | Debug = environmentOptions.Debug;
237 | }
238 |
239 | if (!string.IsNullOrWhiteSpace(environmentOptions.SampleRateValue))
240 | {
241 | SampleRate = environmentOptions.SampleRate;
242 | }
243 |
244 | if (environmentOptions.OtelExporterOtlpProtocol == OtelExporterOtlpProtocolHttpProtobuf || environmentOptions.OtelExporterOtlpProtocol == OtelExporterOtlpProtocolHttpJson)
245 | {
246 | isHttp = true;
247 | }
248 | }
249 |
250 | ///
251 | /// Gets the or falls back to the generic .
252 | ///
253 | internal string GetTracesEndpoint()
254 | {
255 | var endpoint = new UriBuilder(Endpoint);
256 | if (isHttp && (string.IsNullOrWhiteSpace(endpoint.Path) || endpoint.Path == "/"))
257 | {
258 | endpoint.Path = OtelExporterHttpTracesPath;
259 | }
260 | return TracesEndpoint ?? endpoint.ToString();
261 | }
262 |
263 | internal string GetTracesApiKey()
264 | {
265 | return TracesApiKey ?? ApiKey;
266 | }
267 |
268 | internal string GetTracesDataset()
269 | {
270 | return TracesDataset ?? Dataset;
271 | }
272 |
273 | ///
274 | /// Gets the or falls back to the generic .
275 | ///
276 | internal string GetMetricsEndpoint()
277 | {
278 | var endpoint = new UriBuilder(Endpoint);
279 | if (isHttp && (string.IsNullOrWhiteSpace(endpoint.Path) || endpoint.Path == "/"))
280 | {
281 | endpoint.Path = OtelExporterHttpMetricsPath;
282 | }
283 | return MetricsEndpoint ?? endpoint.ToString();
284 | }
285 |
286 | ///
287 | /// Gets the or falls back to the generic .
288 | ///
289 | internal string GetMetricsApiKey()
290 | {
291 | return MetricsApiKey ?? ApiKey;
292 | }
293 |
294 | internal string GetTraceHeaders() => GetTraceHeaders(TracesApiKey, TracesDataset);
295 |
296 | internal static string GetTraceHeaders(string apikey, string dataset)
297 | {
298 | var headers = new List
299 | {
300 | $"x-otlp-version={OtlpVersion}",
301 | $"x-honeycomb-team={apikey}"
302 | };
303 |
304 | if (IsClassicKey(apikey))
305 | {
306 | // if the key is legacy, add dataset to the header
307 | if (!string.IsNullOrWhiteSpace(dataset))
308 | {
309 | headers.Add($"x-honeycomb-dataset={dataset}");
310 | }
311 | else
312 | {
313 | // if legacy key and missing dataset, warn on missing dataset
314 | Console.WriteLine($"WARN: {EnvironmentOptions.GetErrorMessage("dataset", "HONEYCOMB_DATASET")}.");
315 | }
316 | }
317 |
318 | return string.Join(",", headers);
319 | }
320 |
321 | internal string GetMetricsHeaders() => GetMetricsHeaders(MetricsApiKey, MetricsDataset);
322 |
323 | internal static string GetMetricsHeaders(string apikey, string dataset)
324 | {
325 | var headers = new List
326 | {
327 | $"x-otlp-version={OtlpVersion}",
328 | $"x-honeycomb-team={apikey}",
329 | $"x-honeycomb-dataset={dataset}"
330 | };
331 |
332 | return string.Join(",", headers);
333 | }
334 | }
335 | }
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # honeycomb-opentelemetry-dotnet changelog
2 |
3 | ## [1.5.0/0.29.0-beta] - 2024-03-06
4 |
5 | ### Enhancements
6 |
7 | - feat: support classic ingest keys (#371) | @brookesargent
8 |
9 | ## [1.4.0/0.28.0-beta] - 2024-02-27
10 |
11 | ### Maintenance
12 |
13 | - docs: Update README with details on SDK builder overwriting issue (#351) | @MikeGoldsmith
14 | - maint: Bump OpenTelemetry dependencies (#365) | @MikeGoldsmith
15 | - maint: update codeowners to pipeline-team (#363) | @JamieDanielson
16 | - maint: update codeowners to pipeline (#362) | @JamieDanielson
17 | - maint: Bump Microsoft.Extensions.Configuration from 6.0.0 to 7.0.0 (#330) | @dependabot
18 | - maint(deps): bump System.Text.Json from 7.0.2 to 7.0.3 (#360) | @dependabot
19 | - maint(deps): bump coverlet.collector from 3.2.0 to 6.0.1 (#366) | @dependabot
20 | - maint(deps): bump Microsoft.NET.Test.Sdk from 17.5.0 to 17.6.3 (#359) | @dependabot
21 | - maint(deps): bump OpenTelemetry.Instrumentation.EntityFrameworkCore from 1.0.0-beta.5 to 1.0.0-beta.6 (#346) | @dependabot
22 | - maint(deps): bump Microsoft.NET.Test.Sdk from 17.4.1 to 17.5.0 (#344) | @dependabot
23 | - maint(deps): bump System.Text.Json from 7.0.0 to 7.0.2 (#343) | @dependabot
24 |
25 | ## [1.3.1/0.27.1-beta] - 2023-04-25
26 |
27 | ### Fixes
28 |
29 | - fix: De-bump Npgsql.OpenTelemetry to work with LTS EntityFramework (#348) | [@JamieDanielson](https://github.com/JamieDanielson)
30 |
31 | ## [1.3.0/0.27.0-beta] - 2023-03-02
32 |
33 | ### !!! Breaking Changes !!!
34 |
35 | ### Maintenance
36 |
37 | - maint: Rename AutoInstrumentations package to CommonInstrumentations (#327) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
38 | - renamed the package to make it more clear that this is common instrumentation, not technically "automatic" instrumentation.
39 | - `Honeycomb.OpenTelemetry.AutoInstrumentations` -> `Honeycomb.OpenTelemetry.CommonInstrumentations`
40 | - `AddAutoInstrumentations` -> `AddCommonInstrumentations`
41 | - maint: Update OpenTelemetry instrumentation packages (#334) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
42 | - The new `OpenTelemetry` packages change how tracing and metrics are setup
43 | - `AddOpenTelemetryTracing` -> `AddOpenTelemetry().WithTracing`
44 | - `AddOpenTelemetryMetrics` -> `AddOpenTelemetry().WithMetrics`
45 | - maint(deps): bump OpenTelemetry.Instrumentation.StackExchangeRedis from 1.0.0-rc9.7 to 1.0.0-rc9.8 (#345)
46 | - maint(deps): bump Microsoft.NET.Test.Sdk from 17.3.2 to 17.4.1 (#336)
47 | - maint: new signed snkgpg, use long cmd lines for clarity (#341) | [@JamieDanielson](https://github.com/JamieDanielson)
48 |
49 | ## [1.2.1/0.26.1-beta] - 2022-11-22
50 |
51 | ### Fixes
52 |
53 | - Only add Redis instrumentation if connection found in DI (#323) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
54 |
55 | ## [1.2.0/0.26.0-beta] - 2022-11-16
56 |
57 | ### Enhancements
58 |
59 | - Support IConfiguration with Honeycomb Options (#317) | [@pjwilliams2](https://github.com/pjwilliams2)
60 |
61 | ### Maintenance
62 |
63 | - Remove step from releasing (#312) | [@vreynolds](https://github.com/vreynolds)
64 | - Update README.md (#313) | [@isaacabraham](https://github.com/isaacabraham)
65 | - Fix metrics smoke tests (#320) | [@pkanal](https://github.com/pkanal)
66 |
67 | ### Dependencies
68 |
69 | - Bump instrumentation pacakges to 1.0.0-rc9.9 (#318)
70 | - Update aspnetcore instrumentation to 1.0.0-rc9.9 (#319)
71 | - Bump OpenTelemetry.Instrumentation.MySqlData from 1.0.0-beta.3 to 1.0.0-beta.4 (#314)
72 | - Bump OpenTelemetry.Instrumentation.AspNet from 1.0.0-rc9.5 to 1.0.0-rc9.6 (#289)
73 | - Bump Microsoft.NET.Test.Sdk from 17.3.1 to 17.3.2 (#315)
74 | - Bump coverlet.collector from 3.1.2 to 3.2.0 (#316)
75 |
76 | ## [1.1.0/0.25.0-beta] - 2022-10-27
77 |
78 | ### Fixes
79 |
80 | - De-bump Npgsql.OpenTelemetry to 6.0.7 to avoid collisions with LTS entityframework (#298) | @cartermp
81 |
82 | ### Maintenance
83 |
84 | - Update OTel hosting & instrumentation packages (#306) | @MikeGoldsmith
85 | - Add F# example? ( ・ω・) (#296) | @cartermp
86 |
87 | ## [1.0.0/0.24.0-beta] - 2022-09-30
88 |
89 | ### !!! Breaking Changes !!!
90 |
91 | ### Enhancements
92 |
93 | - Add support for `OTEL_SERVICE_NAME` environment variable (#245) | [@pkanal](https://github.com/pkanal)
94 | - Attempt to match Java distro resources (#249) | [@cartermp](https://github.com/cartermp)
95 | - Don't bundle instrumentation packages in distro (#250) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
96 | - Support debug option (#254) | [@cartermp](https://github.com/cartermp)
97 | - Add AspNetCore instrumentation extension to add baggage to new spans (#255) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
98 | - Set options with environment variables if they're present (#261) | [@cartermp](https://github.com/cartermp)
99 | - Add Honeycomb.OpenTelemetry.Autoinstrumentations #270 | [@cartermp](https://github.com/cartermp)
100 | - Append /v1/metrics to endpoint path if the protocol is HTTP (#284) | [@pkanal](https://github.com/pkanal)
101 | - Append /v1/traces path to http endpoint (#279) | [@pkanal](https://github.com/pkanal)
102 | - Remove custom command line argument parsing (#282) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
103 | - Add ConfigurationManager extensions methods (#280) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
104 | - Move extensions into owning class namespace & rename add instrumentations ext method (#276)
105 | - Add HONEYCOMB prefix to local visualizations env var (#275) | [@cartermp](https://github.com/cartermp)
106 |
107 | ### Maintenance
108 |
109 | - Specify OTel version in README (#246) | [@pkanal](https://github.com/pkanal)
110 | - Add grpc smoke tests (#264) | [@pkanal](https://github.com/pkanal)
111 | - Add http/protobuf smoke tests (#263) | [@pkanal](https://github.com/pkanal)
112 | - Add make targets for smoke tests & set up CI smoke tests (#268) | [@pkanal](https://github.com/pkanal)
113 | - Dockerize example and prep for smoke tests, target .NET6 (#243) | [@JamieDanielson](https://github.com/JamieDanielson)
114 | - Add Redis instrumentation example app (#242) | [@JamieDanielson](https://github.com/JamieDanielson)
115 | - Move aspnetcore samples to modern .NET 6-style apps (#271) | [@cartermp](https://github.com/cartermp)
116 | - Minor code formatting (#260) | [@cartermp](https://github.com/cartermp)
117 | - Idiomatic code formatting (#247) | [@cartermp](https://github.com/cartermp)
118 | - Add Tracer to DI in aspnet examples (#262) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
119 | - Update aspnetcore example to send metrics (#281) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
120 | - Update CircleCI config to publish tags correctly (#286) | [@pkanal](https://github.com/pkanal)
121 |
122 | ### Dependencies
123 |
124 | - Bump xunit from 2.4.1 to 2.4.2 (#259)
125 | - Bump System.Text.Json from 6.0.5 to 6.0.6 (#258)
126 | - Bump xunit.runner.visualstudio from 2.4.3 to 2.4.5 (#257)
127 | - Bump Microsoft.NET.Test.Sdk from 17.2.0 to 17.3.1 (#256)
128 |
129 | ## [0.23.0-beta] - 2022-08-03
130 |
131 | ### Enhancements
132 |
133 | - Added Console Trace link writer (#222) | [@martinjt](https://github.com/martinjt)
134 |
135 | ### Maintenance
136 |
137 | - Update minimum target framework from net461 to net462 (#226) | [@vreynolds](https://github.com/vreynolds)
138 | - Bump OpenTelemetry.Instrumentation.AspNet from 1.0.0-rc9.1 to 1.0.0-rc9.5 (#224) | [dependabot](https://github.com/dependabot)
139 | - Bump Microsoft.NET.Test.Sdk from 17.1.0 to 17.2.0 (#221) | [dependabot](https://github.com/dependabot)
140 |
141 | ## [0.22.0-beta] - 2022-07-01
142 |
143 | ### Enhancements
144 |
145 | - Add OTLP version to headers (HTTP & gRPC) (#205) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
146 |
147 | ### Maintenance
148 |
149 | - Update README to point to docs website for setup instructions (#208) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
150 | - Bump otel dependencies #213 | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
151 | - Bump Microsoft.NET.Test.Sdk from 17.0.0 to 17.1.0 (#195)
152 |
153 | ## [0.21.0-beta] - 2022-04-14
154 |
155 | ### Enhancements
156 |
157 | - Capture null options in IServiceColletion.AddHoneycomb (#184) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
158 |
159 | ### Fixes
160 |
161 | - Add support for providing ResouceBuilder as configuration option (#190) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
162 |
163 | ### Maintenance
164 |
165 | - Bump otel dependdencies (#193)
166 | - Bump OpenTelemetry.Instrumentation.AspNet from 1.0.0-rc8 to 1.0.0-rc9.1 (#186)
167 | - Bump coverlet.collector from 3.1.0 to 3.1.2 (#181)
168 |
169 | ## [0.20.0-beta] - 2022-03-07
170 |
171 | ### Fixes
172 |
173 | - Remove white space in default service.name (#182)
174 |
175 | ## [0.19.0-beta] - 2022-02-09
176 |
177 | ### Enhancements
178 |
179 | - Provide more feedback to users to help configure for use in E&S (#175) | [@JamieDanielson](https://github.com/JamieDanielson)
180 |
181 | ### Fixes
182 |
183 | - Validate that HoneycombOptions exists before we do anything (#171) | [@cartermp](https://github.com/cartermp)
184 |
185 | ### Maintenance
186 |
187 | - gh: add re-triage workflow (#166) | [@vreynolds](https://github.com/vreynolds)
188 |
189 | ## [0.18.0-beta] - 2021-12-23
190 |
191 | ### Fixes
192 |
193 | - remove parent-based sampler, sample with trace ID ratio only (#164) | [@vreynolds](https://github.com/vreynolds)
194 |
195 | ## [0.17.0-beta] - 2021-12-15
196 |
197 | ### Changed
198 |
199 | - Make API key and dataset optional (#161) | [@vreynolds](https://github.com/vreynolds)
200 |
201 | ### Maintenance
202 |
203 | - Update example core app to use metrics (#158) | [@vreynolds](https://github.com/vreynolds)
204 |
205 | ### Dependencies
206 |
207 | - Bump OpenTelemetry from 1.2.0-beta2.1 to 1.2.0-rc1 (#151)
208 | - Bump OpenTelemetry.Exporter.OpenTelemetryProtocol (#152)
209 |
210 | ## [0.16.0-beta] - 2021-12-06
211 |
212 | ### Improvements
213 |
214 | - Add support for enabling OTLP metrics (#146) | [@MikeGoldsmith](https://github.com/MikeGoldsmith) [@vreynolds](https://github.com/vreynolds)
215 | - Parse missing command line arguments (#154) | [@vreynolds](https://github.com/vreynolds)
216 |
217 | ### Fixes
218 |
219 | - Re-add net461 target (#155) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
220 | - Trace extension should use trace config (#156) | [@vreynolds](https://github.com/vreynolds)
221 |
222 | ## [0.15.0-beta] - 2021-12-01
223 |
224 | ### Enhancements
225 |
226 | - Update DeterminisitcSampler to use OTel core Parent/TraceIDRatio samplers (#145) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
227 |
228 | ### Fixes
229 |
230 | - Fixed Redis auto-detection (#150) | [@JamieDanielson](https://github.com/JamieDanielson)
231 |
232 | ### Maintenance
233 |
234 | - Update dependabot.yml (#147) | [@vreynolds](https://github.com/vreynolds)
235 | - Update dependencies, remove netcoreapp2.1 (#144) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
236 | - Update docs when releasing (#142) | [@vreynolds](https://github.com/vreynolds)
237 |
238 | ## Dependencies
239 |
240 | - Bump Microsoft.NET.Test.Sdk from 16.11.0 to 17.0.0 (#148)
241 |
242 | ## [0.14.0-beta] - 2021-11-18
243 |
244 | ## Added
245 |
246 | - Allow disabling auto-instrumentations (#129) | [@ericsampson](https://github.com/ericsampson)
247 |
248 | ## Maintenance
249 |
250 | - Remove whitespace failing build (#137) | [@JamieDanielson](https://github.com/JamieDanielson)
251 | - Empower apply-labels action to apply labels (#131) | [@robbkidd](https://github.com/robbkidd)
252 | - Add prerelease flag to install command (#120) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
253 | - Add NOTICE (#114) | [@cartermp](https://github.com/cartermp)
254 | - Only add stale to info needed or revision needed (#115) | [@JamieDanielson](https://github.com/JamieDanielson)
255 | - Adds stalebot effective Sept 1 2021 (#113) | [@JamieDanielson](https://github.com/JamieDanielson)
256 | - Fix netcoreapp2.1 example (#102) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
257 | - Clarify renaming in changelog (#101) | [@cartermp](https://github.com/cartermp)
258 |
259 | ## Dependencies
260 |
261 | - Bump Microsoft.AspNetCore.Razor.Design from 2.1.2 to 2.2.0 (#104)
262 | - Bump coverlet.collector from 1.3.0 to 3.1.0 (#77)
263 |
264 | ## [0.13.0-beta] - 2021-08-26
265 |
266 | ## Added
267 |
268 | - Support for netcoreapp2.1 (#99) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
269 | - Rename `UseHoneycomb` to `AddHoneycomb` IServiceCollection extension method to be more idiomatic (#98) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
270 |
271 | ## Maintenance
272 |
273 | - Allow dependabot and forked PRs to run in CI (#97) | [@vreynolds](https://github.com/vreynolds)
274 | - Add issue and PR templates (#91) | [@vreynolds](https://github.com/vreynolds)
275 | - Add OSS lifecycle badge (#90) | [@vreynolds](https://github.com/vreynolds)
276 | - Add community health files (#89) | [@vreynolds](https://github.com/vreynolds)
277 | - Trim commit hash from honeycomb.distro.version attribute (#87) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
278 |
279 | ## Dependencies
280 |
281 | - Bump Microsoft.NET.Test.Sdk from 16.7.1 to 16.11.0 (#92)
282 |
283 | ## [0.12.0-beta] - 2021-07-29
284 |
285 | ## Added
286 |
287 | - Add ASP.NET instrumentation (#76, #80) | [@vreynolds](https://github.com/vreynolds) [@MikeGoldsmith](https://github.com/MikeGoldsmith)
288 |
289 | ## Maintenance
290 |
291 | - Only sign builds when publishing through CI (#81) | [@MikeGoldsmith](https://github.com/MikeGoldsmith)
292 | - Clarify releasing steps (#79) | [@vreynolds](https://github.com/vreynolds)
293 |
294 | ## [0.11.0-alpha] - 2021-07-27
295 |
296 | ### Added
297 |
298 | - Redis instrumentation (#66, #74) | [@vreynolds](https://github.com/vreynolds)
299 |
300 | ## [0.10.0-alpha] - 2021-07-15
301 |
302 | ### Added
303 |
304 | - Initial preview release of Honeycomb's OpenTelemetry distribution for .NET!
305 |
306 | ### Breaking Changes
307 |
308 | - As of this version, this project is now Honeycomb's OpenTelemetry distribution for .NET.
309 | If you are still using the [Honeycomb exporter](https://github.com/honeycombio/opentelemetry-dotnet) use version 0.9.0-pre.
310 |
311 | ## [0.9.0-pre]
312 |
313 | - Pre-release of an OpenTelemetry Exporter for Honeycomb.
314 | This was the last release of the Exporter published under the Honeycomb.OpenTelemetry Package name.
315 |
--------------------------------------------------------------------------------
/test/Honeycomb.OpenTelemetry.Tests/HoneycombOptionsTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using System.Collections.Generic;
3 | using Xunit;
4 |
5 | namespace Honeycomb.OpenTelemetry.Tests
6 | {
7 | public class HoneycombOptionsHelperTests
8 | {
9 | [Fact]
10 | public void CanParseOptionsFromConfiguration()
11 | {
12 | var options =
13 | new ConfigurationBuilder()
14 | .AddJsonFile("appsettings.test.json")
15 | .Build()
16 | .GetSection(HoneycombOptions.ConfigSectionName)
17 | .Get()
18 | ;
19 |
20 | Assert.Equal("my-apikey", options.ApiKey);
21 | Assert.Equal("my-traces-apikey", options.TracesApiKey);
22 | Assert.Equal("my-metrics-apikey", options.MetricsApiKey);
23 | Assert.Equal("my-dataset", options.Dataset);
24 | Assert.Equal("my-traces-dataset", options.TracesDataset);
25 | Assert.Equal("my-metrics-dataset", options.MetricsDataset);
26 | Assert.Equal((uint)5, options.SampleRate);
27 | Assert.Equal("my-endpoint", options.Endpoint);
28 | Assert.Equal("my-traces-endpoint", options.TracesEndpoint);
29 | Assert.Equal("my-metrics-endpoint", options.MetricsEndpoint);
30 | Assert.Equal("my-service", options.ServiceName);
31 | Assert.Equal("my-version", options.ServiceVersion);
32 | Assert.Equal(new List { "meter1", "meter2" }, options.MeterNames);
33 | Assert.True(options.EnableLocalVisualizations);
34 | Assert.True(options.Debug);
35 | }
36 |
37 | [Fact]
38 | public void CanParseOptionsFromEnvironmentVariables()
39 | {
40 | // set up HoneycombOptions class
41 | var options = new HoneycombOptions { };
42 | // env var values
43 | var values = new Dictionary
44 | {
45 | {"HONEYCOMB_API_KEY", "my-api-key-env-var"},
46 | {"HONEYCOMB_TRACES_API_KEY", "my-traces-api-key-env-var"},
47 | {"HONEYCOMB_METRICS_API_KEY", "my-metrics-api-key-env-var"},
48 | {"HONEYCOMB_DATASET", "my-dataset-env-var"},
49 | {"HONEYCOMB_TRACES_DATASET", "my-traces-dataset-env-var"},
50 | {"HONEYCOMB_METRICS_DATASET", "my-metrics-dataset-env-var"},
51 | {"HONEYCOMB_API_ENDPOINT", "my-endpoint-env-var"},
52 | {"HONEYCOMB_TRACES_ENDPOINT", "my-traces-endpoint-env-var"},
53 | {"HONEYCOMB_METRICS_ENDPOINT", "my-metrics-endpoint-env-var"},
54 | {"HONEYCOMB_SAMPLE_RATE", "20"},
55 | {"OTEL_SERVICE_NAME", "my-service-name-env-var"},
56 | {"SERVICE_VERSION", "my-service-version-env-var"},
57 | {"HONEYCOMB_ENABLE_LOCAL_VISUALIZATIONS", "false" },
58 | {"DEBUG", "false"}
59 | };
60 |
61 | // override HoneycombOptions with Environment options
62 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
63 |
64 | Assert.Equal("my-api-key-env-var", options.ApiKey);
65 | Assert.Equal("my-traces-api-key-env-var", options.TracesApiKey);
66 | Assert.Equal("my-metrics-api-key-env-var", options.MetricsApiKey);
67 | Assert.Equal("my-dataset-env-var", options.Dataset);
68 | Assert.Equal("my-traces-dataset-env-var", options.TracesDataset);
69 | Assert.Equal("my-metrics-dataset-env-var", options.MetricsDataset);
70 | Assert.Equal("my-endpoint-env-var", options.Endpoint);
71 | Assert.Equal("my-traces-endpoint-env-var", options.TracesEndpoint);
72 | Assert.Equal("my-metrics-endpoint-env-var", options.MetricsEndpoint);
73 | Assert.Equal((uint)20, options.SampleRate);
74 | Assert.Equal("my-service-name-env-var", options.ServiceName);
75 | Assert.Equal("my-service-version-env-var", options.ServiceVersion);
76 | Assert.False(options.EnableLocalVisualizations);
77 | Assert.False(options.Debug);
78 | }
79 |
80 | [Fact]
81 | public void CanOverrideConfigWithEnvVars()
82 | {
83 | // read options from appsettings.json file
84 | var options = new ConfigurationBuilder()
85 | .AddJsonFile("appsettings.test.json")
86 | .Build()
87 | .GetSection(HoneycombOptions.ConfigSectionName)
88 | .Get();
89 |
90 | // env var values
91 | var values = new Dictionary
92 | {
93 | {"HONEYCOMB_API_KEY", "my-api-key-env-var"},
94 | {"HONEYCOMB_TRACES_API_KEY", "my-traces-api-key-env-var"},
95 | {"HONEYCOMB_METRICS_API_KEY", "my-metrics-api-key-env-var"},
96 | {"HONEYCOMB_DATASET", "my-dataset-env-var"},
97 | {"HONEYCOMB_TRACES_DATASET", "my-traces-dataset-env-var"},
98 | {"HONEYCOMB_METRICS_DATASET", "my-metrics-dataset-env-var"},
99 | {"HONEYCOMB_API_ENDPOINT", "my-endpoint-env-var"},
100 | {"HONEYCOMB_TRACES_ENDPOINT", "my-traces-endpoint-env-var"},
101 | {"HONEYCOMB_METRICS_ENDPOINT", "my-metrics-endpoint-env-var"},
102 | {"HONEYCOMB_SAMPLE_RATE", "20"},
103 | {"OTEL_SERVICE_NAME", "my-service-name-env-var"},
104 | {"SERVICE_VERSION", "my-service-version-env-var"},
105 | {"HONEYCOMB_ENABLE_LOCAL_VISUALIZATIONS", "false" },
106 | {"DEBUG", "false"}
107 | };
108 |
109 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
110 |
111 | Assert.Equal("my-api-key-env-var", options.ApiKey);
112 | Assert.Equal("my-traces-api-key-env-var", options.TracesApiKey);
113 | Assert.Equal("my-metrics-api-key-env-var", options.MetricsApiKey);
114 | Assert.Equal("my-dataset-env-var", options.Dataset);
115 | Assert.Equal("my-traces-dataset-env-var", options.TracesDataset);
116 | Assert.Equal("my-metrics-dataset-env-var", options.MetricsDataset);
117 | Assert.Equal("my-endpoint-env-var", options.Endpoint);
118 | Assert.Equal("my-traces-endpoint-env-var", options.TracesEndpoint);
119 | Assert.Equal("my-metrics-endpoint-env-var", options.MetricsEndpoint);
120 | Assert.Equal((uint)20, options.SampleRate);
121 | Assert.Equal("my-service-name-env-var", options.ServiceName);
122 | Assert.Equal("my-service-version-env-var", options.ServiceVersion);
123 | Assert.False(options.EnableLocalVisualizations);
124 | Assert.False(options.Debug);
125 | }
126 |
127 | [Fact]
128 | public void CanFallbackToDefault_Config()
129 | {
130 | // set up empty HoneycombOptions class
131 | var options = new HoneycombOptions { };
132 | Assert.Null(options.ApiKey);
133 | Assert.Null(options.TracesApiKey);
134 | Assert.Null(options.MetricsApiKey);
135 | Assert.Null(options.Dataset);
136 | Assert.Null(options.TracesDataset);
137 | Assert.Null(options.MetricsDataset);
138 | Assert.Equal(HoneycombOptions.DefaultEndpoint, options.Endpoint);
139 | Assert.Null(options.TracesEndpoint);
140 | Assert.Null(options.MetricsEndpoint);
141 | Assert.Equal(HoneycombOptions.DefaultSampleRate, options.SampleRate);
142 | Assert.Equal(HoneycombOptions.SDefaultServiceName, options.ServiceName);
143 | Assert.Equal(HoneycombOptions.SDefaultServiceVersion, options.ServiceVersion);
144 | Assert.False(options.EnableLocalVisualizations);
145 | Assert.False(options.Debug);
146 | }
147 |
148 | [Fact]
149 | public void UsesGenericValuesIfTracesSpecificValuesAreNotSet_Config()
150 | {
151 | var options = new HoneycombOptions
152 | {
153 | Endpoint = "http://collector:4318",
154 | ApiKey = "my-api-key",
155 | Dataset = "my-dataset"
156 | };
157 |
158 | Assert.Equal("http://collector:4318/", options.GetTracesEndpoint());
159 | Assert.Equal("my-api-key", options.GetTracesApiKey());
160 | Assert.Equal("my-dataset", options.GetTracesDataset());
161 | }
162 |
163 | [Fact]
164 | public void UsesGenericValuesIfMetricsSpecificValuesAreNotSet_Config()
165 | {
166 | var options = new HoneycombOptions
167 | {
168 | Endpoint = "http://collector:4318",
169 | ApiKey = "my-api-key",
170 | Dataset = "my-dataset"
171 | };
172 |
173 | Assert.Equal("http://collector:4318/", options.GetMetricsEndpoint());
174 | Assert.Equal("my-api-key", options.GetMetricsApiKey());
175 | // Should not fall override metrics dataset
176 | Assert.NotEqual("my-dataset", options.MetricsDataset);
177 | }
178 |
179 | [Fact]
180 | public void UsesTracesSpecificValuesIfSet_Config()
181 | {
182 | var options = new HoneycombOptions
183 | {
184 | TracesEndpoint = "http://collector:4318",
185 | TracesApiKey = "my-api-key",
186 | TracesDataset = "my-dataset"
187 | };
188 | Assert.Equal("http://collector:4318", options.GetTracesEndpoint());
189 | Assert.Equal("my-api-key", options.GetTracesApiKey());
190 | Assert.Equal("my-dataset", options.GetTracesDataset());
191 | }
192 |
193 | [Fact]
194 | public void UsesMetricsSpecificValuesIfSet_Config()
195 | {
196 | var options = new HoneycombOptions
197 | {
198 | MetricsEndpoint = "http://collector:4318",
199 | MetricsApiKey = "my-api-key",
200 | };
201 | Assert.Equal("http://collector:4318", options.GetMetricsEndpoint());
202 | Assert.Equal("my-api-key", options.GetMetricsApiKey());
203 | }
204 |
205 | [Fact]
206 | public void UseTracesSpecificValuesOverGenericValues_Config()
207 | {
208 | var options = new HoneycombOptions
209 | {
210 | Endpoint = "http://collector:4318",
211 | ApiKey = "my-api-key",
212 | Dataset = "my-dataset",
213 | TracesEndpoint = "http://collector:4318/v1/traces",
214 | TracesApiKey = "my-api-key-traces",
215 | TracesDataset = "my-dataset-traces"
216 | };
217 |
218 | Assert.Equal("http://collector:4318/v1/traces", options.GetTracesEndpoint());
219 | Assert.Equal("my-api-key-traces", options.GetTracesApiKey());
220 | Assert.Equal("my-dataset-traces", options.GetTracesDataset());
221 | }
222 |
223 | [Fact]
224 | public void UseMetricsSpecificValuesOverGenericValues_Config()
225 | {
226 | var options = new HoneycombOptions
227 | {
228 | Endpoint = "http://collector:4318",
229 | ApiKey = "my-api-key",
230 | MetricsEndpoint = "http://collector:4318/v1/metrics",
231 | MetricsApiKey = "my-api-key-metrics",
232 | };
233 |
234 | Assert.Equal("http://collector:4318/v1/metrics", options.GetMetricsEndpoint());
235 | Assert.Equal("my-api-key-metrics", options.GetMetricsApiKey());
236 | }
237 |
238 | [Fact]
239 | public void UsesGenericValuesIfTracesSpecificValuesAreNotSet_EnvVars()
240 | {
241 | var options = new HoneycombOptions { };
242 | var values = new Dictionary
243 | {
244 | {"HONEYCOMB_API_KEY", "my-api-key-env-var"},
245 | {"HONEYCOMB_DATASET", "my-dataset-env-var"},
246 | {"HONEYCOMB_API_ENDPOINT", "http://collector:4318/"},
247 | };
248 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
249 |
250 | Assert.Equal("http://collector:4318/", options.GetTracesEndpoint());
251 | Assert.Equal("my-api-key-env-var", options.GetTracesApiKey());
252 | Assert.Equal("my-dataset-env-var", options.GetTracesDataset());
253 | }
254 |
255 | [Fact]
256 | public void UsesGenericValuesIfMetricsSpecificValuesAreNotSet_EnvVars()
257 | {
258 | var options = new HoneycombOptions { };
259 | var values = new Dictionary
260 | {
261 | {"HONEYCOMB_API_KEY", "my-api-key-env-var"},
262 | {"HONEYCOMB_DATASET", "my-dataset-env-var"},
263 | {"HONEYCOMB_API_ENDPOINT", "http://collector:4318/"},
264 | };
265 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
266 |
267 | Assert.Equal("http://collector:4318/", options.GetMetricsEndpoint());
268 | Assert.Equal("my-api-key-env-var", options.GetMetricsApiKey());
269 | }
270 |
271 | [Fact]
272 | public void UsesTracesSpecificValuesIfSet_EnvVars()
273 | {
274 | var options = new HoneycombOptions { };
275 | var values = new Dictionary
276 | {
277 | {"HONEYCOMB_TRACES_API_KEY", "my-traces-api-key-env-var"},
278 | {"HONEYCOMB_TRACES_DATASET", "my-traces-dataset-env-var"},
279 | {"HONEYCOMB_TRACES_ENDPOINT", "http://collector:4318/v1/traces"},
280 | };
281 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
282 |
283 | Assert.Equal("http://collector:4318/v1/traces", options.GetTracesEndpoint());
284 | Assert.Equal("my-traces-api-key-env-var", options.GetTracesApiKey());
285 | Assert.Equal("my-traces-dataset-env-var", options.GetTracesDataset());
286 | }
287 |
288 | [Fact]
289 | public void UsesMetricsSpecificValuesIfSet_EnvVars()
290 | {
291 | var options = new HoneycombOptions { };
292 | var values = new Dictionary
293 | {
294 | {"HONEYCOMB_METRICS_API_KEY", "my-metrics-api-key-env-var"},
295 | {"HONEYCOMB_METRICS_ENDPOINT", "http://collector:4318/v1/metrics"},
296 | };
297 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
298 |
299 | Assert.Equal("http://collector:4318/v1/metrics", options.GetMetricsEndpoint());
300 | Assert.Equal("my-metrics-api-key-env-var", options.GetMetricsApiKey());
301 | }
302 |
303 | [Fact]
304 | public void UseTracesSpecificValuesOverGenericValues_EnvVars()
305 | {
306 | var options = new HoneycombOptions { };
307 | var values = new Dictionary
308 | {
309 | {"HONEYCOMB_API_KEY", "my-api-key-env-var"},
310 | {"HONEYCOMB_DATASET", "my-dataset-env-var"},
311 | {"HONEYCOMB_API_ENDPOINT", "http://collector:4318/"},
312 | {"HONEYCOMB_TRACES_API_KEY", "my-traces-api-key-env-var"},
313 | {"HONEYCOMB_TRACES_DATASET", "my-traces-dataset-env-var"},
314 | {"HONEYCOMB_TRACES_ENDPOINT", "http://collector:4318/v1/traces"},
315 | };
316 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
317 |
318 | Assert.Equal("http://collector:4318/v1/traces", options.GetTracesEndpoint());
319 | Assert.Equal("my-traces-api-key-env-var", options.GetTracesApiKey());
320 | Assert.Equal("my-traces-dataset-env-var", options.GetTracesDataset());
321 | }
322 |
323 | [Fact]
324 | public void UseMetricsSpecificValuesOverGenericValues_EnvVars()
325 | {
326 | var options = new HoneycombOptions { };
327 | var values = new Dictionary
328 | {
329 | {"HONEYCOMB_API_KEY", "my-api-key-env-var"},
330 | {"HONEYCOMB_API_ENDPOINT", "http://collector:4318/"},
331 | {"HONEYCOMB_METRICS_API_KEY", "my-metrics-api-key-env-var"},
332 | {"HONEYCOMB_METRICS_ENDPOINT", "http://collector:4318/v1/metrics"},
333 | };
334 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
335 |
336 | Assert.Equal("http://collector:4318/v1/metrics", options.GetMetricsEndpoint());
337 | Assert.Equal("my-metrics-api-key-env-var", options.GetMetricsApiKey());
338 | }
339 |
340 | [Theory]
341 | [InlineData("http/protobuf", "http://collector:4318", null)]
342 | [InlineData("http/json", "http://collector:4318", null)]
343 | [InlineData("http/protobuf", null, "http://collector:4318")]
344 | [InlineData("http/json", null, "http://collector:4318")]
345 | [InlineData("http/protobuf", "http://collector:4318", "http://collector:4318")]
346 | [InlineData("http/json", "http://collector:4318", "http://collector:4318")]
347 | public void AppendsTracesPathIfProtocolIsHttp(string protocol, string configEndpoint, string envVarEndpoint)
348 | {
349 | var options = new HoneycombOptions
350 | {
351 | Endpoint = configEndpoint
352 | };
353 | var values = new Dictionary
354 | {
355 | {"OTEL_EXPORTER_OTLP_PROTOCOL", protocol},
356 | {"HONEYCOMB_API_ENDPOINT", envVarEndpoint},
357 | };
358 |
359 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
360 | Assert.Equal($"{options.Endpoint}/v1/traces", options.GetTracesEndpoint());
361 | }
362 |
363 | [Theory]
364 | [InlineData("http://collector:4317", null)]
365 | [InlineData(null, "http://collector:4317")]
366 | [InlineData("http://collector:4317", "http://collector:4317")]
367 | public void DoesNotAppendTracesPathIfProtocolIsGrpc(string configEndpoint, string envVarEndpoint)
368 | {
369 | var options = new HoneycombOptions
370 | {
371 | Endpoint = configEndpoint
372 | };
373 | var values = new Dictionary
374 | {
375 | {"OTEL_EXPORTER_OTLP_PROTOCOL", "grpc"},
376 | {"HONEYCOMB_API_ENDPOINT", envVarEndpoint},
377 | };
378 |
379 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
380 | Assert.Equal("http://collector:4317/", options.GetTracesEndpoint());
381 | Assert.DoesNotContain("/v1/traces", options.GetTracesEndpoint());
382 | }
383 |
384 | [Theory]
385 | [InlineData("http/protobuf", "http://collector:4318", null)]
386 | [InlineData("http/json", "http://collector:4318", null)]
387 | [InlineData("http/protobuf", null, "http://collector:4318")]
388 | [InlineData("http/json", null, "http://collector:4318")]
389 | [InlineData("http/protobuf", "http://collector:4318", "http://collector:4318")]
390 | [InlineData("http/json", "http://collector:4318", "http://collector:4318")]
391 | public void DoesNotAppendTracesPathToTracesEndpoints(string protocol, string configEndpoint, string envVarEndpoint)
392 | {
393 | var options = new HoneycombOptions
394 | {
395 | TracesEndpoint = configEndpoint
396 | };
397 | var values = new Dictionary
398 | {
399 | {"OTEL_EXPORTER_OTLP_PROTOCOL", protocol},
400 | {"HONEYCOMB_TRACES_ENDPOINT", envVarEndpoint},
401 |
402 | };
403 |
404 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
405 | Assert.Equal("http://collector:4318", options.GetTracesEndpoint());
406 | Assert.DoesNotContain("/v1/traces", options.GetTracesEndpoint());
407 | }
408 |
409 | [Theory]
410 | [InlineData("http/protobuf", "http://collector:4318/my-special-path", null)]
411 | [InlineData("http/json", "http://collector:4318/my-special-path", null)]
412 | [InlineData("http/protobuf", null, "http://collector:4318/my-special-path")]
413 | [InlineData("http/json", null, "http://collector:4318/my-special-path")]
414 | [InlineData("http/protobuf", "http://collector:4318/my-special-path", "http://collector:4318/my-special-path")]
415 | [InlineData("http/json", "http://collector:4318/my-special-path", "http://collector:4318/my-special-path")]
416 | public void DoesNotAppendTracesPathToGenericEndpointIfPathSpecified(string protocol, string configEndpoint, string envVarEndpoint)
417 | {
418 | var options = new HoneycombOptions
419 | {
420 | Endpoint = configEndpoint
421 | };
422 | var values = new Dictionary
423 | {
424 | {"OTEL_EXPORTER_OTLP_PROTOCOL", protocol},
425 | {"HONEYCOMB_API_ENDPOINT", envVarEndpoint},
426 | };
427 |
428 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
429 | Assert.Equal("http://collector:4318/my-special-path", options.GetTracesEndpoint());
430 | Assert.DoesNotContain("/v1/traces", options.GetTracesEndpoint());
431 | }
432 |
433 | [Theory]
434 | [InlineData("http/protobuf", "http://collector:4318", null)]
435 | [InlineData("http/json", "http://collector:4318", null)]
436 | [InlineData("http/protobuf", null, "http://collector:4318")]
437 | [InlineData("http/json", null, "http://collector:4318")]
438 | [InlineData("http/protobuf", "http://collector:4318", "http://collector:4318")]
439 | [InlineData("http/json", "http://collector:4318", "http://collector:4318")]
440 | public void AppendsMetricsPathIfProtocolIsHttp(string protocol, string configEndpoint, string envVarEndpoint)
441 | {
442 | var options = new HoneycombOptions
443 | {
444 | Endpoint = configEndpoint
445 | };
446 | var values = new Dictionary
447 | {
448 | {"OTEL_EXPORTER_OTLP_PROTOCOL", protocol},
449 | {"HONEYCOMB_API_ENDPOINT", envVarEndpoint},
450 | };
451 |
452 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
453 | Assert.Equal($"{options.Endpoint}/v1/metrics", options.GetMetricsEndpoint());
454 | }
455 |
456 | [Theory]
457 | [InlineData("http://collector:4317", null)]
458 | [InlineData(null, "http://collector:4317")]
459 | [InlineData("http://collector:4317", "http://collector:4317")]
460 | public void DoesNotAppendMetricsPathIfProtocolIsGrpc(string configEndpoint, string envVarEndpoint)
461 | {
462 | var options = new HoneycombOptions
463 | {
464 | Endpoint = configEndpoint
465 | };
466 | var values = new Dictionary
467 | {
468 | {"OTEL_EXPORTER_OTLP_PROTOCOL", "grpc"},
469 | {"HONEYCOMB_API_ENDPOINT", envVarEndpoint},
470 | };
471 |
472 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
473 | Assert.Equal("http://collector:4317/", options.GetMetricsEndpoint());
474 | Assert.DoesNotContain("/v1/metrics", options.GetMetricsEndpoint());
475 | }
476 |
477 | [Theory]
478 | [InlineData("http/protobuf", "http://collector:4318", null)]
479 | [InlineData("http/json", "http://collector:4318", null)]
480 | [InlineData("http/protobuf", null, "http://collector:4318")]
481 | [InlineData("http/json", null, "http://collector:4318")]
482 | [InlineData("http/protobuf", "http://collector:4318", "http://collector:4318")]
483 | [InlineData("http/json", "http://collector:4318", "http://collector:4318")]
484 | public void DoesNotAppendMetricsPathToMetricsEndpoints(string protocol, string configEndpoint, string envVarEndpoint)
485 | {
486 | var options = new HoneycombOptions
487 | {
488 | MetricsEndpoint = configEndpoint
489 | };
490 | var values = new Dictionary
491 | {
492 | {"OTEL_EXPORTER_OTLP_PROTOCOL", protocol},
493 | {"HONEYCOMB_METRICS_ENDPOINT", envVarEndpoint},
494 |
495 | };
496 |
497 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
498 | Assert.Equal("http://collector:4318", options.GetMetricsEndpoint());
499 | Assert.DoesNotContain("/v1/metrics", options.GetMetricsEndpoint());
500 | }
501 |
502 | [Theory]
503 | [InlineData("http/protobuf", "http://collector:4318/my-special-path", null)]
504 | [InlineData("http/json", "http://collector:4318/my-special-path", null)]
505 | [InlineData("http/protobuf", null, "http://collector:4318/my-special-path")]
506 | [InlineData("http/json", null, "http://collector:4318/my-special-path")]
507 | [InlineData("http/protobuf", "http://collector:4318/my-special-path", "http://collector:4318/my-special-path")]
508 | [InlineData("http/json", "http://collector:4318/my-special-path", "http://collector:4318/my-special-path")]
509 | public void DoesNotAppendMetricsPathToGenericEndpointIfPathSpecified(string protocol, string configEndpoint, string envVarEndpoint)
510 | {
511 | var options = new HoneycombOptions
512 | {
513 | Endpoint = configEndpoint
514 | };
515 | var values = new Dictionary
516 | {
517 | {"OTEL_EXPORTER_OTLP_PROTOCOL", protocol},
518 | {"HONEYCOMB_API_ENDPOINT", envVarEndpoint},
519 | };
520 |
521 | options.ApplyEnvironmentOptions(new EnvironmentOptions(values));
522 | Assert.Equal("http://collector:4318/my-special-path", options.GetMetricsEndpoint());
523 | Assert.DoesNotContain("/v1/metrics", options.GetMetricsEndpoint());
524 | }
525 |
526 | [Theory]
527 | [InlineData("", false)]
528 | [InlineData("12345678901234567890123456789012", true)]
529 | [InlineData("hcaic_1234567890123456789012345678901234567890123456789012345678", true)]
530 | [InlineData("kgvSpPwegJshQkuowXReLD", false)]
531 | [InlineData("hcaic_12345678901234567890123456", false)]
532 | [InlineData("hcxik_01hqk4k20cjeh63wca8vva5stw70nft6m5n8wr8f5mjx3762s8269j50wc", false)]
533 | public void IsClassicKey(string key, bool expected)
534 | {
535 | var options = new HoneycombOptions { ApiKey = key };
536 | Assert.Equal(HoneycombOptions.IsClassicKey(key), expected);
537 | }
538 | }
539 | }
540 |
--------------------------------------------------------------------------------