Install vFunction Agent and DataDog on .NET Framework Application running on Containerized Windows-x64 via Dockerfile



Overview

Microsoft .NET Applications have a limitation that only one Agent can be hooked into the Application at a time. To work around this limitation, the Datadog Tracer can be used as the Base Agent. This Datadog Tracer includes a configuration file that allows you to define additional .NET Agents to run simultaneously on the Application without conflict.

At a high level, you’ll need to:

  1. Download and install the vFunction Monolithic .NET Agent
  2. Modify the Datadog .NET Tracer to add the vFunction Monolithic .NET Agent as a Custom Profiler
  3. Start the Application

.NET Framework Compatibility

vFunction supports C# .NET Framework version 4.8.x applications.


Installation Steps


Install the vFunction Monolithic Agent
  1. Ensure vFunction Monolithic Agent Prerequisites are met
  2. Download the vFunction Windows Controller Installation ZIP for the vFunction Monolithic Agent
  3. On the Build machine, create a vFunction directory where files can be stored
  4. Add the vFunction Windows Controller Installation ZIP to this directory
  5. Retrieve the vFunction UI’s Application UUIDs:
  1. Log into the vFunction Server’s UI in a browser
  2. In the top-left corner, click the dropdown and select the relevant Application
  3. In the top-center menu bar, click the “Learning” tab
  4. On the left-side, click the “Select Controllers” link
  5. On the left-side, click the “Install Controller” link
  6. In the dialog box, find the YAML-formatted text box that contains the following details. You’ll need these details at a later stage below:
controller:
  name: {display name for this controller}
  host: $your_VF_Server_address
  org_id: 93af7f38-0000-0000-0000-bd9516798497
  app_id: 9fb228fc-0000-0000-0000-db8e83427e14
  client_id: caeadcd1-0000-0000-0000-9c9b37a9e119
  client_secret: 68cb85eb-0000-0000-0000-fb9e7f1d9240
  1. Create an installation.yaml to be added to this vfunction directory on the Build machine
controller:
  name: 'Windows-Container-Test'
  host: 'https://vfunction.mycompany.com'
  org_id: '45faddbf-1111-1111-1111-5c3846b4e751'
  app_id: '2bef40e7-1111-1111-1111-b17975a62ca0'
  client_id: '6f809ad3-1111-1111-1111-a86c17f9f9a9'
  client_secret: 'b946d2d2-1111-1111-1111-463dc172b40a'
  type: dotnet
  instrconf_additions:
    inclusions:
#      - a.b.c.
    exclusions:
#      - a.b.c.
  tags:
#    - tag1

server_application:
#  name:
#  include_classes: com.
#  allowed_users:
#  new_user_default_password:

agent:
  # optional versions: framework, dotnet
  version: framework
  # optional environments: iis, service, command
  environment: service
#  application_name:
#  architecture: x86
#  application_command:
### Set the log level for the agent (trace, debug, info, warning, error, critical). The default is debug.
#  log_level: info
### Add process ID to log file name (true/false). Default is false ###
#  add_pid_to_log_file: false
  enable_rejit: true

Create a PowerShell Script to Modify Datadog and add Environment Variables
  1. Create a vfunction-dockerfile-windows-service.ps1 to add to the vFunction directory on the Build machine. This script adds the vFunction Agent to the Datadog’s Loader.conf and it adds the vFunction Agent Environment Variables to the Registry for the relevant Windows Service
param (
    [parameter(Mandatory=$true)] [string]$svc
)

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process -Force

# print all parameters
Write-Output "Running with parameters:"
if ($null -ne $svc -and $svc -ne ""){
    Write-Output "instance: $svc"
}

#################################################################
###################### Helper Functions #########################
#################################################################

