You've already forked opentelemetry-go
							
							
				mirror of
				https://github.com/open-telemetry/opentelemetry-go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	OS description attribute detector (#1840)
* Added Linux-specific detector for the os.description attribute * Generalized OS description detector with placeholder function for unimplemented OSes * Extended osDescription function to *nix OSes based on golang.org/x/sys/unix * Added WithOS resource configuration function to configure all of the OS resource attributes * Implemented osDescription funtion for Windows OS * Improved documentation header for *nix version of the osDescription function * Added support for reading os-release file * Added/updated documentation headers for *nix implementation of osDescription and related functions * Changelog update * Added support for reading macOS version information * Mock approach to test OS description attribute * Extracted common function getFirstAvailableFile to read the first available file from a list of candidates * Upgraded golang.org/x/sys * Changelog update * Fixed wrong function name in documentation header for WithOSDescription * Updated documentation header for platformOSDescription function * Renamed restoreProcessAttributesProviders test helper function The function restoreProcessAttributesProviders was renamed to simply restoreAttributesProviders to better reflect its broader scope, which not only applies to process attribute's providers. * Fixed os_linux.go overriding build tags defined inside the file The suffix on os_linux.go was overriding the build tags already defined in that file. The file was renamed to os_release_unix.go, reflecting the main function defined in the file. For consistency, os_darwin.go was renamed to os_release_darwing.go, as its primary purpose is to also define the osRelease function. * Removed use of discontinued function resource.WithoutBuiltin * Added PR number to changelog entries * Updated go.sum files after run of make lint * Linux implementation: ignore lines with an empty key * Linux implementation: avoid unquoting strings less than two chars * WIP: added tests for Linux support functions * WIP: added tests for charsToString and getFirstAvailableFile functions * Replaced os.CreateTemp with ioutil.TempFile as the former only exists in Go 1.16 * Added unameProvider type to decouple direct reference to unix.Uname function inside Uname() * Added tests for Uname() function * Replaced *os.File with io.Reader in parseOSReleaseFile to ease testing * Added tests for parseOSReleaseFile function * Darwin implementation: added tests for buildOSRelease function * Replaced *os.File with io.Reader in parsePlistFile to ease testing * Darwin implementation: added tests for parsePlistFile function * Type in documentation header for Linux osRelease function * Extracted logic for reading specific registry values into helper functions * Added basic tests for Windows version of platformOSDescription and helper functions * Manually formatted uint64 to strings to have an uniform interface for test assertions * Asserts there's no error when opening registry key for testing Co-authored-by: Robert Pająk <pellared@hotmail.com> * Simplified subtests by using a single test with multiple asserts * go.sum update after running make * Fix typo Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com> * WIP: added placeholder implementation of platformOSDescription for unsupported OSes * Fixed typo on osRelease documentation header Co-authored-by: Chris Bandy <bandy.chris@gmail.com> * Fixed typo on test case name for ParsePlistFile tests Co-authored-by: Chris Bandy <bandy.chris@gmail.com> * Linter fix in changelog * go.sum updates after running make * Used strings.Replacer instead of multiple strings.ReplaceAll calls * Optimized implementation of charsToString * Safer temporary file deletion with t.TempDir() * Used t.Cleanup() for safer mocking of runtime providers in OS resource tests * Handled optionality of DisplayVersion registry key. For example, CI machine runs on: Windows Server 2019 Datacenter (1809) [Version 10.0.17763.1999] So, to not add an extra white space due to missing DisplayVersion, this value is checked to be not empty, and only in such case a trailing space is added for that component. * Workaround to handle the case of DisplayVersion registry key not present * Excluded unsupported GOOSes by negation of supported ones * go.sum update after running make Co-authored-by: Anthony Mirabella <a9@aneurysm9.com> Co-authored-by: Robert Pająk <pellared@hotmail.com> Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com> Co-authored-by: Chris Bandy <bandy.chris@gmail.com>
This commit is contained in:
		| @@ -11,6 +11,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm | ||||
