diff --git a/.github/workflows/bootstrap/action.yml b/.github/workflows/bootstrap/action.yml index a34568a..cec62c4 100644 --- a/.github/workflows/bootstrap/action.yml +++ b/.github/workflows/bootstrap/action.yml @@ -26,6 +26,14 @@ runs: restore-keys: | ${{ runner.os }}-nuget + # ensures we don't hit GitHub releases all the time to download the OpenTelemetry auto instrumentation assets + # if not available they will be download in .artifacts/otel-distribution/{otel-version} + - name: Cache OpenTelemetry Distribution + uses: actions/cache@v4 + with: + path: .artifacts/otel-distribution + key: otel-distribution + - name: Setup dotnet uses: actions/setup-dotnet@v4 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 55d97a4..31da39d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,7 +48,10 @@ jobs: - name: Bootstrap Action Workspace id: bootstrap uses: ./.github/workflows/bootstrap + + - name: Test + run: ./build.sh test --test-suite=skip-e2e # We still run the full release build on pull-requests this ensures packages are validated ahead of time - name: Release - run: ./build.sh release --test-suite=skip-e2e + run: ./build.sh release -c \ No newline at end of file diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml index c08fd67..9c5e6db 100644 --- a/.github/workflows/prerelease.yml +++ b/.github/workflows/prerelease.yml @@ -10,6 +10,7 @@ permissions: env: NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages RELEASE_PACKAGES: ".artifacts/package/release/*.nupkg" + RELEASE_DISTRO: ".artifacts/elastic-distribution/*" jobs: release: @@ -25,14 +26,28 @@ jobs: id: bootstrap uses: ./.github/workflows/bootstrap - - run: ./build.sh release --test-suite=skip-e2e + - name: Test + run: ./build.sh test --test-suite=skip-e2e + + - run: ./build.sh release -c name: Release + + - uses: actions/upload-artifact@v4 + with: + name: elastic-distribution + path: ${{ env.RELEASE_DISTRO }} - - name: Generate build provenance + - name: Generate build provenance (Distribution) + uses: actions/attest-build-provenance@5e9cb68e95676991667494a6a4e59b8a2f13e1d0 # v1.3.3 + with: + subject-path: "${{ github.workspace }}/${{ env.RELEASE_DISTRO }}" + + - name: Generate build provenance (Packages) uses: actions/attest-build-provenance@5e9cb68e95676991667494a6a4e59b8a2f13e1d0 # v1.3.3 with: subject-path: "${{ github.workspace }}/${{ env.RELEASE_PACKAGES }}" + # Push to feedz.io - name: publish canary packages to feedz.io run: dotnet nuget push '${{ env.RELEASE_PACKAGES }}' -k ${{ secrets.FEEDZ_IO_API_KEY }} -s ${{ secrets.FEEDZ_IO_API_URL }} --skip-duplicate --no-symbols diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9854735..3ed0fdf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,6 +15,7 @@ env: JOB_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} SLACK_CHANNEL: "#apm-agent-dotnet" RELEASE_PACKAGES: ".artifacts/package/release/*.nupkg" + RELEASE_DISTRO: ".artifacts/elastic-distribution/*" jobs: release: @@ -31,10 +32,21 @@ jobs: id: bootstrap uses: ./.github/workflows/bootstrap - - run: ./build.sh release --test-suite=skip-all + - run: ./build.sh release name: Release - - name: Generate build provenance + - name: Attach Distribution to release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release upload ${{ github.ref_name }} "${{ env.RELEASE_DISTRO }}" + + - name: Generate build provenance (Distribution) + uses: actions/attest-build-provenance@5e9cb68e95676991667494a6a4e59b8a2f13e1d0 # v1.3.3 + with: + subject-path: "${{ github.workspace }}/${{ env.RELASE_DISTRO }}" + + - name: Generate build provenance (Packages) uses: actions/attest-build-provenance@5e9cb68e95676991667494a6a4e59b8a2f13e1d0 # v1.3.3 with: subject-path: "${{ github.workspace }}/${{ env.RELEASE_PACKAGES }}" diff --git a/build/patch-dotnet-auto-install.sh b/build/patch-dotnet-auto-install.sh new file mode 100644 index 0000000..4ab6ef0 --- /dev/null +++ b/build/patch-dotnet-auto-install.sh @@ -0,0 +1,74 @@ +#!/bin/sh +set -e + +# guess OS_TYPE if not provided +if [ -z "$OS_TYPE" ]; then + case "$(uname -s | tr '[:upper:]' '[:lower:]')" in + cygwin_nt*|mingw*|msys_nt*) + OS_TYPE="windows" + ;; + linux*) + if [ "$(ldd /bin/ls | grep -m1 'musl')" ]; then + OS_TYPE="linux-musl" + else + OS_TYPE="linux-glibc" + fi + ;; + darwin*) + OS_TYPE="macos" + ;; + esac +fi + +case "$OS_TYPE" in + "linux-glibc"|"linux-musl"|"macos"|"windows") + ;; + *) + echo "Set the operating system type using the OS_TYPE environment variable. Supported values: linux-glibc, linux-musl, macos, windows." >&2 + exit 1 + ;; +esac + +# guess OS architecture if not provided +if [ -z "$ARCHITECTURE" ]; then + case $(uname -m) in + x86_64) ARCHITECTURE="x64" ;; + aarch64) ARCHITECTURE="arm64" ;; + esac +fi + +case "$ARCHITECTURE" in + "x64"|"arm64") + ;; + *) + echo "Set the architecture type using the ARCHITECTURE environment variable. Supported values: x64, arm64." >&2 + exit 1 + ;; +esac + +test -z "$OTEL_DOTNET_AUTO_HOME" && OTEL_DOTNET_AUTO_HOME="$HOME/.otel-dotnet-auto" +test -z "$VERSION" && VERSION="v1.7.0" + +DOWNLOAD_DIR="${DOWNLOAD_DIR:=${TMPDIR:=$(mktemp -d)}}" + +RELEASES_URL="https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases" +ARCHIVE="opentelemetry-dotnet-instrumentation-$OS_TYPE.zip" + +# In case of Linux, use architecture in the download path +if echo "$OS_TYPE" | grep -q "linux"; then + ARCHIVE="opentelemetry-dotnet-instrumentation-$OS_TYPE-$ARCHITECTURE.zip" +fi + +LOCAL_PATH="${LOCAL_PATH:=$DOWNLOAD_DIR/$ARCHIVE}" +if [ ! -f "${LOCAL_PATH}" ]; then + ( + cd "$DOWNLOAD_DIR" + echo "Downloading $VERSION for $OS_TYPE ($LOCAL_PATH)..." + curl -sSfLo "$LOCAL_PATH" "$RELEASES_URL/download/$VERSION/$ARCHIVE" + ) +else + echo "Using local installation archive: $LOCAL_PATH" +fi + +rm -rf "$OTEL_DOTNET_AUTO_HOME" +unzip -q "$LOCAL_PATH" -d "$OTEL_DOTNET_AUTO_HOME" diff --git a/build/scripts/BuildInformation.fs b/build/scripts/BuildInformation.fs index e12988d..02c5530 100644 --- a/build/scripts/BuildInformation.fs +++ b/build/scripts/BuildInformation.fs @@ -7,20 +7,47 @@ module BuildInformation open System open System.IO open System.Threading +open System.Xml.Linq +open System.Xml.XPath open Fake.Core open Proc.Fs open Fake.Tools.Git +type Paths = + static member Root = + let mutable dir = DirectoryInfo(".") + while dir.GetFiles("*.sln").Length = 0 do dir <- dir.Parent + Environment.CurrentDirectory <- dir.FullName + dir + + static member RelativePathToRoot path = Path.GetRelativePath(Paths.Root.FullName, path) + + static member ArtifactFolder = DirectoryInfo(Path.Combine(Paths.Root.FullName, ".artifacts")) + static member ArtifactPath t = DirectoryInfo(Path.Combine(Paths.ArtifactFolder.FullName, t)) + + static member private SrcFolder = DirectoryInfo(Path.Combine(Paths.Root.FullName, "src")) + static member SrcPath (t: string list) = DirectoryInfo(Path.Combine([Paths.SrcFolder.FullName] @ t |> List.toArray)) + + type BuildConfiguration = static member ValidateAssemblyName = false static member GenerateApiChanges = false - static member OpenTelemetryAutoInstrumentationVersion = SemVer.parse("1.7.0") + + + type Software = static member Organization = "elastic" static member Repository = "elastic-otel-dotnet" static member GithubMoniker = $"%s{Software.Organization}/%s{Software.Repository}" static member SignKey = "069ca2728db333c1" + + static let queryPackageRef upstreamPackage distroPackage = + let path = Paths.SrcPath [distroPackage; $"{distroPackage}.csproj"] + let project = XDocument.Load(path.FullName) + let packageRef = project.XPathSelectElement($"//PackageReference[@Include = '{upstreamPackage}']") + let upstreamVersion = packageRef.Attribute("Version").Value + SemVer.parse(upstreamVersion) static let restore = Lazy((fun _ -> exec { run "dotnet" "tool" "restore" }), LazyThreadSafetyMode.ExecutionAndPublication) @@ -35,20 +62,19 @@ type Software = } SemVer.parse <| $"%s{output.Line}+%s{sha}" , LazyThreadSafetyMode.ExecutionAndPublication) - + static member Version = restore.Value; versionInfo.Value - -type Paths = - static member private Root = - let mutable dir = DirectoryInfo(".") - while dir.GetFiles("*.sln").Length = 0 do dir <- dir.Parent - Environment.CurrentDirectory <- dir.FullName - dir + + static member OpenTelemetryAutoInstrumentationVersion = + let upstreamPackage = "OpenTelemetry.AutoInstrumentation"; + let distroPackage = $"Elastic.{upstreamPackage}" + queryPackageRef upstreamPackage distroPackage - static member RelativePathToRoot path = Path.GetRelativePath(Paths.Root.FullName, path) + static member OpenTelemetryVersion = + let upstreamPackage = "OpenTelemetry"; + let distroPackage = $"Elastic.{upstreamPackage}" + queryPackageRef upstreamPackage distroPackage - static member ArtifactFolder = DirectoryInfo(Path.Combine(Paths.Root.FullName, ".artifacts")) - static member ArtifactPath t = DirectoryInfo(Path.Combine(Paths.ArtifactFolder.FullName, t)) type OS = | OSX | Windows | Linux diff --git a/build/scripts/CommandLine.fs b/build/scripts/CommandLine.fs index e150787..4be8fd7 100644 --- a/build/scripts/CommandLine.fs +++ b/build/scripts/CommandLine.fs @@ -18,6 +18,7 @@ type TestSuite = All | Unit | Integration | E2E | Skip_All | Skip_E2E type Build = | [] Clean | [] Version + | [] Compile | [] Build | [] Test @@ -64,6 +65,7 @@ with | ValidateLicenses | ValidatePackages | GenerateReleaseNotes + | Compile | Redistribute | GenerateApiChanges -> "Undocumented, dependent target" diff --git a/build/scripts/Packaging.fs b/build/scripts/Packaging.fs index c76c662..a29d775 100644 --- a/build/scripts/Packaging.fs +++ b/build/scripts/Packaging.fs @@ -14,15 +14,38 @@ open BuildInformation open CommandLine open Octokit -let private otelAutoVersion = BuildConfiguration.OpenTelemetryAutoInstrumentationVersion; +/// +/// This module is hard to read, with so many file manipulations it's kinda hard to avoid. +/// +/// Packaging ultimately ensures artifacts are available under .artifacts/elastic-distribution/{version} +/// +/// - Download release assets from: github.com/open-telemetry/opentelemetry-dotnet-instrumentation/{version} +/// - cached under .artifacts/otel-distribution/{version}, only downloaded again if an asset is missing +/// - Staging copies are created in the `otel-distribution`, renaming `opentelemetry-` to `staging-` +/// - these copies are used to do mutations and removed afterward +/// - Zip mutations +/// - Ensure we package our plugin dll and related files under net/netfx inside the staging zips. +/// - Ensure we rename `instrument.sh` to `_instrument.sh` inside the scripts +/// - Include our wrapping `instrument.sh` as the new main entry script. +/// - Move mutated staging zips `.artifacts/elastic-distribution/{version}` renaming `stage-` to `elastic-`. +/// + +let private otelAutoVersion = Software.OpenTelemetryAutoInstrumentationVersion; let private downloadFolder = Path.Combine(".artifacts", "otel-distribution", otelAutoVersion.AsString) |> Directory.CreateDirectory -let private distroFolder = Path.Combine(".artifacts", "elastic-distribution", otelAutoVersion.AsString) |> Directory.CreateDirectory +let private distroFolder = Path.Combine(".artifacts", "elastic-distribution") |> Directory.CreateDirectory let private fileInfo (directory: DirectoryInfo) file = Path.Combine(directory.FullName, file) |> FileInfo -let private downloadFile (asset: ReleaseAsset) = fileInfo downloadFolder asset.Name -let private stageFile (asset: ReleaseAsset) = fileInfo downloadFolder (asset.Name.Replace("opentelemetry", "stage")) -let private distroFile (asset: ReleaseAsset) = fileInfo distroFolder (asset.Name.Replace("opentelemetry", "elastic")) +let private downloadFileInfo (file: string) = fileInfo downloadFolder file +let private downloadAsset (asset: ReleaseAsset) = fileInfo downloadFolder asset.Name + +let private _stage (s: string) = s.Replace("opentelemetry", "stage").Replace("otel", "stage").Replace("OpenTelemetry", "stage") +let private stageFile (file: FileInfo) = fileInfo downloadFolder (file.Name |> _stage) +let private stageAsset (asset: ReleaseAsset) = fileInfo downloadFolder (asset.Name |> _stage) + +let private _distro (s: string) = (s |> _stage).Replace("stage", "elastic") +let private distroFile (file: FileInfo) = fileInfo distroFolder (file.Name |> _distro) +let private distroAsset (asset: ReleaseAsset) = fileInfo distroFolder (asset.Name |> _distro) let pluginFiles tfm = ["dll"; "pdb"; "xml"] @@ -36,7 +59,7 @@ let downloadArtifacts (_:ParseResults) = let client = GitHubClient(ProductHeaderValue("Elastic.OpenTelemetry")) let token = Environment.GetEnvironmentVariable("GITHUB_TOKEN") if not(String.IsNullOrWhiteSpace(token)) then - Console.WriteLine($"using GITHUB_TOKEN"); + printfn "using GITHUB_TOKEN"; let tokenAuth = Credentials(token); client.Credentials <- tokenAuth @@ -45,7 +68,7 @@ let downloadArtifacts (_:ParseResults) = let! release = client.Repository.Release.Get("open-telemetry", "opentelemetry-dotnet-instrumentation", $"v{otelAutoVersion.AsString}") |> Async.AwaitTask; Console.WriteLine($"Release %s{release.Name} has %i{release.Assets.Count} assets"); return release.Assets - |> Seq.map (fun asset -> (asset, downloadFile asset)) + |> Seq.map (fun asset -> (asset, downloadAsset asset)) |> Seq.toList } |> Async.RunSynchronously @@ -68,32 +91,116 @@ let downloadArtifacts (_:ParseResults) = let injectPluginFiles (asset: ReleaseAsset) (stagedZip: FileInfo) tfm target = use zipArchive = ZipFile.Open(stagedZip.FullName, ZipArchiveMode.Update) pluginFiles tfm |> List.iter(fun f -> - printfn $"Staging zip: %s{asset.Name}, Adding: %s{f.Name} (%s{tfm}_ to %s{target}" + printfn $"Staging zip: %s{stagedZip.Name}, Adding: %s{f.Name} (%s{tfm}) to %s{target}" zipArchive.CreateEntryFromFile(f.FullName, Path.Combine(target, f.Name)) |> ignore ) +let injectPluginScripts (stagedZip: FileInfo) (otelScript: FileInfo) (script: FileInfo) = + use zipArchive = ZipFile.Open(stagedZip.FullName, ZipArchiveMode.Update) + + printfn $"Staging : %s{stagedZip.Name}, Adding: %s{otelScript.Name}" + zipArchive.CreateEntryFromFile(otelScript.FullName, otelScript.Name) |> ignore + + printfn $"Staging : %s{stagedZip.Name}, Adding: %s{script.FullName}" + let entry = zipArchive.Entries |> Seq.find(fun e -> e.Name = "instrument.sh") + entry.Delete() + + zipArchive.CreateEntryFromFile(script.FullName, script.Name) |> ignore + +let stageInstrumentationScript (stagedZips:List) = + let openTelemetryVersion = downloadFileInfo "opentelemetry-instrument.sh" + let stageVersion = downloadFileInfo "_instrument.sh" + let stageScript = + match stageVersion.Exists with + | true -> stageVersion + | _ -> + let instrumentShZip = + stagedZips + |> List.map(fun (_, p) -> p) + |> List.find (fun p -> not <| p.Name.EndsWith("-windows.zip")) + use zipArchive = ZipFile.Open(instrumentShZip.FullName, ZipArchiveMode.Read) + let shArchive = zipArchive.Entries |> Seq.find(fun e -> e.Name = "instrument.sh") + shArchive.ExtractToFile openTelemetryVersion.FullName + openTelemetryVersion.Refresh() + openTelemetryVersion.MoveTo stageVersion.FullName + stageVersion.Refresh() + stageVersion + + let wrapperScript = downloadFileInfo "instrument.sh" + let copyScript = Path.Combine("src", "Elastic.OpenTelemetry.AutoInstrumentation", "instrument.sh") |> FileInfo + let script = copyScript.CopyTo(wrapperScript.FullName, true) + (stageVersion, script) + +let stageInstallationBashScript () = + let installScript = downloadFileInfo "otel-dotnet-auto-install.sh" + let staged = installScript.CopyTo ((stageFile installScript).FullName, true) + // temporary while https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/pull/3549 is not released. + // Should be released after 1.7.0. + // We should be able to read from `staged` instead after + let patchScript = fileInfo Paths.Root <| Path.Combine("build", "patch-dotnet-auto-install.sh") + + let contents = + (File.ReadAllText patchScript.FullName) + .Replace("/open-telemetry/opentelemetry-dotnet-instrumentation/", "/elastic/elastic-otel-dotnet/") + .Replace("opentelemetry-dotnet-instrumentation", "elastic-dotnet-instrumentation") + .Replace("v" + Software.OpenTelemetryAutoInstrumentationVersion.AsString, "v" + Software.Version.NormalizeToShorter()) + + let elasticInstall = distroFile installScript + File.WriteAllText(elasticInstall.FullName, contents) + +let stageInstallationPsScript () = + let installScript = downloadFileInfo "OpenTelemetry.DotNet.Auto.psm1" + let staged = installScript.CopyTo ((stageFile installScript).FullName, true) + + let envMarker = "\"OTEL_DOTNET_AUTO_HOME\" = $OTEL_DOTNET_AUTO_HOME;" + let contents = + (File.ReadAllText staged.FullName) + .Replace("/open-telemetry/opentelemetry-dotnet-instrumentation/", "/elastic/elastic-otel-dotnet/") + .Replace("opentelemetry-dotnet-instrumentation", "elastic-dotnet-instrumentation") + .Replace("OpenTelemetry .NET Automatic Instrumentation", "Elastic Distribution for OpenTelemetry .NET") + .Replace("OpenTelemetry.Dotnet.Auto", "Elastic.OpenTelemetry.DotNet") + .Replace(envMarker, + [ + envMarker + "#Elastic Distribution" + "\"OTEL_DOTNET_AUTO_PLUGINS\" = \"Elastic.OpenTelemetry.AutoInstrumentationPlugin, Elastic.OpenTelemetry\"" + ] + |> String.concat "\r\n " + ) + .Replace("v" + Software.OpenTelemetryAutoInstrumentationVersion.AsString, "v" + Software.Version.NormalizeToShorter()) + let elasticInstall = distroFile installScript + //ensure we write our new module name + File.WriteAllText(elasticInstall.FullName.Replace("elastic.DotNet.Auto", "Elastic.OpenTelemetry.DotNet"), contents); + + /// moves artifacts from open-distribution to elastic-distribution and renames them to `staged-dotnet-instrumentation*`. /// staged meaning we haven't injected our opentelemetry dll into the zip yet, let stageArtifacts (assets:List) = let stagedZips = assets |> List.filter(fun (a, _) -> a.Name.EndsWith(".zip")) + |> List.filter(fun (a, _) -> not <| a.Name.EndsWith("nuget-packages.zip")) |> List.map(fun (z, f) -> - let stage = stageFile z + let stage = stageAsset z z, f.CopyTo(stage.FullName, true) ) + let (otelScript, wrapperScript) = stageInstrumentationScript stagedZips + printfn $"Staged (%s{wrapperScript.Name}) calling into (%s{otelScript.Name} for repackaging)" + stagedZips |> List.iter (fun (asset, path) -> injectPluginFiles asset path "netstandard2.1" "net" if asset.Name.EndsWith("-windows.zip") then injectPluginFiles asset path "net462" "netfx" + + injectPluginScripts path otelScript wrapperScript - let distro = distroFile asset + let distro = distroAsset asset path.MoveTo(distro.FullName, true) distro.Refresh() - printfn $"Created: %s{distro.FullName}" + printfn $"Moved staging to: %s{distro.FullName}" ) stagedZips @@ -101,11 +208,15 @@ let stageArtifacts (assets:List) = let redistribute (arguments:ParseResults) = let assets = downloadArtifacts arguments - let staged = stageArtifacts assets - printfn "" assets |> List.iter (fun (asset, path) -> printfn "Asset: %s" asset.Name ) + stageInstallationBashScript() + stageInstallationPsScript() + let staged = stageArtifacts assets + ignore() + + diff --git a/build/scripts/Targets.fs b/build/scripts/Targets.fs index b70bba4..316564b 100644 --- a/build/scripts/Targets.fs +++ b/build/scripts/Targets.fs @@ -20,14 +20,19 @@ let private clean _ = removeArtifacts "release-notes" removeArtifacts "tests" -let private build _ = exec { run "dotnet" "build" "-c" "release" } +let private compile _ = exec { run "dotnet" "build" "-c" "release" } +let private build _ = printfn "build" let private release _ = printfn "release" let private version _ = let version = Software.Version printfn $"Informational version: %s{version.AsString}" printfn $"Semantic version: %s{version.NormalizeToShorter()}" + let otelVersion = Software.OpenTelemetryVersion; + printfn $"OpenTelemetry version: %s{otelVersion.AsString}" + let otelAutoVersion = Software.OpenTelemetryAutoInstrumentationVersion; + printfn $"OpenTelemetry Auto Instrumentation version: %s{otelAutoVersion.AsString}" let private generatePackages _ = exec { run "dotnet" "pack" } @@ -162,16 +167,19 @@ let Setup (parsed:ParseResults) = // commands | Version -> Build.Step version | Clean -> Build.Cmd [Version] [] clean - | Build -> Build.Cmd [Clean; CheckFormat] [] build + | Compile -> Build.Step compile + | Build -> Build.Cmd [Clean; CheckFormat; Compile] [] build | End_To_End -> Build.Cmd [] [Build] <| runTests E2E | Integrate -> Build.Cmd [] [Build] <| runTests Integration | Unit_Test -> Build.Cmd [] [Build] <| runTests Unit | Test -> Build.Cmd [] [Build] test + | Redistribute -> Build.Cmd [Compile;] [] Packaging.redistribute + | Release -> Build.Cmd - [PristineCheck; Test] + [PristineCheck; Build; Redistribute] [ValidateLicenses; GeneratePackages; ValidatePackages; GenerateReleaseNotes; GenerateApiChanges] release @@ -185,7 +193,6 @@ let Setup (parsed:ParseResults) = | ValidatePackages -> Build.Step validatePackages | GenerateReleaseNotes -> Build.Step generateReleaseNotes | GenerateApiChanges -> Build.Step generateApiChanges - | Redistribute -> Build.Step Packaging.redistribute // flags | Single_Target diff --git a/examples/Example.AutoInstrumentation/README.md b/examples/Example.AutoInstrumentation/README.md index 15468bf..42c48b9 100644 --- a/examples/Example.AutoInstrumentation/README.md +++ b/examples/Example.AutoInstrumentation/README.md @@ -17,4 +17,10 @@ To quickly see the `DockerFile` in action run the following from the root of th ```bash $ docker build -t example.autoinstrumentation:latest -f examples/Example.AutoInstrumentation/Dockerfile --no-cache . && \ docker run -it --rm -p 5000:8080 --name autoin example.autoinstrumentation:latest +``` + + +```bash +docker build -t distribution.autoinstrumentation:latest -f examples/Example.AutoInstrumentation/distribution.Dockerfile --platform linux/arm64 --no-cache . && \ + docker run -it --rm -p 5000:8080 --name distri --platform linux/arm64 distribution.autoinstrumentation:latest ``` \ No newline at end of file diff --git a/examples/Example.AutoInstrumentation/distribution.Dockerfile b/examples/Example.AutoInstrumentation/distribution.Dockerfile new file mode 100644 index 0000000..e965f3c --- /dev/null +++ b/examples/Example.AutoInstrumentation/distribution.Dockerfile @@ -0,0 +1,34 @@ +ARG OTEL_VERSION=1.7.0 +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG TARGETPLATFORM +ARG TARGETARCH +ARG TARGETVARIANT + +ENV _PROJECT="Example.AutoInstrumentation" +ENV _PROJECTPATH="${_PROJECT}/${_PROJECT}.csproj" + +RUN apt-get update && apt-get install -y unzip + +WORKDIR /work + +COPY ["examples/${_PROJECTPATH}", "examples/${_PROJECT}/"] +RUN dotnet restore -a $TARGETARCH "examples/${_PROJECT}" + +COPY .git .git +COPY examples/${_PROJECT} examples/${_PROJECT} +WORKDIR "/work/examples/${_PROJECT}" +RUN dotnet publish "${_PROJECT}.csproj" -c Release -a $TARGETARCH --no-restore -o /app/example + + +FROM build AS final + +COPY ".artifacts/elastic-distribution" /distro/elastic + +COPY --from=build /app/example /app/example + +ENV OTEL_DOTNET_AUTO_HOME="/app/otel" +# Use already downloaded release assets (call ./build.sh redistribute locally if you run this dockerfile manually) +RUN DOWNLOAD_DIR="/distro/elastic" sh /distro/elastic/elastic-dotnet-auto-install.sh + +ENV OTEL_LOG_LEVEL=debug +ENTRYPOINT ["sh", "/app/otel/instrument.sh", "dotnet", "/app/example/Example.AutoInstrumentation.dll"]