function Modify-DatadogLoaderConf {
	
	Write-Host "Configuring Datadog Loader.conf"

    $X86_CUSTOM = "CUSTOM;{CD7D4B53-96C8-4552-9C11-6E41DF8EAB8A};win-x86;C:\vfunction\agent\vfagent.net.x86.dll"
	$X64_CUSTOM = "CUSTOM;{CD7D4B53-96C8-4552-9C11-6E41DF8EAB8A};win-x64;C:\vfunction\agent\vfagent.net.dll"
	
	$X86_LOADER = "C:\Program Files\Datadog\.NET Tracer\win-x86\loader.conf"
	$X64_LOADER = "C:\Program Files\Datadog\.NET Tracer\win-x64\loader.conf"

	if (-not (Get-Content $X86_LOADER | Select-String -SimpleMatch $X86_CUSTOM -Quiet)) {
		#Write-Host "X86 Datadog Loader.conf before VFunction modification:"
		#Get-Content $X86_LOADER
		Add-Content -Path $X86_LOADER -Value ""
		Add-Content -Path $X86_LOADER -Value $X86_CUSTOM
		#Write-Host "X86 Datadog Loader.conf after VFunction modification:"
		#Get-Content $X86_LOADER
	}
	if (-not (Get-Content $X64_LOADER | Select-String -SimpleMatch $X64_CUSTOM -Quiet)) {
		#Write-Host "X64 Datadog Loader.conf before VFunction modification:"
		#Get-Content $X64_LOADER
		Add-Content -Path $X64_LOADER -Value ""
		Add-Content -Path $X64_LOADER -Value $X64_CUSTOM
		#Write-Host "X64 Datadog Loader.conf after VFunction modification:"
		#Get-Content $X64_LOADER
	}
}

function Set-WinSvcEnvVars {

	$regPath = "HKLM:\SYSTEM\CurrentControlSet\Services\${svc}"
    $newValues = @(
        "VF_AGENT_CONF_LOCATION=C:\vfunction\config\agent\instances\${svc}\conf.json",
        "COMPlus_TailCallOpt=0"
    )
	
	# Read existing values (default to empty array if none)
	$item = Get-ItemProperty -Path $regPath -ErrorAction SilentlyContinue

    if ($item -and $item.Environment) {
        $existing = $item.Environment
    }
    else {
        $existing = @()
    }
    
	# Merge, filtering out any duplicates
	$merged = ($existing + $newValues) | Select-Object -Unique

	New-ItemProperty `
    -Path $regPath `
    -Name Environment `
    -Value $merged `
    -PropertyType MultiString `
    -Force
}

#################################################################
###################### Datadog Configuration ####################
#################################################################

Modify-DatadogLoaderConf

#################################################################
###################### Win SVC Configuration ####################
#################################################################

Set-WinSvcEnvVars

Modify the Dockerfile to add all new components
  1. Modify the Dockerfile used by the Application to add the vFunction Agent
# escape=`

FROM mcr.microsoft.com/dotnet/framework/runtime:4.8

# Main Content of Dockerfile related to App

# Location where Datadog is added to the Container
RUN powershell -Command `
    # Datadog APM
    Start-Process msiexec.exe -Wait -ArgumentList '/I C:\datadog-dotnet-apm.msi /quiet'; `
    net stop /y was;

# New details for vFunction (VF)
COPY ["vfunction/vfunction-controller-windows*.zip", "C:/vfunction.zip"]
COPY ["vfunction/vfunction-dockerfile-windows-service.ps1", "C:/vfunction.ps1"]
COPY ["vfunction/installation.yaml", "C:/vfunction.yaml"]

# Set Windows Service Name for VF to hook
ENV SVC="CHANGE_ME"

# Expand VF dir
RUN powershell -ExecutionPolicy Bypass Expand-Archive -Path "C:/vfunction.zip" -DestinationPath "C:/";

# Create App-specific VF instance
RUN powershell -ExecutionPolicy Bypass -Command "& C:\vfunction\controller-installation\create-instance.ps1  ` 
    -instance $env:SVC `  
    -agentMode true `  
    -type dotnet"

# Move App-specific configuration to created VF instance
RUN powershell -ExecutionPolicy Bypass Move-Item -Path "C:/vfunction.yaml" `  
    -Destination "C:/vfunction/config/installation/instances/$env:SVC/installation.yaml" -Force; `
    icacls "C:\vfunction" /grant Everyone:F /T

# Set all VF Configuration Files
RUN powershell -ExecutionPolicy Bypass -Command "& C:\vfunction\controller-installation\install.ps1 `
	-instance $env:SVC `
    -noServices true `
	-scriptMode true"

# Modify Datadog Loader.conf and add VF Env Vars to Windows Service's Registry
RUN powershell -ExecutionPolicy Bypass -Command "& C:\vfunction.ps1 -svc $env:SVC"

# End of Dockerfile that starts the Container

Confirm Functionality

  1. Confirm the Docker Container builds as expected
  2. Confirm the Application functions as expected
  3. Confirm that Datadog is capturing informaton about the Application as expected
  4. Confirm that the vFunction Monolithic Agent is capturing data as expected by starting Learning and validating learning results