| ### Added | ||||
|  | ||||
| - Adds HTTP support for OTLP metrics exporter. (#2022) | ||||
| - Added `WithOSDescription` resource configuration option to set OS (Operating System) description resource attribute (`os.description`). (#1840) | ||||
| - Added `WithOS` resource configuration option to set all OS (Operating System) resource attributes at once. (#1840) | ||||
|  | ||||
| ### Changed | ||||
|  | ||||
|   | ||||
| @@ -37,6 +37,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ | ||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
|   | ||||
| @@ -8,6 +8,8 @@ github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||
|   | ||||
| @@ -7,6 +7,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||
|   | ||||
| @@ -39,6 +39,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ | ||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
|   | ||||
| @@ -80,8 +80,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | ||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
|   | ||||
| @@ -7,6 +7,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||
|   | ||||
| @@ -121,6 +121,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w | ||||
| golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q= | ||||
| golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
|   | ||||
| @@ -71,6 +71,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | ||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
| golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | ||||
|   | ||||
| @@ -8,6 +8,8 @@ github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||
|   | ||||
| @@ -82,8 +82,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | ||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
|   | ||||
| @@ -82,8 +82,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | ||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
|   | ||||
| @@ -81,8 +81,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | ||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
|   | ||||
| @@ -80,8 +80,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | ||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
|   | ||||
| @@ -80,8 +80,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | ||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
|   | ||||
| @@ -79,8 +79,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | ||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
|   | ||||
| @@ -121,6 +121,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w | ||||
| golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q= | ||||
| golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
|   | ||||
| @@ -9,6 +9,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||
|   | ||||
| @@ -7,6 +7,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||
|   | ||||
| @@ -71,6 +71,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | ||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
| golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | ||||
|   | ||||
| @@ -7,6 +7,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||
|   | ||||
| @@ -10,6 +10,7 @@ require ( | ||||
| 	go.opentelemetry.io/otel v1.0.0-RC1 | ||||
| 	go.opentelemetry.io/otel/oteltest v1.0.0-RC1 | ||||
| 	go.opentelemetry.io/otel/trace v1.0.0-RC1 | ||||
| 	golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 | ||||
| ) | ||||
|  | ||||
| replace go.opentelemetry.io/otel/bridge/opencensus => ../bridge/opencensus | ||||
|   | ||||
| @@ -7,6 +7,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||
|   | ||||
| @@ -9,6 +9,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||
|   | ||||
							
								
								
									
										28
									
								
								sdk/resource/export_common_unix_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								sdk/resource/export_common_unix_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos | ||||
|  | ||||
| package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||
|  | ||||
| var ( | ||||
| 	Uname                 = uname | ||||
| 	CharsToString         = charsToString | ||||
| 	GetFirstAvailableFile = getFirstAvailableFile | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	SetUnameProvider        = setUnameProvider | ||||
| 	SetDefaultUnameProvider = setDefaultUnameProvider | ||||
| ) | ||||
							
								
								
									
										20
									
								
								sdk/resource/export_os_release_darwin_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								sdk/resource/export_os_release_darwin_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||
|  | ||||
| var ( | ||||
| 	ParsePlistFile = parsePlistFile | ||||
| 	BuildOSRelease = buildOSRelease | ||||
| ) | ||||
| @@ -21,6 +21,8 @@ var ( | ||||
| 	SetRuntimeProviders             = setRuntimeProviders | ||||
| 	SetDefaultUserProviders         = setDefaultUserProviders | ||||
| 	SetUserProviders                = setUserProviders | ||||
| 	SetDefaultOSDescriptionProvider = setDefaultOSDescriptionProvider | ||||
| 	SetOSDescriptionProvider        = setOSDescriptionProvider | ||||
| ) | ||||
|  | ||||
| var ( | ||||
|   | ||||
							
								
								
									
										26
									
								
								sdk/resource/export_unix_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								sdk/resource/export_unix_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| // +build aix dragonfly freebsd linux netbsd openbsd solaris zos | ||||
|  | ||||
| package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||
|  | ||||
| var ( | ||||
| 	ParseOSReleaseFile = parseOSReleaseFile | ||||
| 	Skip               = skip | ||||
| 	Parse              = parse | ||||
| 	Unquote            = unquote | ||||
| 	Unescape           = unescape | ||||
| 	BuildOSRelease     = buildOSRelease | ||||
| ) | ||||
							
								
								
									
										26
									
								
								sdk/resource/export_windows_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								sdk/resource/export_windows_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||
|  | ||||
| var ( | ||||
| 	PlatformOSDescription         = platformOSDescription | ||||
| 	ReadProductName               = readProductName | ||||
| 	ReadDisplayVersion            = readDisplayVersion | ||||
| 	ReadReleaseID                 = readReleaseID | ||||
| 	ReadCurrentMajorVersionNumber = readCurrentMajorVersionNumber | ||||
| 	ReadCurrentMinorVersionNumber = readCurrentMinorVersionNumber | ||||
| 	ReadCurrentBuildNumber        = readCurrentBuildNumber | ||||
| 	ReadUBR                       = readUBR | ||||
| ) | ||||
| @@ -21,7 +21,22 @@ import ( | ||||
| 	semconv "go.opentelemetry.io/otel/semconv/v1.4.0" | ||||
| ) | ||||
|  | ||||
| type osDescriptionProvider func() (string, error) | ||||
|  | ||||
| var defaultOSDescriptionProvider osDescriptionProvider = platformOSDescription | ||||
|  | ||||
| var osDescription = defaultOSDescriptionProvider | ||||
|  | ||||
| func setDefaultOSDescriptionProvider() { | ||||
| 	setOSDescriptionProvider(defaultOSDescriptionProvider) | ||||
| } | ||||
|  | ||||
| func setOSDescriptionProvider(osDescriptionProvider osDescriptionProvider) { | ||||
| 	osDescription = osDescriptionProvider | ||||
| } | ||||
|  | ||||
| type osTypeDetector struct{} | ||||
| type osDescriptionDetector struct{} | ||||
|  | ||||
| // Detect returns a *Resource that describes the operating system type the | ||||
| // service is running on. | ||||
| @@ -34,7 +49,38 @@ func (osTypeDetector) Detect(ctx context.Context) (*Resource, error) { | ||||
| 	), nil | ||||
| } | ||||
|  | ||||
| // Detect returns a *Resource that describes the operating system the | ||||
| // service is running on. | ||||
| func (osDescriptionDetector) Detect(ctx context.Context) (*Resource, error) { | ||||
| 	description, err := osDescription() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return NewWithAttributes( | ||||
| 		semconv.SchemaURL, | ||||
| 		semconv.OSDescriptionKey.String(description), | ||||
| 	), nil | ||||
| } | ||||
|  | ||||
| // WithOSType adds an attribute with the operating system type to the configured Resource. | ||||
| func WithOSType() Option { | ||||
| 	return WithDetectors(osTypeDetector{}) | ||||
| } | ||||
|  | ||||
| // WithOSDescription adds an attribute with the operating system description to the | ||||
| // configured Resource. The formatted string is equivalent to the output of the | ||||
| // `uname -snrvm` command. | ||||
| func WithOSDescription() Option { | ||||
| 	return WithDetectors(osDescriptionDetector{}) | ||||
| } | ||||
|  | ||||
| // WithOS adds all the OS attributes to the configured Resource. | ||||
| // See individual WithOS* functions to configure specific attributes. | ||||
| func WithOS() Option { | ||||
| 	return WithDetectors( | ||||
| 		osTypeDetector{}, | ||||
| 		osDescriptionDetector{}, | ||||
| 	) | ||||
| } | ||||
|   | ||||
							
								
								
									
										102
									
								
								sdk/resource/os_release_darwin.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								sdk/resource/os_release_darwin.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||
|  | ||||
| import ( | ||||
| 	"encoding/xml" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| type plist struct { | ||||
| 	XMLName xml.Name `xml:"plist"` | ||||
| 	Dict    dict     `xml:"dict"` | ||||
| } | ||||
|  | ||||
| type dict struct { | ||||
| 	Key    []string `xml:"key"` | ||||
| 	String []string `xml:"string"` | ||||
| } | ||||
|  | ||||
| // osRelease builds a string describing the operating system release based on the | ||||
| // contents of the property list (.plist) system files. If no .plist files are found, | ||||
| // or if the required properties to build the release description string are missing, | ||||
| // an empty string is returned instead. The generated string resembles the output of | ||||
| // the `sw_vers` commandline program, but in a single-line string. For more information | ||||
| // about the `sw_vers` program, see: https://www.unix.com/man-page/osx/1/SW_VERS. | ||||
| func osRelease() string { | ||||
| 	file, err := getPlistFile() | ||||
| 	if err != nil { | ||||
| 		return "" | ||||
| 	} | ||||
|  | ||||
| 	defer file.Close() | ||||
|  | ||||
| 	values, err := parsePlistFile(file) | ||||
| 	if err != nil { | ||||
| 		return "" | ||||
| 	} | ||||
|  | ||||
| 	return buildOSRelease(values) | ||||
| } | ||||
|  | ||||
| // getPlistFile returns a *os.File pointing to one of the well-known .plist files | ||||
| // available on macOS. If no file can be opened, it returns an error. | ||||
| func getPlistFile() (*os.File, error) { | ||||
| 	return getFirstAvailableFile([]string{ | ||||
| 		"/System/Library/CoreServices/SystemVersion.plist", | ||||
| 		"/System/Library/CoreServices/ServerVersion.plist", | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // parsePlistFile process the file pointed by `file` as a .plist file and returns | ||||
| // a map with the key-values for each pair of correlated <key> and <string> elements | ||||
| // contained in it. | ||||
| func parsePlistFile(file io.Reader) (map[string]string, error) { | ||||
| 	var v plist | ||||
|  | ||||
| 	err := xml.NewDecoder(file).Decode(&v) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if len(v.Dict.Key) != len(v.Dict.String) { | ||||
| 		return nil, fmt.Errorf("the number of <key> and <string> elements doesn't match") | ||||
| 	} | ||||
|  | ||||
| 	properties := make(map[string]string, len(v.Dict.Key)) | ||||
| 	for i, key := range v.Dict.Key { | ||||
| 		properties[key] = v.Dict.String[i] | ||||
| 	} | ||||
|  | ||||
| 	return properties, nil | ||||
| } | ||||
|  | ||||
| // buildOSRelease builds a string describing the OS release based on the properties | ||||
| // available on the provided map. It tries to find the `ProductName`, `ProductVersion` | ||||
| // and `ProductBuildVersion` properties. If some of these properties are not found, | ||||
| // it returns an empty string. | ||||
| func buildOSRelease(properties map[string]string) string { | ||||
| 	productName := properties["ProductName"] | ||||
| 	productVersion := properties["ProductVersion"] | ||||
| 	productBuildVersion := properties["ProductBuildVersion"] | ||||
|  | ||||
| 	if productName == "" || productVersion == "" || productBuildVersion == "" { | ||||
| 		return "" | ||||
| 	} | ||||
|  | ||||
| 	return fmt.Sprintf("%s %s (%s)", productName, productVersion, productBuildVersion) | ||||
| } | ||||
							
								
								
									
										176
									
								
								sdk/resource/os_release_darwin_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								sdk/resource/os_release_darwin_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| package resource_test | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/stretchr/testify/require" | ||||
|  | ||||
| 	"go.opentelemetry.io/otel/sdk/resource" | ||||
| ) | ||||
|  | ||||
| func TestParsePlistFile(t *testing.T) { | ||||
| 	standardPlist := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?> | ||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||
| <plist version="1.0"> | ||||
| <dict> | ||||
| 	<key>ProductBuildVersion</key> | ||||
| 	<string>20E232</string> | ||||
| 	<key>ProductCopyright</key> | ||||
| 	<string>1983-2021 Apple Inc.</string> | ||||
| 	<key>ProductName</key> | ||||
| 	<string>macOS</string> | ||||
| 	<key>ProductUserVisibleVersion</key> | ||||
| 	<string>11.3</string> | ||||
| 	<key>ProductVersion</key> | ||||
| 	<string>11.3</string> | ||||
| 	<key>iOSSupportVersion</key> | ||||
| 	<string>14.5</string> | ||||
| </dict> | ||||
| </plist>`) | ||||
|  | ||||
| 	parsedPlist := map[string]string{ | ||||
| 		"ProductBuildVersion":       "20E232", | ||||
| 		"ProductCopyright":          "1983-2021 Apple Inc.", | ||||
| 		"ProductName":               "macOS", | ||||
| 		"ProductUserVisibleVersion": "11.3", | ||||
| 		"ProductVersion":            "11.3", | ||||
| 		"iOSSupportVersion":         "14.5", | ||||
| 	} | ||||
|  | ||||
| 	emptyPlist := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?> | ||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||
| <plist version="1.0"> | ||||
| <dict> | ||||
| </dict> | ||||
| </plist>`) | ||||
|  | ||||
| 	missingDictPlist := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?> | ||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||
| <plist version="1.0"> | ||||
| </plist>`) | ||||
|  | ||||
| 	unknownElementsPlist := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?> | ||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||
| <plist version="1.0"> | ||||
| <dict> | ||||
| 	<a> | ||||
| 		<b>123</b> | ||||
| 	</a> | ||||
| 	<key>ProductBuildVersion</key> | ||||
| 	<c>Value</c> | ||||
| 	<string>20E232</string> | ||||
| 	<d attr="1"></d> | ||||
| </dict> | ||||
| </plist>`) | ||||
|  | ||||
| 	parsedUnknownElementsPlist := map[string]string{ | ||||
| 		"ProductBuildVersion": "20E232", | ||||
| 	} | ||||
|  | ||||
| 	tt := []struct { | ||||
| 		Name   string | ||||
| 		Plist  io.Reader | ||||
| 		Parsed map[string]string | ||||
| 	}{ | ||||
| 		{"Standard", standardPlist, parsedPlist}, | ||||
| 		{"Empty", emptyPlist, map[string]string{}}, | ||||
| 		{"Missing dict", missingDictPlist, map[string]string{}}, | ||||
| 		{"Unknown elements", unknownElementsPlist, parsedUnknownElementsPlist}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tt { | ||||
| 		tc := tc | ||||
|  | ||||
| 		t.Run(tc.Name, func(t *testing.T) { | ||||
| 			result, err := resource.ParsePlistFile(tc.Plist) | ||||
|  | ||||
| 			require.Equal(t, tc.Parsed, result) | ||||
| 			require.NoError(t, err) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestParsePlistFileUnevenKeys(t *testing.T) { | ||||
| 	plist := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?> | ||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||
| <plist version="1.0"> | ||||
| <dict> | ||||
| 	<key>ProductBuildVersion</key> | ||||
| 	<string>20E232</string> | ||||
| 	<key>ProductCopyright</key> | ||||
| </dict> | ||||
| </plist>`) | ||||
|  | ||||
| 	result, err := resource.ParsePlistFile(plist) | ||||
|  | ||||
| 	require.Nil(t, result) | ||||
| 	require.Error(t, err) | ||||
| } | ||||
|  | ||||
| func TestParsePlistFileMalformed(t *testing.T) { | ||||
| 	plist := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?> | ||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||
| <plist version="1.0"> | ||||
| <dict> | ||||
| 	<key>Product | ||||
| </dict> | ||||
| </plist>`) | ||||
|  | ||||
| 	result, err := resource.ParsePlistFile(plist) | ||||
|  | ||||
| 	require.Nil(t, result) | ||||
| 	require.Error(t, err) | ||||
| } | ||||
|  | ||||
| func TestBuildOSRelease(t *testing.T) { | ||||
| 	tt := []struct { | ||||
| 		Name       string | ||||
| 		Properties map[string]string | ||||
| 		OSRelease  string | ||||
| 	}{ | ||||
| 		{"Empty properties", map[string]string{}, ""}, | ||||
| 		{"Empty properties (nil)", nil, ""}, | ||||
| 		{"Missing product name", map[string]string{ | ||||
| 			"ProductVersion":      "11.3", | ||||
| 			"ProductBuildVersion": "20E232", | ||||
| 		}, ""}, | ||||
| 		{"Missing product version", map[string]string{ | ||||
| 			"ProductName":         "macOS", | ||||
| 			"ProductBuildVersion": "20E232", | ||||
| 		}, ""}, | ||||
| 		{"Missing product build version", map[string]string{ | ||||
| 			"ProductName":    "macOS", | ||||
| 			"ProductVersion": "11.3", | ||||
| 		}, ""}, | ||||
| 		{"All properties available", map[string]string{ | ||||
| 			"ProductName":         "macOS", | ||||
| 			"ProductVersion":      "11.3", | ||||
| 			"ProductBuildVersion": "20E232", | ||||
| 		}, "macOS 11.3 (20E232)"}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tt { | ||||
| 		tc := tc | ||||
|  | ||||
| 		t.Run(tc.Name, func(t *testing.T) { | ||||
| 			result := resource.BuildOSRelease(tc.Properties) | ||||
| 			require.Equal(t, tc.OSRelease, result) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										153
									
								
								sdk/resource/os_release_unix.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								sdk/resource/os_release_unix.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| // +build aix dragonfly freebsd linux netbsd openbsd solaris zos | ||||
|  | ||||
| package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // osRelease builds a string describing the operating system release based on the | ||||
| // properties of the os-release file. If no os-release file is found, or if the | ||||
| // required properties to build the release description string are missing, an empty | ||||
| // string is returned instead. For more information about os-release files, see: | ||||
| // https://www.freedesktop.org/software/systemd/man/os-release.html | ||||
| func osRelease() string { | ||||
| 	file, err := getOSReleaseFile() | ||||
| 	if err != nil { | ||||
| 		return "" | ||||
| 	} | ||||
|  | ||||
| 	defer file.Close() | ||||
|  | ||||
| 	values := parseOSReleaseFile(file) | ||||
|  | ||||
| 	return buildOSRelease(values) | ||||
| } | ||||
|  | ||||
| // getOSReleaseFile returns a *os.File pointing to one of the well-known os-release | ||||
| // files, according to their order of preference. If no file can be opened, it | ||||
| // returns an error. | ||||
| func getOSReleaseFile() (*os.File, error) { | ||||
| 	return getFirstAvailableFile([]string{"/etc/os-release", "/usr/lib/os-release"}) | ||||
| } | ||||
|  | ||||
| // parseOSReleaseFile process the file pointed by `file` as an os-release file and | ||||
| // returns a map with the key-values contained in it. Empty lines or lines starting | ||||
| // with a '#' character are ignored, as well as lines with the missing key=value | ||||
| // separator. Values are unquoted and unescaped. | ||||
| func parseOSReleaseFile(file io.Reader) map[string]string { | ||||
| 	values := make(map[string]string) | ||||
| 	scanner := bufio.NewScanner(file) | ||||
|  | ||||
| 	for scanner.Scan() { | ||||
| 		line := scanner.Text() | ||||
|  | ||||
| 		if skip(line) { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		key, value, ok := parse(line) | ||||
| 		if ok { | ||||
| 			values[key] = value | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return values | ||||
| } | ||||
|  | ||||
| // skip returns true if the line is blank or starts with a '#' character, and | ||||
| // therefore should be skipped from processing. | ||||
| func skip(line string) bool { | ||||
| 	line = strings.TrimSpace(line) | ||||
|  | ||||
| 	return len(line) == 0 || strings.HasPrefix(line, "#") | ||||
| } | ||||
|  | ||||
| // parse attempts to split the provided line on the first '=' character, and then | ||||
| // sanitize each side of the split before returning them as a key-value pair. | ||||
| func parse(line string) (string, string, bool) { | ||||
| 	parts := strings.SplitN(line, "=", 2) | ||||
|  | ||||
| 	if len(parts) != 2 || len(parts[0]) == 0 { | ||||
| 		return "", "", false | ||||
| 	} | ||||
|  | ||||
| 	key := strings.TrimSpace(parts[0]) | ||||
| 	value := unescape(unquote(strings.TrimSpace(parts[1]))) | ||||
|  | ||||
| 	return key, value, true | ||||
| } | ||||
|  | ||||
| // unquote checks whether the string `s` is quoted with double or single quotes | ||||
| // and, if so, returns a version of the string without them. Otherwise it returns | ||||
| // the provided string unchanged. | ||||
| func unquote(s string) string { | ||||
| 	if len(s) < 2 { | ||||
| 		return s | ||||
| 	} | ||||
|  | ||||
| 	if (s[0] == '"' || s[0] == '\'') && s[0] == s[len(s)-1] { | ||||
| 		return s[1 : len(s)-1] | ||||
| 	} | ||||
|  | ||||
| 	return s | ||||
| } | ||||
|  | ||||
| // unescape removes the `\` prefix from some characters that are expected | ||||
| // to have it added in front of them for escaping purposes. | ||||
| func unescape(s string) string { | ||||
| 	return strings.NewReplacer( | ||||
| 		`\$`, `$`, | ||||
| 		`\"`, `"`, | ||||
| 		`\'`, `'`, | ||||
| 		`\\`, `\`, | ||||
| 		"\\`", "`", | ||||
| 	).Replace(s) | ||||
| } | ||||
|  | ||||
| // buildOSRelease builds a string describing the OS release based on the properties | ||||
| // available on the provided map. It favors a combination of the `NAME` and `VERSION` | ||||
| // properties as first option (falling back to `VERSION_ID` if `VERSION` isn't | ||||
| // found), and using `PRETTY_NAME` alone if some of the previous are not present. If | ||||
| // none of these properties are found, it returns an empty string. | ||||
| // | ||||
| // The rationale behind not using `PRETTY_NAME` as first choice was that, for some | ||||
| // Linux distributions, it doesn't include the same detail that can be found on the | ||||
| // individual `NAME` and `VERSION` properties, and combining `PRETTY_NAME` with | ||||
| // other properties can produce "pretty" redundant strings in some cases. | ||||
| func buildOSRelease(values map[string]string) string { | ||||
| 	var osRelease string | ||||
|  | ||||
| 	name := values["NAME"] | ||||
| 	version := values["VERSION"] | ||||
|  | ||||
| 	if version == "" { | ||||
| 		version = values["VERSION_ID"] | ||||
| 	} | ||||
|  | ||||
| 	if name != "" && version != "" { | ||||
| 		osRelease = fmt.Sprintf("%s %s", name, version) | ||||
| 	} else { | ||||
| 		osRelease = values["PRETTY_NAME"] | ||||
| 	} | ||||
|  | ||||
| 	return osRelease | ||||
| } | ||||
							
								
								
									
										306
									
								
								sdk/resource/os_release_unix_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										306
									
								
								sdk/resource/os_release_unix_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,306 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| // +build aix dragonfly freebsd linux netbsd openbsd solaris zos | ||||
|  | ||||
| package resource_test | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/stretchr/testify/require" | ||||
|  | ||||
| 	"go.opentelemetry.io/otel/sdk/resource" | ||||
| ) | ||||
|  | ||||
| func TestParseOSReleaseFile(t *testing.T) { | ||||
| 	osReleaseUbuntu := bytes.NewBufferString(`NAME="Ubuntu" | ||||
| VERSION="20.04.2 LTS (Focal Fossa)" | ||||
| ID=ubuntu | ||||
| ID_LIKE=debian | ||||
| PRETTY_NAME="Ubuntu 20.04.2 LTS" | ||||
| VERSION_ID="20.04" | ||||
| HOME_URL="https://www.ubuntu.com/" | ||||
| SUPPORT_URL="https://help.ubuntu.com/" | ||||
| BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" | ||||
| PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" | ||||
| VERSION_CODENAME=focal | ||||
| UBUNTU_CODENAME=focal`) | ||||
|  | ||||
| 	parsedUbuntu := map[string]string{ | ||||
| 		"NAME":               "Ubuntu", | ||||
| 		"VERSION":            "20.04.2 LTS (Focal Fossa)", | ||||
| 		"ID":                 "ubuntu", | ||||
| 		"ID_LIKE":            "debian", | ||||
| 		"PRETTY_NAME":        "Ubuntu 20.04.2 LTS", | ||||
| 		"VERSION_ID":         "20.04", | ||||
| 		"HOME_URL":           "https://www.ubuntu.com/", | ||||
| 		"SUPPORT_URL":        "https://help.ubuntu.com/", | ||||
| 		"BUG_REPORT_URL":     "https://bugs.launchpad.net/ubuntu/", | ||||
| 		"PRIVACY_POLICY_URL": "https://www.ubuntu.com/legal/terms-and-policies/privacy-policy", | ||||
| 		"VERSION_CODENAME":   "focal", | ||||
| 		"UBUNTU_CODENAME":    "focal", | ||||
| 	} | ||||
|  | ||||
| 	osReleaseDebian := bytes.NewBufferString(`PRETTY_NAME="Debian GNU/Linux 10 (buster)" | ||||
| NAME="Debian GNU/Linux" | ||||
| VERSION_ID="10" | ||||
| VERSION="10 (buster)" | ||||
| VERSION_CODENAME=buster | ||||
| ID=debian | ||||
| HOME_URL="https://www.debian.org/" | ||||
| SUPPORT_URL="https://www.debian.org/support" | ||||
| BUG_REPORT_URL="https://bugs.debian.org/"`) | ||||
|  | ||||
| 	parsedDebian := map[string]string{ | ||||
| 		"PRETTY_NAME":      "Debian GNU/Linux 10 (buster)", | ||||
| 		"NAME":             "Debian GNU/Linux", | ||||
| 		"VERSION_ID":       "10", | ||||
| 		"VERSION":          "10 (buster)", | ||||
| 		"VERSION_CODENAME": "buster", | ||||
| 		"ID":               "debian", | ||||
| 		"HOME_URL":         "https://www.debian.org/", | ||||
| 		"SUPPORT_URL":      "https://www.debian.org/support", | ||||
| 		"BUG_REPORT_URL":   "https://bugs.debian.org/", | ||||
| 	} | ||||
|  | ||||
| 	osReleaseAlpine := bytes.NewBufferString(`NAME="Alpine Linux" | ||||
| ID=alpine | ||||
| VERSION_ID=3.13.4 | ||||
| PRETTY_NAME="Alpine Linux v3.13" | ||||
| HOME_URL="https://alpinelinux.org/" | ||||
| BUG_REPORT_URL="https://bugs.alpinelinux.org/"`) | ||||
|  | ||||
| 	parsedAlpine := map[string]string{ | ||||
| 		"NAME":           "Alpine Linux", | ||||
| 		"ID":             "alpine", | ||||
| 		"VERSION_ID":     "3.13.4", | ||||
| 		"PRETTY_NAME":    "Alpine Linux v3.13", | ||||
| 		"HOME_URL":       "https://alpinelinux.org/", | ||||
| 		"BUG_REPORT_URL": "https://bugs.alpinelinux.org/", | ||||
| 	} | ||||
|  | ||||
| 	osReleaseMock := bytes.NewBufferString(` | ||||
| # This line should be skipped | ||||
|  | ||||
| QUOTED1="Quoted value 1" | ||||
| QUOTED2='Quoted value 2' | ||||
| ESCAPED1="\$HOME" | ||||
| ESCAPED2="\"release\"" | ||||
| ESCAPED3="rock\'n\'roll" | ||||
| ESCAPED4="\\var" | ||||
|  | ||||
| =line with missing key should be skipped | ||||
|  | ||||
| PROP1=name=john | ||||
| 	PROP2  =  Value   | ||||
| PROP3='This value will be overwritten by the next one' | ||||
| PROP3='Final value'`) | ||||
|  | ||||
| 	parsedMock := map[string]string{ | ||||
| 		"QUOTED1":  "Quoted value 1", | ||||
| 		"QUOTED2":  "Quoted value 2", | ||||
| 		"ESCAPED1": "$HOME", | ||||
| 		"ESCAPED2": `"release"`, | ||||
| 		"ESCAPED3": "rock'n'roll", | ||||
| 		"ESCAPED4": `\var`, | ||||
| 		"PROP1":    "name=john", | ||||
| 		"PROP2":    "Value", | ||||
| 		"PROP3":    "Final value", | ||||
| 	} | ||||
|  | ||||
| 	tt := []struct { | ||||
| 		Name      string | ||||
| 		OSRelease io.Reader | ||||
| 		Parsed    map[string]string | ||||
| 	}{ | ||||
| 		{"Ubuntu", osReleaseUbuntu, parsedUbuntu}, | ||||
| 		{"Debian", osReleaseDebian, parsedDebian}, | ||||
| 		{"Alpine", osReleaseAlpine, parsedAlpine}, | ||||
| 		{"Mock", osReleaseMock, parsedMock}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tt { | ||||
| 		tc := tc | ||||
|  | ||||
| 		t.Run(tc.Name, func(t *testing.T) { | ||||
| 			result := resource.ParseOSReleaseFile(tc.OSRelease) | ||||
| 			require.EqualValues(t, tc.Parsed, result) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestSkip(t *testing.T) { | ||||
| 	tt := []struct { | ||||
| 		Name     string | ||||
| 		Line     string | ||||
| 		Expected bool | ||||
| 	}{ | ||||
| 		{"Empty string", "", true}, | ||||
| 		{"Only whitespace", "   ", true}, | ||||
| 		{"Hashtag prefix 1", "# Sample text", true}, | ||||
| 		{"Hashtag prefix 2", "  # Sample text", true}, | ||||
| 		{"Hashtag and whitespace 1", "#  ", true}, | ||||
| 		{"Hashtag and whitespace 2", "  #", true}, | ||||
| 		{"Hashtag and whitespace 3", "  #  ", true}, | ||||
| 		{"Nonempty string", "Sample text", false}, | ||||
| 		{"Nonempty string with whitespace around", " Sample text ", false}, | ||||
| 		{"Nonempty string with middle hashtag", "Sample #text", false}, | ||||
| 		{"Nonempty string with ending hashtag", "Sample text #", false}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tt { | ||||
| 		tc := tc | ||||
|  | ||||
| 		t.Run(tc.Name, func(t *testing.T) { | ||||
| 			result := resource.Skip(tc.Line) | ||||
| 			require.EqualValues(t, tc.Expected, result) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestParse(t *testing.T) { | ||||
| 	tt := []struct { | ||||
| 		Name          string | ||||
| 		Line          string | ||||
| 		ExpectedKey   string | ||||
| 		ExpectedValue string | ||||
| 		OK            bool | ||||
| 	}{ | ||||
| 		{"Empty string", "", "", "", false}, | ||||
| 		{"No separator", "wrong", "", "", false}, | ||||
| 		{"Empty key", "=john", "", "", false}, | ||||
| 		{"Empty key value", "=", "", "", false}, | ||||
| 		{"Empty value", "name=", "name", "", true}, | ||||
| 		{"Key value 1", "name=john", "name", "john", true}, | ||||
| 		{"Key value 2", "name=john=dev", "name", "john=dev", true}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tt { | ||||
| 		tc := tc | ||||
|  | ||||
| 		t.Run(tc.Name, func(t *testing.T) { | ||||
| 			key, value, ok := resource.Parse(tc.Line) | ||||
| 			require.EqualValues(t, tc.ExpectedKey, key) | ||||
| 			require.EqualValues(t, tc.ExpectedValue, value) | ||||
| 			require.EqualValues(t, tc.OK, ok) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestUnquote(t *testing.T) { | ||||
| 	tt := []struct { | ||||
| 		Name     string | ||||
| 		Text     string | ||||
| 		Expected string | ||||
| 	}{ | ||||
| 		{"Empty string", ``, ``}, | ||||
| 		{"Single double quote", `"`, `"`}, | ||||
| 		{"Single single quote", `'`, `'`}, | ||||
| 		{"Empty double quotes", `""`, ``}, | ||||
| 		{"Empty single quotes", `''`, ``}, | ||||
| 		{"Empty mixed quotes 1", `"'`, `"'`}, | ||||
| 		{"Empty mixed quotes 2", `'"`, `'"`}, | ||||
| 		{"Double quotes", `"Sample text"`, `Sample text`}, | ||||
| 		{"Single quotes", `'Sample text'`, `Sample text`}, | ||||
| 		{"Half-open starting double quote", `"Sample text`, `"Sample text`}, | ||||
| 		{"Half-open ending double quote", `Sample text"`, `Sample text"`}, | ||||
| 		{"Half-open starting single quote", `'Sample text`, `'Sample text`}, | ||||
| 		{"Half-open ending single quote", `Sample text'`, `Sample text'`}, | ||||
| 		{"Double double quotes", `""Sample text""`, `"Sample text"`}, | ||||
| 		{"Double single quotes", `''Sample text''`, `'Sample text'`}, | ||||
| 		{"Mismatch quotes 1", `"Sample text'`, `"Sample text'`}, | ||||
| 		{"Mismatch quotes 2", `'Sample text"`, `'Sample text"`}, | ||||
| 		{"No quotes", `Sample text`, `Sample text`}, | ||||
| 		{"Internal double quote", `Sample "text"`, `Sample "text"`}, | ||||
| 		{"Internal single quote", `Sample 'text'`, `Sample 'text'`}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tt { | ||||
| 		tc := tc | ||||
|  | ||||
| 		t.Run(tc.Name, func(t *testing.T) { | ||||
| 			result := resource.Unquote(tc.Text) | ||||
| 			require.EqualValues(t, tc.Expected, result) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestUnescape(t *testing.T) { | ||||
| 	tt := []struct { | ||||
| 		Name     string | ||||
| 		Text     string | ||||
| 		Expected string | ||||
| 	}{ | ||||
| 		{"Empty string", ``, ``}, | ||||
| 		{"Escaped dollar sign", `\$var`, `$var`}, | ||||
| 		{"Escaped double quote", `\"var`, `"var`}, | ||||
| 		{"Escaped single quote", `\'var`, `'var`}, | ||||
| 		{"Escaped backslash", `\\var`, `\var`}, | ||||
| 		{"Escaped backtick", "\\`var", "`var"}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tt { | ||||
| 		tc := tc | ||||
|  | ||||
| 		t.Run(tc.Name, func(t *testing.T) { | ||||
| 			result := resource.Unescape(tc.Text) | ||||
| 			require.EqualValues(t, tc.Expected, result) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestBuildOSRelease(t *testing.T) { | ||||
| 	tt := []struct { | ||||
| 		Name     string | ||||
| 		Values   map[string]string | ||||
| 		Expected string | ||||
| 	}{ | ||||
| 		{"Nil values", nil, ""}, | ||||
| 		{"Empty values", map[string]string{}, ""}, | ||||
| 		{"Name and version only", map[string]string{ | ||||
| 			"NAME":    "Ubuntu", | ||||
| 			"VERSION": "20.04.2 LTS (Focal Fossa)", | ||||
| 		}, "Ubuntu 20.04.2 LTS (Focal Fossa)"}, | ||||
| 		{"Name and version preferred", map[string]string{ | ||||
| 			"NAME":        "Ubuntu", | ||||
| 			"VERSION":     "20.04.2 LTS (Focal Fossa)", | ||||
| 			"VERSION_ID":  "20.04", | ||||
| 			"PRETTY_NAME": "Ubuntu 20.04.2 LTS", | ||||
| 		}, "Ubuntu 20.04.2 LTS (Focal Fossa)"}, | ||||
| 		{"Version ID fallback", map[string]string{ | ||||
| 			"NAME":       "Ubuntu", | ||||
| 			"VERSION_ID": "20.04", | ||||
| 		}, "Ubuntu 20.04"}, | ||||
| 		{"Pretty name fallback due to missing name", map[string]string{ | ||||
| 			"VERSION":     "20.04.2 LTS (Focal Fossa)", | ||||
| 			"PRETTY_NAME": "Ubuntu 20.04.2 LTS", | ||||
| 		}, "Ubuntu 20.04.2 LTS"}, | ||||
| 		{"Pretty name fallback due to missing version", map[string]string{ | ||||
| 			"NAME":        "Ubuntu", | ||||
| 			"PRETTY_NAME": "Ubuntu 20.04.2 LTS", | ||||
| 		}, "Ubuntu 20.04.2 LTS"}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tt { | ||||
| 		tc := tc | ||||
|  | ||||
| 		t.Run(tc.Name, func(t *testing.T) { | ||||
| 			result := resource.BuildOSRelease(tc.Values) | ||||
| 			require.EqualValues(t, tc.Expected, result) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| @@ -30,10 +30,15 @@ func mockRuntimeProviders() { | ||||
| 		func() string { return "LINUX" }, | ||||
| 		fakeRuntimeArchProvider, | ||||
| 	) | ||||
|  | ||||
| 	resource.SetOSDescriptionProvider( | ||||
| 		func() (string, error) { return "Test", nil }, | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func TestWithOSType(t *testing.T) { | ||||
| 	mockRuntimeProviders() | ||||
| 	t.Cleanup(restoreAttributesProviders) | ||||
|  | ||||
| 	ctx := context.Background() | ||||
|  | ||||
| @@ -45,6 +50,37 @@ func TestWithOSType(t *testing.T) { | ||||
| 	require.EqualValues(t, map[string]string{ | ||||
| 		"os.type": "linux", | ||||
| 	}, toMap(res)) | ||||
|  | ||||
| 	restoreProcessAttributesProviders() | ||||
| } | ||||
|  | ||||
| func TestWithOSDescription(t *testing.T) { | ||||
| 	mockRuntimeProviders() | ||||
| 	t.Cleanup(restoreAttributesProviders) | ||||
|  | ||||
| 	ctx := context.Background() | ||||
|  | ||||
| 	res, err := resource.New(ctx, | ||||
| 		resource.WithOSDescription(), | ||||
| 	) | ||||
|  | ||||
| 	require.NoError(t, err) | ||||
| 	require.EqualValues(t, map[string]string{ | ||||
| 		"os.description": "Test", | ||||
| 	}, toMap(res)) | ||||
| } | ||||
|  | ||||
| func TestWithOS(t *testing.T) { | ||||
| 	mockRuntimeProviders() | ||||
| 	t.Cleanup(restoreAttributesProviders) | ||||
|  | ||||
| 	ctx := context.Background() | ||||
|  | ||||
| 	res, err := resource.New(ctx, | ||||
| 		resource.WithOS(), | ||||
| 	) | ||||
|  | ||||
| 	require.NoError(t, err) | ||||
| 	require.EqualValues(t, map[string]string{ | ||||
| 		"os.type":        "linux", | ||||
| 		"os.description": "Test", | ||||
| 	}, toMap(res)) | ||||
| } | ||||
|   | ||||
							
								
								
									
										99
									
								
								sdk/resource/os_unix.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								sdk/resource/os_unix.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos | ||||
|  | ||||
| package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| type unameProvider func(buf *unix.Utsname) (err error) | ||||
|  | ||||
| var defaultUnameProvider unameProvider = unix.Uname | ||||
|  | ||||
| var currentUnameProvider = defaultUnameProvider | ||||
|  | ||||
| func setDefaultUnameProvider() { | ||||
| 	setUnameProvider(defaultUnameProvider) | ||||
| } | ||||
|  | ||||
| func setUnameProvider(unameProvider unameProvider) { | ||||
| 	currentUnameProvider = unameProvider | ||||
| } | ||||
|  | ||||
| // platformOSDescription returns a human readable OS version information string. | ||||
| // The final string combines OS release information (where available) and the | ||||
| // result of the `uname` system call. | ||||
| func platformOSDescription() (string, error) { | ||||
| 	uname, err := uname() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	osRelease := osRelease() | ||||
| 	if osRelease != "" { | ||||
| 		return fmt.Sprintf("%s (%s)", osRelease, uname), nil | ||||
| 	} | ||||
|  | ||||
| 	return uname, nil | ||||
| } | ||||
|  | ||||
| // uname issues a uname(2) system call (or equivalent on systems which doesn't | ||||
| // have one) and formats the output in a single string, similar to the output | ||||
| // of the `uname` commandline program. The final string resembles the one | ||||
| // obtained with a call to `uname -snrvm`. | ||||
| func uname() (string, error) { | ||||
| 	var utsName unix.Utsname | ||||
|  | ||||
| 	err := currentUnameProvider(&utsName) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	return fmt.Sprintf("%s %s %s %s %s", | ||||
| 		charsToString(utsName.Sysname[:]), | ||||
| 		charsToString(utsName.Nodename[:]), | ||||
| 		charsToString(utsName.Release[:]), | ||||
| 		charsToString(utsName.Version[:]), | ||||
| 		charsToString(utsName.Machine[:]), | ||||
| 	), nil | ||||
| } | ||||
|  | ||||
| // charsToString converts a C-like null-terminated char array to a Go string. | ||||
| func charsToString(charArray []byte) string { | ||||
| 	if i := bytes.IndexByte(charArray, 0); i >= 0 { | ||||
| 		charArray = charArray[:i] | ||||
| 	} | ||||
|  | ||||
| 	return string(charArray) | ||||
| } | ||||
|  | ||||
| // getFirstAvailableFile returns an *os.File of the first available | ||||
| // file from a list of candidate file paths. | ||||
| func getFirstAvailableFile(candidates []string) (*os.File, error) { | ||||
| 	for _, c := range candidates { | ||||
| 		file, err := os.Open(c) | ||||
| 		if err == nil { | ||||
| 			return file, nil | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil, fmt.Errorf("no candidate file available: %v", candidates) | ||||
| } | ||||
							
								
								
									
										134
									
								
								sdk/resource/os_unix_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								sdk/resource/os_unix_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos | ||||
|  | ||||
| package resource_test | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/stretchr/testify/require" | ||||
|  | ||||
| 	"go.opentelemetry.io/otel/sdk/resource" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| func fakeUnameProvider(buf *unix.Utsname) error { | ||||
| 	copy(buf.Sysname[:], "Mock OS") | ||||
| 	copy(buf.Nodename[:], "DESKTOP-PC") | ||||
| 	copy(buf.Release[:], "5.0.0") | ||||
| 	copy(buf.Version[:], "#1 SMP Thu May 6 12:34:56 UTC 2021") | ||||
| 	copy(buf.Machine[:], "x86_64") | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func fakeUnameProviderWithError(buf *unix.Utsname) error { | ||||
| 	return fmt.Errorf("Error invoking uname(2)") | ||||
| } | ||||
|  | ||||
| func TestUname(t *testing.T) { | ||||
| 	resource.SetUnameProvider(fakeUnameProvider) | ||||
|  | ||||
| 	uname, err := resource.Uname() | ||||
|  | ||||
| 	require.Equal(t, uname, "Mock OS DESKTOP-PC 5.0.0 #1 SMP Thu May 6 12:34:56 UTC 2021 x86_64") | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| 	resource.SetDefaultUnameProvider() | ||||
| } | ||||
|  | ||||
| func TestUnameError(t *testing.T) { | ||||
| 	resource.SetUnameProvider(fakeUnameProviderWithError) | ||||
|  | ||||
| 	uname, err := resource.Uname() | ||||
|  | ||||
| 	require.Empty(t, uname) | ||||
| 	require.Error(t, err) | ||||
|  | ||||
| 	resource.SetDefaultUnameProvider() | ||||
| } | ||||
|  | ||||
| func TestCharsToString(t *testing.T) { | ||||
| 	tt := []struct { | ||||
| 		Name     string | ||||
| 		Bytes    []byte | ||||
| 		Expected string | ||||
| 	}{ | ||||
| 		{"Nil array", nil, ""}, | ||||
| 		{"Empty array", []byte{}, ""}, | ||||
| 		{"Empty string (null terminated)", []byte{0x00}, ""}, | ||||
| 		{"Nonempty string (null terminated)", []byte{0x31, 0x32, 0x33, 0x00}, "123"}, | ||||
| 		{"Nonempty string (non-null terminated)", []byte{0x31, 0x32, 0x33}, "123"}, | ||||
| 		{"Nonempty string with values after null", []byte{0x31, 0x32, 0x33, 0x00, 0x34}, "123"}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tt { | ||||
| 		tc := tc | ||||
|  | ||||
| 		t.Run(tc.Name, func(t *testing.T) { | ||||
| 			result := resource.CharsToString(tc.Bytes) | ||||
| 			require.EqualValues(t, tc.Expected, result) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestGetFirstAvailableFile(t *testing.T) { | ||||
| 	tempDir := t.TempDir() | ||||
|  | ||||
| 	file1, _ := ioutil.TempFile(tempDir, "candidate_") | ||||
| 	file2, _ := ioutil.TempFile(tempDir, "candidate_") | ||||
|  | ||||
| 	filename1, filename2 := file1.Name(), file2.Name() | ||||
|  | ||||
| 	tt := []struct { | ||||
| 		Name             string | ||||
| 		Candidates       []string | ||||
| 		ExpectedFileName string | ||||
| 		ExpectedErr      string | ||||
| 	}{ | ||||
| 		{"Gets first, skip second candidate", []string{filename1, filename2}, filename1, ""}, | ||||
| 		{"Skips first, gets second candidate", []string{"does_not_exists", filename2}, filename2, ""}, | ||||
| 		{"Skips first, gets second, ignores third candidate", []string{"does_not_exists", filename2, filename1}, filename2, ""}, | ||||
| 		{"No candidates (empty slice)", []string{}, "", "no candidate file available: []"}, | ||||
| 		{"No candidates (nil slice)", nil, "", "no candidate file available: []"}, | ||||
| 		{"Single nonexisting candidate", []string{"does_not_exists"}, "", "no candidate file available: [does_not_exists]"}, | ||||
| 		{"Multiple nonexisting candidates", []string{"does_not_exists", "this_either"}, "", "no candidate file available: [does_not_exists this_either]"}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tt { | ||||
| 		tc := tc | ||||
|  | ||||
| 		t.Run(tc.Name, func(t *testing.T) { | ||||
| 			file, err := resource.GetFirstAvailableFile(tc.Candidates) | ||||
|  | ||||
| 			filename := "" | ||||
| 			if file != nil { | ||||
| 				filename = file.Name() | ||||
| 			} | ||||
|  | ||||
| 			errString := "" | ||||
| 			if err != nil { | ||||
| 				errString = err.Error() | ||||
| 			} | ||||
|  | ||||
| 			require.Equal(t, tc.ExpectedFileName, filename) | ||||
| 			require.Equal(t, tc.ExpectedErr, errString) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										34
									
								
								sdk/resource/os_unsupported.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								sdk/resource/os_unsupported.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| // +build !aix | ||||
| // +build !darwin | ||||
| // +build !dragonfly | ||||
| // +build !freebsd | ||||
| // +build !linux | ||||
| // +build !netbsd | ||||
| // +build !openbsd | ||||
| // +build !solaris | ||||
| // +build !windows | ||||
| // +build !zos | ||||
|  | ||||
| package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||
|  | ||||
| // platformOSDescription is a placeholder implementation for OSes | ||||
| // for which this project currently doesn't support os.description | ||||
| // attribute detection. See build tags declaration early on this file | ||||
| // for a list of unsupported OSes. | ||||
| func platformOSDescription() (string, error) { | ||||
| 	return "<unknown>", nil | ||||
| } | ||||
							
								
								
									
										101
									
								
								sdk/resource/os_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								sdk/resource/os_windows.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
|  | ||||
| 	"golang.org/x/sys/windows/registry" | ||||
| ) | ||||
|  | ||||
| // platformOSDescription returns a human readable OS version information string. | ||||
| // It does so by querying registry values under the | ||||
| // `SOFTWARE\Microsoft\Windows NT\CurrentVersion` key. The final string | ||||
| // resembles the one displayed by the Version Reporter Applet (winver.exe). | ||||
| func platformOSDescription() (string, error) { | ||||
| 	k, err := registry.OpenKey( | ||||
| 		registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	defer k.Close() | ||||
|  | ||||
| 	var ( | ||||
| 		productName               = readProductName(k) | ||||
| 		displayVersion            = readDisplayVersion(k) | ||||
| 		releaseID                 = readReleaseID(k) | ||||
| 		currentMajorVersionNumber = readCurrentMajorVersionNumber(k) | ||||
| 		currentMinorVersionNumber = readCurrentMinorVersionNumber(k) | ||||
| 		currentBuildNumber        = readCurrentBuildNumber(k) | ||||
| 		ubr                       = readUBR(k) | ||||
| 	) | ||||
|  | ||||
| 	if displayVersion != "" { | ||||
| 		displayVersion += " " | ||||
| 	} | ||||
|  | ||||
| 	return fmt.Sprintf("%s %s(%s) [Version %s.%s.%s.%s]", | ||||
| 		productName, | ||||
| 		displayVersion, | ||||
| 		releaseID, | ||||
| 		currentMajorVersionNumber, | ||||
| 		currentMinorVersionNumber, | ||||
| 		currentBuildNumber, | ||||
| 		ubr, | ||||
| 	), nil | ||||
| } | ||||
|  | ||||
| func getStringValue(name string, k registry.Key) string { | ||||
| 	value, _, _ := k.GetStringValue(name) | ||||
|  | ||||
| 	return value | ||||
| } | ||||
|  | ||||
| func getIntegerValue(name string, k registry.Key) uint64 { | ||||
| 	value, _, _ := k.GetIntegerValue(name) | ||||
|  | ||||
| 	return value | ||||
| } | ||||
|  | ||||
| func readProductName(k registry.Key) string { | ||||
| 	return getStringValue("ProductName", k) | ||||
| } | ||||
|  | ||||
| func readDisplayVersion(k registry.Key) string { | ||||
| 	return getStringValue("DisplayVersion", k) | ||||
| } | ||||
|  | ||||
| func readReleaseID(k registry.Key) string { | ||||
| 	return getStringValue("ReleaseID", k) | ||||
| } | ||||
|  | ||||
| func readCurrentMajorVersionNumber(k registry.Key) string { | ||||
| 	return strconv.FormatUint(getIntegerValue("CurrentMajorVersionNumber", k), 10) | ||||
| } | ||||
|  | ||||
| func readCurrentMinorVersionNumber(k registry.Key) string { | ||||
| 	return strconv.FormatUint(getIntegerValue("CurrentMinorVersionNumber", k), 10) | ||||
| } | ||||
|  | ||||
| func readCurrentBuildNumber(k registry.Key) string { | ||||
| 	return getStringValue("CurrentBuildNumber", k) | ||||
| } | ||||
|  | ||||
| func readUBR(k registry.Key) string { | ||||
| 	return strconv.FormatUint(getIntegerValue("UBR", k), 10) | ||||
| } | ||||
							
								
								
									
										49
									
								
								sdk/resource/os_windows_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								sdk/resource/os_windows_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| package resource_test | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 	"golang.org/x/sys/windows/registry" | ||||
|  | ||||
| 	"go.opentelemetry.io/otel/sdk/resource" | ||||
| ) | ||||
|  | ||||
| func TestPlatformOSDescription(t *testing.T) { | ||||
| 	osDescription, err := resource.PlatformOSDescription() | ||||
|  | ||||
| 	require.NoError(t, err) | ||||
| 	require.Regexp(t, `^(\w+\s)+\(\d+\)\s\[Version\s\d+(\.\d+){3}\]$`, osDescription) | ||||
| } | ||||
|  | ||||
| func TestReadRegistryValues(t *testing.T) { | ||||
| 	k, err := registry.OpenKey( | ||||
| 		registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) | ||||
|  | ||||
| 	require.NoError(t, err, "should open Windows CurrentVersion registry key") | ||||
|  | ||||
| 	defer k.Close() | ||||
|  | ||||
| 	assert.NotEmpty(t, resource.ReadProductName(k), "should read ProductName") | ||||
| 	assert.NotEmpty(t, resource.ReadReleaseID(k), "should read ReleaseID") | ||||
| 	assert.NotEmpty(t, resource.ReadCurrentMajorVersionNumber(k), "should read CurrentMajorVersionNumber") | ||||
| 	assert.NotEmpty(t, resource.ReadCurrentMinorVersionNumber(k), "should read CurrentMinorVersionNumber") | ||||
| 	assert.NotEmpty(t, resource.ReadCurrentBuildNumber(k), "should read CurrentBuildNumber") | ||||
| 	assert.NotEmpty(t, resource.ReadUBR(k), "should read UBR") | ||||
| 	assert.NotPanics(t, func() { resource.ReadDisplayVersion(k) }, "should not panic when reading DisplayVersion") | ||||
| } | ||||
| @@ -97,10 +97,11 @@ func mockProcessAttributesProvidersWithErrors() { | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func restoreProcessAttributesProviders() { | ||||
| func restoreAttributesProviders() { | ||||
| 	resource.SetDefaultOSProviders() | ||||
| 	resource.SetDefaultRuntimeProviders() | ||||
| 	resource.SetDefaultUserProviders() | ||||
| 	resource.SetDefaultOSDescriptionProvider() | ||||
| } | ||||
|  | ||||
| func TestWithProcessFuncs(t *testing.T) { | ||||
| @@ -116,7 +117,7 @@ func TestWithProcessFuncs(t *testing.T) { | ||||
| 	t.Run("WithRuntimeDescription", testWithProcessRuntimeDescription) | ||||
| 	t.Run("WithProcess", testWithProcess) | ||||
|  | ||||
| 	restoreProcessAttributesProviders() | ||||
| 	restoreAttributesProviders() | ||||
| } | ||||
|  | ||||
| func TestWithProcessFuncsErrors(t *testing.T) { | ||||
| @@ -125,7 +126,7 @@ func TestWithProcessFuncsErrors(t *testing.T) { | ||||
| 	t.Run("WithPID", testWithProcessExecutablePathError) | ||||
| 	t.Run("WithExecutableName", testWithProcessOwnerError) | ||||
|  | ||||
| 	restoreProcessAttributesProviders() | ||||
| 	restoreAttributesProviders() | ||||
| } | ||||
|  | ||||
| func TestCommandArgs(t *testing.T) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user