Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dotnet multi stage image example #52

Merged
merged 4 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions integration-examples/splunk-otel-dotnet-docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER app
WORKDIR /app
EXPOSE 8080

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["MultiStageDocker/MultiStageDocker.csproj", "MultiStageDocker/"]
RUN dotnet restore "./MultiStageDocker/./MultiStageDocker.csproj"
COPY . .
WORKDIR "/src/MultiStageDocker"
RUN dotnet build "./MultiStageDocker.csproj" -c $BUILD_CONFIGURATION -o /app/build

# Add dependencies for splunk-otel-dotnet-install.sh
RUN apt-get update && \
apt-get install -y unzip

# Download Splunk OTel .NET installer
RUN curl -sSfL https://github.com/signalfx/splunk-otel-dotnet/releases/latest/download/splunk-otel-dotnet-install.sh -O

# Install the distribution
RUN sh ./splunk-otel-dotnet-install.sh

FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./MultiStageDocker.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

FROM base AS final

# Copy instrumentation file tree
WORKDIR "//home/app/.splunk-otel-dotnet"
COPY --from=build /root/.splunk-otel-dotnet/ .

WORKDIR /app
COPY --from=publish /app/publish .
COPY --from=build /src/MultiStageDocker/entrypoint.sh .

ENTRYPOINT ["sh", "entrypoint.sh"]
CMD ["dotnet", "MultiStageDocker.dll"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" />
</ItemGroup>

</Project>
6 changes: 6 additions & 0 deletions integration-examples/splunk-otel-dotnet-docker/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();
88 changes: 88 additions & 0 deletions integration-examples/splunk-otel-dotnet-docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Splunk OTel Dotnet & Docker

This example demonstrates the execution of a .NET application within a Docker container, utilizing the Splunk Distribution of OpenTelemetry for .NET.
The Docker image is constructed using a multi-stage Docker image approach, wherein the build image is more substantial, and the runtime image is a barebone image.

The installation of instrumentation needs to be divided between different stages.
During the build step, the instrumentation is installed, and subsequently, the outcome is transferred to the final image, eliminating the necessity for additional dependencies specified in a separate build step.

The `entrypoint.sh` is essential for sourcing environment variables from the `instrument.sh` script, which is included with the instrumentation. This ensures the correct setup of environment variables for each platform.

## Instructions

Execute or run points 1-3 manually:

```bash
docker run -d \
-e OTEL_DOTNET_AUTO_TRACES_CONSOLE_EXPORTER_ENABLED=true \
-p 8181:8080 \
multistagedocker:latest
```

1. Set `ENV OTEL_DOTNET_AUTO_TRACES_CONSOLE_EXPORTER_ENABLED=true` in the Dockerfile for verification purposes.
1. Build the Docker image.
1. Map a random host port (e.g.: 8181) to the container port (8080).
Comment on lines +23 to +24
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you wanted to be really hand holdy you could have the docker commands here for folks to copy and paste.
Just a thought.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. Added script, removed hard coded env from the dockerfile just in case.

1. Open your browser and navigate to `http://localhost:8181`.
1. Verify the execution of instrumentation by examining the container logs, which should now include Activity information. (Refer to the sample output below.)

Sample log output:

```txt
2023-12-01 15:34:28 info: Microsoft.Hosting.Lifetime[14]
2023-12-01 15:34:28 Now listening on: http://[::]:8080
2023-12-01 15:34:28 info: Microsoft.Hosting.Lifetime[0]
2023-12-01 15:34:28 Application started. Press Ctrl+C to shut down.
2023-12-01 15:34:28 info: Microsoft.Hosting.Lifetime[0]
2023-12-01 15:34:28 Hosting environment: Production
2023-12-01 15:34:28 info: Microsoft.Hosting.Lifetime[0]
2023-12-01 15:34:28 Content root path: /app
2023-12-01 15:34:32 Activity.TraceId: 7f34db4b569f6b6dd6c77c1a5d5164e2
2023-12-01 15:34:32 Activity.SpanId: 87c76863b1d6b603
2023-12-01 15:34:32 Activity.TraceFlags: Recorded
2023-12-01 15:34:32 Activity.ActivitySourceName: OpenTelemetry.Instrumentation.AspNetCore
2023-12-01 15:34:32 Activity.DisplayName: GET /
2023-12-01 15:34:32 Activity.Kind: Server
2023-12-01 15:34:32 Activity.StartTime: 2023-12-01T13:34:32.4239711Z
2023-12-01 15:34:32 Activity.Duration: 00:00:00.0958729
2023-12-01 15:34:32 Activity.Tags:
2023-12-01 15:34:32 net.host.name: localhost
2023-12-01 15:34:32 net.host.port: 8181
2023-12-01 15:34:32 http.method: GET
2023-12-01 15:34:32 http.scheme: http
2023-12-01 15:34:32 http.target: /
2023-12-01 15:34:32 http.url: http://localhost:8181/
2023-12-01 15:34:32 http.flavor: 1.1
2023-12-01 15:34:32 http.user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0
2023-12-01 15:34:32 http.route: /
2023-12-01 15:34:32 http.status_code: 200
2023-12-01 15:34:32 Resource associated with Activity:
2023-12-01 15:34:32 service.name: MultiStageDocker
2023-12-01 15:34:32 splunk.distro.version: 1.2.0
2023-12-01 15:34:32 telemetry.distro.name: splunk-otel-dotnet
2023-12-01 15:34:32 telemetry.distro.version: 1.2.0
2023-12-01 15:34:32 container.id: 9cc3abcf5e01dd5276768fe5e008ffc0a83cb57073d8dd98dc2e2c79f5620100
2023-12-01 15:34:32 telemetry.sdk.name: opentelemetry
2023-12-01 15:34:32 telemetry.sdk.language: dotnet
2023-12-01 15:34:32 telemetry.sdk.version: 1.6.0
2023-12-01 15:34:32
```

## Common known issues
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this detailed readme and common issue fixes!
This is great!


### Visual Studio is not starting the instrumentation

Utilize Visual Studio for constructing the Docker image by right-clicking on the Dockerfile and selecting "Build Docker image." Use Docker Desktop to run the image. It is noteworthy that initiating a container directly from Visual Studio is known to not start the instrumentation.

### instrument.sh is not found

Linux distributions that do not recognize CRLF (Carriage Return Line Feed) file endings may encounter issues when executing the `entrypoint.sh` script. It is necessary to ensure that on such systems, `entrypoint.sh` uses LF (Line Feed) file endings, especially when the file has been modified in a Windows environment.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

worth linking to some other resource on the difference between CRLF / LF? maybe https://en.wikipedia.org/wiki/Newline#Issues_with_different_newline_formats

Just a thought.


See more info [here](https://en.wikipedia.org/wiki/Newline#Issues_with_different_newline_formats).

### The docker exec process may not display all environment variables

The environment variables derived from the `instrument.sh` are not visible when the `env` command is executed through `docker exec`. This occurs because `docker exec` initiates a new session, and the environment variables set in the entry point only apply to the `dotnet MultiStageDocker.dll` session.

### Activity log does not appear

Either the instrumentation wasn't configured properly, or there is no action triggering the activity. In this example, opening the browser at `http://localhost:8181` generates HTTP activity.
6 changes: 6 additions & 0 deletions integration-examples/splunk-otel-dotnet-docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh
# Read in the file of environment settings
. /$HOME/.splunk-otel-dotnet/instrument.sh

# Then run the CMD
exec "$@"