467 lines
16 KiB
PowerShell
467 lines
16 KiB
PowerShell
#
|
|
# Copyright The OpenTelemetry Authors
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
#
|
|
|
|
#Requires -RunAsAdministrator
|
|
|
|
$ServiceLocatorVariable = "OTEL_DOTNET_AUTO_INSTALL_DIR"
|
|
|
|
function Get-Current-InstallDir() {
|
|
return [System.Environment]::GetEnvironmentVariable($ServiceLocatorVariable, [System.EnvironmentVariableTarget]::Machine)
|
|
}
|
|
|
|
function Get-CLIInstallDir-From-InstallDir([string]$InstallDir) {
|
|
$dir = "OpenTelemetry .NET AutoInstrumentation"
|
|
|
|
if ($InstallDir -eq "<auto>") {
|
|
return (Join-Path $Env:ProgramFiles $dir)
|
|
}
|
|
elseif (Test-Path $InstallDir -IsValid) {
|
|
return $InstallDir
|
|
}
|
|
|
|
throw "Invalid install directory provided '$InstallDir'"
|
|
}
|
|
|
|
function Get-Temp-Directory() {
|
|
$temp = $env:TEMP
|
|
|
|
if (-not (Test-Path $temp)) {
|
|
New-Item -ItemType Directory -Force -Path $temp | Out-Null
|
|
}
|
|
|
|
return $temp
|
|
}
|
|
|
|
function Prepare-Install-Directory([string]$InstallDir) {
|
|
if (Test-Path $InstallDir) {
|
|
# Cleanup old directory
|
|
Remove-Item -LiteralPath $InstallDir -Force -Recurse
|
|
}
|
|
|
|
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
|
|
}
|
|
|
|
function Reset-IIS() {
|
|
Start-Process "iisreset.exe" -NoNewWindow -Wait
|
|
}
|
|
|
|
function Download-OpenTelemetry([string]$Version, [string]$Path) {
|
|
$archive = "opentelemetry-dotnet-instrumentation-windows.zip"
|
|
$dlUrl = "https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/download/$Version/$archive"
|
|
$dlPath = Join-Path $Path $archive
|
|
|
|
Invoke-WebRequest -Uri $dlUrl -OutFile $dlPath
|
|
|
|
return $dlPath
|
|
}
|
|
|
|
function Get-Environment-Variables-Table([string]$InstallDir, [string]$OTelServiceName) {
|
|
$COR_PROFILER_PATH_32 = Join-Path $InstallDir "/win-x86/OpenTelemetry.AutoInstrumentation.Native.dll"
|
|
$COR_PROFILER_PATH_64 = Join-Path $InstallDir "/win-x64/OpenTelemetry.AutoInstrumentation.Native.dll"
|
|
$CORECLR_PROFILER_PATH_32 = Join-Path $InstallDir "/win-x86/OpenTelemetry.AutoInstrumentation.Native.dll"
|
|
$CORECLR_PROFILER_PATH_64 = Join-Path $InstallDir "/win-x64/OpenTelemetry.AutoInstrumentation.Native.dll"
|
|
|
|
$DOTNET_ADDITIONAL_DEPS = Join-Path $InstallDir "AdditionalDeps"
|
|
$DOTNET_SHARED_STORE = Join-Path $InstallDir "store"
|
|
$DOTNET_STARTUP_HOOKS = Join-Path $InstallDir "net/OpenTelemetry.AutoInstrumentation.StartupHook.dll"
|
|
|
|
$OTEL_DOTNET_AUTO_HOME = $InstallDir
|
|
$OTEL_DOTNET_AUTO_INTEGRATIONS_FILE = Join-Path $InstallDir "integrations.json"
|
|
|
|
$vars = @{
|
|
# .NET Framework
|
|
"COR_ENABLE_PROFILING" = "1";
|
|
"COR_PROFILER" = "{918728DD-259F-4A6A-AC2B-B85E1B658318}";
|
|
"COR_PROFILER_PATH_32" = $COR_PROFILER_PATH_32;
|
|
"COR_PROFILER_PATH_64" = $COR_PROFILER_PATH_64;
|
|
# .NET Core
|
|
"CORECLR_ENABLE_PROFILING" = "1";
|
|
"CORECLR_PROFILER" = "{918728DD-259F-4A6A-AC2B-B85E1B658318}";
|
|
"CORECLR_PROFILER_PATH_32" = $CORECLR_PROFILER_PATH_32;
|
|
"CORECLR_PROFILER_PATH_64" = $CORECLR_PROFILER_PATH_64;
|
|
# ASP.NET Core
|
|
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES" = "OpenTelemetry.AutoInstrumentation.AspNetCoreBootstrapper";
|
|
# .NET Common
|
|
"DOTNET_ADDITIONAL_DEPS" = $DOTNET_ADDITIONAL_DEPS;
|
|
"DOTNET_SHARED_STORE" = $DOTNET_SHARED_STORE;
|
|
"DOTNET_STARTUP_HOOKS" = $DOTNET_STARTUP_HOOKS;
|
|
# OpenTelemetry
|
|
"OTEL_DOTNET_AUTO_HOME" = $OTEL_DOTNET_AUTO_HOME;
|
|
"OTEL_DOTNET_AUTO_INTEGRATIONS_FILE" = $OTEL_DOTNET_AUTO_INTEGRATIONS_FILE
|
|
}
|
|
|
|
if (-not [string]::IsNullOrWhiteSpace($OTelServiceName)) {
|
|
$vars.Add("OTEL_SERVICE_NAME", $OTelServiceName)
|
|
}
|
|
|
|
return $vars
|
|
}
|
|
|
|
function Setup-Windows-Service([string]$InstallDir, [string]$WindowsServiceName, [string]$OTelServiceName) {
|
|
$varsTable = Get-Environment-Variables-Table -InstallDir $InstallDir -OTelServiceName $OTelServiceName
|
|
[string []] $varsList = ($varsTable.Keys | foreach-object { "$_=$($varsTable[$_])" }) # [string []] definition is required for WS2016
|
|
$regPath = "HKLM:SYSTEM\CurrentControlSet\Services\"
|
|
$regKey = Join-Path $regPath $WindowsServiceName
|
|
|
|
if (Test-Path $regKey) {
|
|
Set-ItemProperty $regKey -Name Environment -Value $varsList
|
|
}
|
|
else {
|
|
throw "Invalid service '$WindowsServiceName'. Service does not exist."
|
|
}
|
|
}
|
|
|
|
function Remove-Windows-Service([string]$WindowsServiceName) {
|
|
[string[]] $filters = @(
|
|
# .NET Framework
|
|
"COR_ENABLE_PROFILING",
|
|
"COR_PROFILER",
|
|
"COR_PROFILER_PATH_32",
|
|
"COR_PROFILER_PATH_64",
|
|
# .NET Core
|
|
"CORECLR_ENABLE_PROFILING",
|
|
"CORECLR_PROFILER",
|
|
"CORECLR_PROFILER_PATH_32",
|
|
"CORECLR_PROFILER_PATH_64",
|
|
# ASP.NET Core
|
|
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES",
|
|
# .NET Common
|
|
"DOTNET_ADDITIONAL_DEPS",
|
|
"DOTNET_SHARED_STORE",
|
|
"DOTNET_STARTUP_HOOKS",
|
|
# OpenTelemetry
|
|
"OTEL_DOTNET_"
|
|
)
|
|
|
|
$regPath = "HKLM:SYSTEM\CurrentControlSet\Services\"
|
|
$regKey = Join-Path $regPath $WindowsServiceName
|
|
|
|
if (Test-Path $regKey) {
|
|
$values = Get-ItemPropertyValue $regKey -Name Environment
|
|
$vars = Filter-Env-List -EnvValues $values -Filters $filters
|
|
|
|
Set-ItemProperty $regKey -Name Environment -Value $vars
|
|
}
|
|
else {
|
|
throw "Invalid service '$WindowsServiceName'. Service does not exist."
|
|
}
|
|
|
|
$remaining = Get-ItemPropertyValue $regKey -Name Environment
|
|
if (-not $remaining) {
|
|
Remove-ItemProperty $regKey -Name Environment
|
|
}
|
|
}
|
|
|
|
function Filter-Env-List([string[]]$EnvValues, [string[]]$Filters) {
|
|
$remaining = @()
|
|
|
|
foreach ($value in $EnvValues) {
|
|
$match = $false
|
|
|
|
foreach ($filter in $Filters) {
|
|
if ($value -clike "$($filter)*") {
|
|
$match = $true
|
|
break
|
|
}
|
|
}
|
|
|
|
if (-not $match) {
|
|
$remaining += $value
|
|
}
|
|
}
|
|
|
|
return $remaining
|
|
}
|
|
|
|
function Get-OpenTelemetry-Archive([string] $Version, [string] $LocalPath) {
|
|
if ($LocalPath) {
|
|
if (Test-Path $LocalPath) {
|
|
return $LocalPath
|
|
}
|
|
|
|
throw "Could not find archive '$LocalPath'"
|
|
}
|
|
|
|
$tempDir = Get-Temp-Directory
|
|
return Download-OpenTelemetry $Version $tempDir
|
|
}
|
|
|
|
function Test-AssemblyNotForGAC([string] $Name) {
|
|
switch ($Name) {
|
|
"netstandard.dll" { return $true }
|
|
"grpc_csharp_ext.x64.dll" { return $true }
|
|
"grpc_csharp_ext.x86.dll" { return $true }
|
|
}
|
|
return $false
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Installs OpenTelemetry .NET Automatic Instrumentation.
|
|
.PARAMETER InstallDir
|
|
Default: <auto> - the default path is Program Files dir.
|
|
Install path of the OpenTelemetry .NET Automatic Instrumentation
|
|
Possible values: <auto>, (Custom path)
|
|
#>
|
|
function Install-OpenTelemetryCore() {
|
|
param(
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$InstallDir = "<auto>",
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$LocalPath
|
|
)
|
|
|
|
$version = "v0.6.0"
|
|
$installDir = Get-CLIInstallDir-From-InstallDir $InstallDir
|
|
$archivePath = $null
|
|
$deleteArchive = $true
|
|
|
|
try {
|
|
if ($LocalPath) {
|
|
# Keep the archive if it's user downloaded
|
|
$deleteArchive = $false
|
|
}
|
|
|
|
$archivePath = Get-OpenTelemetry-Archive $version $LocalPath
|
|
|
|
Prepare-Install-Directory $installDir
|
|
|
|
# Extract files from zip
|
|
Expand-Archive $archivePath $installDir -Force
|
|
|
|
# OpenTelemetry service locator
|
|
[System.Environment]::SetEnvironmentVariable($ServiceLocatorVariable, $installDir, [System.EnvironmentVariableTarget]::Machine)
|
|
|
|
# Register .NET Framweworks dlls in GAC
|
|
[System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") | Out-Null
|
|
$publish = New-Object System.EnterpriseServices.Internal.Publish
|
|
$dlls = Get-ChildItem -Path $installDir\netfx\ -Filter *.dll -File
|
|
for ($i = 0; $i -lt $dlls.Count; $i++) {
|
|
$percentageComplete = $i / $dlls.Count * 100
|
|
Write-Progress -Activity "Registering .NET Framweworks dlls in GAC" `
|
|
-Status "Module $($i+1) out of $($dlls.Count). Installing $($dlls[$i].Name):" `
|
|
-PercentComplete $percentageComplete
|
|
|
|
if (Test-AssemblyNotForGAC $dlls[$i].Name) {
|
|
continue
|
|
}
|
|
|
|
$publish.GacInstall($dlls[$i].FullName)
|
|
}
|
|
Write-Progress -Activity "Registering .NET Framweworks dlls in GAC" -Status "Ready" -Completed
|
|
}
|
|
catch {
|
|
$message = $_
|
|
Write-Error "Could not setup OpenTelemetry .NET Automatic Instrumentation. $message"
|
|
}
|
|
finally {
|
|
if ($archivePath -and $deleteArchive) {
|
|
# Cleanup
|
|
Remove-Item $archivePath
|
|
}
|
|
}
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Uninstalls OpenTelemetry .NET Automatic Instrumentation.
|
|
#>
|
|
function Uninstall-OpenTelemetryCore() {
|
|
$installDir = Get-Current-InstallDir
|
|
|
|
if (-not $installDir) {
|
|
throw "OpenTelemetry Core is already removed."
|
|
}
|
|
|
|
# Unregister .NET Framwework dlls from GAC
|
|
[System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") | Out-Null
|
|
$publish = New-Object System.EnterpriseServices.Internal.Publish
|
|
$dlls = Get-ChildItem -Path $installDir\netfx\ -Filter *.dll -File
|
|
for ($i = 0; $i -lt $dlls.Count; $i++) {
|
|
$percentageComplete = $i / $dlls.Count * 100
|
|
Write-Progress -Activity "Unregistering .NET Framweworks dlls from GAC" `
|
|
-Status "Module $($i+1) out of $($dlls.Count). Uninstalling $($dlls[$i].Name):" `
|
|
-PercentComplete $percentageComplete
|
|
|
|
if (Test-AssemblyNotForGAC $dlls[$i].Name) {
|
|
continue
|
|
}
|
|
|
|
$publish.GacRemove($dlls[$i].FullName)
|
|
}
|
|
Write-Progress -Activity "Unregistering .NET Framweworks dlls from GAC" -Status "Ready" -Completed
|
|
|
|
Remove-Item -LiteralPath $installDir -Force -Recurse
|
|
|
|
# Remove OTel service locator variable
|
|
[System.Environment]::SetEnvironmentVariable($ServiceLocatorVariable, $null, [System.EnvironmentVariableTarget]::Machine)
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Setups environment variables to enable automatic instrumentation started from the current PowerShell session.
|
|
.PARAMETER OTelServiceName
|
|
Specifies OpenTelemetry service name to identify your service.
|
|
#>
|
|
function Register-OpenTelemetryForCurrentSession() {
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$OTelServiceName
|
|
)
|
|
|
|
$installDir = Get-Current-InstallDir
|
|
|
|
if (-not $installDir) {
|
|
throw "OpenTelemetry Core must be setup first. Run 'Install-OpenTelemetryCore' to setup OpenTelemetry Core."
|
|
}
|
|
|
|
$varsTable = Get-Environment-Variables-Table -InstallDir $installDir -OTelServiceName $OTelServiceName
|
|
|
|
foreach ($var in $varsTable.Keys) {
|
|
Set-Item "env:$var" $varsTable[$var]
|
|
}
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Setups IIS environment variables to enable automatic instrumentation.
|
|
Performs IIS reset after registration.
|
|
#>
|
|
function Register-OpenTelemetryForIIS() {
|
|
$installDir = Get-Current-InstallDir
|
|
|
|
if (-not $installDir) {
|
|
throw "OpenTelemetry Core must be setup first. Run 'Install-OpenTelemetryCore' to setup OpenTelemetry Core."
|
|
}
|
|
|
|
if ($installDir -notlike "$env:ProgramFiles\*") {
|
|
Write-Warning "OpenTelemetry is installed to custom path. Make sure that IIS user has access to the path."
|
|
}
|
|
|
|
Setup-Windows-Service -InstallDir $installDir -WindowsServiceName "W3SVC"
|
|
Setup-Windows-Service -InstallDir $installDir -WindowsServiceName "WAS"
|
|
|
|
Reset-IIS
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Setups specific Windows service environment variables to enable automatic instrumentation.
|
|
Performs service restart after registration.
|
|
.PARAMETER WindowsServiceName
|
|
Actual Windows service name in registry.
|
|
.PARAMETER OTelServiceName
|
|
Specifies OpenTelemetry service name to identify your service.
|
|
#>
|
|
function Register-OpenTelemetryForWindowsService() {
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$WindowsServiceName,
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$OTelServiceName
|
|
)
|
|
|
|
$installDir = Get-Current-InstallDir
|
|
|
|
if (-not $installDir) {
|
|
throw "OpenTelemetry Core must be setup first. Run 'Install-OpenTelemetryCore' to setup OpenTelemetry Core."
|
|
}
|
|
|
|
Setup-Windows-Service -InstallDir $installDir -WindowsServiceName $WindowsServiceName -OTelServiceName $OTelServiceName
|
|
Restart-Service -Name $WindowsServiceName -Force
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Removes environment variables to disable automatic instrumentation started from the current PowerShell session.
|
|
#>
|
|
function Unregister-OpenTelemetryForCurrentSession() {
|
|
# .NET Framework
|
|
$env:COR_ENABLE_PROFILING = $null
|
|
$env:COR_PROFILER = $null
|
|
$env:COR_PROFILER_PATH_32 = $null
|
|
$env:COR_PROFILER_PATH_64 = $null
|
|
|
|
# .NET Core
|
|
$env:CORECLR_ENABLE_PROFILING = $null
|
|
$env:CORECLR_PROFILER = $null
|
|
$env:CORECLR_PROFILER_PATH_32 = $null
|
|
$env:CORECLR_PROFILER_PATH_64 = $null
|
|
|
|
# ASP.NET Core
|
|
$env:ASPNETCORE_HOSTINGSTARTUPASSEMBLIES = $null
|
|
|
|
# .NET Common
|
|
$env:DOTNET_ADDITIONAL_DEPS = $null
|
|
$env:DOTNET_SHARED_STORE = $null
|
|
$env:DOTNET_STARTUP_HOOKS = $null
|
|
|
|
# OpenTelemetry
|
|
Get-ChildItem env: | Where-Object { $_.Name -like "OTEL_DOTNET_*" } | ForEach-Object { Set-Item "env:$($_.Name)" $null }
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Removes IIS environment variables to disable automatic instrumentation.
|
|
Performs IIS reset after removal.
|
|
#>
|
|
function Unregister-OpenTelemetryForIIS() {
|
|
Remove-Windows-Service -WindowsServiceName "W3SVC"
|
|
Remove-Windows-Service -WindowsServiceName "WAS"
|
|
Reset-IIS
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Removes specific Windows service environment variables to disable automatic instrumentation.
|
|
Performs service restart after removal.
|
|
.PARAMETER WindowsServiceName
|
|
Actual Windows service Name in registry.
|
|
#>
|
|
function Unregister-OpenTelemetryForWindowsService() {
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$WindowsServiceName
|
|
)
|
|
|
|
Remove-Windows-Service -WindowsServiceName $WindowsServiceName
|
|
Restart-Service -Name $WindowsServiceName -Force
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Locates OpenTelemetry .NET Automatic Instrumentation's install path.
|
|
#>
|
|
function Get-OpenTelemetryInstallDirectory() {
|
|
$installDir = Get-Current-InstallDir
|
|
|
|
if ($installDir) {
|
|
return $installDir
|
|
}
|
|
|
|
Write-Warning "OpenTelemetry .NET Automatic Instrumentation is not installed."
|
|
}
|
|
|
|
Export-ModuleMember -Function Install-OpenTelemetryCore
|
|
Export-ModuleMember -Function Register-OpenTelemetryForIIS
|
|
Export-ModuleMember -Function Register-OpenTelemetryForWindowsService
|
|
Export-ModuleMember -Function Register-OpenTelemetryForCurrentSession
|
|
Export-ModuleMember -Function Uninstall-OpenTelemetryCore
|
|
Export-ModuleMember -Function Unregister-OpenTelemetryForIIS
|
|
Export-ModuleMember -Function Unregister-OpenTelemetryForWindowsService
|
|
Export-ModuleMember -Function Unregister-OpenTelemetryForCurrentSession
|
|
Export-ModuleMember -Function Get-OpenTelemetryInstallDirectory
|