├── .github └── workflows │ └── powershell.yml ├── .gitignore ├── Changelog.md ├── LICENSE ├── README.md ├── build.ps1 ├── docs ├── Add-ActivityEvent.md ├── Add-ActivityTag.md ├── Add-ExporterConsole.md ├── Add-ExporterOtlpTrace.md ├── Add-HttpClientInstrumentation.md ├── Add-ResourceConfiguration.md ├── Add-TracerSource.md ├── Disable-OtelDiagnosticLog.md ├── Enable-OtelDiagnosticLog.md ├── Get-OtelDiagnosticLog.md ├── New-ActivitySource.md ├── New-TracerProviderBuilder.md ├── README.md ├── Set-ActivityStatus.md ├── Start-Activity.md ├── Start-Tracer.md ├── Stop-Tracer.md └── images │ ├── dynatrace.png │ └── honeycombtrace.png ├── potel.sln ├── samples ├── README.md ├── jaegersample.jpg └── sample.psm1 ├── src ├── dotnet │ ├── global.json │ └── potel.csproj ├── internal │ ├── Add-PackageTypes.ps1 │ └── Export-HelpToMd.ps1 ├── potel.psm1 └── public │ ├── Add-ActivityEvent.ps1 │ ├── Add-ActivityTag.ps1 │ ├── Add-ExporterConsole.ps1 │ ├── Add-ExporterOtlpTrace.ps1 │ ├── Add-HttpClientInstrumentation.ps1 │ ├── Add-ResourceConfiguration.ps1 │ ├── Add-TracerSource.ps1 │ ├── Disable-OtelDiagnosticLog.ps1 │ ├── Enable-OtelDiagnosticLog.ps1 │ ├── Get-OtelDiagnosticLog.ps1 │ ├── New-ActivitySource.ps1 │ ├── New-TracerProviderBuilder.ps1 │ ├── Set-ActivityStatus.ps1 │ ├── Start-Activity.ps1 │ ├── Start-Tracer.ps1 │ └── Stop-Tracer.ps1 ├── test └── Tracer.Tests.ps1 └── version.json /.github/workflows/powershell.yml: -------------------------------------------------------------------------------- 1 | name: PowerShell 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | paths-ignore: 7 | - 'docs/**' 8 | - 'Changelog.md' 9 | - 'README.md' 10 | - src/internal/Export-HelpToMd.ps1 11 | pull_request: 12 | branches: [ "main" ] 13 | 14 | permissions: 15 | contents: read 16 | 17 | jobs: 18 | build: 19 | permissions: 20 | contents: read # for actions/checkout to fetch code 21 | security-events: write # for github/codeql-action/upload-sarif to upload SARIF results 22 | actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status 23 | name: Build 24 | runs-on: ubuntu-latest 25 | 26 | steps: 27 | - uses: actions/checkout@v4 28 | with: 29 | fetch-depth: 0 # avoid shallow clone so nbgv can do its work. 30 | 31 | - name: Run PSScriptAnalyzer 32 | uses: microsoft/psscriptanalyzer-action@6b2948b1944407914a58661c49941824d149734f 33 | with: 34 | # Check https://github.com/microsoft/action-psscriptanalyzer for more info about the options. 35 | # The below set up runs PSScriptAnalyzer to your entire repository and runs some basic security rules. 36 | path: .\src 37 | recurse: true 38 | # Include your own basic security rules. Removing this option will run all the rules 39 | includeRule: '"PSAvoidGlobalAliases", "PSAvoidUsingConvertToSecureStringWithPlainText"' 40 | output: results.sarif 41 | 42 | # Upload the SARIF file generated in the previous step 43 | - name: Upload SARIF results file 44 | uses: github/codeql-action/upload-sarif@v2 45 | with: 46 | sarif_file: results.sarif 47 | 48 | - uses: dotnet/nbgv@1801854259a50d987aaa03b99b28cebf49faa779 49 | id: nbgv 50 | 51 | - name: Build 52 | shell: pwsh 53 | run: ./build.ps1 build ${{ steps.nbgv.outputs.VersionMajor }} ${{ steps.nbgv.outputs.VersionMinor }} ${{ steps.nbgv.outputs.BuildNumber }} ${{ steps.nbgv.outputs.VersionRevision }} ${{ steps.nbgv.outputs.PrereleaseVersionNoLeadingHyphen }} 54 | 55 | - name: Store build output 56 | uses: actions/upload-artifact@v3 57 | with: 58 | name: build 59 | path: | 60 | publish 61 | retention-days: 1 62 | 63 | test: 64 | permissions: 65 | contents: read # for actions/checkout to fetch code 66 | actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status 67 | name: Test 68 | needs: Build 69 | runs-on: ubuntu-latest 70 | container: 71 | image: mcr.microsoft.com/powershell:${{ matrix.pwshv }}-ubuntu-22.04 72 | strategy: 73 | matrix: 74 | pwshv: ['7.4','preview-7.5'] 75 | 76 | steps: 77 | - uses: actions/checkout@v4 78 | 79 | - name: Download build output 80 | uses: actions/download-artifact@v3 81 | with: 82 | name: build 83 | path: publish 84 | 85 | - name: Test 86 | shell: pwsh 87 | run: ./build.ps1 test 88 | 89 | publish: 90 | permissions: 91 | contents: read # for actions/checkout to fetch code 92 | actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status 93 | name: Publish 94 | needs: Test 95 | runs-on: ubuntu-latest 96 | container: 97 | image: mcr.microsoft.com/dotnet/sdk:8.0 98 | if: github.ref == 'refs/heads/main' 99 | steps: 100 | - uses: actions/checkout@v4 101 | 102 | - name: Download build output 103 | uses: actions/download-artifact@v3 104 | with: 105 | name: build 106 | path: publish 107 | 108 | - name: Publish 109 | shell: pwsh 110 | run: ./build.ps1 publish 111 | env: 112 | PSPublishApiKey: ${{ secrets.NUGETAPIKEY }} 113 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | build/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.tlog 95 | *.vspscc 96 | *.vssscc 97 | .builds 98 | *.pidb 99 | *.svclog 100 | *.scc 101 | 102 | # Chutzpah Test files 103 | _Chutzpah* 104 | 105 | # Visual C++ cache files 106 | ipch/ 107 | *.aps 108 | *.ncb 109 | *.opendb 110 | *.opensdf 111 | *.sdf 112 | *.cachefile 113 | *.VC.db 114 | *.VC.VC.opendb 115 | 116 | # Visual Studio profiler 117 | *.psess 118 | *.vsp 119 | *.vspx 120 | *.sap 121 | 122 | # Visual Studio Trace Files 123 | *.e2e 124 | 125 | # TFS 2012 Local Workspace 126 | $tf/ 127 | 128 | # Guidance Automation Toolkit 129 | *.gpState 130 | 131 | # ReSharper is a .NET coding add-in 132 | _ReSharper*/ 133 | *.[Rr]e[Ss]harper 134 | *.DotSettings.user 135 | 136 | # TeamCity is a build add-in 137 | _TeamCity* 138 | 139 | # DotCover is a Code Coverage Tool 140 | *.dotCover 141 | 142 | # AxoCover is a Code Coverage Tool 143 | .axoCover/* 144 | !.axoCover/settings.json 145 | 146 | # Coverlet is a free, cross platform Code Coverage Tool 147 | coverage*.json 148 | coverage*.xml 149 | coverage*.info 150 | 151 | # Visual Studio code coverage results 152 | *.coverage 153 | *.coveragexml 154 | 155 | # NCrunch 156 | _NCrunch_* 157 | .*crunch*.local.xml 158 | nCrunchTemp_* 159 | 160 | # MightyMoose 161 | *.mm.* 162 | AutoTest.Net/ 163 | 164 | # Web workbench (sass) 165 | .sass-cache/ 166 | 167 | # Installshield output folder 168 | [Ee]xpress/ 169 | 170 | # DocProject is a documentation generator add-in 171 | DocProject/buildhelp/ 172 | DocProject/Help/*.HxT 173 | DocProject/Help/*.HxC 174 | DocProject/Help/*.hhc 175 | DocProject/Help/*.hhk 176 | DocProject/Help/*.hhp 177 | DocProject/Help/Html2 178 | DocProject/Help/html 179 | 180 | # Click-Once directory 181 | publish/ 182 | 183 | # Publish Web Output 184 | *.[Pp]ublish.xml 185 | *.azurePubxml 186 | # Note: Comment the next line if you want to checkin your web deploy settings, 187 | # but database connection strings (with potential passwords) will be unencrypted 188 | *.pubxml 189 | *.publishproj 190 | 191 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 192 | # checkin your Azure Web App publish settings, but sensitive information contained 193 | # in these scripts will be unencrypted 194 | PublishScripts/ 195 | 196 | # NuGet Packages 197 | *.nupkg 198 | # NuGet Symbol Packages 199 | *.snupkg 200 | # The packages folder can be ignored because of Package Restore 201 | **/[Pp]ackages/* 202 | # except build/, which is used as an MSBuild target. 203 | !**/[Pp]ackages/build/ 204 | # Uncomment if necessary however generally it will be regenerated when needed 205 | #!**/[Pp]ackages/repositories.config 206 | # NuGet v3's project.json files produces more ignorable files 207 | *.nuget.props 208 | *.nuget.targets 209 | 210 | # Microsoft Azure Build Output 211 | csx/ 212 | *.build.csdef 213 | 214 | # Microsoft Azure Emulator 215 | ecf/ 216 | rcf/ 217 | 218 | # Windows Store app package directories and files 219 | AppPackages/ 220 | BundleArtifacts/ 221 | Package.StoreAssociation.xml 222 | _pkginfo.txt 223 | *.appx 224 | *.appxbundle 225 | *.appxupload 226 | 227 | # Visual Studio cache files 228 | # files ending in .cache can be ignored 229 | *.[Cc]ache 230 | # but keep track of directories ending in .cache 231 | !?*.[Cc]ache/ 232 | 233 | # Others 234 | ClientBin/ 235 | ~$* 236 | *~ 237 | *.dbmdl 238 | *.dbproj.schemaview 239 | *.jfm 240 | *.pfx 241 | *.publishsettings 242 | orleans.codegen.cs 243 | 244 | # Including strong name files can present a security risk 245 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 246 | #*.snk 247 | 248 | # Since there are multiple workflows, uncomment next line to ignore bower_components 249 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 250 | #bower_components/ 251 | 252 | # RIA/Silverlight projects 253 | Generated_Code/ 254 | 255 | # Backup & report files from converting an old project file 256 | # to a newer Visual Studio version. Backup files are not needed, 257 | # because we have git ;-) 258 | _UpgradeReport_Files/ 259 | Backup*/ 260 | UpgradeLog*.XML 261 | UpgradeLog*.htm 262 | ServiceFabricBackup/ 263 | *.rptproj.bak 264 | 265 | # SQL Server files 266 | *.mdf 267 | *.ldf 268 | *.ndf 269 | 270 | # Business Intelligence projects 271 | *.rdl.data 272 | *.bim.layout 273 | *.bim_*.settings 274 | *.rptproj.rsuser 275 | *- [Bb]ackup.rdl 276 | *- [Bb]ackup ([0-9]).rdl 277 | *- [Bb]ackup ([0-9][0-9]).rdl 278 | 279 | # Microsoft Fakes 280 | FakesAssemblies/ 281 | 282 | # GhostDoc plugin setting file 283 | *.GhostDoc.xml 284 | 285 | # Node.js Tools for Visual Studio 286 | .ntvs_analysis.dat 287 | node_modules/ 288 | 289 | # Visual Studio 6 build log 290 | *.plg 291 | 292 | # Visual Studio 6 workspace options file 293 | *.opt 294 | 295 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 296 | *.vbw 297 | 298 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 299 | *.vbp 300 | 301 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 302 | *.dsw 303 | *.dsp 304 | 305 | # Visual Studio 6 technical files 306 | *.ncb 307 | *.aps 308 | 309 | # Visual Studio LightSwitch build output 310 | **/*.HTMLClient/GeneratedArtifacts 311 | **/*.DesktopClient/GeneratedArtifacts 312 | **/*.DesktopClient/ModelManifest.xml 313 | **/*.Server/GeneratedArtifacts 314 | **/*.Server/ModelManifest.xml 315 | _Pvt_Extensions 316 | 317 | # Paket dependency manager 318 | .paket/paket.exe 319 | paket-files/ 320 | 321 | # FAKE - F# Make 322 | .fake/ 323 | 324 | # CodeRush personal settings 325 | .cr/personal 326 | 327 | # Python Tools for Visual Studio (PTVS) 328 | __pycache__/ 329 | *.pyc 330 | 331 | # Cake - Uncomment if you are using it 332 | # tools/** 333 | # !tools/packages.config 334 | 335 | # Tabs Studio 336 | *.tss 337 | 338 | # Telerik's JustMock configuration file 339 | *.jmconfig 340 | 341 | # BizTalk build output 342 | *.btp.cs 343 | *.btm.cs 344 | *.odx.cs 345 | *.xsd.cs 346 | 347 | # OpenCover UI analysis results 348 | OpenCover/ 349 | 350 | # Azure Stream Analytics local run output 351 | ASALocalRun/ 352 | 353 | # MSBuild Binary and Structured Log 354 | *.binlog 355 | 356 | # NVidia Nsight GPU debugger configuration file 357 | *.nvuser 358 | 359 | # MFractors (Xamarin productivity tool) working folder 360 | .mfractor/ 361 | 362 | # Local History for Visual Studio 363 | .localhistory/ 364 | 365 | # Visual Studio History (VSHistory) files 366 | .vshistory/ 367 | 368 | # BeatPulse healthcheck temp database 369 | healthchecksdb 370 | 371 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 372 | MigrationBackup/ 373 | 374 | # Ionide (cross platform F# VS Code tools) working folder 375 | .ionide/ 376 | 377 | # Fody - auto-generated XML schema 378 | FodyWeavers.xsd 379 | 380 | # VS Code files for those working on multiple tools 381 | .vscode/* 382 | !.vscode/settings.json 383 | !.vscode/tasks.json 384 | !.vscode/launch.json 385 | !.vscode/extensions.json 386 | *.code-workspace 387 | 388 | # Local History for Visual Studio Code 389 | .history/ 390 | 391 | # Windows Installer files from build outputs 392 | *.cab 393 | *.msi 394 | *.msix 395 | *.msm 396 | *.msp 397 | 398 | # JetBrains Rider 399 | *.sln.iml 400 | -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v0.1.21 4 | 5 | - [f62dd7f](https://github.com/cdhunt/potel/commit/f62dd7fb2dadacc747dd1974f491db5941cad113) Fixes some parameter names 6 | 7 | ## v0.1.20 8 | 9 | - [e4092f7](https://github.com/cdhunt/potel/commit/e4092f7d5bbd891e10c4968db2ab5498d85602ff) Attempt to green the build 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # potel 2 | PowerShell module for collecting and sending Open Telemetry 3 | 4 | ## CI Status 5 | 6 | [![PowerShell](https://github.com/cdhunt/potel/actions/workflows/powershell.yml/badge.svg)](https://github.com/cdhunt/potel/actions/workflows/powershell.yml) 7 | 8 | ## Install 9 | 10 | [powershellgallery.com/packages/potel](https://www.powershellgallery.com/packages/potel) 11 | 12 | `Install-Module -Name potel` or `Install-PSResource -Name potel` 13 | 14 | ## Docs 15 | 16 | [Full Docs](docs) 17 | 18 | ### Getting Started 19 | 20 | Auto-instrument `HttpClient` calls within the current PowerShell session and send traces to [HoneyComb.io](https://honeycomb.io) and the console. 21 | 22 | ```powershell 23 | New-TracerProviderBuilder | 24 | Add-TracerSource -Name "potel" | 25 | Add-ResourceConfiguration -ServiceName $ExecutionContext.Host.Name -Attribute @{"host.name" = $(hostname)} | 26 | Add-HttpClientInstrumentation | 27 | Add-ExporterOtlpTrace -Endpoint https://api.honeycomb.io:443 -Headers @{'x-honeycomb-team'='abc123'} | 28 | Add-ExporterConsole | 29 | Start-Tracer 30 | ``` 31 | 32 | See the [sample](samples/) module for a walkthrough of how to instrument your own module. 33 | -------------------------------------------------------------------------------- /build.ps1: -------------------------------------------------------------------------------- 1 | #! /usr/bin/pwsh 2 | 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter(Position = 0)] 6 | [ValidateSet('clean', 'build', 'test', 'changelog', 'publish', 'docs')] 7 | [string[]] 8 | $Task, 9 | 10 | [Parameter(Position = 1)] 11 | [int] 12 | $Major, 13 | 14 | [Parameter(Position = 2)] 15 | [int] 16 | $Minor, 17 | 18 | [Parameter(Position = 3)] 19 | [int] 20 | $Build, 21 | 22 | [Parameter(Position = 4)] 23 | [int] 24 | $Revision, 25 | 26 | [Parameter(Position = 5)] 27 | [string] 28 | $Prerelease 29 | ) 30 | 31 | if ( (Get-Command 'nbgv' -CommandType Application -ErrorAction SilentlyContinue) ) { 32 | if (!$PSBoundParameters.ContainsKey('Major')) { $Major = $(nbgv get-version -v VersionMajor) } 33 | if (!$PSBoundParameters.ContainsKey('Minor')) { $Minor = $(nbgv get-version -v VersionMinor) } 34 | if (!$PSBoundParameters.ContainsKey('Build')) { $Build = $(nbgv get-version -v BuildNumber) } 35 | if (!$PSBoundParameters.ContainsKey('Revision')) { $Revision = $(nbgv get-version -v VersionRevision) } 36 | } 37 | 38 | $module = 'potel' 39 | $parent = $PSScriptRoot 40 | $parent = [string]::IsNullOrEmpty($parent) ? $pwd.Path : $parent 41 | $src = Join-Path $parent -ChildPath "src" 42 | $docs = Join-Path $parent -ChildPath "docs" 43 | $publish = [System.IO.Path]::Combine($parent, "publish", $module) 44 | $csproj = Join-Path -Path $src -ChildPath "dotnet" -AdditionalChildPath "potel.csproj" 45 | $bin = Join-Path -Path $src -ChildPath "dotnet" -AdditionalChildPath "bin" 46 | $obj = Join-Path -Path $src -ChildPath "dotnet" -AdditionalChildPath "obj" 47 | $lib = Join-Path -Path $publish -ChildPath "lib" 48 | $libwin64 = Join-Path -Path $lib -ChildPath "win-x64" 49 | $liblin64 = Join-Path -Path $lib -ChildPath "linux-x64" 50 | 51 | Write-Host "src: $src" 52 | Write-Host "docs: $docs" 53 | Write-Host "publish: $publish" 54 | Write-Host "lib: $lib" 55 | Write-Host "dotnet: $([Environment]::Version)" 56 | Write-Host "ps: $($PSVersionTable.PSVersion)" 57 | 58 | $manifest = @{ 59 | Path = Join-Path -Path $publish -ChildPath "$module.psd1" 60 | Author = 'Chris Hunt' 61 | CompanyName = 'Chris Hunt' 62 | Copyright = '(c) Chris Hunt. All rights reserved.' 63 | CompatiblePSEditions = "Core" 64 | Description = 'PowerShell module for collecting and sending Open Telemetry' 65 | GUID = '0be70178-3d95-45cd-b3c5-d024ba8c18c7' 66 | LicenseUri = "https://github.com/cdhunt/$module/blob/main/LICENSE" 67 | FunctionsToExport = @() 68 | ModuleVersion = [version]::new($Major, $Minor, $Build, $Revision) 69 | ProcessorArchitecture = 'Amd64' 70 | PowerShellVersion = '7.4' 71 | ProjectUri = "https://github.com/cdhunt/$module" 72 | RootModule = "$module.psm1" 73 | Tags = @('otel', 'distributed-tracing', 'metrics', 'telemetry', 'diagnostics') 74 | } 75 | 76 | function Clean { 77 | param () 78 | 79 | if (Test-Path $publish) { 80 | Remove-Item -Path $publish -Recurse -Force 81 | } 82 | } 83 | 84 | function Build { 85 | param () 86 | 87 | New-Item -Path $publish -ItemType Directory -ErrorAction SilentlyContinue | Out-Null 88 | 89 | dotnet publish $csproj --runtime win-x64 -o $libwin64 90 | dotnet publish $csproj --runtime linux-x64 -o $liblin64 91 | 92 | @($libwin64, $liblin64) | ForEach-Object { 93 | Get-ChildItem -Path $_ -filter "*.json" | Remove-Item -Force -ErrorAction SilentlyContinue 94 | Get-ChildItem -Path $_ -filter "*.pdb" | Remove-Item -Force -ErrorAction SilentlyContinue 95 | Get-ChildItem -Path $_ -filter "System.Management.Automation.dll" | Remove-Item -Force -ErrorAction SilentlyContinue 96 | Get-ChildItem -Path $_ -filter "potel.dll" | Remove-Item -Force -ErrorAction SilentlyContinue 97 | } 98 | 99 | Copy-Item -Path "$src/$module.psm1" -Destination $publish 100 | Copy-Item -Path @("$parent/LICENSE", "$parent/README.md") -Destination $publish 101 | 102 | $internalFunctions = Get-ChildItem -Path "$src/internal/*.ps1" 103 | $publicFunctions = Get-ChildItem -Path "$src/public/*.ps1" 104 | $privateFunctions = Get-ChildItem -Path "$src/private/*.ps1" -ErrorAction SilentlyContinue 105 | 106 | New-Item -Path "$publish/internal" -ItemType Directory -ErrorAction SilentlyContinue | Out-Null 107 | foreach ($function in $internalFunctions) { 108 | Copy-Item -Path $function.FullName -Destination "$publish/internal/$($function.Name)" 109 | } 110 | 111 | New-Item -Path "$publish/public" -ItemType Directory -ErrorAction SilentlyContinue | Out-Null 112 | foreach ($function in $publicFunctions) { 113 | Copy-Item -Path $function.FullName -Destination "$publish/public/$($function.Name)" 114 | '. "$PSSCriptRoot/public/{0}"' -f $function.Name | Add-Content "$publish/potel.psm1" 115 | $manifest.FunctionsToExport += $function.BaseName 116 | } 117 | 118 | New-Item -Path "$publish/private" -ItemType Directory -ErrorAction SilentlyContinue | Out-Null 119 | foreach ($function in $privateFunctions) { 120 | Copy-Item -Path $function.FullName -Destination "$publish/private/$($function.Name)" 121 | '. "$PSSCriptRoot/private/{0}"' -f $function.Name | Add-Content "$publish/potel.psm1" 122 | } 123 | 124 | if ($PSBoundParameters.ContainsKey('Prerelease')) { 125 | $manifest.Add('Prerelease', $PreRelease) 126 | } 127 | 128 | New-ModuleManifest @manifest 129 | } 130 | 131 | function Test { 132 | param () 133 | 134 | if ($null -eq (Get-Module Pester -ListAvailable | Where-Object { [version]$_.Version -ge [version]"5.5.0" })) { 135 | Install-Module -Name Pester -MinimumVersion 5.5.0 -Confirm:$false -Force 136 | } 137 | 138 | $config = New-PesterConfiguration -Hashtable @{ 139 | Run = @{ Path = "test" } 140 | TestResult = @{ 141 | Enabled = $true 142 | OutputFormat = "NUnitXml" 143 | } 144 | Output = @{ Verbosity = "Detailed" } 145 | } 146 | 147 | Invoke-Pester -Configuration $config 148 | } 149 | 150 | function ChangeLog { 151 | param () 152 | 153 | "# Changelog" 154 | 155 | # Start log at >0.1.11 156 | for ($m = $Minor; $m -ge 1; $m--) { 157 | for ($b = $Build; $b -gt 11; $b--) { 158 | "## v$Major.$m.$b" 159 | nbgv get-commits "$Major.$m.$b" | ForEach-Object { 160 | $hash, $ver, $message = $_.split(' ') 161 | $shortHash = $hash.Substring(0, 7) 162 | 163 | "- [$shortHash](https://github.com/cdhunt/potel/commit/$hash) $($message -join ' ')" 164 | } 165 | } 166 | } 167 | } 168 | 169 | function Commit { 170 | param () 171 | 172 | git rev-parse --short HEAD 173 | } 174 | 175 | function Publish { 176 | param () 177 | 178 | <# Disabled for now 179 | $docChanges = git status docs -s 180 | 181 | if ($docChanges.count -gt 0) { 182 | Write-Warning "There are pending Docs change. Run './build.ps1 docs', review and commit updated docs." 183 | } 184 | #> 185 | 186 | $repo = if ($env:PSPublishRepo) { $env:PSPublishRepo } else { 'PSGallery' } 187 | 188 | $notes = ChangeLog 189 | Publish-Module -Path $publish -Repository $repo -NuGetApiKey $env:PSPublishApiKey -ReleaseNotes $notes 190 | } 191 | 192 | function Docs { 193 | param () 194 | 195 | if ($null -eq (Get-Module Build-Docs -ListAvailable | Where-Object { [version]$_.Version -ge [version]"0.2.0.2" })) { 196 | Install-Module -Name Build-Docs -MinimumVersion 0.2.0.2 -Confirm:$false -Force 197 | } 198 | 199 | Import-Module $publish -Force 200 | 201 | $help = Get-HelpModuleData $module 202 | 203 | # docs/README.md 204 | $help | New-HelpDoc | 205 | Add-ModuleProperty Name -H1 | 206 | Add-ModuleProperty Description | 207 | Add-HelpDocText "Commands" -H2 | 208 | Add-ModuleCommand -AsLinks | 209 | Out-HelpDoc -Path 'docs/README.md' 210 | 211 | # Individual Commands 212 | foreach ($command in $help.Commands) { 213 | $name = $command.Name 214 | $doc = New-HelpDoc -HelpModuleData $help 215 | $doc.Text = $command.ToMD() 216 | $doc | Out-HelpDoc -Path "docs/$name.md" 217 | } 218 | 219 | ChangeLog | Set-Content -Path "$parent/Changelog.md" 220 | } 221 | 222 | switch ($Task) { 223 | { $_ -contains 'clean' } { 224 | Clean 225 | } 226 | { $_ -contains 'build' } { 227 | Clean 228 | Build 229 | } 230 | { $_ -contains 'test' } { 231 | Test 232 | } 233 | { $_ -contains 'changelog' } { 234 | ChangeLog 235 | } 236 | { $_ -contains 'publish' } { 237 | Docs 238 | Publish 239 | } 240 | { $_ -contains 'docs' } { 241 | Docs 242 | } 243 | Default { 244 | Clean 245 | Build 246 | } 247 | } -------------------------------------------------------------------------------- /docs/Add-ActivityEvent.md: -------------------------------------------------------------------------------- 1 | # Add-ActivityEvent 2 | 3 | Add a timestamped message to an Activity. 4 | 5 | ## Parameters 6 | 7 | ### Parameter Set 1 8 | 9 | - `[String]` **Message** _The message string for the ActivityEvent._ Mandatory 10 | - `[Activity]` **Activity** _An instance of an Activity._ Mandatory, ValueFromPipeline 11 | 12 | ## Links 13 | 14 | - [Start-Activity](Start-Activity.md) 15 | 16 | ## Notes 17 | 18 | Events are timestamped messages that can attach an arbitrary stream of additional diagnostic data to Activities. 19 | -------------------------------------------------------------------------------- /docs/Add-ActivityTag.md: -------------------------------------------------------------------------------- 1 | # Add-ActivityTag 2 | 3 | Add key-value data called Tags to an Activity. 4 | 5 | ## Parameters 6 | 7 | ### Parameter Set 1 8 | 9 | - `[Hashtable]` **Tags** _A collection of key/value pairs._ Mandatory 10 | - `[Activity]` **Activity** _An instance of an Activity._ Mandatory, ValueFromPipeline 11 | 12 | ## Links 13 | 14 | - [Start-Activity](Start-Activity.md) 15 | 16 | ## Notes 17 | 18 | Commonly used to store any parameters of the work that may be useful for diagnostics 19 | -------------------------------------------------------------------------------- /docs/Add-ExporterConsole.md: -------------------------------------------------------------------------------- 1 | # Add-ExporterConsole 2 | 3 | Adds OpenTelemetry.Exporter.Console 4 | 5 | ## Parameters 6 | 7 | ### Parameter Set 1 8 | 9 | - `[TracerProviderBuilderBase]` **TracerProvider** _Instance of TracerProviderBuilderBase._ Mandatory, ValueFromPipeline 10 | 11 | ### Parameter Set 2 12 | 13 | - `[MeterProviderBuilderBase]` **MeterBuilder** _Instance of MeterProviderBuilderBase._ Mandatory, ValueFromPipeline 14 | 15 | ## Examples 16 | 17 | ### Example 1 18 | 19 | 20 | 21 | ```powershell 22 | New-TracerProviderBuilder | Add-HttpClientInstrumentation | Add-ExporterConsole | Start-Trace 23 | ``` 24 | 25 | ## Links 26 | 27 | - [Add-HttpClientInstrumentation](Add-HttpClientInstrumentation.md) 28 | - [Start-Tracer](Start-Tracer.md) 29 | 30 | ## Outputs 31 | 32 | - `TracerProviderBuilderBase` 33 | -------------------------------------------------------------------------------- /docs/Add-ExporterOtlpTrace.md: -------------------------------------------------------------------------------- 1 | # Add-ExporterOtlpTrace 2 | 3 | Adds OpenTelemetry.Exporter.Console 4 | 5 | ## Parameters 6 | 7 | ### Parameter Set 1 8 | 9 | - `[TracerProviderBuilderBase]` **TracerProvider** _Instance of TracerProviderBuilderBase._ Mandatory, ValueFromPipeline 10 | - `[String]` **Endpoint** _OTLP endpoint address_ Mandatory 11 | - `[Hashtable]` **Headers** _Headers to send_ 12 | - `[UInt32]` **Timeout** _Send timeout in ms_ 13 | - `[String]` **Protocol** _'grpc' or 'http/protobuf'_ 14 | 15 | ### Parameter Set 2 16 | 17 | - `[MeterProviderBuilderBase]` **MeterBuilder** _Instance of MeterProviderBuilderBase._ Mandatory, ValueFromPipeline 18 | - `[String]` **Endpoint** _OTLP endpoint address_ Mandatory 19 | - `[Hashtable]` **Headers** _Headers to send_ 20 | - `[UInt32]` **Timeout** _Send timeout in ms_ 21 | - `[String]` **Protocol** _'grpc' or 'http/protobuf'_ 22 | 23 | ## Examples 24 | 25 | ### Example 1 26 | 27 | 28 | 29 | ```powershell 30 | New-TracerProviderBuilder | Add-HttpClientInstrumentation | Add-ExporterOtlpTrace -Endpoint http://localhost:9999 | Start-Trace 31 | ``` 32 | ### Example 2 33 | 34 | Configure the Otlp Exporter for Honeycomb. 35 | 36 | ```powershell 37 | Add-ExporterOtlpTrace https://api.honeycomb.io:443 -Headers @{'x-honeycomb-team'='token'} 38 | ``` 39 | ### Example 3 40 | 41 | Configure the Otlp Exporter for Dynatrace. 42 | 43 | ```powershell 44 | Add-ExporterOtlpTrace -Endpoint https://{your-environment-id}.live.dynatrace.com/api/v2/otlp -Headers @{'Authorization'='Api-Token dt.....'} -Protocol 'http/protobuf' 45 | ``` 46 | 47 | ## Links 48 | 49 | - [New-TracerProviderBuilder](New-TracerProviderBuilder.md) 50 | - [Add-HttpClientInstrumentation](Add-HttpClientInstrumentation.md) 51 | - [Start-Tracer](Start-Tracer.md) 52 | - [https://docs.honeycomb.io/getting-data-in/opentelemetry-overview/#using-the-honeycomb-opentelemetry-endpoint](https://docs.honeycomb.io/getting-data-in/opentelemetry-overview/#using-the-honeycomb-opentelemetry-endpoint) 53 | - [https://docs.dynatrace.com/docs/extend-dynatrace/opentelemetry/getting-started/otlp-export](https://docs.dynatrace.com/docs/extend-dynatrace/opentelemetry/getting-started/otlp-export) 54 | 55 | ## Outputs 56 | 57 | - `TracerProviderBuilderBase` 58 | -------------------------------------------------------------------------------- /docs/Add-HttpClientInstrumentation.md: -------------------------------------------------------------------------------- 1 | # Add-HttpClientInstrumentation 2 | 3 | Adds Http Client Instrumentation. 4 | 5 | ## Parameters 6 | 7 | ### Parameter Set 1 8 | 9 | - `[TracerProviderBuilderBase]` **TracerProvider** _Instance of TracerProviderBuilderBase._ Mandatory, ValueFromPipeline 10 | - `[ScriptBlock]` **RequestFilter** _A filter function that determines whether or not to collect telemetry on a per request basis. Must return a `[bool]` and act on an instance of `[Net.Http.HttpRequestMessage]`._ 11 | - `[Switch]` **RecordException** _Indicating whether exception will be recorded ActivityEvent or not. This instrumentation automatically sets Activity Status to Error if the Http StatusCode is >= 400. Additionally, `RecordException` feature may be turned on, to store the exception to the Activity itself as ActivityEvent._ 12 | 13 | ## Examples 14 | 15 | ### Example 1 16 | 17 | Enabled the zero-code instrumentation of System.Net.Http.HttpClient methods. 18 | 19 | ```powershell 20 | New-TracerProviderBuilder | Add-HttpClientInstrumentation 21 | ``` 22 | ### Example 2 23 | 24 | Only collect web requests with a `Method` of `Get`. 25 | 26 | ```powershell 27 | New-TracerProviderBuilder | Add-HttpClientInstrumentation { $_.Method -eq 'Get' } 28 | ``` 29 | ### Example 3 30 | 31 | Only collect web requests sent to the "google.com" domain. 32 | 33 | ```powershell 34 | New-TracerProviderBuilder | Add-HttpClientInstrumentation { $this.RequestUri -like '*google.com*' } 35 | ``` 36 | 37 | ## Links 38 | 39 | - [New-TracerProviderBuilder](New-TracerProviderBuilder.md) 40 | - [https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/main/src/OpenTelemetry.Instrumentation.Http/README.md](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/main/src/OpenTelemetry.Instrumentation.Http/README.md) 41 | - [https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httprequestmessage?view=netstandard-2.1#properties](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httprequestmessage?view=netstandard-2.1#properties) 42 | 43 | ## Outputs 44 | 45 | - `TracerProviderBuilderBase` 46 | -------------------------------------------------------------------------------- /docs/Add-ResourceConfiguration.md: -------------------------------------------------------------------------------- 1 | # Add-ResourceConfiguration 2 | 3 | Adds a Resource Configuration to a Tracer. A resource represents the entity producing telemetry as resource attributes. 4 | 5 | ## Parameters 6 | 7 | ### Parameter Set 1 8 | 9 | - `[String]` **ServiceName** _An identifier usually base off of the name of the Service or Application generating the traces._ Mandatory 10 | - `[Hashtable]` **Attribute** _A key-value pair. Used across telemetry signals - e.g. in Traces to attach data to an Activity (Span)_ Mandatory 11 | - `[TracerProviderBuilderBase]` **TracerProvider** _A TracerProviderBuilderBase object_ Mandatory, ValueFromPipeline 12 | 13 | ### Parameter Set 2 14 | 15 | - `[String]` **ServiceName** _An identifier usually base off of the name of the Service or Application generating the traces._ Mandatory 16 | - `[Hashtable]` **Attribute** _A key-value pair. Used across telemetry signals - e.g. in Traces to attach data to an Activity (Span)_ Mandatory 17 | - `[MeterProviderBuilderBase]` **MeterBuilder** _Instance of MeterProviderBuilderBase_ Mandatory, ValueFromPipeline 18 | 19 | ## Examples 20 | 21 | ### Example 1 22 | 23 | 24 | 25 | ```powershell 26 | New-TracerProviderBuilder | Add-HttpClientInstrumentation | Add-ResourceConfiguration -ServiceName $ExecutionContext.Host.Name -Attribute @{"host.name" = $(hostname)} | Add-ExporterConsole | Start-Tracer 27 | ``` 28 | 29 | ## Links 30 | 31 | - [https://opentelemetry.io/docs/instrumentation/net/resources/](https://opentelemetry.io/docs/instrumentation/net/resources/) 32 | 33 | ## Outputs 34 | 35 | - `TracerProviderBuilderBase` 36 | -------------------------------------------------------------------------------- /docs/Add-TracerSource.md: -------------------------------------------------------------------------------- 1 | # Add-TracerSource 2 | 3 | Adds and ActivitySource to a TracerProviderBuilder 4 | 5 | ## Parameters 6 | 7 | ### Parameter Set 1 8 | 9 | - `[String[]]` **Name** _Name of the Activity_ Mandatory 10 | - `[TracerProviderBuilderBase]` **TracerProviderBuilder** _A TracerProviderBuilderBase object_ Mandatory, ValueFromPipeline 11 | 12 | ### Parameter Set 2 13 | 14 | - `[ActivitySource]` **ActivitySource** _An ActivitySource object_ Mandatory 15 | - `[TracerProviderBuilderBase]` **TracerProviderBuilder** _A TracerProviderBuilderBase object_ Mandatory, ValueFromPipeline 16 | 17 | ## Examples 18 | 19 | ### Example 1 20 | 21 | Add a source by Name. 22 | 23 | ```powershell 24 | New-TracerProviderBuilder | Add-TracerSource -Name "MyActivity" 25 | ``` 26 | ### Example 2 27 | 28 | Create an Activity Soruce object. 29 | 30 | ```powershell 31 | $source = New-ActivitySource -Name "MyActivity" 32 | New-TracerProviderBuilder | Add-TracerSource -AcvititySource $source 33 | ``` 34 | 35 | ## Links 36 | 37 | - [New-TracerProviderBuilder](New-TracerProviderBuilder.md) 38 | - [New-ActivitySource](New-ActivitySource.md) 39 | - [https://opentelemetry.io/docs/instrumentation/net/manual/#setting-up-an-activitysource](https://opentelemetry.io/docs/instrumentation/net/manual/#setting-up-an-activitysource) 40 | 41 | ## Outputs 42 | 43 | - `TracerProviderBuilderBase` 44 | -------------------------------------------------------------------------------- /docs/Disable-OtelDiagnosticLog.md: -------------------------------------------------------------------------------- 1 | # Disable-OtelDiagnosticLog 2 | 3 | Remove the `OTEL_DIAGNOSTICS.json` file to disabled the internal logs generated by all OpenTelemetry components. 4 | 5 | ## Parameters 6 | 7 | 8 | ## Examples 9 | 10 | ### Example 1 11 | 12 | Disable the internal logs. 13 | 14 | ```powershell 15 | Disable-OtelDiagnosticLog 16 | ``` 17 | 18 | ## Links 19 | 20 | - [Enable-OtelDiagnosticLog](Enable-OtelDiagnosticLog.md) 21 | -------------------------------------------------------------------------------- /docs/Enable-OtelDiagnosticLog.md: -------------------------------------------------------------------------------- 1 | # Enable-OtelDiagnosticLog 2 | 3 | Create the `OTEL_DIAGNOSTICS.json` file to enable the internal logs generated by all OpenTelemetry components. 4 | 5 | ## Parameters 6 | 7 | ### Parameter Set 1 8 | 9 | - `[String]` **LogDirectory** _The directory where the output log file will be stored. It can be an absolute path or a relative path to the current directory. Default is current directory._ 10 | - `[Int32]` **FileSize** _Specifies the log file size in KiB. The log file will never exceed this configured size, and will be overwritten in a circular way. Default is `32768`._ 11 | - `[Diagnostics.Tracing.EventLevel]` **LogLevel** _The lowest level of the events to be captured. Default is `Warning`._ 12 | 13 | ## Examples 14 | 15 | ### Example 1 16 | 17 | Write an Otel Diagnostic log to C:\logs. 18 | 19 | ```powershell 20 | Enable-OtelDiagnosticLog -LogDirectory C:\logs 21 | ``` 22 | 23 | ### Example 2 24 | 25 | Includes the Error and Critical levels. 26 | 27 | ```powershell 28 | Enable-OtelDiagnosticLog -LogLevel Warning 29 | ``` 30 | 31 | ## Links 32 | 33 | - [Disable-OtelDiagnosticLog](Disable-OtelDiagnosticLog.md) 34 | - [https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry#self-diagnostics](https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry#self-diagnostics) 35 | 36 | ## Notes 37 | 38 | The self-diagnostics feature can be enabled/changed/disabled while the process is running (without restarting the process). The SDK will attempt to read the configuration file every 10 seconds in non-exclusive read-only mode. The SDK will create or overwrite a file with new logs according to the configuration. This file will not exceed the configured max size and will be overwritten in a circular way. 39 | 40 | A log file named as `ExecutableName.ProcessId.log` (e.g. pwsh.exe.12345.log) will be generated at the specified directory LogDirectory, into which logs are written to. 41 | -------------------------------------------------------------------------------- /docs/Get-OtelDiagnosticLog.md: -------------------------------------------------------------------------------- 1 | # Get-OtelDiagnosticLog 2 | 3 | Read the contents of the file ExecutableName.ProcessId.log from the path specified with Enable-OtelDiagnosticLog. 4 | 5 | ## Parameters 6 | 7 | 8 | ## Examples 9 | 10 | ### Example 1 11 | 12 | Get the internal logs. 13 | 14 | ```powershell 15 | Get-OtelDiagnosticLog 16 | ``` 17 | 18 | ## Links 19 | 20 | - [Enable-OtelDiagnosticLog](Enable-OtelDiagnosticLog.md) 21 | -------------------------------------------------------------------------------- /docs/New-ActivitySource.md: -------------------------------------------------------------------------------- 1 | # New-ActivitySource 2 | 3 | Create an instance of ActivitySource. ActivitySource provides APIs to create and start Activity objects. 4 | 5 | ## Parameters 6 | 7 | ### Parameter Set 1 8 | 9 | - `[String]` **Name** _The Source Name. The source name passed to the constructor has to be unique to avoid the conflicts with any other sources._ Mandatory 10 | - `[String]` **Version** _The version parameter is optional._ 11 | 12 | ## Links 13 | 14 | - [Start-Activity](Start-Activity.md) 15 | - [https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs#activitysource](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs#activitysource) 16 | 17 | ## Notes 18 | 19 | ActivitySource is the .Net implementation of an OpenTelemetry "Tracer" 20 | 21 | ## Outputs 22 | 23 | - `System.Diagnostics.ActivitySource` 24 | -------------------------------------------------------------------------------- /docs/New-TracerProviderBuilder.md: -------------------------------------------------------------------------------- 1 | # New-TracerProviderBuilder 2 | 3 | Creates instance of OpenTelemetry.Sdk TracerProviderBuilder 4 | 5 | ## Parameters 6 | 7 | ### Parameter Set 1 8 | 9 | - `[String]` **ActivityName** _Parameter help description_ 10 | 11 | ### Parameter Set 2 12 | 13 | - `[ActivitySource]` **ActivitySource** _Parameter help description_ 14 | 15 | ## Examples 16 | 17 | ### Example 1 18 | 19 | 20 | 21 | ```powershell 22 | New-TracerProviderBuilder 23 | ``` 24 | ### Example 2 25 | 26 | 27 | 28 | ```powershell 29 | New-TracerProviderBuilder -ActivyName "MyActivity" 30 | ``` 31 | 32 | ## Links 33 | 34 | - [https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry/Sdk.cs](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry/Sdk.cs) 35 | - [Add-TracerSource](Add-TracerSource.md) 36 | - [Start-Tracer](Start-Tracer.md) 37 | - [Stop-Tracer](Stop-Tracer.md) 38 | 39 | ## Outputs 40 | 41 | - `TracerProviderBuilder` 42 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # potel 2 | 3 | PowerShell module for collecting and sending Open Telemetry 4 | 5 | ## Commands 6 | 7 | - [Add-ActivityEvent](Add-ActivityEvent.md) _Add a timestamped message to an Activity._ 8 | - [Add-ActivityTag](Add-ActivityTag.md) _Add key-value data called Tags to an Activity._ 9 | - [Add-ExporterConsole](Add-ExporterConsole.md) _Adds a Console Exporter_ 10 | - [Add-ExporterOtlpTrace](Add-ExporterOtlpTrace.md) _Adds an OTLP Exporter_ 11 | - [Add-HttpClientInstrumentation](Add-HttpClientInstrumentation.md) _Adds Http Client Instrumentation._ 12 | - [Add-ResourceConfiguration](Add-ResourceConfiguration.md) _Adds a Resource Configuration to a Tracer_ 13 | - [Add-TracerSource](Add-TracerSource.md) _Adds and ActivitySource to a TracerProviderBuilder_ 14 | - [Disable-OtelDiagnosticLog](Disable-OtelDiagnosticLog.md) _Disable the internal logs generated by all OpenTelemetry components._ 15 | - [Enable-OtelDiagnosticLog](Enable-OtelDiagnosticLog.md) _Enable the internal logs generated by all OpenTelemetry components._ 16 | - [Get-OtelDiagnosticLog](Get-OtelDiagnosticLog.md) _Get the contents of the diagnostic log._ 17 | - [New-ActivitySource](New-ActivitySource.md) _Create an instance of ActivitySource._ 18 | - [New-TracerProviderBuilder](New-TracerProviderBuilder.md) _Creates new Tracer Provider Builder_ 19 | - [Set-ActivityStatus](Set-ActivityStatus.md) _Set the Activity Status._ 20 | - [Start-Activity](Start-Activity.md) _Start an Activity._ 21 | - [Start-Tracer](Start-Tracer.md) _Start the Tracer_ 22 | - [Stop-Tracer](Stop-Tracer.md) _Stop the Tracer_ 23 | 24 | -------------------------------------------------------------------------------- /docs/Set-ActivityStatus.md: -------------------------------------------------------------------------------- 1 | # Set-ActivityStatus 2 | 3 | OpenTelemetry allows each Activity to report a Status that represents the pass/fail result of the work. 4 | 5 | ## Parameters 6 | 7 | ### Parameter Set 1 8 | 9 | - `[Switch]` **StatusCode** _An ActivityStatusCode. The ActivityStatusCode values are represented as either, `Unset`, `Ok`, and `Error`._ Mandatory 10 | - `[String]` **Description** _Optional Description that provides a descriptive message of the Status. `Description` **MUST** only be used with the `Error` `StatusCode` value._ 11 | - `[Activity]` **Activity** _Parameter help description_ Mandatory, ValueFromPipeline 12 | 13 | ## Links 14 | 15 | - [Start-Activity](Start-Activity.md) 16 | 17 | ## Notes 18 | 19 | StatusCode is one of the following values: 20 | - Unset: The default status. 21 | - Ok: The operation has been validated by an Application developer or Operator to have completed successfully. 22 | - Error: The operation contains an error. 23 | -------------------------------------------------------------------------------- /docs/Start-Activity.md: -------------------------------------------------------------------------------- 1 | # Start-Activity 2 | 3 | Start an Activity. 4 | 5 | ## Parameters 6 | 7 | ### Parameter Set 1 8 | 9 | - `[String]` **Name** _The name of the activity._ Mandatory 10 | - `[Switch]` **Kind** _An Activity.Kind for this Activity. 11 | - Internal: Internal operation within an application, as opposed to operations with remote parents or children. This is the default value. 12 | - Server: Requests incoming from external component 13 | - Client: Outgoing request to the external component 14 | - Producer: Output provided to external components 15 | - Consumer: Output received from an external component_ 16 | - `[ActivitySource]` **ActivitySource** _An ActivitySource._ Mandatory, ValueFromPipeline 17 | 18 | ## Links 19 | 20 | - [New-ActivitySource](New-ActivitySource.md) 21 | - [https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs) 22 | 23 | ## Notes 24 | 25 | Activity is the .Net implementation of an OpenTelemetry "Span". 26 | If there are no registered listeners or there are listeners that are not interested, Start-Activity 27 | will return null and avoid creating the Activity object. This is a performance optimization so that 28 | the code pattern can still be used in functions that are called frequently. 29 | 30 | ## Outputs 31 | 32 | - `System.Diagnostics.Activity` 33 | -------------------------------------------------------------------------------- /docs/Start-Tracer.md: -------------------------------------------------------------------------------- 1 | # Start-Tracer 2 | 3 | Start the Tracer 4 | 5 | ## Parameters 6 | 7 | ### Parameter Set 1 8 | 9 | - `[TracerProviderBuilderBase]` **TracerProviderBuilder** _A TracerProviderBuilderBase object_ Mandatory, ValueFromPipeline 10 | - `[Switch]` **PassThru** _Send the build TracerProvider to the pipeline_ 11 | 12 | ## Links 13 | 14 | - [New-TracerProviderBuilder](New-TracerProviderBuilder.md) 15 | -------------------------------------------------------------------------------- /docs/Stop-Tracer.md: -------------------------------------------------------------------------------- 1 | # Stop-Tracer 2 | 3 | Stop the Tracer 4 | 5 | ## Parameters 6 | 7 | ### Parameter Set 1 8 | 9 | - `[TracerProvider]` **TracerProvider** _Parameter help description_ ValueFromPipeline 10 | -------------------------------------------------------------------------------- /docs/images/dynatrace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/potel/315564944f00842f9e844fc433dbbed26f8635d8/docs/images/dynatrace.png -------------------------------------------------------------------------------- /docs/images/honeycombtrace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/potel/315564944f00842f9e844fc433dbbed26f8635d8/docs/images/honeycombtrace.png -------------------------------------------------------------------------------- /potel.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.002.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{1866D5BC-286B-439D-93DC-5B92BFD32243}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "potel", "src\dotnet\potel.csproj", "{71D8F499-4C39-4DD2-865F-8A6CD4D27EAD}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {71D8F499-4C39-4DD2-865F-8A6CD4D27EAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {71D8F499-4C39-4DD2-865F-8A6CD4D27EAD}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {71D8F499-4C39-4DD2-865F-8A6CD4D27EAD}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {71D8F499-4C39-4DD2-865F-8A6CD4D27EAD}.Release|Any CPU.Build.0 = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(SolutionProperties) = preSolution 22 | HideSolutionNode = FALSE 23 | EndGlobalSection 24 | GlobalSection(NestedProjects) = preSolution 25 | {71D8F499-4C39-4DD2-865F-8A6CD4D27EAD} = {1866D5BC-286B-439D-93DC-5B92BFD32243} 26 | EndGlobalSection 27 | GlobalSection(ExtensibilityGlobals) = postSolution 28 | SolutionGuid = {530B74A7-8B5D-4720-BC46-A17AE89C4F6E} 29 | EndGlobalSection 30 | EndGlobal 31 | -------------------------------------------------------------------------------- /samples/README.md: -------------------------------------------------------------------------------- 1 | # Sample.psm1 2 | 3 | This ia a overly simplified sample module used to explain some of the basic functionality of **potel**. 4 | 5 | This sample assume you have a local instance of Jaeger running to receive trace data. You can start up a server with the following Docker command. 6 | 7 | ```powershell 8 | docker run --rm --name jaeger ` 9 | -p 16686:16686 ` 10 | -p 4317:4317 ` 11 | -p 4318:4318 ` 12 | -p 5778:5778 ` 13 | -p 9411:9411 ` 14 | jaegertracing/jaeger:2.1.0 15 | ``` 16 | 17 | ## Terminology 18 | 19 | Here are some terms as documented at [opentelemetry.io/docs/concepts/signals/traces](https://opentelemetry.io/docs/concepts/signals/traces/) and [opentelemetry.io/docs/languages/net/instrumentation/#a-note-on-terminology](https://opentelemetry.io/docs/languages/net/instrumentation/#a-note-on-terminology). 20 | 21 | ### Tracer 22 | 23 | A Tracer creates spans containing more information about what is happening for a given operation, such as a request in a service. Tracers are created from Tracer Providers. 24 | 25 | ### Tracer Provider 26 | 27 | A Tracer Provider is a factory for Tracers. In most applications, a Tracer Provider is initialized once and its lifecycle matches the application's lifecycle. 28 | 29 | PowerShell modules and cmdlets don't seamlessly line up with the typical Tracer lifecycle. More on that later. 30 | 31 | ### Activities (aka Spans) 32 | 33 | A span represents a unit of work or operation. Spans are the building blocks of Traces. 34 | 35 | ### Activity Events (aka Span Events) 36 | 37 | An Activity Event can be thought of as a structured log message on an Activity, typically used to denote a meaningful, singular point in time during the Activity's duration. 38 | 39 | ### Resources 40 | 41 | A Resource represents the entity producing telemetry as resource attributes. The `$env:OTEL_RESOURCE_ATTRIBUTES` environment variable can also be used to inject resources into your application. 42 | 43 | ## How it works 44 | 45 | ### Set up the Tracer 46 | 47 | The Sample module creates a Tracer in manifest using the Service Name `potel-sample`. The Service Name is the top most pieces of metadata and should not change if you want to compare traces across time. It also defines an Activity Source named `potel-sample`. The Activity Source and Service Name do not need to be the same. Along with the Service Name, we add a `host.name` Resource Attribute. You can find an Attribute Registry at [opentelemetry.io/docs/specs/semconv/attributes-registry](https://opentelemetry.io/docs/specs/semconv/attributes-registry/). 48 | 49 | We attach two Exporters - OtlpTrace and Console. All activities will be sent to both Exporters. The OtlpTrace exporter will send data to Jaeger in this instance and the Console exporter will write output to StdOut. 50 | 51 | This sample also uses the [Zero-code instrumentation](https://opentelemetry.io/docs/concepts/instrumentation/zero-code/) for `System.Net.Http.HttPClient` which will automatically create Activities when methods of `HttPClient` are invoked. In this case we pass a filter script to only collect requests made to any google.com address. 52 | 53 | The Tracer exists globally in the PowerShell session in the current version of **potel**. This brings with it some considerations. The `HttPClient` instrumentation will record every instance of `HttPClient` for any process within PowerShell. Filtering has not yet been implemented. It will also continue to generate new Activities/Spans until `Stop-Tracer` is called or the PowerShell process is stopped. 54 | 55 | ```powershell 56 | $activitySource = New-ActivitySource -Name potel-sample 57 | New-TracerProviderBuilder | 58 | Add-TracerSource -ActivitySource $activitySource | 59 | Add-ResourceConfiguration -ServiceName potel-sample -Attribute @{"host.name" = 'chunt' } | 60 | Add-HttpClientInstrumentation | 61 | Add-ExporterOtlpTrace -Endpoint http://localhost:4317 | 62 | Add-ExporterConsole | 63 | Start-Tracer 64 | ``` 65 | 66 | ### Record an Activity 67 | 68 | `Start-Activity` will create a new Activity instance from the given Activity Source. Remember that the Activity Source is what routes Activities to Tracers and the Exporters. 69 | 70 | ```powershell 71 | $activity = $activitySource | Start-Activity -Name "Get-SampleSomething" 72 | ``` 73 | 74 | If you create a new Activity while another Activity instance is still in scope you will create a nested Activity. 75 | 76 | ### Example output 77 | 78 | Here is what the data in looks like in Jaeger when you import the module `sample.psm1` and invoke `Get-SampleSomething`. 79 | 80 | ![](jaegersample.jpg) 81 | 82 | You see three nested spans: `Get-SampleSomething` calls `Get-Google` which makes an Http Get request to google.com. Within `Get-SampleSomething` you can see the two Events logged and all three spans include the resource attribute `host.name = chunt`. 83 | 84 | With HttpClientInstrumentation the Get request will include a standard `traceid` header and if that request hits a service that is also reporting Otel traces to the same Exporter you should be able to follow the Distributed Trace across multiple services. 85 | -------------------------------------------------------------------------------- /samples/jaegersample.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/potel/315564944f00842f9e844fc433dbbed26f8635d8/samples/jaegersample.jpg -------------------------------------------------------------------------------- /samples/sample.psm1: -------------------------------------------------------------------------------- 1 | # The Activity Source binds Activities (Spans) to a Tracer. 2 | $activitySource = New-ActivitySource -Name potel-sample 3 | 4 | # A Tracer provides the configuration and lifecycle of your instrumentation. 5 | # The Tracer does nothing itself, but binds inputs and outputs. 6 | New-TracerProviderBuilder | 7 | Add-TracerSource -ActivitySource $activitySource | 8 | Add-ResourceConfiguration -ServiceName potel-sample -Attribute @{"host.name" = $(hostname) } | 9 | Add-HttpClientInstrumentation { $_.RequestUri -like '*google.com*' } | 10 | Add-ExporterOtlpTrace -Endpoint http://localhost:4317 | 11 | Add-ExporterConsole | 12 | Start-Tracer 13 | 14 | # Enabled the internal Otel SDK log 15 | $diagConfig = Enable-OtelDiagnosticLog -LogLevel Warning 16 | 17 | function Get-SampleSomething { 18 | [CmdletBinding()] 19 | param ( 20 | [Parameter(Position = 0)] 21 | [int] 22 | $SecondsToWait 23 | ) 24 | 25 | # An Activity defines a unit of work and has a start and a stop. 26 | # Each Activity is equivalent to an Otel Span. 27 | $activity = $activitySource | Start-Activity -Name "Get-SampleSomething" 28 | 29 | # Activities have lots of available metadata you can use to enrich your spans. 30 | $activity | Add-ActivityTag @{'SecondsToWait' = $SecondsToWait } 31 | 32 | # Activity Events are timestamped log entries within an Activity 33 | $activity | Add-ActivityEvent -Message "About to go to sleep" 34 | 35 | Start-Sleep -Seconds $SecondsToWait 36 | 37 | $activity | Add-ActivityEvent -Message "Finished sleeping" 38 | 39 | Get-Google 40 | 41 | # You can explicitly stop an activity to capture accurate timing 42 | $activity.Stop() 43 | } 44 | 45 | function Get-Google { 46 | [CmdletBinding()] 47 | param ( 48 | 49 | ) 50 | 51 | # You can nest Activities. Since "Get-Google" Activity is started while the "Get-SampleSomething" Activity it will be a child of "Get-SampleSomething". 52 | $activity = $activitySource | Start-Activity -Name "Get-Google" 53 | 54 | # Calls to methods that are part of HttpClient class will automatically create child spans because we included Add-HttpClientInstrumentation. 55 | # https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/main/src/OpenTelemetry.Instrumentation.Http/README.md 56 | Invoke-WebRequest -Uri https://google.com | Out-Null 57 | 58 | $activity.Stop() 59 | 60 | } -------------------------------------------------------------------------------- /src/dotnet/global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "8.0.0", 4 | "rollForward": "latestFeature" 5 | } 6 | } -------------------------------------------------------------------------------- /src/dotnet/potel.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 1.0.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/internal/Add-PackageTypes.ps1: -------------------------------------------------------------------------------- 1 | function Add-PackageTypes { 2 | param( 3 | [Parameter(Mandatory = $true)] 4 | [string]$LibsDirectory 5 | ) 6 | 7 | begin { 8 | $plat = switch ([System.Environment]::OSVersion.Platform) { 9 | Win32NT { 'win'; break } 10 | Default { 'win' } 11 | } 12 | $bitness = switch ($true) { 13 | [System.Environment]::Is64BitProcess { 'x64'; break } 14 | Default { 'x64' } 15 | } 16 | 17 | $runtime = "$plat-$bitness" 18 | 19 | $target = Join-Path -Path $LibsDirectory -ChildPath $runtime 20 | } 21 | 22 | process { 23 | $files = Get-ChildItem $target | Where-Object { $_.Name -like '*.dll' -and $_.BaseName -ne "grpc_csharp_ext.x64" -and $_.BaseName -ne 'Microsoft.Bcl.AsyncInterfaces' } | Select-Object -ExpandProperty FullName 24 | foreach ($path in ($files)) { 25 | Add-Type -Path $path 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/internal/Export-HelpToMd.ps1: -------------------------------------------------------------------------------- 1 | function Export-HelpToMd { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Mandatory, Position = 0, ValueFromPipeline)] 5 | [PSCustomObject] 6 | $HelpInfo 7 | ) 8 | 9 | begin { 10 | function GetText { 11 | param ([string]$text, [string]$default) 12 | 13 | $text = $text.Trim() 14 | if ([string]::IsNullOrEmpty($text)) { 15 | if ([string]::IsNullOrEmpty($default)) { 16 | $default = 'No description' 17 | } 18 | return $default 19 | } 20 | return $text 21 | } 22 | 23 | function GetName ([PSCustomObject]$help) { 24 | $lines = @() 25 | $lines += '# {0}' -f $help.Name 26 | $lines += [System.Environment]::NewLine 27 | return $lines 28 | } 29 | 30 | function GetDescription { 31 | param ($description, [string]$noDesc) 32 | 33 | $description = $description.Description.Text | Out-String 34 | $line = '{0}' -f (GetText $description $noDesc) 35 | 36 | return $line 37 | } 38 | 39 | function GetParameterSet ([PSCustomObject]$help) { 40 | $lines = @() 41 | $setNum = 1 42 | 43 | $lines += '## Parameters' 44 | 45 | foreach ($set in $help.syntax.syntaxItem) { 46 | $lines += [System.Environment]::NewLine 47 | $lines += '### Parameter Set {0}' -f $setNum 48 | $lines += [System.Environment]::NewLine 49 | 50 | foreach ($param in $set.Parameter) { 51 | $paramStringParts = @() 52 | 53 | $paramStringParts += '- `[{0}]`' -f (GetText $param.parameterValue 'switch') 54 | 55 | $paramStringParts += '**{0}**' -f $param.Name 56 | 57 | $paramStringParts += '_{0}_. ' -f (GetDescription -description $param -noDesc 'Parameter help description') 58 | 59 | $attributes = @() 60 | if ($param.required -eq 'true') { $attributes += 'Mandatory' } 61 | if ($param.pipelineInput -like '*ByValue*') { $attributes += 'ValueFromPipeline' } 62 | 63 | $paramStringParts += $attributes -join ', ' 64 | 65 | $lines += $paramStringParts -join ' ' 66 | } 67 | 68 | $setNum++ 69 | } 70 | 71 | return $lines 72 | } 73 | 74 | function GetExample ([PSCustomObject]$help) { 75 | $lines = @() 76 | $exNum = 1 77 | 78 | $lines += [System.Environment]::NewLine 79 | $lines += '## Examples' 80 | 81 | foreach ($exampleList in $help.examples.example) { 82 | foreach ($example in $exampleList) { 83 | $lines += [System.Environment]::NewLine 84 | $lines += '### Example {0}' -f $exNum 85 | $lines += [System.Environment]::NewLine 86 | 87 | $lines += $example.remarks.Text.Where({ ![string]::IsNullOrEmpty($_) }) 88 | $lines += [System.Environment]::NewLine 89 | 90 | $lines += '```powershell' 91 | $lines += $example.code.Trim("`t") 92 | $lines += '```' 93 | 94 | } 95 | $exNum++ 96 | } 97 | 98 | return $lines 99 | } 100 | 101 | function GetLink ([PSCustomObject]$help, $Commands) { 102 | if ($help.relatedLinks.count -gt 0) { 103 | $lines = @() 104 | 105 | $lines += [System.Environment]::NewLine 106 | $lines += '## Links' 107 | $lines += [System.Environment]::NewLine 108 | 109 | foreach ($link in $help.relatedLinks) { 110 | 111 | foreach ($text in $link.navigationLink.linkText) { 112 | 113 | if ($text -match '\w{3,}-\w{3,}') { 114 | $uri = $text 115 | $lines += '- [{0}]({0}.md)' -f $uri 116 | } 117 | 118 | } 119 | foreach ($uri in $link.navigationLink.uri) { 120 | if (![string]::IsNullOrEmpty($uri)) { 121 | $lines += '- [{0}]({0})' -f $uri 122 | } 123 | } 124 | } 125 | 126 | return $lines 127 | } 128 | } 129 | } 130 | 131 | process { 132 | 133 | GetName $HelpInfo 134 | GetDescription $HelpInfo $HelpInfo.Synopsis 135 | GetParameterSet $HelpInfo 136 | GetExample $HelpInfo 137 | GetLink $HelpInfo 138 | } 139 | 140 | end { 141 | 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/potel.psm1: -------------------------------------------------------------------------------- 1 | # Load all package dlls 2 | . "$PSScriptRoot/internal/Add-PackageTypes.ps1" 3 | Add-PackageTypes -LibsDirectory "$PSScriptRoot/lib" 4 | -------------------------------------------------------------------------------- /src/public/Add-ActivityEvent.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Add a timestamped message to an Activity. 4 | .DESCRIPTION 5 | Add a timestamped message to an Activity. 6 | .PARAMETER Message 7 | The message string for the ActivityEvent. 8 | .PARAMETER Activity 9 | An instance of an Activity. 10 | .NOTES 11 | Events are timestamped messages that can attach an arbitrary stream of additional diagnostic data to Activities. 12 | .LINK 13 | Start-Activity 14 | #> 15 | function Add-ActivityEvent { 16 | [CmdletBinding()] 17 | param ( 18 | [Parameter(Mandatory, Position = 0)] 19 | [string] 20 | $Message, 21 | 22 | [Parameter(Mandatory, Position = 1, ValueFromPipeline)] 23 | [System.Diagnostics.Activity] 24 | $Activity 25 | ) 26 | 27 | if ($null -ne $Activity) { 28 | $activityEvent = [System.Diagnostics.ActivityEvent]::new($Message) 29 | $Activity.AddEvent($activityEvent) 30 | } 31 | } -------------------------------------------------------------------------------- /src/public/Add-ActivityTag.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Add key-value data called Tags to an Activity. 4 | .DESCRIPTION 5 | Add key-value data called Tags to an Activity. 6 | .PARAMETER Tags 7 | A collection of key/value pairs. 8 | .PARAMETER Activity 9 | An instance of an Activity. 10 | .NOTES 11 | Commonly used to store any parameters of the work that may be useful for diagnostics 12 | .LINK 13 | Start-Activity 14 | #> 15 | function Add-ActivityTag { 16 | [CmdletBinding()] 17 | param ( 18 | [Parameter(Mandatory, Position = 0)] 19 | [hashtable] 20 | $Tags, 21 | 22 | [Parameter(Mandatory, Position = 1, ValueFromPipeline)] 23 | [System.Diagnostics.Activity] 24 | $Activity 25 | ) 26 | 27 | if ($null -ne $Activity) { 28 | foreach ($entry in $Tags.GetEnumerator()) { 29 | $Activity.AddTag($entry.Key, $entry.Value) 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/public/Add-ExporterConsole.ps1: -------------------------------------------------------------------------------- 1 | function Add-ExporterConsole { 2 | <# 3 | .SYNOPSIS 4 | Adds a Console Exporter 5 | .DESCRIPTION 6 | Adds OpenTelemetry.Exporter.Console 7 | .PARAMETER TracerProvider 8 | Instance of TracerProviderBuilderBase. 9 | .PARAMETER MeterBuilder 10 | Instance of MeterProviderBuilderBase. 11 | .INPUTS 12 | Instance of TracerProviderBuilderBase 13 | .OUTPUTS 14 | TracerProviderBuilderBase 15 | .EXAMPLE 16 | New-TracerProviderBuilder | Add-HttpClientInstrumentation | Add-ExporterConsole | Start-Trace 17 | .LINK 18 | New-TracerBuilder 19 | .LINK 20 | Add-HttpClientInstrumentation 21 | .LINK 22 | Start-Tracer 23 | #> 24 | [CmdletBinding()] 25 | param ( 26 | # Parameter help description 27 | [Parameter(Mandatory, Position = 0, ValueFromPipeline, ParameterSetName = "Trace" )] 28 | [OpenTelemetry.Trace.TracerProviderBuilderBase] 29 | $TracerProvider, 30 | 31 | [Parameter(Mandatory, Position = 0, ValueFromPipeline, ParameterSetName = "Meter" )] 32 | [OpenTelemetry.Metrics.MeterProviderBuilderBase] 33 | $MeterBuilder 34 | ) 35 | 36 | switch ($PSBoundParameters) { 37 | { $_.ContainsKey('TracerProvider') } { [OpenTelemetry.Trace.ConsoleExporterHelperExtensions]::AddConsoleExporter($TracerProvider) } 38 | { $_.ContainsKey('MeterBuilder') } { [OpenTelemetry.Metrics.ConsoleExporterMetricsExtensions]::AddConsoleExporter($MeterBuilder) } 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /src/public/Add-ExporterOtlpTrace.ps1: -------------------------------------------------------------------------------- 1 | function Add-ExporterOtlpTrace { 2 | <# 3 | .SYNOPSIS 4 | Adds an OTLP Exporter 5 | .DESCRIPTION 6 | Adds OpenTelemetry.Exporter.Console 7 | .PARAMETER TracerProvider 8 | Instance of TracerProviderBuilderBase. 9 | .PARAMETER MeterBuilder 10 | Instance of MeterProviderBuilderBase. 11 | .PARAMETER Endpoint 12 | OTLP endpoint address 13 | .PARAMETER Headers 14 | Headers to send 15 | .PARAMETER Timeout 16 | Send timeout in ms 17 | .PARAMETER Protocol 18 | 'grpc' or 'http/protobuf' 19 | .INPUTS 20 | Instance of TracerProviderBuilderBase 21 | .OUTPUTS 22 | TracerProviderBuilderBase 23 | .EXAMPLE 24 | New-TracerProviderBuilder | Add-HttpClientInstrumentation | Add-ExporterOtlpTrace -Endpoint http://localhost:9999 | Start-Trace 25 | .EXAMPLE 26 | Add-ExporterOtlpTrace https://api.honeycomb.io:443 -Headers @{'x-honeycomb-team'='token'} 27 | 28 | Configure the Otlp Exporter for Honeycomb. 29 | .EXAMPLE 30 | Add-ExporterOtlpTrace -Endpoint https://{your-environment-id}.live.dynatrace.com/api/v2/otlp -Headers @{'Authorization'='Api-Token dt.....'} -Protocol 'http/protobuf' 31 | 32 | Configure the Otlp Exporter for Dynatrace. 33 | .LINK 34 | New-TracerProviderBuilder 35 | .LINK 36 | Add-HttpClientInstrumentation 37 | .LINK 38 | Start-Tracer 39 | .LINK 40 | https://docs.honeycomb.io/getting-data-in/opentelemetry-overview/#using-the-honeycomb-opentelemetry-endpoint 41 | .LINK 42 | https://docs.dynatrace.com/docs/extend-dynatrace/opentelemetry/getting-started/otlp-export 43 | #> 44 | [CmdletBinding()] 45 | param ( 46 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = "Trace")] 47 | [OpenTelemetry.Trace.TracerProviderBuilderBase] 48 | $TracerProvider, 49 | 50 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = "Meter" )] 51 | [OpenTelemetry.Metrics.MeterProviderBuilderBase] 52 | $MeterBuilder, 53 | 54 | [Parameter(Mandatory, Position = 0)] 55 | [string] 56 | $Endpoint, 57 | 58 | [Parameter(Position = 1)] 59 | [hashtable] 60 | $Headers, 61 | 62 | [Parameter(Position = 2)] 63 | [uint] 64 | $Timeout, 65 | 66 | [Parameter(Position = 3)] 67 | [ValidateSet('grpc', 'http/protobuf')] 68 | [string] 69 | $Protocol 70 | ) 71 | 72 | switch ($PSBoundParameters) { 73 | { $_.ContainsKey('Endpoint') } { $env:OTEL_EXPORTER_OTLP_ENDPOINT = $Endpoint } 74 | { $_.ContainsKey('Headers') } { $env:OTEL_EXPORTER_OTLP_HEADERS = $Headers.Keys.ForEach({ "$_=$($Headers[$_])" }) -join ',' } 75 | { $_.ContainsKey('Timeout') } { $env:OTEL_EXPORTER_OTLP_TIMEOUT = $Timeout } 76 | { $_.ContainsKey('Protocol') } { $env:OTEL_EXPORTER_OTLP_PROTOCOL = $Protocol } 77 | Default {} 78 | } 79 | 80 | $type = [System.AppDomain]::CurrentDomain.GetAssemblies() | Where-Object Location -like "*potel*lib*OpenTelemetry.Exporter.OpenTelemetryProtocol.dll" | Select-Object -Last 1 81 | 82 | switch ($PSBoundParameters) { 83 | { $_.ContainsKey('TracerProvider') } { 84 | $type.GetType('OpenTelemetry.Trace.OtlpTraceExporterHelperExtensions').GetMethod('AddOtlpExporter', ([System.Reflection.BindingFlags]::Public -bor [System.Reflection.BindingFlags]::Static), [OpenTelemetry.Trace.TracerProviderBuilder]).Invoke($null, @($TracerProvider)) 85 | } 86 | 87 | { $_.ContainsKey('MeterBuilder') } { 88 | $type.GetType('OpenTelemetry.Metrics.OtlpMetricExporterExtensions').GetMethod('AddOtlpExporter', ([System.Reflection.BindingFlags]::Public -bor [System.Reflection.BindingFlags]::Static), [OpenTelemetry.Metrics.MeterProviderBuilder]).Invoke($null, @($MeterBuilder)) 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /src/public/Add-HttpClientInstrumentation.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Adds Http Client Instrumentation. 4 | .DESCRIPTION 5 | Adds Http Client Instrumentation. 6 | .PARAMETER TracerProvider 7 | Instance of TracerProviderBuilderBase. 8 | .PARAMETER RequestFilter 9 | A filter function that determines whether or not to collect telemetry on a per request basis. Must return a `[bool]` and act on an instance of `[Net.Http.HttpRequestMessage]`. 10 | .PARAMETER RecordException 11 | Indicating whether exception will be recorded ActivityEvent or not. This instrumentation automatically sets Activity Status to Error if the Http StatusCode is >= 400. Additionally, `RecordException` feature may be turned on, to store the exception to the Activity itself as ActivityEvent. 12 | .INPUTS 13 | Instance of TracerProviderBuilderBase 14 | .OUTPUTS 15 | TracerProviderBuilderBase 16 | .EXAMPLE 17 | New-TracerProviderBuilder | Add-HttpClientInstrumentation 18 | 19 | Enabled the zero-code instrumentation of System.Net.Http.HttpClient methods. 20 | .EXAMPLE 21 | New-TracerProviderBuilder | Add-HttpClientInstrumentation { $_.Method -eq 'Get' } 22 | 23 | Only collect web requests with a `Method` of `Get`. 24 | .EXAMPLE 25 | New-TracerProviderBuilder | Add-HttpClientInstrumentation { $this.RequestUri -like '*google.com*' } 26 | 27 | Only collect web requests sent to the "google.com" domain. 28 | .LINK 29 | New-TracerProviderBuilder 30 | .LINK 31 | https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/main/src/OpenTelemetry.Instrumentation.Http/README.md 32 | .LINK 33 | https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httprequestmessage?view=netstandard-2.1#properties 34 | #> 35 | function Add-HttpClientInstrumentation { 36 | [CmdletBinding()] 37 | param ( 38 | [Parameter(Mandatory, Position = 1, ValueFromPipeline)] 39 | [OpenTelemetry.Trace.TracerProviderBuilderBase] 40 | $TracerProvider, 41 | 42 | [Parameter(Position = 0)] 43 | [scriptblock] 44 | $RequestFilter = { $true }, 45 | 46 | [Parameter()] 47 | [switch] 48 | $RecordException 49 | ) 50 | 51 | $options = { 52 | param([OpenTelemetry.Instrumentation.Http.HttpClientTraceInstrumentationOptions]$o) 53 | 54 | $o.FilterHttpRequestMessage = { param([Net.Http.HttpRequestMessage]$request) 55 | $context = [system.Collections.Generic.List[PSVariable]]::new() 56 | $context.Add([PSVariable]::new('_', $request)) 57 | $context.Add([PSVariable]::new('this', $request)) 58 | $context.Add([PSVariable]::new('PSItem', $request)) 59 | $RequestFilter.InvokeWithContext($null, $context) 60 | } 61 | 62 | $o.RecordException = $RecordException 63 | 64 | }.GetNewClosure() 65 | 66 | [OpenTelemetry.Trace.HttpClientInstrumentationTracerProviderBuilderExtensions]::AddHttpClientInstrumentation($TracerProvider, $null, $options) 67 | 68 | } -------------------------------------------------------------------------------- /src/public/Add-ResourceConfiguration.ps1: -------------------------------------------------------------------------------- 1 | function Add-ResourceConfiguration { 2 | <# 3 | .SYNOPSIS 4 | Adds a Resource Configuration to a Tracer 5 | .DESCRIPTION 6 | Adds a Resource Configuration to a Tracer. A resource represents the entity producing telemetry as resource attributes. 7 | .PARAMETER ServiceName 8 | An identifier usually base off of the name of the Service or Application generating the traces. 9 | .PARAMETER Attribute 10 | A key-value pair. Used across telemetry signals - e.g. in Traces to attach data to an Activity (Span) 11 | .PARAMETER TracerProvider 12 | A TracerProviderBuilderBase object 13 | .PARAMETER MeterBuilder 14 | Instance of MeterProviderBuilderBase 15 | .INPUTS 16 | Instance of TracerProviderBuilderBase 17 | .OUTPUTS 18 | TracerProviderBuilderBase 19 | .EXAMPLE 20 | New-TracerProviderBuilder | Add-HttpClientInstrumentation | Add-ResourceConfiguration -ServiceName $ExecutionContext.Host.Name -Attribute @{"host.name" = $(hostname)} | Add-ExporterConsole | Start-Tracer 21 | .LINK 22 | https://opentelemetry.io/docs/instrumentation/net/resources/ 23 | #> 24 | [CmdletBinding()] 25 | param ( 26 | [Parameter(Mandatory, Position = 0)] 27 | [string] 28 | $ServiceName, 29 | 30 | [Parameter(Mandatory, Position = 1)] 31 | [hashtable] 32 | $Attribute, 33 | 34 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = "Trace")] 35 | [OpenTelemetry.Trace.TracerProviderBuilderBase] 36 | $TracerProvider, 37 | 38 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = "Meter" )] 39 | [OpenTelemetry.Metrics.MeterProviderBuilderBase] 40 | $MeterBuilder 41 | ) 42 | 43 | $listOfAttributes = [Collections.Generic.List[Collections.Generic.KeyValuePair[string, object]]]::new() 44 | 45 | Foreach ($key in $Attribute.Keys) { 46 | 47 | $listOfAttributes.Add([Collections.Generic.KeyValuePair[string, object]]::new($key, $Attribute[$key])) 48 | } 49 | 50 | $action = [Action[OpenTelemetry.Resources.ResourceBuilder]] { 51 | param([OpenTelemetry.Resources.ResourceBuilder]$resource) 52 | $resource = [OpenTelemetry.Resources.ResourceBuilderExtensions]::AddService($resource, $ServiceName) 53 | $resource = [OpenTelemetry.Resources.ResourceBuilderExtensions]::AddAttributes($resource, $listOfAttributes) 54 | }.GetNewClosure() 55 | 56 | switch ($PSBoundParameters) { 57 | { $_.ContainsKey('TracerProvider') } { [OpenTelemetry.Trace.TracerProviderBuilderExtensions]::ConfigureResource($TracerProvider, $action) } 58 | { $_.ContainsKey('MeterBuilder') } { [OpenTelemetry.Metrics.MeterProviderBuilderExtensions]::ConfigureResource($MeterBuilder, $action) } 59 | Default { Write-Warning "No parameter set" } 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /src/public/Add-TracerSource.ps1: -------------------------------------------------------------------------------- 1 | function Add-TracerSource { 2 | <# 3 | .SYNOPSIS 4 | Adds and ActivitySource to a TracerProviderBuilder 5 | .DESCRIPTION 6 | Adds and ActivitySource to a TracerProviderBuilder 7 | .PARAMETER Name 8 | Name of the Activity 9 | .PARAMETER ActivitySource 10 | An ActivitySource object 11 | .PARAMETER TracerProviderBuilder 12 | A TracerProviderBuilderBase object 13 | .INPUTS 14 | Instance of TracerProviderBuilderBase 15 | .OUTPUTS 16 | TracerProviderBuilderBase 17 | .EXAMPLE 18 | New-TracerProviderBuilder | Add-TracerSource -Name "MyActivity" 19 | 20 | Add a source by Name. 21 | .EXAMPLE 22 | $source = New-ActivitySource -Name "MyActivity" 23 | New-TracerProviderBuilder | Add-TracerSource -AcvititySource $source 24 | 25 | Create an Activity Soruce object. 26 | .LINK 27 | New-TracerProviderBuilder 28 | .LINK 29 | New-ActivitySource 30 | .LINK 31 | https://opentelemetry.io/docs/instrumentation/net/manual/#setting-up-an-activitysource 32 | #> 33 | [CmdletBinding(DefaultParameterSetName = "byString")] 34 | param ( 35 | [Parameter(Mandatory, Position = 0, ParameterSetName = "byString")] 36 | [string[]] 37 | $Name, 38 | 39 | [Parameter(Mandatory, Position = 0, ParameterSetName = "byActivity")] 40 | [System.Diagnostics.ActivitySource] 41 | $ActivitySource, 42 | 43 | [Parameter(Mandatory, Position = 1, ValueFromPipeline)] 44 | [OpenTelemetry.Trace.TracerProviderBuilderBase] 45 | $TracerProviderBuilder 46 | ) 47 | 48 | if ($PSBoundParameters.ContainsKey('ActivitySource')) { 49 | $Name = $ActivitySource.Name 50 | } 51 | 52 | $TracerProviderBuilder.AddSource($Name) 53 | } -------------------------------------------------------------------------------- /src/public/Disable-OtelDiagnosticLog.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Disable the internal logs generated by all OpenTelemetry components. 4 | .DESCRIPTION 5 | Remove the `OTEL_DIAGNOSTICS.json` file to disabled the internal logs generated by all OpenTelemetry components. 6 | .PARAMETER RemoveLog 7 | 8 | .LINK 9 | Enable-OtelDiagnosticLog 10 | .EXAMPLE 11 | Disable-OtelDiagnosticLog 12 | 13 | Disable the internal logs. 14 | #> 15 | function Disable-OtelDiagnosticLog { 16 | [CmdletBinding()] 17 | param ( 18 | [Parameter()] 19 | [switch] 20 | $RemoveLog 21 | ) 22 | 23 | $name = 'OTEL_DIAGNOSTICS.json' 24 | $path = Join-Path -Path ([System.IO.Directory]::GetCurrentDirectory()) -ChildPath $name 25 | 26 | Remove-Item -Path $path 27 | 28 | if ($RemoveLog) { 29 | Write-Information "Sleeping for 10 seconds to allow SDK to reconfigure diagnostics." 30 | Start-Sleep -Seconds 10 31 | Get-OtelDiagnosticLog | Remove-Item 32 | } 33 | } -------------------------------------------------------------------------------- /src/public/Enable-OtelDiagnosticLog.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Enable the internal logs generated by all OpenTelemetry components. 4 | .DESCRIPTION 5 | Create the `OTEL_DIAGNOSTICS.json` file to enable the internal logs generated by all OpenTelemetry components. 6 | .PARAMETER LogDirectory 7 | The directory where the output log file will be stored. It can be an absolute path or a relative path to the current directory. Default is current directory. 8 | .PARAMETER FileSize 9 | Specifies the log file size in KiB. The log file will never exceed this configured size, and will be overwritten in a circular way. Default is `32768`. 10 | .PARAMETER LogLevel 11 | The lowest level of the events to be captured. Default is `Warning`. 12 | .NOTES 13 | The self-diagnostics feature can be enabled/changed/disabled while the process is running (without restarting the process). The SDK will attempt to read the configuration file every 10 seconds in non-exclusive read-only mode. The SDK will create or overwrite a file with new logs according to the configuration. This file will not exceed the configured max size and will be overwritten in a circular way. 14 | 15 | A log file named as `ExecutableName.ProcessId.log` (e.g. pwsh.exe.12345.log) will be generated at the specified directory LogDirectory, into which logs are written to. 16 | .LINK 17 | Get-OtelDiagnosticLog 18 | .LINK 19 | Disable-OtelDiagnosticLog 20 | .LINK 21 | https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry#self-diagnostics 22 | .EXAMPLE 23 | Enable-OtelDiagnosticLog -LogDirectory C:\logs 24 | 25 | Write an Otel Diagnostic log to C:\logs. 26 | .EXAMPLE 27 | Enable-OtelDiagnosticLog -LogLevel Warning 28 | 29 | Includes the Error and Critical levels. 30 | #> 31 | function Enable-OtelDiagnosticLog { 32 | [CmdletBinding()] 33 | param ( 34 | [Parameter(Position = 0)] 35 | [Alias("Path", "PSPath")] 36 | [ValidateNotNullOrEmpty()] 37 | [string] 38 | $LogDirectory = '.', 39 | 40 | [Parameter(Position = 1)] 41 | [ValidateRange(1024, 131072)] 42 | [int] 43 | $FileSize = 32768, 44 | 45 | [Parameter(Position = 2)] 46 | [System.Diagnostics.Tracing.EventLevel] 47 | $LogLevel = 'Warning' 48 | ) 49 | 50 | $name = 'OTEL_DIAGNOSTICS.json' 51 | $settings = [pscustomobject]@{ 52 | LogDirectory = $LogDirectory 53 | FileSize = $FileSize 54 | LogLevel = $LogLevel.ToString() 55 | } 56 | $content = $settings | ConvertTo-Json 57 | $path = Join-Path -Path ([System.IO.Directory]::GetCurrentDirectory()) -ChildPath $name 58 | 59 | $content | Set-Content -Path $path 60 | 61 | Get-Item $path 62 | 63 | } -------------------------------------------------------------------------------- /src/public/Get-OtelDiagnosticLog.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Get the contents of the diagnostic log. 4 | .DESCRIPTION 5 | Read the contents of the file ExecutableName.ProcessId.log from the path specified with Enable-OtelDiagnosticLog. 6 | .LINK 7 | Enable-OtelDiagnosticLog 8 | .EXAMPLE 9 | Get-OtelDiagnosticLog 10 | Directory: C:\Users\user 11 | Mode LastWriteTime Length Name 12 | ---- ------------- ------ ---- 13 | -a--- 12/23/2024 12:02 PM 33554432 pwsh.exe.131616.log 14 | 15 | Get the internal logs. 16 | #> 17 | function Get-OtelDiagnosticLog { 18 | [CmdletBinding()] 19 | param () 20 | 21 | $configName = 'OTEL_DIAGNOSTICS.json' 22 | $configPath = Join-Path -Path ([System.IO.Directory]::GetCurrentDirectory()) -ChildPath $configName 23 | 24 | if (Test-Path -Path $configPath) { 25 | $config = Get-Content -Path $configPath 26 | $settings = $config | ConvertFrom-Json 27 | 28 | $executableName = Get-Process -Id $PID | Select-Object -ExpandProperty ProcessName 29 | $logName = '{0}.exe.{1}.log' -f $executableName, $PID 30 | 31 | if ([IO.Path]::IsPathFullyQualified($settings.LogDirectory)) { 32 | $logPath = Join-Path -Path $settings.LogDirectory -ChildPath $logName 33 | } else { 34 | $logPath = Join-Path -Path ([System.IO.Directory]::GetCurrentDirectory()) -ChildPath $settings.LogDirectory -AdditionalChildPath $logName 35 | } 36 | 37 | Get-Item -Path $logPath 38 | } 39 | } -------------------------------------------------------------------------------- /src/public/New-ActivitySource.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Create an instance of ActivitySource. 4 | .DESCRIPTION 5 | Create an instance of ActivitySource. ActivitySource provides APIs to create and start Activity objects. 6 | .PARAMETER Name 7 | The Source Name. The source name passed to the constructor has to be unique to avoid the conflicts with any other sources. 8 | .PARAMETER Version 9 | The version parameter is optional. 10 | .LINK 11 | Start-Activity 12 | .LINK 13 | https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs#activitysource 14 | .NOTES 15 | ActivitySource is the .Net implementation of an OpenTelemetry "Tracer" 16 | #> 17 | function New-ActivitySource { 18 | [CmdletBinding()] 19 | [OutputType('System.Diagnostics.ActivitySource')] 20 | param ( 21 | [Parameter(Mandatory, Position = 0)] 22 | [string] 23 | $Name, 24 | 25 | [Parameter(Position = 1)] 26 | [string] 27 | $Version = [string]::Empty 28 | ) 29 | 30 | [System.Diagnostics.ActivitySource]::new($Name, $Version) 31 | } -------------------------------------------------------------------------------- /src/public/New-TracerProviderBuilder.ps1: -------------------------------------------------------------------------------- 1 | function New-TracerProviderBuilder { 2 | <# 3 | .SYNOPSIS 4 | Creates new Tracer Provider Builder 5 | .DESCRIPTION 6 | Creates instance of OpenTelemetry.Sdk TracerProviderBuilder 7 | .INPUTS 8 | None. You cannot pipe objects to New-TracerBuilder 9 | .OUTPUTS 10 | TracerProviderBuilder 11 | .EXAMPLE 12 | New-TracerProviderBuilder 13 | .EXAMPLE 14 | New-TracerProviderBuilder -ActivyName "MyActivity" 15 | .LINK 16 | https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry/Sdk.cs 17 | .LINK 18 | Add-TracerSource 19 | .LINK 20 | Start-Tracer 21 | .LINK 22 | Stop-Tracer 23 | #> 24 | [CmdletBinding(DefaultParameterSetName = "byString")] 25 | param ( 26 | [Parameter(Position = 0, ParameterSetName = "byString")] 27 | [string] 28 | $ActivityName, 29 | 30 | [Parameter(Position = 0, ParameterSetName = "byActivity")] 31 | [System.Diagnostics.ActivitySource] 32 | $ActivitySource 33 | ) 34 | 35 | 36 | if ($PSBoundParameters.ContainsKey('ActivityName')) { 37 | $ActivitySource = New-ActivitySource -Name $ActivityName 38 | } 39 | 40 | if ($null -ne $ActivitySource) { 41 | [OpenTelemetry.Sdk]::CreateTracerProviderBuilder() | Add-TracerSource -ActivitySource $ActivitySource 42 | } 43 | else { 44 | [OpenTelemetry.Sdk]::CreateTracerProviderBuilder() 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /src/public/Set-ActivityStatus.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Set the Activity Status. 4 | .DESCRIPTION 5 | OpenTelemetry allows each Activity to report a Status that represents the pass/fail result of the work. 6 | .PARAMETER StatusCode 7 | An ActivityStatusCode. The ActivityStatusCode values are represented as either, `Unset`, `Ok`, and `Error`. 8 | .PARAMETER Description 9 | Optional Description that provides a descriptive message of the Status. `Description` **MUST** only be used with the `Error` `StatusCode` value. 10 | .NOTES 11 | StatusCode is one of the following values: 12 | - Unset: The default status. 13 | - Ok: The operation has been validated by an Application developer or Operator to have completed successfully. 14 | - Error: The operation contains an error. 15 | .LINK 16 | Start-Activity 17 | #> 18 | function Set-ActivityStatus { 19 | [CmdletBinding()] 20 | param ( 21 | # Parameter help description 22 | [Parameter(Mandatory, Position = 0)] 23 | [System.Diagnostics.ActivityStatusCode] 24 | $StatusCode, 25 | 26 | [Parameter(Position = 1)] 27 | [string] 28 | $Description, 29 | 30 | [Parameter(Mandatory, Position = 2, ValueFromPipeline)] 31 | [System.Diagnostics.Activity] 32 | $Activity 33 | ) 34 | 35 | if ($PSBoundParameters.ContainsKey('Description') -and $StatusCode -ne [System.Diagnostics.ActivityStatusCode]::Error ) { 36 | $Description = $null 37 | Write-Warning "Description MUST only be used with the Error StatusCode value." 38 | } 39 | 40 | if ($null -ne $Activity) { 41 | $Activity.SetStatus($StatusCode, $Description) 42 | } 43 | } -------------------------------------------------------------------------------- /src/public/Start-Activity.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Start an Activity. 4 | .PARAMETER Name 5 | The name of the activity. 6 | .PARAMETER Kind 7 | An Activity.Kind for this Activity. 8 | - Internal: Internal operation within an application, as opposed to operations with remote parents or children. This is the default value. 9 | - Server: Requests incoming from external component 10 | - Client: Outgoing request to the external component 11 | - Producer: Output provided to external components 12 | - Consumer: Output received from an external component 13 | .PARAMETER ActivitySource 14 | An ActivitySource. 15 | .LINK 16 | New-ActivitySource 17 | .LINK 18 | https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs 19 | .NOTES 20 | Activity is the .Net implementation of an OpenTelemetry "Span". 21 | If there are no registered listeners or there are listeners that are not interested, Start-Activity 22 | will return null and avoid creating the Activity object. This is a performance optimization so that 23 | the code pattern can still be used in functions that are called frequently. 24 | #> 25 | function Start-Activity { 26 | [CmdletBinding()] 27 | [OutputType('System.Diagnostics.Activity')] 28 | param ( 29 | [Parameter(Mandatory, Position = 0)] 30 | [string] 31 | $Name, 32 | 33 | [Parameter(Position = 1)] 34 | [System.Diagnostics.ActivityKind] 35 | $Kind = [System.Diagnostics.ActivityKind]::Internal, 36 | 37 | [Parameter(Mandatory, Position = 2, ValueFromPipeline)] 38 | [System.Diagnostics.ActivitySource] 39 | $ActivitySource 40 | ) 41 | 42 | $ActivitySource.StartActivity($Name, $Kind) 43 | } -------------------------------------------------------------------------------- /src/public/Start-Tracer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Start the Tracer 4 | .PARAMETER TracerProviderBuilder 5 | A TracerProviderBuilderBase object 6 | .PARAMETER PassThru 7 | Send the build TracerProvider to the pipeline 8 | .LINK 9 | New-TracerProviderBuilder 10 | #> 11 | function Start-Tracer { 12 | [CmdletBinding()] 13 | param ( 14 | [Parameter(Mandatory, Position = 0, ValueFromPipeline)] 15 | [OpenTelemetry.Trace.TracerProviderBuilderBase] 16 | $TracerProviderBuilder, 17 | 18 | [Parameter()] 19 | [switch]$PassThru 20 | ) 21 | 22 | $global:potel_provider = [OpenTelemetry.Trace.TracerProviderBuilderExtensions]::Build($TracerProviderBuilder) 23 | 24 | if ($PassThru) { 25 | Write-Output $potel_provider 26 | } 27 | } -------------------------------------------------------------------------------- /src/public/Stop-Tracer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Stop the Tracer 4 | #> 5 | function Stop-Tracer { 6 | [CmdletBinding()] 7 | param ( 8 | [Parameter(Position = 0, ValueFromPipeline)] 9 | [OpenTelemetry.Trace.TracerProvider] 10 | $TracerProvider = $global:potel_provider 11 | 12 | ) 13 | 14 | $result = [OpenTelemetry.Trace.TracerProviderExtensions]::Shutdown($TracerProvider) # For exporter 15 | $TracerProvider.Dispose() # For Instrumentation 16 | 17 | if (!$result) { 18 | Write-Warning "Tracer Shutdown operation did not return True" 19 | } 20 | } -------------------------------------------------------------------------------- /test/Tracer.Tests.ps1: -------------------------------------------------------------------------------- 1 | BeforeAll { 2 | Import-Module $PSScriptRoot/../publish/potel/potel.psd1 -Force 3 | } 4 | 5 | Describe 'New-TracePRoviderBuilder' { 6 | Context 'No Parameters' { 7 | It 'Returns a new TracerProviderBuilder' -Tag @('unit', 'trace') { 8 | $result = New-TracerProviderBuilder 9 | $result.GetType().FullName | Should -Be 'OpenTelemetry.Trace.TracerProviderBuilderBase' 10 | } 11 | } 12 | Context 'ActivityName Parameter' { 13 | BeforeAll { 14 | Mock -ModuleName potel Add-TracerSource { return [OpenTelemetry.Sdk]::CreateTracerProviderBuilder().AddSource("TestSource") } 15 | Mock -ModuleName potel New-ActivitySource { return [System.Diagnostics.ActivitySource]::new("TestSource") } 16 | } 17 | 18 | It 'Returns a new TracerProviderBuilder' -Tag @('unit', 'trace') { 19 | $result = New-TracerProviderBuilder -ActivityName "TestSource" 20 | $result.GetType().FullName | Should -Be 'OpenTelemetry.Trace.TracerProviderBuilderBase' 21 | Should -Invoke New-ActivitySource -ModuleName potel -Times 1 -ParameterFilter { 22 | $Name -eq "TestSource" 23 | } 24 | Should -Invoke Add-TracerSource -ModuleName potel -Times 1 -ParameterFilter { 25 | $null -eq $Name 26 | $null -ne $ActivitySource 27 | } 28 | } 29 | } 30 | 31 | Context 'ActivitySource Prarameter' { 32 | BeforeAll { 33 | Mock -ModuleName potel Add-TracerSource { return [OpenTelemetry.Sdk]::CreateTracerProviderBuilder().AddSource("TestSource") } 34 | Mock -ModuleName potel New-ActivitySource { return [System.Diagnostics.ActivitySource]::new("TestSource") } 35 | } 36 | 37 | It 'Returns a new TracerProviderBuilder' -Tag @('unit', 'trace') { 38 | $result = New-TracerProviderBuilder -ActivitySource ([System.Diagnostics.ActivitySource]::new("TestSource")) 39 | $result.GetType().FullName | Should -Be 'OpenTelemetry.Trace.TracerProviderBuilderBase' 40 | Should -Invoke New-ActivitySource -ModuleName potel -Times 0 41 | Should -Invoke Add-TracerSource -ModuleName potel -Times 1 -ParameterFilter { 42 | $null -eq $Name 43 | $null -ne $ActivitySource 44 | } 45 | } 46 | } 47 | } 48 | 49 | Describe 'New-ActivitySource' { 50 | It 'Returns a new System.Diagnostics.ActivitySource' -Tag @('unit', 'trace') { 51 | $result = New-ActivitySource -Name 'TestSource' 52 | $result.GetType().FullName | Should -be 'System.Diagnostics.ActivitySource' 53 | $result.Name | Should -Be 'TestSource' 54 | } 55 | } 56 | 57 | Describe 'Add-TracerSource' { 58 | Context 'Name Parameter' { 59 | It 'Should accept a string name' -Tag @('unit', 'trace') { 60 | { New-TracerProviderBuilder | Add-TracerSource -Name "MyActivity" } | Should -Not -Throw 61 | } 62 | } 63 | 64 | Context 'ActivitySource Prarameter' { 65 | It 'Should accept a Diagnostics.ActivitySource' -Tag @('unit', 'trace') { 66 | { $source = New-ActivitySource -Name "MyActivity" 67 | New-TracerProviderBuilder | Add-TracerSource -ActivitySource $source } | Should -Not -Throw 68 | } 69 | } 70 | } 71 | 72 | Describe 'Add-HttpClientInstrumentation' { 73 | It 'Should find type OpenTelemetry.Instrumentation.Http' -Tag @('unit', 'trace') { 74 | { New-TracerProviderBuilder -ActivityName "TestSource" | Add-HttpClientInstrumentation } | Should -Not -Throw 75 | } 76 | } 77 | 78 | Describe 'Add-ExporterOtlpTrace' { 79 | BeforeEach { 80 | Remove-Item env:\OTEL_EXPORTER_OTLP_ENDPOINT -ErrorAction SilentlyContinue 81 | Remove-Item env:\OTEL_EXPORTER_OTLP_HEADERS -ErrorAction SilentlyContinue 82 | Remove-Item env:\OTEL_EXPORTER_OTLP_TIMEOUT -ErrorAction SilentlyContinue 83 | Remove-Item env:\OTEL_EXPORTER_OTLP_PROTOCOL -ErrorAction SilentlyContinue 84 | } 85 | 86 | It 'Should work with TracerProviderBuilder' -Tag @('unit', 'trace') { 87 | $result = [OpenTelemetry.Sdk]::CreateTracerProviderBuilder() | Add-ExporterOtlpTrace -Endpoint http://tracer/ 88 | $result.GetType().FullName | Should -be 'OpenTelemetry.Trace.TracerProviderBuilderBase' 89 | $env:OTEL_EXPORTER_OTLP_ENDPOINT | Should -Be 'http://tracer/' 90 | } 91 | 92 | It 'Should work with MeterProviderBuilder' -Tag @('unit', 'metric') { 93 | $result = [OpenTelemetry.Sdk]::CreateMeterProviderBuilder() | Add-ExporterOtlpTrace -Endpoint http://meter/ 94 | $result.GetType().FullName | Should -be 'OpenTelemetry.Metrics.MeterProviderBuilderBase' 95 | $env:OTEL_EXPORTER_OTLP_ENDPOINT | Should -Be 'http://meter/' 96 | } 97 | 98 | It 'Should set $env:OTEL_EXPORTER_OTLP_HEADERS with Headers parameter' -Tag @('unit', 'trace') { 99 | $null = [OpenTelemetry.Sdk]::CreateTracerProviderBuilder() | Add-ExporterOtlpTrace -Endpoint http://tracer/ -Headers @{"header1" = "value1"; "header2" = "value2" } 100 | $env:OTEL_EXPORTER_OTLP_HEADERS | Should -BeLikeExactly "*header1=value1*" 101 | $env:OTEL_EXPORTER_OTLP_HEADERS | Should -BeLikeExactly "*header2=value2*" 102 | $env:OTEL_EXPORTER_OTLP_HEADERS | Should -BeLikeExactly "header?=value?,header?=value?" 103 | } 104 | 105 | It 'Should set $env:OTEL_EXPORTER_OTLP_TIMEOUT with Timeout parameter' -Tag @('unit', 'trace') { 106 | $null = [OpenTelemetry.Sdk]::CreateTracerProviderBuilder() | Add-ExporterOtlpTrace -Endpoint http://tracer/ -Timeout 100 107 | $env:OTEL_EXPORTER_OTLP_TIMEOUT | Should -Be 100 108 | } 109 | 110 | It 'Should set throw with a negative Timeout parameter' -Tag @('unit', 'trace') { 111 | { $null = [OpenTelemetry.Sdk]::CreateTracerProviderBuilder() | Add-ExporterOtlpTrace -Endpoint http://tracer/ -Timeout -1 } | Should -Throw 112 | $env:OTEL_EXPORTER_OTLP_TIMEOUT | Should -BeNullOrEmpty 113 | } 114 | 115 | It 'Should set $env:OTEL_EXPORTER_OTLP_PROTOCOL with Protocol parameter (grpc)' -Tag @('unit', 'trace') { 116 | $null = [OpenTelemetry.Sdk]::CreateTracerProviderBuilder() | Add-ExporterOtlpTrace -Endpoint http://tracer/ -Protocol grpc 117 | $env:OTEL_EXPORTER_OTLP_PROTOCOL | Should -Be 'grpc' 118 | } 119 | 120 | It 'Should set $env:OTEL_EXPORTER_OTLP_PROTOCOL with Protocol parameter (http/protobuf)' -Tag @('unit', 'trace') { 121 | $null = [OpenTelemetry.Sdk]::CreateTracerProviderBuilder() | Add-ExporterOtlpTrace -Endpoint http://tracer/ -Protocol 'http/protobuf' 122 | $env:OTEL_EXPORTER_OTLP_PROTOCOL | Should -Be 'http/protobuf' 123 | } 124 | 125 | It 'Should set throw with a bad Protocol parameter' -Tag @('unit', 'trace') { 126 | { $null = [OpenTelemetry.Sdk]::CreateTracerProviderBuilder() | Add-ExporterOtlpTrace -Endpoint http://tracer/ -Protocol 'magic' } | Should -Throw 127 | $env:OTEL_EXPORTER_OTLP_PROTOCOL | Should -BeNullOrEmpty 128 | } 129 | 130 | Describe 'Add-ExporterConsole' { 131 | 132 | It 'Should work with TracerProviderBuilder' -Tag @('unit', 'trace') { 133 | $result = [OpenTelemetry.Sdk]::CreateTracerProviderBuilder() | Add-ExporterConsole 134 | $result.GetType().FullName | Should -be 'OpenTelemetry.Trace.TracerProviderBuilderBase' 135 | } 136 | 137 | It 'Should work with MeterProviderBuilder' -Tag @('unit', 'metric') { 138 | $result = [OpenTelemetry.Sdk]::CreateMeterProviderBuilder() | Add-ExporterConsole 139 | $result.GetType().FullName | Should -be 'OpenTelemetry.Metrics.MeterProviderBuilderBase' 140 | } 141 | } 142 | } 143 | 144 | Describe 'Enable-OtelDiagnosticLog' { 145 | Context 'Create new config file with' { 146 | BeforeAll { 147 | Push-Location TestDrive:/ 148 | $cwd = Get-PSDrive -Name TestDrive | Select-Object -ExpandProperty Root 149 | [System.IO.Directory]::SetCurrentDirectory($cwd) 150 | } 151 | AfterAll { 152 | Pop-Location 153 | [System.IO.Directory]::SetCurrentDirectory($PWD.Path) 154 | } 155 | 156 | It 'Should create "OTEL_DIAGNOSTICS.json"' { 157 | $config = Enable-OtelDiagnosticLog 158 | $config.FullName | Should -Exist 159 | $config.FullName | Should -FileContentMatchMultiline '{\r?\n\s+"LogDirectory": "\.\",\r?\n\s+"FileSize": 32768,\r?\n\s+"LogLevel": "Warning"\r?\n}' 160 | } 161 | 162 | It 'Should set "OTEL_DIAGNOSTICS.json" options' { 163 | $config = Enable-OtelDiagnosticLog -LogDirectory "./logs" -FileSize 2048 -LogLevel Verbose 164 | $config.FullName | Should -Exist 165 | $config.FullName | Should -FileContentMatchMultiline '{\r?\n\s+"LogDirectory": "\.\/logs",\r?\n\s+"FileSize": 2048,\r?\n\s+"LogLevel": "Verbose"\r?\n}' 166 | } 167 | 168 | } 169 | } 170 | 171 | Describe 'Disabled-OtelDiagnosticLog' { 172 | Context 'Remove existing file' { 173 | BeforeEach { 174 | Push-Location TestDrive:/ 175 | $cwd = Get-PSDrive -Name TestDrive | Select-Object -ExpandProperty Root 176 | [System.IO.Directory]::SetCurrentDirectory($cwd) 177 | @" 178 | { 179 | "LogDirectory": ".", 180 | "FileSize": 32768, 181 | "LogLevel": "Warning" 182 | } 183 | "@ | Set-Content TestDrive:/OTEL_DIAGNOSTICS.json 184 | } 185 | 186 | AfterAll { 187 | Pop-Location 188 | [System.IO.Directory]::SetCurrentDirectory($PWD.Path) 189 | } 190 | 191 | It 'Should remove "OTEL_DIAGNOSTICS.json"' { 192 | Disable-OtelDiagnosticLog 193 | 194 | "TestDrive:/OTEL_DIAGNOSTICS.json" | Should -Not -Exist 195 | } 196 | 197 | } 198 | } 199 | 200 | AfterAll { 201 | Remove-Module potel 202 | } -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/main/src/NerdBank.GitVersioning/version.schema.json", 3 | "version": "0.3", 4 | "cloudBuild": { 5 | "buildNumber": { 6 | "enabled": true 7 | } 8 | } 9 | } --------------------------------------------------------------------------------