-
Download and install .NET 6.0 (LTS) SDK x64:
https://dotnet.microsoft.com/download
-
Open Command Prompt or PowerShell console
-
Check to make sure dotnet core is installed:
dotnet --version
-
Create dotnet project folder and change directory
mkdir dotnet-api
cd dotnet-api
-
Create new dotnet web API project
dotnet new webapi
-
Get path from console and go run
dotnet .\bin\Debug\net6.0\dotnet-webapi.dll
-
Open browser to check if it works/running:
https://localhost:5001/WeatherForecast
or
http://localhost:5000/WeatherForecast
-
Once it works, publish web API application to FolderProfile (Release, not Debug)
dotnet publish -c Release -p:PublishProfile=FolderProfile
-
Create application folder somewhere convienient and copy everything in the publish folder here
mkdir C:\dotnet-webapi
xcopy .\bin\Release\net6.0\publish\ C:\dotnet-webapi\ /y
-
Control Panel > Programs and Features > Turn Windows features on or off > Install Internet Information Services
-
Download and install .NET Core Hosting Bundle
https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/hosting-bundle?view=aspnetcore-6.0
-
Open Internet Information Services (IIS) Manager (Start Menu)
-
Enter a website name (
dotnet-webapi
in this example
Note: Name of application pool will be reported to New Relic by default -
Physical path:
C:\dotnet-webapi\
-
Port:
90
(Since Port 80 is in use by the default website)
- Go to one.newrelic.com >
Add more data
- Guided install > APM (Application Monitoring) > .NET > Begin installation > Windows
- Copy the command on screen and paste in PowerShell running as Administrator
- Follow the prompts to complete .NET agent installation
- Go to
http://localhost:90/WeatherForecast
a few times to generate traffic - Check New Relic APM > DefaultAppPool for APM data
- Get a sample
dockerfile
from New Relic or use the sample below. Placedockerfile
in the root of this repository.
# Use the correct tagged version for your application's targeted runtime. See https://hub.docker.com/_/microsoft-dotnet-aspnet/
FROM mcr.microsoft.com/dotnet/aspnet:6.0
# Publish your application.
COPY ./bin/Release/net6.0/publish /app
# Install the agent
RUN apt-get update && apt-get install -y wget ca-certificates gnupg \
&& echo 'deb http://apt.newrelic.com/debian/ newrelic non-free' | tee /etc/apt/sources.list.d/newrelic.list \
&& wget https://download.newrelic.com/548C16BF.gpg \
&& apt-key add 548C16BF.gpg \
&& apt-get update \
&& apt-get install -y newrelic-netcore20-agent \
&& rm -rf /var/lib/apt/lists/*
# Enable the agent
ENV CORECLR_ENABLE_PROFILING=1 \
CORECLR_PROFILER={36032161-FFC0-4B61-B559-F6C5D41BAE5A} \
CORECLR_NEWRELIC_HOME=/usr/local/newrelic-netcore20-agent \
CORECLR_PROFILER_PATH=/usr/local/newrelic-netcore20-agent/libNewRelicProfiler.so
WORKDIR /app
EXPOSE 80
ENTRYPOINT ["dotnet", "./dotnet-webapi.dll"]
- Download and Install Docker Desktop
- Open a terminal and navigate to the root of this repository
- Create a file called
.env
to put in environment variables for your container (the.env
has been placed in the.gitignore
file to prevent you from uploading your license key online).
NEW_RELIC_LICENSE_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXNRAL
NEW_RELIC_APP_NAME=dotnet-api.docker
- Run this command to build the Docker container:
docker build -t dotnet-webapi:latest .
- Run this command to run the container:
docker run -d --env-file .env -p 80:80 dotnet-webapi:latest
- Alternatively, run
docker run -d -e NEW_RELIC_LICENSE_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXNRAL" -e NEW_RELIC_APP_NAME="dotnet-api.docker" -p 80:80 dotnet-webapi:latest
- Access the webapi at:
http:/127.0.0.1/WeatherForecast
- Check New Relic One > APM to see transactions
- In your project folder containing
.csproj
by entering the following in the terminal:
dotnet add package NewRelic.Agent.Api --version 9.5.0
-
Edit
WeatherForecastController.cs
and add the following on the first line:using NewRelic.Api.Agent;
-
Also, add the following just before the
return
statement on line 25
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
IAgent agent = NewRelic.Api.Agent.NewRelic.GetAgent();
ITransaction transaction = agent.CurrentTransaction;
transaction.AddCustomAttribute("dockerVersion", "4.4.4");
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
- Rebuild the application and docker image, and run to test
dotnet build .
dotnet publish -c Release -p:PublishProfile=FolderProfile
xcopy .\bin\Release\net6.0\publish\ C:\dotnet-webapi\
docker build -t dotnet-webapi:latest .
docker run -d --env-file .env -p 80:80 dotnet-webapi:latest
- In New Relic, try this NRQL query to see your newly added custom attribute:
SELECT * FROM Transaction WHERE appName='dotnet-api.docker' SINCE 1 hour ago
-
Get download
minikube
andkubectl
, and set path to the folder containing these. -
Open Hyper-V Manager and create a new external virtual switch called
New Virtual Switch
-
Open terminal as Administrator and create a new minikube (kubernetes) cluster
minikube start --driver=hyperv --hyperv-virtual-switch='New Virtual Switch' --cni=flannel --cpus=4 --memory=4096 -p dotnet-webapi
- We need to re-build the Docker image so it appears in the minikube Docker repository instead of your localhost Docker image repository. Run this command to switch Docker repository to minikiube:
minikube -p dotnet-webapi docker-env | Invoke-Expression
-
Check
docker images
to see the images in your minikube image repository instead of your local Docker image repository.
-
Before you re-build the docker image, update the
dockerfile
to include the environment variables forNEW_RELIC_LICENSE_KEY
andNEW_RELIC_APP_NAME
. This was left out previously to prevent uploading keys online.
# Enable the agent
ENV CORECLR_ENABLE_PROFILING=1 \
CORECLR_PROFILER={36032161-FFC0-4B61-B559-F6C5D41BAE5A} \
CORECLR_NEWRELIC_HOME=/usr/local/newrelic-netcore20-agent \
CORECLR_PROFILER_PATH=/usr/local/newrelic-netcore20-agent/libNewRelicProfiler.so \
NEW_RELIC_LICENSE_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXNRAL \
NEW_RELIC_APP_NAME=dotnet-api.docker
- Build the Docker image with the new
dockerfile
usingdocker build -t dotnet-webapi:test .
- Run this with
kubectl apply -f dotnet-webapi.yaml
- In a different terminal, expose the service to an external IP in minikube:
minikube tunnel -p dotnet-webapi
- Check
kubectl get pods
to make sure the pod is running. - Get the external IP using
kubectl get services
- Check out the service
http://<EXTERNAL-IP>/WeatherForecast
- If the new Docker image was built correctly with the environment variables added in, you should now be able to see this data in New Relic as well under Kubernetes Cluster Explorer
- Download
helm
and set PATH to its containing folder. - Go to New Relic to add more data and select "Kubernetes"
- Enter a namespace for the Kubernetes instrumentation and click next.
- Copy and paste the code to a notepad and replace
&&
with;
and replace\
with`
to run in PowerShell. It should look something like this for PowerShell:
kubectl apply -f https://download.newrelic.com/install/kubernetes/pixie/latest/px.dev_viziers.yaml;
kubectl apply -f https://download.newrelic.com/install/kubernetes/pixie/latest/olm_crd.yaml;
helm repo add newrelic https://helm-charts.newrelic.com;
helm repo update;
kubectl create namespace newrelic;
helm upgrade --install newrelic-bundle newrelic/nri-bundle `
--set global.licenseKey=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8NRAL `
--set global.cluster=tiny-hat `
--namespace=newrelic `
--set newrelic-infrastructure.privileged=true `
--set global.lowDataMode=true `
--set ksm.enabled=true `
--set prometheus.enabled=true `
--set kubeEvents.enabled=true `
--set logging.enabled=true `
--set newrelic-pixie.enabled=true `
--set newrelic-pixie.apiKey=px-api-a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o0p5 `
--set pixie-chart.enabled=true `
--set pixie-chart.deployKey=px-dep-d4c3b2a1-f6e5-h8g7-j0i9-p5o0n4m3l2k1 `
--set pixie-chart.clusterName=tiny-hat
-
New pods will be created under the
newrelic
,olm
, andpx-operator
namespace within 5 minutes. -
Go back to the Kubernetes Cluster Explorer to see your minikube cluster.
-
Check out the
Control Plane
andEvents
to get a feel for what kind of data is coming in, and compare it to what you see in APM. Then, check outLive debugging with Pixie
. -
In
Live debugging with Pixie
click on the dropdown forscript
and selectpx/perf_flamegraph
and filter as needed to see performance data,.
- Install the following. Notice it will add to your
.csproj
file.
dotnet add package OpenTelemetry --prerelease
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol --prerelease
dotnet add package OpenTelemetry.Instrumentation.AspNetCore --prerelease
dotnet add package OpenTelemetry.Instrumentation.Http --prerelease
dotnet add package OpenTelemetry.Extensions.Hosting --prerelease
- In the
program.cs
file, add the following at the top of the code:
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
- Finally, just before
builder.Services.AddControllers();
add the following:
builder.Services.AddOpenTelemetryTracing(b =>
{
b
.AddOtlpExporter(options =>
{
options.Endpoint = new Uri($"{Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT")}");
options.Headers = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_HEADERS");
})
.SetResourceBuilder(
ResourceBuilder
.CreateDefault()
.AddService("dotnet-webapi.otel")
.AddAttributes(new Dictionary<string, object> { {"environment", "production"} })
)
.AddHttpClientInstrumentation()
.AddAspNetCoreInstrumentation();
});
-
Build the application with
dotnet build .
-
Before running with
dotnet bin/Debug/net6.0/dotnet-webapi.dll
set the following environment variables:
OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.nr-data.net:4317
OTEL_EXPORTER_OTLP_HEADERS=api-key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXNRAL
- Check New Relic One > Services - OpenTelemetry to see the data.
-
To see OpenTelemetry data in Jaeger UI instead, change the endpoint and spin up a jaeger container
$env:OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317" docker run --name jaeger -p 13133:13133 -p 16686:16686 -p 4317:55680 -d --restart=unless-stopped jaegertracing/opentelemetry-all-in-one
-
Run the application generate some traffic
-
Go to http://localhost:16686 to see Jaeger UI.
-
Notice no change was done to the code, only environment variables were changed to specify which endpoint to export traces.