diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0a269668b..9a355b490 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -64,51 +64,6 @@ updates: schedule: interval: weekly day: sunday - - package-ecosystem: docker - directory: /offsets-tracker - labels: - - dependencies - - docker - - Skip Changelog - schedule: - interval: weekly - day: sunday - - package-ecosystem: docker - directory: /test/e2e/databasesql - labels: - - dependencies - - docker - - Skip Changelog - schedule: - interval: weekly - day: sunday - - package-ecosystem: docker - directory: /test/e2e/gin - labels: - - dependencies - - docker - - Skip Changelog - schedule: - interval: weekly - day: sunday - - package-ecosystem: docker - directory: /test/e2e/gorillamux - labels: - - dependencies - - docker - - Skip Changelog - schedule: - interval: weekly - day: sunday - - package-ecosystem: docker - directory: /test/e2e/nethttp - labels: - - dependencies - - docker - - Skip Changelog - schedule: - interval: weekly - day: sunday - package-ecosystem: gomod directory: / labels: @@ -172,48 +127,3 @@ updates: schedule: interval: weekly day: sunday - - package-ecosystem: gomod - directory: /offsets-tracker - labels: - - dependencies - - go - - Skip Changelog - schedule: - interval: weekly - day: sunday - - package-ecosystem: gomod - directory: /test/e2e/databasesql - labels: - - dependencies - - go - - Skip Changelog - schedule: - interval: weekly - day: sunday - - package-ecosystem: gomod - directory: /test/e2e/gin - labels: - - dependencies - - go - - Skip Changelog - schedule: - interval: weekly - day: sunday - - package-ecosystem: gomod - directory: /test/e2e/gorillamux - labels: - - dependencies - - go - - Skip Changelog - schedule: - interval: weekly - day: sunday - - package-ecosystem: gomod - directory: /test/e2e/nethttp - labels: - - dependencies - - go - - Skip Changelog - schedule: - interval: weekly - day: sunday diff --git a/.github/workflows/kind.yml b/.github/workflows/kind.yml index 19f79ab15..b4174348b 100644 --- a/.github/workflows/kind.yml +++ b/.github/workflows/kind.yml @@ -30,7 +30,7 @@ jobs: IMG=otel-go-instrumentation:latest make docker-build - name: Build sample app run: | - cd test/e2e/${{ matrix.library }} + cd internal/test/e2e/${{ matrix.library }} docker build -t sample-app:latest . - name: Set up Helm uses: azure/setup-helm@v3.5 @@ -71,8 +71,8 @@ jobs: kubectl wait --for=condition=Complete --timeout=60s job/sample-job - name: copy telemetry trace output run: | - kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./test/e2e/${{ matrix.library }}/traces-orig.json - rm -f ./test/e2e/${{ matrix.library }}/traces.json + kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./internal/test/e2e/${{ matrix.library }}/traces-orig.json + rm -f ./internal/test/e2e/${{ matrix.library }}/traces.json - name: verify output and redact to traces.json run: | - bats ./test/e2e/${{ matrix.library }}/verify.bats + bats ./internal/test/e2e/${{ matrix.library }}/verify.bats diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b9018998..52ac1b4fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,30 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http ### Removed +- The deprecated `go.opentelemetry.io/auto/offsets-tracker` module is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/instrumentors/bpf/github.com/gorilla/mux` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/test/e2e/gorillamux` module is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/inject` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/errors` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/process` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/process/ptrace` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/opentelemetry` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/instrumentors/bpf/net/http/client` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/instrumentors/bpf/net/http/server` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/instrumentors/bpf/github.com/gin-gonic/gin` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/instrumentors/bpf/github.com/gorilla/mux` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/instrumentors/bpf/google/golang/org/grpc` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/instrumentors/bpf/google/golang/org/grpc/server` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/instrumentors/utils` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/instrumentors/context` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/instrumentors` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/instrumentors/allocator` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/instrumentors/bpffs` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/instrumentors/events` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/pkg/log` package is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/test/e2e/gin` module is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/test/e2e/gorillamux` module is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) +- The deprecated `go.opentelemetry.io/auto/test/e2e/nethttp` module is removed. ([#302](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/302)) - The deprecated instrumentation support for `github.com/gorilla/mux` is removed. ([#303](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/303)) ## [v0.3.0-alpha] - 2023-09-12 diff --git a/Makefile b/Makefile index 07e53429e..363fe5959 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,7 @@ docker-build: .PHONY: offsets offsets: | $(OFFSETS) - OFFSETS_OUTPUT_FILE="$(REPODIR)/pkg/inject/offset_results.json" $(OFFSETS) + OFFSETS_OUTPUT_FILE="$(REPODIR)/internal/pkg/inject/offset_results.json" $(OFFSETS) .PHONY: docker-offsets docker-offsets: diff --git a/internal/pkg/inject/offset_results.json b/internal/pkg/inject/offset_results.json index 96a46f9ec..521b2f675 100755 --- a/internal/pkg/inject/offset_results.json +++ b/internal/pkg/inject/offset_results.json @@ -172,7 +172,7 @@ "Header": { "versions": { "oldest": "1.12.0", - "newest": "1.21.0" + "newest": "1.21.1" }, "offsets": [ { @@ -184,7 +184,7 @@ "Method": { "versions": { "oldest": "1.12.0", - "newest": "1.21.0" + "newest": "1.21.1" }, "offsets": [ { @@ -196,7 +196,7 @@ "RemoteAddr": { "versions": { "oldest": "1.12.0", - "newest": "1.21.0" + "newest": "1.21.1" }, "offsets": [ { @@ -208,7 +208,7 @@ "URL": { "versions": { "oldest": "1.12.0", - "newest": "1.21.0" + "newest": "1.21.1" }, "offsets": [ { @@ -220,7 +220,7 @@ "ctx": { "versions": { "oldest": "1.12.0", - "newest": "1.21.0" + "newest": "1.21.1" }, "offsets": [ { @@ -248,7 +248,7 @@ "goid": { "versions": { "oldest": "1.12.0", - "newest": "1.21.0" + "newest": "1.21.1" }, "offsets": [ { diff --git a/offsets-tracker/.gitignore b/offsets-tracker/.gitignore deleted file mode 100644 index 9f11b755a..000000000 --- a/offsets-tracker/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.idea/ diff --git a/offsets-tracker/Dockerfile b/offsets-tracker/Dockerfile deleted file mode 100644 index e1d7b0c8d..000000000 --- a/offsets-tracker/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM golang:1.20 -COPY . /offsets-tracker -WORKDIR /offsets-tracker -RUN go build -o offsets-tracker -ENTRYPOINT ["/offsets-tracker/offsets-tracker"] \ No newline at end of file diff --git a/offsets-tracker/LICENSE b/offsets-tracker/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/offsets-tracker/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/offsets-tracker/README.md b/offsets-tracker/README.md deleted file mode 100644 index 8d2ee3046..000000000 --- a/offsets-tracker/README.md +++ /dev/null @@ -1,100 +0,0 @@ -# offsets-tracker - -**Deprecated**: This module is no longer supported. - -This project tracks offsets of fields inside of Go structs across versions. - -This tracking is needed in order to create a [stable eBPF based instrumentation](https://github.com/keyval-dev/opentelemetry-go-instrumentation/blob/master/docs/how-it-works.md#instrumentation-stability). - -Calculating offsets is accomplished by creating a binary file containing the relevant struct and analyzing its DWARF information. -## Tracking targets - -The `main.go` file specifies all the tracking targets. -Each tracking target has a name which can be either a fully qualified go module name or `go` for tracking parameters in the standard library. - -For example, in order to track the `URL` field inside the `net/http.Request` struct in the Go standard library we register the following target: -```go -target.New("go"). - FindOffsets([]*binary.DataMember{ - { - StructName: "net/http.Request", - Field: "URL", - }, - }) -``` - -## Output - -offsets-tracker writes all the tracked offsets into a file named `offset_results.json`. -For example, here is the tracking of `method` field inside `transport.Stream` struct in the `google.golang.org/grpc` module: -```go -{ - "name": "google.golang.org/grpc", - "data_members": [ - { - "struct": "google.golang.org/grpc/internal/transport.Stream", - "field_name": "method", - "offsets": [ - { - "offset": 72, - "version": "v1.0.2" - }, - { - "offset": 72, - "version": "v1.0.3" - }, - { - "offset": 72, - "version": "v1.0.4" - }, - { - "offset": 80, - "version": "v1.3.0" - }, - { - "offset": 80, - "version": "v1.4.0" - }, -``` - -## Versions Discovery - -By default, offsets-tracker finds available versions by executing `go list -versions `. - -Unfortunately, Go standard library versions are not discoverable via `go list`. -In order to discover Go versions, the offsets-tracker fetch the versions published at `https://go.dev/dl`. -Fetching `go.dev` for discovering versions can be enabled by setting`.FindVersionsBy(target.GoDevFileVersionsStrategy)` when registering a new target. - -## Download Strategy - -offsets-tracker wraps every Go module version as a Go application that depends on that module. -Those applications are the result of [generating template files](./downloader/wrapper) with the appropriate version. - -In the case of the Go standard library, the offsets-tracker creates a dummy application that depends on the specific library. For example - -```go -import ( - _ "net/http" -) -``` - -## Version Constraints - -offsets-tracker downloads and compiles every version found in the previous step by default. -Some targets do not require support for very old versions. Add the following to limit the version scope: -```go -minimunGoVersion, err := version.NewConstraint(">= 1.12") - -target.New('go') -... -VersionConstraint(&minimunGoVersion) -``` - -## Project Status - -This project is currently in Alpha. -Check out our [issues section](https://github.com/open-telemetry/opentelemetry-go-instrumentation/issues) to learn more about improvements we're working on. - -## License - -This project is licensed under the terms of the Apache 2.0 open source license. Please refer to [LICENSE](LICENSE) for the full terms. diff --git a/offsets-tracker/binary/data_member.go b/offsets-tracker/binary/data_member.go deleted file mode 100644 index e6054483e..000000000 --- a/offsets-tracker/binary/data_member.go +++ /dev/null @@ -1,74 +0,0 @@ -// 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 binary - -import ( - "debug/dwarf" - "io" -) - -func findDataMemberOffset(dwarfData *dwarf.Data, dm *DataMember) (int64, bool) { - reader := dwarfData.Reader() - for { - entry, err := reader.Next() - if err == io.EOF || entry == nil { - break - } - - if entry.Tag == dwarf.TagStructType { - // Go through fields - for _, field := range entry.Field { - if field.Attr == dwarf.AttrName { - str := field.Val.(string) - if str == dm.StructName { - return findFieldOffset(reader, dm.Field) - } - } - } - } - } - - return 0, false -} - -func findFieldOffset(reader *dwarf.Reader, field string) (int64, bool) { - for { - entry, err := reader.Next() - if err == io.EOF || entry == nil { - break - } - - for _, f := range entry.Field { - if f.Attr == dwarf.AttrName { - str := f.Val.(string) - if str == field { - return findOffsetByEntry(entry) - } - } - } - } - - return 0, false -} - -func findOffsetByEntry(entry *dwarf.Entry) (int64, bool) { - for _, field := range entry.Field { - if field.Attr == dwarf.AttrDataMemberLoc { - return field.Val.(int64), true - } - } - - return 0, false -} diff --git a/offsets-tracker/binary/reader.go b/offsets-tracker/binary/reader.go deleted file mode 100644 index c6d35f838..000000000 --- a/offsets-tracker/binary/reader.go +++ /dev/null @@ -1,71 +0,0 @@ -// 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 binary provides utilities to handle binary file offset analysis. -// -// Deprecated: This package is no longer supported. -package binary - -import ( - "debug/elf" - "errors" - "os" -) - -// DataMember defines a data structure. -type DataMember struct { - StructName string - Field string -} - -// DataMemberOffset is the offset of a DataMember. -type DataMemberOffset struct { - *DataMember - Offset uint64 -} - -// Results are all the returned offsets for a data member. -type Result struct { - DataMembers []*DataMemberOffset -} - -// ErrOffsetsNotFound is returned when the requested offsets cannot be found. -var ErrOffsetsNotFound = errors.New("could not find offset") - -// FindOffsets finds all the dataMembers offsets. -func FindOffsets(file *os.File, dataMembers []*DataMember) (*Result, error) { - elfF, err := elf.NewFile(file) - if err != nil { - return nil, err - } - - dwarfData, err := elfF.DWARF() - if err != nil { - return nil, err - } - - result := &Result{} - for _, dm := range dataMembers { - offset, found := findDataMemberOffset(dwarfData, dm) - if !found { - return nil, ErrOffsetsNotFound - } - result.DataMembers = append(result.DataMembers, &DataMemberOffset{ - DataMember: dm, - Offset: uint64(offset), - }) - } - - return result, nil -} diff --git a/offsets-tracker/cache/cache.go b/offsets-tracker/cache/cache.go deleted file mode 100644 index afb1b86af..000000000 --- a/offsets-tracker/cache/cache.go +++ /dev/null @@ -1,118 +0,0 @@ -// 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 cache provides offset caching utilities. -// -// Deprecated: This package is no longer supported. -package cache - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "log" - "os" - - "github.com/hashicorp/go-version" - - "go.opentelemetry.io/auto/offsets-tracker/binary" // nolint:staticcheck // atomic deprecation. - "go.opentelemetry.io/auto/offsets-tracker/schema" // nolint:staticcheck // atomic deprecation. - "go.opentelemetry.io/auto/offsets-tracker/versions" // nolint:staticcheck // atomic deprecation. -) - -// Cache holds already seen offsets. -type Cache struct { - data *schema.TrackedOffsets -} - -// NewCache returns a new [Cache]. -func NewCache(prevOffsetFile string) *Cache { - f, err := os.Open(prevOffsetFile) - if err != nil { - fmt.Println("could not find existing offset file, cache will be empty") - return nil - } - - defer f.Close() - data, err := ioutil.ReadAll(f) - if err != nil { - log.Printf("error reading existing offsets file: %v. Ignoring existing file.\n", err) - return nil - } - - var offsets schema.TrackedOffsets - err = json.Unmarshal(data, &offsets) - if err != nil { - log.Printf("error parsing existing offsets file: %v Ignoring existing file.\n", err) - return nil - } - - return &Cache{ - data: &offsets, - } -} - -// IsAllInCache checks whether the passed datamembers exist in the cache for a -// given version. -func (c *Cache) IsAllInCache(version string, dataMembers []*binary.DataMember) ([]*binary.DataMemberOffset, bool) { - var results []*binary.DataMemberOffset - for _, dm := range dataMembers { - // first, look for the field and check that the target version is in - // chache. - strct, ok := c.data.Data[dm.StructName] - if !ok { - return nil, false - } - field, ok := strct[dm.Field] - if !ok { - return nil, false - } - if !versions.Between(version, field.Versions.Oldest, field.Versions.Newest) { - return nil, false - } - - off, ok := searchOffset(field, version) - if !ok { - return nil, false - } - results = append(results, &binary.DataMemberOffset{ - DataMember: dm, - Offset: off, - }) - } - return results, true -} - -// searchOffset searches an offset from the newest field whose version -// is lower than or equal to the target version. -func searchOffset(field schema.TrackedField, targetVersion string) (uint64, bool) { - target := versions.MustParse(targetVersion) - - // Search from the newest version - for o := len(field.Offsets) - 1; o >= 0; o-- { - od := &field.Offsets[o] - fieldVersion, err := version.NewVersion(od.Since) - if err != nil { - // Malformed version: return not found - return 0, false - } - if target.Compare(fieldVersion) >= 0 { - // if target version is larger or equal than lib version: - // we certainly know that it is the most recent tracked offset - return od.Offset, true - } - } - - return 0, false -} diff --git a/offsets-tracker/downloader/go_wrapper.go b/offsets-tracker/downloader/go_wrapper.go deleted file mode 100644 index e738e6141..000000000 --- a/offsets-tracker/downloader/go_wrapper.go +++ /dev/null @@ -1,80 +0,0 @@ -// 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 downloader provides downloading utilities. -// -// Deprecated: This package is no longer supported. -package downloader - -import ( - _ "embed" - "fmt" - "io/fs" - "os" - "path" - - "go.opentelemetry.io/auto/offsets-tracker/utils" // nolint:staticcheck // atomic deprecation. -) - -const appName = "testapp" - -var ( - //go:embed wrapper/go.mod.txt - goMod string - - //go:embed wrapper/go.modstd.txt - goModStdLib string - - //go:embed wrapper/main.go.txt - goMain string -) - -// DownloadBinary downloads the module with modName at version. -// revive:disable-next-line:flag-parameter -func DownloadBinary(modName string, version string, isGoStandartLib bool) (string, string, error) { - dir, err := os.MkdirTemp("", appName) - if err != nil { - return "", "", err - } - - var goModContent string - if isGoStandartLib { - goModContent = fmt.Sprintf(goModStdLib, version) - } else { - goModContent = fmt.Sprintf(goMod, modName, version) - } - - err = os.WriteFile(path.Join(dir, "go.mod"), []byte(goModContent), fs.ModePerm) - if err != nil { - return "", "", err - } - - goMainContent := fmt.Sprintf(goMain, modName) - err = os.WriteFile(path.Join(dir, "main.go"), []byte(goMainContent), fs.ModePerm) - if err != nil { - return "", "", err - } - - _, _, err = utils.RunCommand("go mod tidy -compat=1.17", dir) - if err != nil { - return "", "", err - } - - _, _, err = utils.RunCommand(fmt.Sprintf("GOOS=linux GOARCH=amd64 go build -o %s", appName), dir) - if err != nil { - return "", "", err - } - - return path.Join(dir, appName), dir, nil -} diff --git a/offsets-tracker/downloader/remote_targz.go b/offsets-tracker/downloader/remote_targz.go deleted file mode 100644 index dd5134fa0..000000000 --- a/offsets-tracker/downloader/remote_targz.go +++ /dev/null @@ -1,61 +0,0 @@ -// 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 downloader - -import ( - "fmt" - "io" - "io/ioutil" - "net/http" - "os" - "path" - - "go.opentelemetry.io/auto/offsets-tracker/utils" // nolint:staticcheck // atomic deprecation. -) - -const ( - urlPattern = "https://go.dev/dl/go%s.linux-amd64.tar.gz" -) - -// DownloadBinaryFromRemote returns the downloaded Go binary at version from -// https://go.dev/dl/. -func DownloadBinaryFromRemote(_ string, version string) (string, string, error) { - dir, err := ioutil.TempDir("", version) - if err != nil { - return "", "", err - } - dest, err := os.Create(path.Join(dir, "go.tar.gz")) - if err != nil { - return "", "", err - } - defer dest.Close() - - resp, err := http.Get(fmt.Sprintf(urlPattern, version)) - if err != nil { - return "", "", err - } - defer resp.Body.Close() - _, err = io.Copy(dest, resp.Body) - if err != nil { - return "", "", err - } - - _, _, err = utils.RunCommand("tar -xf go.tar.gz -C .", dir) - if err != nil { - return "", "", err - } - - return fmt.Sprintf("%s/go/bin/go", dir), dir, nil -} diff --git a/offsets-tracker/downloader/wrapper/go.mod.txt b/offsets-tracker/downloader/wrapper/go.mod.txt deleted file mode 100644 index 24905f048..000000000 --- a/offsets-tracker/downloader/wrapper/go.mod.txt +++ /dev/null @@ -1,5 +0,0 @@ -module testapp - -go 1.19 - -require %s %s \ No newline at end of file diff --git a/offsets-tracker/downloader/wrapper/go.modstd.txt b/offsets-tracker/downloader/wrapper/go.modstd.txt deleted file mode 100644 index 4e0829122..000000000 --- a/offsets-tracker/downloader/wrapper/go.modstd.txt +++ /dev/null @@ -1,3 +0,0 @@ -module testapp - -go %s \ No newline at end of file diff --git a/offsets-tracker/downloader/wrapper/main.go.txt b/offsets-tracker/downloader/wrapper/main.go.txt deleted file mode 100644 index cfc277d48..000000000 --- a/offsets-tracker/downloader/wrapper/main.go.txt +++ /dev/null @@ -1,7 +0,0 @@ -package main - -import ( - _ "%s" -) - -func main() {} \ No newline at end of file diff --git a/offsets-tracker/go.mod b/offsets-tracker/go.mod deleted file mode 100644 index 4c5f14b08..000000000 --- a/offsets-tracker/go.mod +++ /dev/null @@ -1,6 +0,0 @@ -// Deprecated: This module is no longer supported. -module go.opentelemetry.io/auto/offsets-tracker - -go 1.17 - -require github.com/hashicorp/go-version v1.6.0 diff --git a/offsets-tracker/go.sum b/offsets-tracker/go.sum deleted file mode 100644 index 805e323fb..000000000 --- a/offsets-tracker/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= diff --git a/offsets-tracker/main.go b/offsets-tracker/main.go deleted file mode 100644 index 6225ffb52..000000000 --- a/offsets-tracker/main.go +++ /dev/null @@ -1,159 +0,0 @@ -// 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 main - -import ( - "flag" - "fmt" - "log" - "os" - - "github.com/hashicorp/go-version" - - "go.opentelemetry.io/auto/offsets-tracker/binary" // nolint:staticcheck // atomic deprecation. - "go.opentelemetry.io/auto/offsets-tracker/target" // nolint:staticcheck // atomic deprecation. - "go.opentelemetry.io/auto/offsets-tracker/writer" // nolint:staticcheck // atomic deprecation. -) - -const ( - defaultOutputFile = "/tmp/offset_results.json" -) - -func main() { - outputFilename := defaultOutputFile - if len(os.Getenv("OFFSETS_OUTPUT_FILE")) > 0 { - outputFilename = os.Getenv("OFFSETS_OUTPUT_FILE") - } - outputFile := flag.String("output", outputFilename, "output file") - flag.Parse() - - minimunGoVersion, err := version.NewConstraint(">= 1.12") - if err != nil { - log.Fatalf("error in parsing version constraint: %v\n", err) - } - - stdLibRuntimeOffsets, err := target.New("runtime", *outputFile, true). - FindVersionsBy(target.GoDevFileVersionsStrategy). - DownloadBinaryBy(target.WrapAsGoAppBinaryFetchStrategy). - VersionConstraint(&minimunGoVersion). - FindOffsets([]*binary.DataMember{ - { - StructName: "runtime.g", - Field: "goid", - }, - }) - - if err != nil { - log.Fatalf("error while fetching offsets for \"runtime\": %v\n", err) - } - - stdLibNetHTTPOffsets, err := target.New("net/http", *outputFile, true). - FindVersionsBy(target.GoDevFileVersionsStrategy). - DownloadBinaryBy(target.WrapAsGoAppBinaryFetchStrategy). - VersionConstraint(&minimunGoVersion). - FindOffsets([]*binary.DataMember{ - { - StructName: "net/http.Request", - Field: "Method", - }, - { - StructName: "net/http.Request", - Field: "URL", - }, - { - StructName: "net/http.Request", - Field: "RemoteAddr", - }, - { - StructName: "net/http.Request", - Field: "Header", - }, - { - StructName: "net/http.Request", - Field: "ctx", - }, - }) - - if err != nil { - log.Fatalf("error while fetching offsets for \"net/http\": %v\n", err) - } - - stdLibNetURLOffsets, err := target.New("net/url", *outputFile, true). - FindVersionsBy(target.GoDevFileVersionsStrategy). - DownloadBinaryBy(target.WrapAsGoAppBinaryFetchStrategy). - VersionConstraint(&minimunGoVersion). - FindOffsets([]*binary.DataMember{ - { - StructName: "net/url.URL", - Field: "Path", - }, - }) - - if err != nil { - log.Fatalf("error while fetching offsets for \"net/url\": %v\n", err) - } - - grpcOffsets, err := target.New("google.golang.org/grpc", *outputFile, false). - FindOffsets([]*binary.DataMember{ - { - StructName: "google.golang.org/grpc/internal/transport.Stream", - Field: "method", - }, - { - StructName: "google.golang.org/grpc/internal/transport.Stream", - Field: "id", - }, - { - StructName: "google.golang.org/grpc/internal/transport.Stream", - Field: "ctx", - }, - { - StructName: "google.golang.org/grpc.ClientConn", - Field: "target", - }, - { - StructName: "golang.org/x/net/http2.MetaHeadersFrame", - Field: "Fields", - }, - { - StructName: "golang.org/x/net/http2.FrameHeader", - Field: "StreamID", - }, - { - StructName: "google.golang.org/grpc/internal/transport.http2Client", - Field: "nextID", - }, - { - StructName: "google.golang.org/grpc/internal/transport.headerFrame", - Field: "streamID", - }, - { - StructName: "google.golang.org/grpc/internal/transport.headerFrame", - Field: "hf", - }, - }) - - if err != nil { - log.Fatalf("error while fetching offsets: %v\n", err) - } - - fmt.Println("Done collecting offsets, writing results to file ...") - err = writer.WriteResults(*outputFile, stdLibRuntimeOffsets, stdLibNetHTTPOffsets, stdLibNetURLOffsets, grpcOffsets) - if err != nil { - log.Fatalf("error while writing results to file: %v\n", err) - } - - fmt.Println("Done!") -} diff --git a/offsets-tracker/schema/schema.go b/offsets-tracker/schema/schema.go deleted file mode 100644 index 0dc1b8830..000000000 --- a/offsets-tracker/schema/schema.go +++ /dev/null @@ -1,49 +0,0 @@ -// 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 schema provides a data-model for offsets. -// -// Deprecated: This package is no longer supported. -package schema - -// TrackedOffsets are all the tracked offsets. -type TrackedOffsets struct { - // Data key: struct name, which includes the library name in external - // libraries. - Data map[string]TrackedStruct `json:"data"` -} - -// TrackedStruct maps fields names to the tracked fields offsets. -type TrackedStruct map[string]TrackedField - -// TrackedField are the field offsets for a tracked struct. -type TrackedField struct { - // Versions range that are tracked for this given field. - Versions VersionInfo `json:"versions"` - // Offsets are the sorted version offsets for the field. These need to be - // sorted in descending order. - Offsets []VersionedOffset `json:"offsets"` -} - -// VersionInfo is the span of supported versions. -type VersionInfo struct { - Oldest string `json:"oldest"` - Newest string `json:"newest"` -} - -// VersionedOffset if a offset for a version of a module. -type VersionedOffset struct { - Offset uint64 `json:"offset"` - Since string `json:"since"` -} diff --git a/offsets-tracker/target/target.go b/offsets-tracker/target/target.go deleted file mode 100644 index 4a8b0a28f..000000000 --- a/offsets-tracker/target/target.go +++ /dev/null @@ -1,211 +0,0 @@ -// 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 target provides Go code offset discovery utilities. -// -// Deprecated: This package is no longer supported. -package target - -import ( - "fmt" - "os" - - "github.com/hashicorp/go-version" - - "go.opentelemetry.io/auto/offsets-tracker/binary" // nolint:staticcheck // atomic deprecation. - "go.opentelemetry.io/auto/offsets-tracker/cache" // nolint:staticcheck // atomic deprecation. - "go.opentelemetry.io/auto/offsets-tracker/downloader" // nolint:staticcheck // atomic deprecation. - "go.opentelemetry.io/auto/offsets-tracker/versions" // nolint:staticcheck // atomic deprecation. -) - -// VersionsStrategy is a strategy used when determining the version of a Go -// module. -type VersionsStrategy int - -// BinaryFetchStrategy is a strategy used when fetching executable binaries. -type BinaryFetchStrategy int - -// Target parsing strategies. -const ( - GoListVersionsStrategy VersionsStrategy = 0 - GoDevFileVersionsStrategy VersionsStrategy = 1 - - WrapAsGoAppBinaryFetchStrategy BinaryFetchStrategy = 0 - DownloadPreCompiledBinaryFetchStrategy BinaryFetchStrategy = 1 -) - -// Result are all the offsets for a module. -type Result struct { - ModuleName string - ResultsByVersion []*VersionedResult -} - -// VersionedResult is the offset for a version of a module. -type VersionedResult struct { - Version string - OffsetData *binary.Result -} - -// Data represents the target Go module data. -type Data struct { - name string - isGoStdlib bool - versionsStrategy VersionsStrategy - binaryFetchStrategy BinaryFetchStrategy - versionConstraint *version.Constraints - cache *cache.Cache -} - -// New returns a new Data. -func New(name string, fileName string, isStdlib bool) *Data { - return &Data{ - name: name, - versionsStrategy: GoListVersionsStrategy, - binaryFetchStrategy: WrapAsGoAppBinaryFetchStrategy, - cache: cache.NewCache(fileName), - isGoStdlib: isStdlib, - } -} - -// VersionConstraint sets the version constraint used to constraint. -func (t *Data) VersionConstraint(constraint *version.Constraints) *Data { - t.versionConstraint = constraint - return t -} - -// FindVersionsBy sets the VersionsStrategy used. -func (t *Data) FindVersionsBy(strategy VersionsStrategy) *Data { - t.versionsStrategy = strategy - return t -} - -// DownloadBinaryBy sets the BinaryFetchStrategy used. -func (t *Data) DownloadBinaryBy(strategy BinaryFetchStrategy) *Data { - t.binaryFetchStrategy = strategy - return t -} - -// FindOffsets returns all the offsets found based on dm. -func (t *Data) FindOffsets(dm []*binary.DataMember) (*Result, error) { - fmt.Printf("%s: Discovering available versions\n", t.name) - vers, err := t.findVersions() - if err != nil { - return nil, err - } - - result := &Result{ - ModuleName: t.name, - } - for _, v := range vers { - if t.cache != nil { - cachedResults, found := t.cache.IsAllInCache(v, dm) - if found { - fmt.Printf("%s: Found all requested offsets in cache for version %s\n", t.name, v) - result.ResultsByVersion = append(result.ResultsByVersion, &VersionedResult{ - Version: v, - OffsetData: &binary.Result{ - DataMembers: cachedResults, - }, - }) - continue - } - } - - fmt.Printf("%s: Downloading version %s\n", t.name, v) - exePath, dir, err := t.downloadBinary(t.name, v) - if err != nil { - return nil, err - } - - fmt.Printf("%s: Analyzing binary for version %s\n", t.name, v) - res, err := t.analyzeFile(exePath, dm) - if err == binary.ErrOffsetsNotFound { - fmt.Printf("%s: could not find offsets for version %s\n", t.name, v) - } else if err != nil { - return nil, err - } else { - result.ResultsByVersion = append(result.ResultsByVersion, &VersionedResult{ - Version: v, - OffsetData: res, - }) - } - - _ = os.RemoveAll(dir) - } - - return result, nil -} - -func (t *Data) analyzeFile(exePath string, dm []*binary.DataMember) (*binary.Result, error) { - f, err := os.Open(exePath) - if err != nil { - return nil, err - } - defer f.Close() - - res, err := binary.FindOffsets(f, dm) - if err != nil { - return nil, err - } - - return res, nil -} - -func (t *Data) findVersions() ([]string, error) { - var vers []string - var err error - switch t.versionsStrategy { - case GoListVersionsStrategy: - vers, err = versions.FindVersionsUsingGoList(t.name) - if err != nil { - return nil, err - } - case GoDevFileVersionsStrategy: - vers, err = versions.FindVersionsFromGoWebsite() - if err != nil { - return nil, err - } - default: - return nil, fmt.Errorf("unsupported version strategy") - } - - if t.versionConstraint == nil { - return vers, nil - } - - var filteredVers []string - for _, v := range vers { - semver, err := version.NewVersion(v) - if err != nil { - return nil, err - } - - if t.versionConstraint.Check(semver) { - filteredVers = append(filteredVers, v) - } - } - - return filteredVers, nil -} - -func (t *Data) downloadBinary(modName string, version string) (string, string, error) { - switch t.binaryFetchStrategy { - case WrapAsGoAppBinaryFetchStrategy: - return downloader.DownloadBinary(modName, version, t.isGoStdlib) - case DownloadPreCompiledBinaryFetchStrategy: - return downloader.DownloadBinaryFromRemote(modName, version) - } - - return "", "", fmt.Errorf("unsupported binary fetch strategy") -} diff --git a/offsets-tracker/utils/cmd.go b/offsets-tracker/utils/cmd.go deleted file mode 100644 index 429050d02..000000000 --- a/offsets-tracker/utils/cmd.go +++ /dev/null @@ -1,41 +0,0 @@ -// 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 utils provides a wrapper around "os/exec". -// -// Deprecated: This package is no longer supported. -package utils - -import ( - "bytes" - "os/exec" -) - -// ShellToUse is the shell flavor used to run commands. -const ShellToUse = "bash" - -// RunCommand runs command in dir. -func RunCommand(command string, dir string) (string, string, error) { - var stdout bytes.Buffer - var stderr bytes.Buffer - cmd := exec.Command(ShellToUse, "-c", command) - if dir != "" { - cmd.Dir = dir - } - - cmd.Stdout = &stdout - cmd.Stderr = &stderr - err := cmd.Run() - return stdout.String(), stderr.String(), err -} diff --git a/offsets-tracker/versions/go_list.go b/offsets-tracker/versions/go_list.go deleted file mode 100644 index 40c94a3c1..000000000 --- a/offsets-tracker/versions/go_list.go +++ /dev/null @@ -1,44 +0,0 @@ -// 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 versions - -import ( - "encoding/json" - "fmt" - - "go.opentelemetry.io/auto/offsets-tracker/utils" // nolint:staticcheck // atomic deprecation. -) - -type goListResponse struct { - Path string `json:"Path"` - Versions []string `json:"versions"` -} - -// FindVersionsUsingGoList returns all locally known version of module with -// moduleName. -func FindVersionsUsingGoList(moduleName string) ([]string, error) { - stdout, _, err := utils.RunCommand(fmt.Sprintf("go list -m -json -versions %s", moduleName), "") - if err != nil { - return nil, err - } - - resp := goListResponse{} - err = json.Unmarshal([]byte(stdout), &resp) - if err != nil { - return nil, err - } - - return resp.Versions, nil -} diff --git a/offsets-tracker/versions/golang_org.go b/offsets-tracker/versions/golang_org.go deleted file mode 100644 index 55ccece05..000000000 --- a/offsets-tracker/versions/golang_org.go +++ /dev/null @@ -1,62 +0,0 @@ -// 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 versions - -import ( - "encoding/json" - "io/ioutil" - "net/http" - "strings" -) - -const ( - jsonURL = "https://go.dev/dl/?mode=json&include=all" -) - -type goDevResponse struct { - Version string `json:"version"` - Stable bool `json:"stable"` -} - -// FindVersionsFromGoWebsite returns all known Go versions from the Go package -// mirror at https://go.dev/dl/. -func FindVersionsFromGoWebsite() ([]string, error) { - res, err := http.Get(jsonURL) - if err != nil { - return nil, err - } - defer res.Body.Close() - - data, err := ioutil.ReadAll(res.Body) - if err != nil { - return nil, err - } - - var resp []goDevResponse - err = json.Unmarshal(data, &resp) - if err != nil { - return nil, err - } - - var versions []string - for _, v := range resp { - if v.Stable { - stripepdV := strings.ReplaceAll(v.Version, "go", "") - versions = append(versions, stripepdV) - } - } - - return versions, nil -} diff --git a/offsets-tracker/versions/tools.go b/offsets-tracker/versions/tools.go deleted file mode 100644 index 706a18f11..000000000 --- a/offsets-tracker/versions/tools.go +++ /dev/null @@ -1,41 +0,0 @@ -// 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 versions provides versioning utilities. -// -// Deprecated: This package is no longer supported. -package versions - -import "github.com/hashicorp/go-version" - -// Between returns if the target contains a version between the lowerBound and -// higherBound. -func Between(target, lowerBound, higherBound string) bool { - v := MustParse(target) - - return v.GreaterThanOrEqual(MustParse(lowerBound)) && - v.LessThanOrEqual(MustParse(higherBound)) -} - -// MustParse must be used with versions that are embedded in the code or generated by us, -// so we are sure that the format is correct. For versions that are provided by a user -// we should handle properly the error. -func MustParse(v string) *version.Version { - p, err := version.NewVersion(v) - if err != nil { - // if we reach this point, there must be a bug so we panic - panic(err) - } - return p -} diff --git a/offsets-tracker/writer/writer.go b/offsets-tracker/writer/writer.go deleted file mode 100644 index 933422b3e..000000000 --- a/offsets-tracker/writer/writer.go +++ /dev/null @@ -1,133 +0,0 @@ -// 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 writer provides offset writing utilities. -// -// Deprecated: This package is no longer supported. -package writer - -import ( - "bytes" - "encoding/json" - "fmt" - "io/fs" - "os" - "sort" - "strings" - - "github.com/hashicorp/go-version" - - "go.opentelemetry.io/auto/offsets-tracker/schema" // nolint:staticcheck // atomic deprecation. - "go.opentelemetry.io/auto/offsets-tracker/target" // nolint:staticcheck // atomic deprecation. - "go.opentelemetry.io/auto/offsets-tracker/versions" // nolint:staticcheck // atomic deprecation. -) - -// WriteResults writes results to fileName. -func WriteResults(fileName string, results ...*target.Result) error { - offsets := schema.TrackedOffsets{ - Data: map[string]schema.TrackedStruct{}, - } - for _, r := range results { - convertResult(r, &offsets) - } - - jsonData, err := json.Marshal(&offsets) - if err != nil { - return err - } - - var prettyJSON bytes.Buffer - err = json.Indent(&prettyJSON, jsonData, "", " ") - if err != nil { - return err - } - - return os.WriteFile(fileName, prettyJSON.Bytes(), fs.ModePerm) -} - -func convertResult(r *target.Result, offsets *schema.TrackedOffsets) { - offsetsMap := make(map[string][]schema.VersionedOffset) - for _, vr := range r.ResultsByVersion { - for _, od := range vr.OffsetData.DataMembers { - key := fmt.Sprintf("%s,%s", od.StructName, od.Field) - offsetsMap[key] = append(offsetsMap[key], schema.VersionedOffset{ - Offset: od.Offset, - Since: vr.Version, - }) - } - } - - // normalize offsets: just annotate the offsets from the version - // that changed them - fieldVersionsMap := map[string]hiLoSemVers{} - for key, offs := range offsetsMap { - if len(offs) == 0 { - continue - } - // the algorithm below assumes offsets versions are sorted from older to newer - sort.Slice(offs, func(i, j int) bool { - return versions.MustParse(offs[i].Since). - LessThanOrEqual(versions.MustParse(offs[j].Since)) - }) - - hilo := hiLoSemVers{} - var om []schema.VersionedOffset - var last schema.VersionedOffset - for n, off := range offs { - hilo.updateModuleVersion(off.Since) - // only append versions that changed the field value from its predecessor - if n == 0 || off.Offset != last.Offset { - om = append(om, off) - } - last = off - } - offsetsMap[key] = om - fieldVersionsMap[key] = hilo - } - - // Append offsets as fields to the existing file map map - for key, offs := range offsetsMap { - parts := strings.Split(key, ",") - strFields, ok := offsets.Data[parts[0]] - if !ok { - strFields = schema.TrackedStruct{} - offsets.Data[parts[0]] = strFields - } - hl := fieldVersionsMap[key] - strFields[parts[1]] = schema.TrackedField{ - Offsets: offs, - Versions: schema.VersionInfo{ - Oldest: hl.lo.String(), - Newest: hl.hi.String(), - }, - } - } -} - -// hiLoSemVers track highest and lowest version. -type hiLoSemVers struct { - hi *version.Version - lo *version.Version -} - -func (hl *hiLoSemVers) updateModuleVersion(vr string) { - ver := versions.MustParse(vr) - - if hl.lo == nil || ver.LessThan(hl.lo) { - hl.lo = ver - } - if hl.hi == nil || ver.GreaterThan(hl.hi) { - hl.hi = ver - } -} diff --git a/pkg/errors/errors.go b/pkg/errors/errors.go deleted file mode 100644 index 6b715a69e..000000000 --- a/pkg/errors/errors.go +++ /dev/null @@ -1,30 +0,0 @@ -// 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 errors provides common errors. -// -// Deprecated: This package is no longer supported. -package errors - -import "errors" - -var ( - // ErrInterrupted is returned when a process was interrupted but didn't - // fail in any other way. - ErrInterrupted = errors.New("interrupted") - - // ErrProcessNotFound is returned when a requested process is not currently - // running. - ErrProcessNotFound = errors.New("process not found") -) diff --git a/pkg/inject/data.go b/pkg/inject/data.go deleted file mode 100644 index 22bd41ee8..000000000 --- a/pkg/inject/data.go +++ /dev/null @@ -1,47 +0,0 @@ -// 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 inject - -// TrackedOffsets are the offsets for all instrumented packages. -type TrackedOffsets struct { - // Data key: struct name, which includes the library name in external - // libraries. - Data map[string]TrackedStruct `json:"data"` -} - -// TrackedStruct maps fields names to the tracked fields offsets. -type TrackedStruct map[string]TrackedField - -// TrackedField are the field offsets for a tracked struct. -type TrackedField struct { - // Versions range that are tracked for this given field - Versions VersionInfo `json:"versions"` - // Offsets are the sorted version offsets for the field. These need to be - // sorted in descending order. - Offsets []VersionedOffset `json:"offsets"` -} - -// VersionInfo is the span of supported versions. -type VersionInfo struct { - Oldest string `json:"oldest"` - Newest string `json:"newest"` -} - -// VersionedOffset is the offset for a particular version of a data type from a -// package. -type VersionedOffset struct { - Offset uint64 `json:"offset"` - Since string `json:"since"` -} diff --git a/pkg/inject/injector.go b/pkg/inject/injector.go deleted file mode 100644 index fed657156..000000000 --- a/pkg/inject/injector.go +++ /dev/null @@ -1,168 +0,0 @@ -// 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 inject provides injection utilities. -// -// Deprecated: This package is no longer supported. -package inject - -import ( - _ "embed" - "encoding/json" - "fmt" - "runtime" - - "github.com/hashicorp/go-version" - - "github.com/cilium/ebpf" - - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/process" // nolint:staticcheck // Atomic deprecation. -) - -var ( - //go:embed offset_results.json - offsetsData string -) - -// Injector injects OpenTelemetry instrumentation Go packages. -type Injector struct { - data *TrackedOffsets - isRegAbi bool - TotalCPUs uint32 - AllocationDetails *process.AllocationDetails -} - -// New returns an [Injector] configured for the target. -func New(target *process.TargetDetails) (*Injector, error) { - var offsets TrackedOffsets - err := json.Unmarshal([]byte(offsetsData), &offsets) - if err != nil { - return nil, err - } - - return &Injector{ - data: &offsets, - isRegAbi: target.IsRegistersABI(), - TotalCPUs: uint32(runtime.NumCPU()), - AllocationDetails: target.AllocationDetails, - }, nil -} - -type loadBpfFunc func() (*ebpf.CollectionSpec, error) - -// StructField is the definition of a structure field for which instrumentation -// is injected. -type StructField struct { - VarName string - StructName string - Field string -} - -// FlagField is used for configuring the ebpf programs by injecting boolean values. -type FlagField struct { - VarName string - Value bool -} - -// Inject injects instrumentation for the provided library data type. -func (i *Injector) Inject(loadBpf loadBpfFunc, library string, libVersion string, fields []*StructField, flagFields []*FlagField, initAlloc bool) (*ebpf.CollectionSpec, error) { - spec, err := loadBpf() - if err != nil { - return nil, err - } - - injectedVars := make(map[string]interface{}) - - for _, dm := range fields { - offset, found := i.getFieldOffset(dm.StructName, dm.Field, libVersion) - if !found { - log.Logger.V(0).Info("could not find offset", "lib", library, "version", libVersion, "struct", dm.StructName, "field", dm.Field) - } else { - injectedVars[dm.VarName] = offset - } - } - - if err := i.addCommonInjections(injectedVars, initAlloc); err != nil { - return nil, fmt.Errorf("adding instrumenter injections: %w", err) - } - - if err := i.addConfigInjections(injectedVars, flagFields); err != nil { - return nil, fmt.Errorf("adding flags injections: %w", err) - } - - log.Logger.V(0).Info("Injecting variables", "vars", injectedVars) - if len(injectedVars) > 0 { - err = spec.RewriteConstants(injectedVars) - if err != nil { - return nil, err - } - } - - return spec, nil -} - -func (i *Injector) addCommonInjections(varsMap map[string]interface{}, initAlloc bool) error { // nolint:revive // initAlloc is a control flag. - varsMap["is_registers_abi"] = i.isRegAbi - if initAlloc { - if i.AllocationDetails == nil { - return fmt.Errorf("couldn't get process allocation details. Try running it from the KeyVal Launcher") - } - varsMap["total_cpus"] = i.TotalCPUs - varsMap["start_addr"] = i.AllocationDetails.StartAddr - varsMap["end_addr"] = i.AllocationDetails.EndAddr - } - return nil -} - -func (i *Injector) addConfigInjections(varsMap map[string]interface{}, flagFields []*FlagField) error { - for _, dm := range flagFields { - varsMap[dm.VarName] = dm.Value - } - return nil -} - -func (i *Injector) getFieldOffset(structName string, fieldName string, libVersion string) (uint64, bool) { - strct, ok := i.data.Data[structName] - if !ok { - return 0, false - } - field, ok := strct[fieldName] - if !ok { - return 0, false - } - target, err := version.NewVersion(libVersion) - if err != nil { - // shouldn't happen unless a bug in our code/files - panic(err.Error()) - } - - // Search from the newest version (last in the slice) - for o := len(field.Offsets) - 1; o >= 0; o-- { - od := &field.Offsets[o] - fieldVersion, err := version.NewVersion(od.Since) - if err != nil { - // shouldn't happen unless a bug in our code - panic(err.Error()) - } - if target.Compare(fieldVersion) >= 0 { - // if target version is larger or equal than lib version: - // we certainly know that it is the most recent tracked offset - // matching the target libVersion - return od.Offset, true - } - } - - return 0, false -} diff --git a/pkg/inject/injector_test.go b/pkg/inject/injector_test.go deleted file mode 100644 index 7d4c68dde..000000000 --- a/pkg/inject/injector_test.go +++ /dev/null @@ -1,94 +0,0 @@ -// 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 inject - -import ( - "encoding/json" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/stretchr/testify/require" -) - -func TestGetFieldOffset(t *testing.T) { - dataFile := `{ - "data" : { - "struct_1" : { - "field_1" : { - "offsets": [ - { "offset": 1187, "since": "1.18.7" }, - { "offset": 1190, "since": "1.19.0" } - ] - } - } - } -}` - injector := Injector{data: &TrackedOffsets{}} - err := json.Unmarshal([]byte(dataFile), injector.data) - require.NoError(t, err) - - offset, ok := injector.getFieldOffset("struct_1", "field_1", "1.19.7") - assert.True(t, ok) - assert.Equal(t, 1190, int(offset)) - offset, ok = injector.getFieldOffset("struct_1", "field_1", "1.19.0") - assert.True(t, ok) - assert.Equal(t, 1190, int(offset)) - offset, ok = injector.getFieldOffset("struct_1", "field_1", "1.18.9") - assert.True(t, ok) - assert.Equal(t, 1187, int(offset)) - offset, ok = injector.getFieldOffset("struct_1", "field_1", "1.17.9") - assert.Falsef(t, ok, "found: %d", int(offset)) -} - -func TestGetFieldOffset_OffsetResultsJSON(t *testing.T) { - injector := Injector{data: &TrackedOffsets{}} - err := json.Unmarshal([]byte(offsetsData), injector.data) - require.NoError(t, err) - - offset, ok := injector.getFieldOffset("golang.org/x/net/http2.FrameHeader", "StreamID", "1.38.5") - assert.True(t, ok) - assert.Equal(t, 8, int(offset)) - - offset, ok = injector.getFieldOffset("google.golang.org/grpc/internal/transport.Stream", "method", "1.14.9") - assert.True(t, ok) - assert.Equal(t, 80, int(offset)) - - offset, ok = injector.getFieldOffset("google.golang.org/grpc/internal/transport.Stream", "method", "1.15.0") - assert.True(t, ok) - assert.Equal(t, 64, int(offset)) - - offset, ok = injector.getFieldOffset("google.golang.org/grpc/internal/transport.Stream", "method", "1.37.1") - assert.True(t, ok) - assert.Equal(t, 80, int(offset)) - - offset, ok = injector.getFieldOffset("runtime.g", "goid", "1.20.0") - assert.True(t, ok) - assert.Equal(t, 152, int(offset)) - - offset, ok = injector.getFieldOffset("net/http.Request", "URL", "1.20.2") - assert.True(t, ok) - assert.Equal(t, 16, int(offset)) - - offset, ok = injector.getFieldOffset("net/url.URL", "Path", "1.20.2") - assert.True(t, ok) - assert.Equal(t, 56, int(offset)) - - offset, ok = injector.getFieldOffset("net/url.URL", "Path", "1.8.0") - assert.Falsef(t, ok, "found: %d", int(offset)) - - offset, ok = injector.getFieldOffset("net/url.URL", "Foo", "1.15.0") - assert.Falsef(t, ok, "found: %d", int(offset)) -} diff --git a/pkg/inject/offset_results.json b/pkg/inject/offset_results.json deleted file mode 100755 index 521b2f675..000000000 --- a/pkg/inject/offset_results.json +++ /dev/null @@ -1,262 +0,0 @@ -{ - "data": { - "golang.org/x/net/http2.FrameHeader": { - "StreamID": { - "versions": { - "oldest": "1.3.0", - "newest": "1.59.0-dev" - }, - "offsets": [ - { - "offset": 8, - "since": "v1.3.0" - } - ] - } - }, - "golang.org/x/net/http2.MetaHeadersFrame": { - "Fields": { - "versions": { - "oldest": "1.3.0", - "newest": "1.59.0-dev" - }, - "offsets": [ - { - "offset": 8, - "since": "v1.3.0" - } - ] - } - }, - "google.golang.org/grpc.ClientConn": { - "target": { - "versions": { - "oldest": "1.3.0", - "newest": "1.59.0-dev" - }, - "offsets": [ - { - "offset": 24, - "since": "v1.3.0" - } - ] - } - }, - "google.golang.org/grpc/internal/transport.Stream": { - "ctx": { - "versions": { - "oldest": "1.3.0", - "newest": "1.59.0-dev" - }, - "offsets": [ - { - "offset": 32, - "since": "v1.3.0" - }, - { - "offset": 24, - "since": "v1.15.0" - }, - { - "offset": 32, - "since": "v1.25.0" - } - ] - }, - "id": { - "versions": { - "oldest": "1.3.0", - "newest": "1.59.0-dev" - }, - "offsets": [ - { - "offset": 0, - "since": "v1.3.0" - } - ] - }, - "method": { - "versions": { - "oldest": "1.3.0", - "newest": "1.59.0-dev" - }, - "offsets": [ - { - "offset": 80, - "since": "v1.3.0" - }, - { - "offset": 64, - "since": "v1.15.0" - }, - { - "offset": 72, - "since": "v1.25.0" - }, - { - "offset": 80, - "since": "v1.37.0" - } - ] - } - }, - "google.golang.org/grpc/internal/transport.headerFrame": { - "hf": { - "versions": { - "oldest": "1.3.0", - "newest": "1.59.0-dev" - }, - "offsets": [ - { - "offset": 8, - "since": "v1.3.0" - } - ] - }, - "streamID": { - "versions": { - "oldest": "1.3.0", - "newest": "1.59.0-dev" - }, - "offsets": [ - { - "offset": 0, - "since": "v1.3.0" - } - ] - } - }, - "google.golang.org/grpc/internal/transport.http2Client": { - "nextID": { - "versions": { - "oldest": "1.3.0", - "newest": "1.59.0-dev" - }, - "offsets": [ - { - "offset": 412, - "since": "v1.3.0" - }, - { - "offset": 356, - "since": "v1.15.0" - }, - { - "offset": 348, - "since": "v1.24.0" - }, - { - "offset": 340, - "since": "v1.35.0" - }, - { - "offset": 348, - "since": "v1.48.0" - }, - { - "offset": 340, - "since": "v1.51.0" - }, - { - "offset": 412, - "since": "v1.52.0" - }, - { - "offset": 404, - "since": "v1.59.0-dev" - } - ] - } - }, - "net/http.Request": { - "Header": { - "versions": { - "oldest": "1.12.0", - "newest": "1.21.1" - }, - "offsets": [ - { - "offset": 56, - "since": "1.12" - } - ] - }, - "Method": { - "versions": { - "oldest": "1.12.0", - "newest": "1.21.1" - }, - "offsets": [ - { - "offset": 0, - "since": "1.12" - } - ] - }, - "RemoteAddr": { - "versions": { - "oldest": "1.12.0", - "newest": "1.21.1" - }, - "offsets": [ - { - "offset": 176, - "since": "1.12" - } - ] - }, - "URL": { - "versions": { - "oldest": "1.12.0", - "newest": "1.21.1" - }, - "offsets": [ - { - "offset": 16, - "since": "1.12" - } - ] - }, - "ctx": { - "versions": { - "oldest": "1.12.0", - "newest": "1.21.1" - }, - "offsets": [ - { - "offset": 232, - "since": "1.12" - } - ] - } - }, - "net/url.URL": { - "Path": { - "versions": { - "oldest": "1.12.0", - "newest": "1.20.7" - }, - "offsets": [ - { - "offset": 56, - "since": "1.12" - } - ] - } - }, - "runtime.g": { - "goid": { - "versions": { - "oldest": "1.12.0", - "newest": "1.21.1" - }, - "offsets": [ - { - "offset": 152, - "since": "1.12" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/instrumentors/allocator/allocator_linux.go b/pkg/instrumentors/allocator/allocator_linux.go deleted file mode 100644 index ee49623dc..000000000 --- a/pkg/instrumentors/allocator/allocator_linux.go +++ /dev/null @@ -1,50 +0,0 @@ -// 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 allocator provides allocation functionality for unix systems. -// -// Deprecated: This package is no longer supported. -package allocator - -import ( - "go.opentelemetry.io/auto/pkg/instrumentors/bpffs" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/context" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. -) - -// Allocator handles the allocation of the BPF file-system. -type Allocator struct{} - -// New returns a new [Allocator]. -func New() *Allocator { - return &Allocator{} -} - -// Load loads the BPF file-system. -func (a *Allocator) Load(ctx *context.InstrumentorContext) error { - logger := log.Logger.WithName("allocator") - if ctx.TargetDetails.AllocationDetails != nil { - logger = logger.WithValues( - "start_addr", ctx.TargetDetails.AllocationDetails.StartAddr, - "end_addr", ctx.TargetDetails.AllocationDetails.EndAddr) - } - logger.V(0).Info("Loading allocator") - - err := bpffs.Mount(ctx.TargetDetails) - if err != nil { - return err - } - - return nil -} diff --git a/pkg/instrumentors/api.go b/pkg/instrumentors/api.go deleted file mode 100644 index cb67a05f2..000000000 --- a/pkg/instrumentors/api.go +++ /dev/null @@ -1,39 +0,0 @@ -// 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 instrumentors - -import ( - "go.opentelemetry.io/auto/pkg/instrumentors/context" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/events" // nolint:staticcheck // Atomic deprecation. -) - -// Instrumentor provides instrumentation for a Go package. -type Instrumentor interface { - // LibraryName returns the package name being instrumented. - LibraryName() string - - // FuncNames returns the fully-qualified function names that are - // instrumented. - FuncNames() []string - - // Load loads all instrumentation offsets. - Load(ctx *context.InstrumentorContext) error - - // Run runs the events processing loop. - Run(eventsChan chan<- *events.Event) - - // Close stops the Instrumentor. - Close() -} diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c deleted file mode 100644 index ade6c43ca..000000000 --- a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c +++ /dev/null @@ -1,92 +0,0 @@ -// 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. - -#include "arguments.h" -#include "span_context.h" -#include "go_context.h" -#include "uprobe.h" - -char __license[] SEC("license") = "Dual MIT/GPL"; - -#define PATH_MAX_LEN 100 -#define METHOD_MAX_LEN 7 -#define MAX_CONCURRENT 50 - -struct http_request_t { - BASE_SPAN_PROPERTIES - char method[METHOD_MAX_LEN]; - char path[PATH_MAX_LEN]; -}; - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, void *); - __type(value, struct http_request_t); - __uint(max_entries, MAX_CONCURRENT); -} http_events SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); -} events SEC(".maps"); - -// Injected in init -volatile const u64 method_ptr_pos; -volatile const u64 url_ptr_pos; -volatile const u64 path_ptr_pos; -volatile const u64 ctx_ptr_pos; - -// This instrumentation attaches uprobe to the following function: -// func (engine *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) -SEC("uprobe/GinEngine_ServeHTTP") -int uprobe_GinEngine_ServeHTTP(struct pt_regs *ctx) { - u64 request_pos = 4; - struct http_request_t httpReq = {}; - httpReq.start_time = bpf_ktime_get_ns(); - - // Get request struct - void *req_ptr = get_argument(ctx, request_pos); - - // Get method from request - void *method_ptr = 0; - bpf_probe_read(&method_ptr, sizeof(method_ptr), (void *)(req_ptr + method_ptr_pos)); - u64 method_len = 0; - bpf_probe_read(&method_len, sizeof(method_len), (void *)(req_ptr + (method_ptr_pos + 8))); - u64 method_size = sizeof(httpReq.method); - method_size = method_size < method_len ? method_size : method_len; - bpf_probe_read(&httpReq.method, method_size, method_ptr); - - // get path from Request.URL - void *url_ptr = 0; - bpf_probe_read(&url_ptr, sizeof(url_ptr), (void *)(req_ptr + url_ptr_pos)); - void *path_ptr = 0; - bpf_probe_read(&path_ptr, sizeof(path_ptr), (void *)(url_ptr + path_ptr_pos)); - u64 path_len = 0; - bpf_probe_read(&path_len, sizeof(path_len), (void *)(url_ptr + (path_ptr_pos + 8))); - u64 path_size = sizeof(httpReq.path); - path_size = path_size < path_len ? path_size : path_len; - bpf_probe_read(&httpReq.path, path_size, path_ptr); - - // Get key - void *req_ctx_ptr = 0; - bpf_probe_read(&req_ctx_ptr, sizeof(req_ctx_ptr), (void *)(req_ptr + ctx_ptr_pos)); - void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_ptr_pos)); - - // Write event - httpReq.sc = generate_span_context(); - bpf_map_update_elem(&http_events, &key, &httpReq, 0); - start_tracking_span(req_ctx_ptr, &httpReq.sc); - return 0; -} - -UPROBE_RETURN(GinEngine_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events) \ No newline at end of file diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go deleted file mode 100644 index e2aaf959e..000000000 --- a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go +++ /dev/null @@ -1,146 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build arm64 - -package gin - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfHttpRequestT struct { - StartTime uint64 - EndTime uint64 - Sc bpfSpanContext - Psc bpfSpanContext - Method [7]int8 - Path [100]int8 - _ [5]byte -} - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeGinEngineServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_GinEngine_ServeHTTP"` - UprobeGinEngineServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_GinEngine_ServeHTTP_Returns"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - Events *ebpf.MapSpec `ebpf:"events"` - HttpEvents *ebpf.MapSpec `ebpf:"http_events"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - Events *ebpf.Map `ebpf:"events"` - HttpEvents *ebpf.Map `ebpf:"http_events"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.Events, - m.HttpEvents, - m.TrackedSpans, - m.TrackedSpansBySc, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeGinEngineServeHTTP *ebpf.Program `ebpf:"uprobe_GinEngine_ServeHTTP"` - UprobeGinEngineServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_GinEngine_ServeHTTP_Returns"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeGinEngineServeHTTP, - p.UprobeGinEngineServeHTTP_Returns, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel_arm64.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go deleted file mode 100644 index 40a92c783..000000000 --- a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go +++ /dev/null @@ -1,146 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build 386 || amd64 - -package gin - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfHttpRequestT struct { - StartTime uint64 - EndTime uint64 - Sc bpfSpanContext - Psc bpfSpanContext - Method [7]int8 - Path [100]int8 - _ [5]byte -} - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeGinEngineServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_GinEngine_ServeHTTP"` - UprobeGinEngineServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_GinEngine_ServeHTTP_Returns"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - Events *ebpf.MapSpec `ebpf:"events"` - HttpEvents *ebpf.MapSpec `ebpf:"http_events"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - Events *ebpf.Map `ebpf:"events"` - HttpEvents *ebpf.Map `ebpf:"http_events"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.Events, - m.HttpEvents, - m.TrackedSpans, - m.TrackedSpansBySc, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeGinEngineServeHTTP *ebpf.Program `ebpf:"uprobe_GinEngine_ServeHTTP"` - UprobeGinEngineServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_GinEngine_ServeHTTP_Returns"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeGinEngineServeHTTP, - p.UprobeGinEngineServeHTTP_Returns, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel_x86.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go deleted file mode 100644 index 1dc31f072..000000000 --- a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go +++ /dev/null @@ -1,242 +0,0 @@ -// 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 gin provides an instrumentor for the github.com/gin-gonic/gin -// package. -// -// Deprecated: This package is no longer supported. -package gin - -import ( - "bytes" - "encoding/binary" - "errors" - - "os" - - "go.opentelemetry.io/auto/pkg/instrumentors/bpffs" // nolint:staticcheck // Atomic deprecation. - - "github.com/cilium/ebpf" - "github.com/cilium/ebpf/link" - "github.com/cilium/ebpf/perf" - "golang.org/x/sys/unix" - - "go.opentelemetry.io/auto/pkg/inject" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/context" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/events" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/utils" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/otel/attribute" - semconv "go.opentelemetry.io/otel/semconv/v1.18.0" - "go.opentelemetry.io/otel/trace" -) - -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c - -const instrumentedPkg = "github.com/gin-gonic/gin" - -// Event represents an event in the gin-gonic/gin server during an HTTP -// request-response. -type Event struct { - context.BaseSpanProperties - Method [7]byte - Path [100]byte -} - -// Instrumentor is the gin-gonic/gin instrumentor. -type Instrumentor struct { - bpfObjects *bpfObjects - uprobes []link.Link - returnProbs []link.Link - eventsReader *perf.Reader -} - -// New returns a new [Instrumentor]. -func New() *Instrumentor { - return &Instrumentor{} -} - -// LibraryName returns the gin-gonic/gin package import path. -func (h *Instrumentor) LibraryName() string { - return instrumentedPkg -} - -// FuncNames returns the function names from "github.com/gin-gonic/gin" that are -// instrumented. -func (h *Instrumentor) FuncNames() []string { - return []string{"github.com/gin-gonic/gin.(*Engine).ServeHTTP"} -} - -// Load loads all instrumentation offsets. -func (h *Instrumentor) Load(ctx *context.InstrumentorContext) error { - spec, err := ctx.Injector.Inject(loadBpf, "go", ctx.TargetDetails.GoVersion.Original(), []*inject.StructField{ - { - VarName: "method_ptr_pos", - StructName: "net/http.Request", - Field: "Method", - }, - { - VarName: "url_ptr_pos", - StructName: "net/http.Request", - Field: "URL", - }, - { - VarName: "ctx_ptr_pos", - StructName: "net/http.Request", - Field: "ctx", - }, - { - VarName: "path_ptr_pos", - StructName: "net/url.URL", - Field: "Path", - }, - }, nil, false) - - if err != nil { - return err - } - - h.bpfObjects = &bpfObjects{} - err = utils.LoadEBPFObjects(spec, h.bpfObjects, &ebpf.CollectionOptions{ - Maps: ebpf.MapOptions{ - PinPath: bpffs.PathForTargetApplication(ctx.TargetDetails), - }, - }) - if err != nil { - return err - } - - for _, funcName := range h.FuncNames() { - h.registerProbes(ctx, funcName) - } - - rd, err := perf.NewReader(h.bpfObjects.Events, os.Getpagesize()) - if err != nil { - return err - } - h.eventsReader = rd - - return nil -} - -func (h *Instrumentor) registerProbes(ctx *context.InstrumentorContext, funcName string) { - logger := log.Logger.WithName("gin-gonic/gin-instrumentor").WithValues("function", funcName) - offset, err := ctx.TargetDetails.GetFunctionOffset(funcName) - if err != nil { - logger.Error(err, "could not find function start offset. Skipping") - return - } - retOffsets, err := ctx.TargetDetails.GetFunctionReturns(funcName) - if err != nil { - logger.Error(err, "could not find function end offsets. Skipping") - return - } - - up, err := ctx.Executable.Uprobe("", h.bpfObjects.UprobeGinEngineServeHTTP, &link.UprobeOptions{ - Address: offset, - }) - if err != nil { - logger.V(1).Info("could not insert start uprobe. Skipping", - "error", err.Error()) - return - } - - h.uprobes = append(h.uprobes, up) - - for _, ret := range retOffsets { - retProbe, err := ctx.Executable.Uprobe("", h.bpfObjects.UprobeGinEngineServeHTTP_Returns, &link.UprobeOptions{ - Address: ret, - }) - if err != nil { - logger.Error(err, "could not insert return uprobe. Skipping") - return - } - h.returnProbs = append(h.returnProbs, retProbe) - } -} - -// Run runs the events processing loop. -func (h *Instrumentor) Run(eventsChan chan<- *events.Event) { - logger := log.Logger.WithName("gin-gonic/gin-instrumentor") - var event Event - for { - record, err := h.eventsReader.Read() - if err != nil { - if errors.Is(err, perf.ErrClosed) { - return - } - logger.Error(err, "error reading from perf reader") - continue - } - - if record.LostSamples != 0 { - logger.V(0).Info("perf event ring buffer full", "dropped", record.LostSamples) - continue - } - - if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.LittleEndian, &event); err != nil { - logger.Error(err, "error parsing perf event") - continue - } - - eventsChan <- h.convertEvent(&event) - } -} - -func (h *Instrumentor) convertEvent(e *Event) *events.Event { - method := unix.ByteSliceToString(e.Method[:]) - path := unix.ByteSliceToString(e.Path[:]) - - sc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: e.SpanContext.TraceID, - SpanID: e.SpanContext.SpanID, - TraceFlags: trace.FlagsSampled, - }) - - return &events.Event{ - Library: h.LibraryName(), - // Do not include the high-cardinality path here (there is no - // templatized path manifest to reference, given we are instrumenting - // Engine.ServeHTTP which is not passed a Gin Context). - Name: method, - Kind: trace.SpanKindServer, - StartTime: int64(e.StartTime), - EndTime: int64(e.EndTime), - SpanContext: &sc, - Attributes: []attribute.KeyValue{ - semconv.HTTPMethodKey.String(method), - semconv.HTTPTargetKey.String(path), - }, - } -} - -// Close stops the Instrumentor. -func (h *Instrumentor) Close() { - log.Logger.V(0).Info("closing gin-gonic/gin instrumentor") - if h.eventsReader != nil { - h.eventsReader.Close() - } - - for _, r := range h.uprobes { - r.Close() - } - - for _, r := range h.returnProbs { - r.Close() - } - - if h.bpfObjects != nil { - h.bpfObjects.Close() - } -} diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe_test.go b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe_test.go deleted file mode 100644 index e1c9fce3f..000000000 --- a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe_test.go +++ /dev/null @@ -1,68 +0,0 @@ -// 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 gin - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "go.opentelemetry.io/auto/pkg/instrumentors/context" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/events" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/otel/attribute" - semconv "go.opentelemetry.io/otel/semconv/v1.7.0" - "go.opentelemetry.io/otel/trace" -) - -func TestInstrumentorConvertEvent(t *testing.T) { - start := time.Now() - end := start.Add(1 * time.Second) - - traceID := trace.TraceID{1} - spanID := trace.SpanID{1} - - i := New() - got := i.convertEvent(&Event{ - BaseSpanProperties: context.BaseSpanProperties{ - StartTime: uint64(start.UnixNano()), - EndTime: uint64(end.UnixNano()), - SpanContext: context.EBPFSpanContext{TraceID: traceID, SpanID: spanID}, - }, - // "GET" - Method: [7]byte{0x47, 0x45, 0x54}, - // "/foo/bar" - Path: [100]byte{0x2f, 0x66, 0x6f, 0x6f, 0x2f, 0x62, 0x61, 0x72}, - }) - - sc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }) - want := &events.Event{ - Library: instrumentedPkg, - Name: "GET", - Kind: trace.SpanKindServer, - StartTime: int64(start.UnixNano()), - EndTime: int64(end.UnixNano()), - SpanContext: &sc, - Attributes: []attribute.KeyValue{ - semconv.HTTPMethodKey.String("GET"), - semconv.HTTPTargetKey.String("/foo/bar"), - }, - } - assert.Equal(t, want, got) -} diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf/probe.bpf.c b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf/probe.bpf.c deleted file mode 100644 index cc3eb479f..000000000 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf/probe.bpf.c +++ /dev/null @@ -1,92 +0,0 @@ -// 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. - -#include "arguments.h" -#include "span_context.h" -#include "go_context.h" -#include "uprobe.h" - -char __license[] SEC("license") = "Dual MIT/GPL"; - -#define PATH_MAX_LEN 100 -#define METHOD_MAX_LEN 7 -#define MAX_CONCURRENT 50 - -struct http_request_t { - BASE_SPAN_PROPERTIES - char method[METHOD_MAX_LEN]; - char path[PATH_MAX_LEN]; -}; - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, void *); - __type(value, struct http_request_t); - __uint(max_entries, MAX_CONCURRENT); -} http_events SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); -} events SEC(".maps"); - -// Injected in init -volatile const u64 method_ptr_pos; -volatile const u64 url_ptr_pos; -volatile const u64 path_ptr_pos; -volatile const u64 ctx_ptr_pos; - -// This instrumentation attaches uprobe to the following function: -// func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) -SEC("uprobe/GorillaMux_ServeHTTP") -int uprobe_GorillaMux_ServeHTTP(struct pt_regs *ctx) { - u64 request_pos = 4; - struct http_request_t httpReq = {}; - httpReq.start_time = bpf_ktime_get_ns(); - - // Get request struct - void *req_ptr = get_argument(ctx, request_pos); - - // Get method from request - void *method_ptr = 0; - bpf_probe_read(&method_ptr, sizeof(method_ptr), (void *)(req_ptr + method_ptr_pos)); - u64 method_len = 0; - bpf_probe_read(&method_len, sizeof(method_len), (void *)(req_ptr + (method_ptr_pos + 8))); - u64 method_size = sizeof(httpReq.method); - method_size = method_size < method_len ? method_size : method_len; - bpf_probe_read(&httpReq.method, method_size, method_ptr); - - // get path from Request.URL - void *url_ptr = 0; - bpf_probe_read(&url_ptr, sizeof(url_ptr), (void *)(req_ptr + url_ptr_pos)); - void *path_ptr = 0; - bpf_probe_read(&path_ptr, sizeof(path_ptr), (void *)(url_ptr + path_ptr_pos)); - u64 path_len = 0; - bpf_probe_read(&path_len, sizeof(path_len), (void *)(url_ptr + (path_ptr_pos + 8))); - u64 path_size = sizeof(httpReq.path); - path_size = path_size < path_len ? path_size : path_len; - bpf_probe_read(&httpReq.path, path_size, path_ptr); - - // Get key - void *req_ctx_ptr = 0; - bpf_probe_read(&req_ctx_ptr, sizeof(req_ctx_ptr), (void *)(req_ptr + ctx_ptr_pos)); - void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_ptr_pos)); - - // Write event - httpReq.sc = generate_span_context(); - bpf_map_update_elem(&http_events, &key, &httpReq, 0); - start_tracking_span(req_ctx_ptr, &httpReq.sc); - return 0; -} - -UPROBE_RETURN(GorillaMux_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events) \ No newline at end of file diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_arm64.go deleted file mode 100644 index cfc195ab5..000000000 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_arm64.go +++ /dev/null @@ -1,146 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build arm64 - -package mux - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfHttpRequestT struct { - StartTime uint64 - EndTime uint64 - Sc bpfSpanContext - Psc bpfSpanContext - Method [7]int8 - Path [100]int8 - _ [5]byte -} - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeGorillaMuxServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_GorillaMux_ServeHTTP"` - UprobeGorillaMuxServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_GorillaMux_ServeHTTP_Returns"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - Events *ebpf.MapSpec `ebpf:"events"` - HttpEvents *ebpf.MapSpec `ebpf:"http_events"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - Events *ebpf.Map `ebpf:"events"` - HttpEvents *ebpf.Map `ebpf:"http_events"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.Events, - m.HttpEvents, - m.TrackedSpans, - m.TrackedSpansBySc, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeGorillaMuxServeHTTP *ebpf.Program `ebpf:"uprobe_GorillaMux_ServeHTTP"` - UprobeGorillaMuxServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_GorillaMux_ServeHTTP_Returns"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeGorillaMuxServeHTTP, - p.UprobeGorillaMuxServeHTTP_Returns, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel_arm64.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_x86.go deleted file mode 100644 index c43f1c91e..000000000 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_x86.go +++ /dev/null @@ -1,146 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build 386 || amd64 - -package mux - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfHttpRequestT struct { - StartTime uint64 - EndTime uint64 - Sc bpfSpanContext - Psc bpfSpanContext - Method [7]int8 - Path [100]int8 - _ [5]byte -} - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeGorillaMuxServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_GorillaMux_ServeHTTP"` - UprobeGorillaMuxServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_GorillaMux_ServeHTTP_Returns"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - Events *ebpf.MapSpec `ebpf:"events"` - HttpEvents *ebpf.MapSpec `ebpf:"http_events"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - Events *ebpf.Map `ebpf:"events"` - HttpEvents *ebpf.Map `ebpf:"http_events"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.Events, - m.HttpEvents, - m.TrackedSpans, - m.TrackedSpansBySc, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeGorillaMuxServeHTTP *ebpf.Program `ebpf:"uprobe_GorillaMux_ServeHTTP"` - UprobeGorillaMuxServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_GorillaMux_ServeHTTP_Returns"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeGorillaMuxServeHTTP, - p.UprobeGorillaMuxServeHTTP_Returns, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel_x86.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go deleted file mode 100644 index 3211a36db..000000000 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go +++ /dev/null @@ -1,238 +0,0 @@ -// 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 mux provides an instrumentation probe for the github.com/gorilla/mux -// package. -// -// Deprecated: This package will be removed in the next release. -package mux - -import ( - "bytes" - "encoding/binary" - "errors" - "os" - - "go.opentelemetry.io/auto/pkg/instrumentors/bpffs" // nolint:staticcheck // Atomic deprecation. - - "github.com/cilium/ebpf" - "github.com/cilium/ebpf/link" - "github.com/cilium/ebpf/perf" - "golang.org/x/sys/unix" - - "go.opentelemetry.io/auto/pkg/inject" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/context" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/events" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/utils" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/otel/attribute" - semconv "go.opentelemetry.io/otel/semconv/v1.18.0" - "go.opentelemetry.io/otel/trace" -) - -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c - -const instrumentedPkg = "github.com/gorilla/mux" - -// Event represents an event in the gorilla/mux server during an HTTP -// request-response. -type Event struct { - context.BaseSpanProperties - Method [7]byte - Path [100]byte -} - -// Instrumentor is the gorilla/mux instrumentor. -type Instrumentor struct { - bpfObjects *bpfObjects - uprobes []link.Link - returnProbs []link.Link - eventsReader *perf.Reader -} - -// New returns a new [Instrumentor]. -func New() *Instrumentor { - return &Instrumentor{} -} - -// LibraryName returns the gorilla/mux package import path. -func (g *Instrumentor) LibraryName() string { - return instrumentedPkg -} - -// FuncNames returns the function names from "github.com/gorilla/mux" that are -// instrumented. -func (g *Instrumentor) FuncNames() []string { - return []string{"github.com/gorilla/mux.(*Router).ServeHTTP"} -} - -// Load loads all instrumentation offsets. -func (g *Instrumentor) Load(ctx *context.InstrumentorContext) error { - spec, err := ctx.Injector.Inject(loadBpf, "go", ctx.TargetDetails.GoVersion.Original(), []*inject.StructField{ - { - VarName: "method_ptr_pos", - StructName: "net/http.Request", - Field: "Method", - }, - { - VarName: "url_ptr_pos", - StructName: "net/http.Request", - Field: "URL", - }, - { - VarName: "ctx_ptr_pos", - StructName: "net/http.Request", - Field: "ctx", - }, - { - VarName: "path_ptr_pos", - StructName: "net/url.URL", - Field: "Path", - }, - }, nil, false) - - if err != nil { - return err - } - - g.bpfObjects = &bpfObjects{} - err = utils.LoadEBPFObjects(spec, g.bpfObjects, &ebpf.CollectionOptions{ - Maps: ebpf.MapOptions{ - PinPath: bpffs.PathForTargetApplication(ctx.TargetDetails), - }, - }) - if err != nil { - return err - } - - for _, funcName := range g.FuncNames() { - g.registerProbes(ctx, funcName) - } - rd, err := perf.NewReader(g.bpfObjects.Events, os.Getpagesize()) - if err != nil { - return err - } - g.eventsReader = rd - - return nil -} - -func (g *Instrumentor) registerProbes(ctx *context.InstrumentorContext, funcName string) { - logger := log.Logger.WithName("gorilla/mux-instrumentor").WithValues("function", funcName) - offset, err := ctx.TargetDetails.GetFunctionOffset(funcName) - if err != nil { - logger.Error(err, "could not find function start offset. Skipping") - return - } - retOffsets, err := ctx.TargetDetails.GetFunctionReturns(funcName) - if err != nil { - logger.Error(err, "could not find function end offset. Skipping") - return - } - - up, err := ctx.Executable.Uprobe("", g.bpfObjects.UprobeGorillaMuxServeHTTP, &link.UprobeOptions{ - Address: offset, - }) - if err != nil { - logger.Error(err, "could not insert start uprobe. Skipping") - return - } - - g.uprobes = append(g.uprobes, up) - - for _, ret := range retOffsets { - retProbe, err := ctx.Executable.Uprobe("", g.bpfObjects.UprobeGorillaMuxServeHTTP_Returns, &link.UprobeOptions{ - Address: ret, - }) - if err != nil { - logger.Error(err, "could not insert return uprobe. Skipping") - return - } - g.returnProbs = append(g.returnProbs, retProbe) - } -} - -// Run runs the events processing loop. -func (g *Instrumentor) Run(eventsChan chan<- *events.Event) { - logger := log.Logger.WithName("gorilla/mux-instrumentor") - var event Event - for { - record, err := g.eventsReader.Read() - if err != nil { - if errors.Is(err, perf.ErrClosed) { - return - } - logger.Error(err, "error reading from perf reader") - continue - } - - if record.LostSamples != 0 { - logger.V(0).Info("perf event ring buffer full", "dropped", record.LostSamples) - continue - } - - if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.LittleEndian, &event); err != nil { - logger.Error(err, "error parsing perf event") - continue - } - - eventsChan <- g.convertEvent(&event) - } -} - -func (g *Instrumentor) convertEvent(e *Event) *events.Event { - method := unix.ByteSliceToString(e.Method[:]) - path := unix.ByteSliceToString(e.Path[:]) - - sc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: e.SpanContext.TraceID, - SpanID: e.SpanContext.SpanID, - TraceFlags: trace.FlagsSampled, - }) - - return &events.Event{ - Library: g.LibraryName(), - // Do not include the high-cardinality path here (there is no - // templatized path manifest to reference). - Name: method, - Kind: trace.SpanKindServer, - StartTime: int64(e.StartTime), - EndTime: int64(e.EndTime), - SpanContext: &sc, - Attributes: []attribute.KeyValue{ - semconv.HTTPMethodKey.String(method), - semconv.HTTPTargetKey.String(path), - }, - } -} - -// Close stops the Instrumentor. -func (g *Instrumentor) Close() { - log.Logger.V(0).Info("closing gorilla/mux instrumentor") - if g.eventsReader != nil { - g.eventsReader.Close() - } - - for _, r := range g.uprobes { - r.Close() - } - - for _, r := range g.returnProbs { - r.Close() - } - - if g.bpfObjects != nil { - g.bpfObjects.Close() - } -} diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe_test.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/probe_test.go deleted file mode 100644 index 4595d03ac..000000000 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe_test.go +++ /dev/null @@ -1,68 +0,0 @@ -// 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 mux - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "go.opentelemetry.io/auto/pkg/instrumentors/context" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/events" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/otel/attribute" - semconv "go.opentelemetry.io/otel/semconv/v1.7.0" - "go.opentelemetry.io/otel/trace" -) - -func TestInstrumentorConvertEvent(t *testing.T) { - start := time.Now() - end := start.Add(1 * time.Second) - - traceID := trace.TraceID{1} - spanID := trace.SpanID{1} - - i := New() - got := i.convertEvent(&Event{ - BaseSpanProperties: context.BaseSpanProperties{ - StartTime: uint64(start.UnixNano()), - EndTime: uint64(end.UnixNano()), - SpanContext: context.EBPFSpanContext{TraceID: traceID, SpanID: spanID}, - }, - // "GET" - Method: [7]byte{0x47, 0x45, 0x54}, - // "/foo/bar" - Path: [100]byte{0x2f, 0x66, 0x6f, 0x6f, 0x2f, 0x62, 0x61, 0x72}, - }) - - sc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }) - want := &events.Event{ - Library: instrumentedPkg, - Name: "GET", - Kind: trace.SpanKindServer, - StartTime: int64(start.UnixNano()), - EndTime: int64(end.UnixNano()), - SpanContext: &sc, - Attributes: []attribute.KeyValue{ - semconv.HTTPMethodKey.String("GET"), - semconv.HTTPTargetKey.String("/foo/bar"), - }, - } - assert.Equal(t, want, got) -} diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c deleted file mode 100644 index ab7986e87..000000000 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c +++ /dev/null @@ -1,201 +0,0 @@ -// 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. - -#include "arguments.h" -#include "go_types.h" -#include "span_context.h" -#include "go_context.h" -#include "uprobe.h" - -char __license[] SEC("license") = "Dual MIT/GPL"; - -#define MAX_SIZE 50 -#define MAX_CONCURRENT 50 -#define MAX_HEADERS_BUFF_SIZE 500 - -struct grpc_request_t -{ - BASE_SPAN_PROPERTIES - char method[MAX_SIZE]; - char target[MAX_SIZE]; -}; - -struct hpack_header_field -{ - struct go_string name; - struct go_string value; - bool sensitive; -}; - -struct -{ - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, void *); - __type(value, struct grpc_request_t); - __uint(max_entries, MAX_CONCURRENT); -} grpc_events SEC(".maps"); - -struct -{ - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, u32); - __type(value, struct span_context); - __uint(max_entries, MAX_CONCURRENT); -} streamid_to_span_contexts SEC(".maps"); - -struct headers_buff -{ - unsigned char buff[MAX_HEADERS_BUFF_SIZE]; -}; - -struct -{ - __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); - __type(key, s32); - __type(value, struct headers_buff); - __uint(max_entries, 1); -} headers_buff_map SEC(".maps"); - -struct -{ - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); -} events SEC(".maps"); - -// Injected in init -volatile const u64 clientconn_target_ptr_pos; -volatile const u64 httpclient_nextid_pos; -volatile const u64 headerFrame_streamid_pos; -volatile const u64 headerFrame_hf_pos; - -// This instrumentation attaches uprobe to the following function: -// func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...CallOption) error -SEC("uprobe/ClientConn_Invoke") -int uprobe_ClientConn_Invoke(struct pt_regs *ctx) -{ - // positions - u64 clientconn_pos = 1; - u64 context_pos = 3; - u64 method_ptr_pos = 4; - u64 method_len_pos = 5; - - struct grpc_request_t grpcReq = {}; - grpcReq.start_time = bpf_ktime_get_ns(); - - // Read Method - void *method_ptr = get_argument(ctx, method_ptr_pos); - u64 method_len = (u64)get_argument(ctx, method_len_pos); - u64 method_size = sizeof(grpcReq.method); - method_size = method_size < method_len ? method_size : method_len; - bpf_probe_read(&grpcReq.method, method_size, method_ptr); - - // Read ClientConn.Target - void *clientconn_ptr = get_argument(ctx, clientconn_pos); - void *target_ptr = 0; - bpf_probe_read(&target_ptr, sizeof(target_ptr), (void *)(clientconn_ptr + (clientconn_target_ptr_pos))); - u64 target_len = 0; - bpf_probe_read(&target_len, sizeof(target_len), (void *)(clientconn_ptr + (clientconn_target_ptr_pos + 8))); - u64 target_size = sizeof(grpcReq.target); - target_size = target_size < target_len ? target_size : target_len; - bpf_probe_read(&grpcReq.target, target_size, target_ptr); - - // Get parent if exists - void *context_ptr = get_argument(ctx, context_pos); - void *context_ptr_val = 0; - bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); - struct span_context *parent_span_ctx = get_parent_span_context(context_ptr_val); - if (parent_span_ctx != NULL) - { - bpf_probe_read(&grpcReq.psc, sizeof(grpcReq.psc), parent_span_ctx); - copy_byte_arrays(grpcReq.psc.TraceID, grpcReq.sc.TraceID, TRACE_ID_SIZE); - generate_random_bytes(grpcReq.sc.SpanID, SPAN_ID_SIZE); - } - else - { - grpcReq.sc = generate_span_context(); - } - - // Get key - void *key = get_consistent_key(ctx, context_ptr); - - // Write event - bpf_map_update_elem(&grpc_events, &key, &grpcReq, 0); - start_tracking_span(context_ptr_val, &grpcReq.sc); - return 0; -} - -UPROBE_RETURN(ClientConn_Invoke, struct grpc_request_t, 3, 0, grpc_events, events) - -// func (l *loopyWriter) headerHandler(h *headerFrame) error -SEC("uprobe/loopyWriter_headerHandler") -int uprobe_LoopyWriter_HeaderHandler(struct pt_regs *ctx) -{ - void *headerFrame_ptr = get_argument(ctx, 2); - u32 stream_id = 0; - bpf_probe_read(&stream_id, sizeof(stream_id), (void *)(headerFrame_ptr + (headerFrame_streamid_pos))); - void *sc_ptr = bpf_map_lookup_elem(&streamid_to_span_contexts, &stream_id); - if (sc_ptr == NULL) - { - return 0; - } - - bpf_map_delete_elem(&streamid_to_span_contexts, &stream_id); - struct go_slice slice = {}; - struct go_slice_user_ptr slice_user_ptr = {}; - slice_user_ptr.array = (void *)(headerFrame_ptr + (headerFrame_hf_pos)); - slice_user_ptr.len = (void *)(headerFrame_ptr + (headerFrame_hf_pos + 8)); - slice_user_ptr.cap = (void *)(headerFrame_ptr + (headerFrame_hf_pos + 16)); - bpf_probe_read(&slice.array, sizeof(slice.array), slice_user_ptr.array); - bpf_probe_read(&slice.len, sizeof(slice.len), slice_user_ptr.len); - bpf_probe_read(&slice.cap, sizeof(slice.cap), slice_user_ptr.cap); - - struct span_context current_span_context = {}; - bpf_probe_read(¤t_span_context, sizeof(current_span_context), sc_ptr); - - char tp_key[11] = "traceparent"; - struct go_string key_str = write_user_go_string(tp_key, sizeof(tp_key)); - if (key_str.len == 0) { - bpf_printk("write failed, aborting ebpf probe"); - return 0; - } - - // Write headers - char val[SPAN_CONTEXT_STRING_SIZE]; - span_context_to_w3c_string(¤t_span_context, val); - struct go_string val_str = write_user_go_string(val, sizeof(val)); - struct hpack_header_field hf = {}; - hf.name = key_str; - hf.value = val_str; - append_item_to_slice(&slice, &hf, sizeof(hf), &slice_user_ptr, &headers_buff_map); - return 0; -} - -SEC("uprobe/http2Client_NewStream") -// func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, error) -int uprobe_http2Client_NewStream(struct pt_regs *ctx) -{ - void *context_ptr = get_argument(ctx, 3); - void *context_ptr_val = 0; - bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); - - void *httpclient_ptr = get_argument(ctx, 1); - u32 nextid = 0; - bpf_probe_read(&nextid, sizeof(nextid), (void *)(httpclient_ptr + (httpclient_nextid_pos))); - - struct span_context *current_span_context = get_parent_span_context(context_ptr_val); - if (current_span_context != NULL) { - bpf_map_update_elem(&streamid_to_span_contexts, &nextid, current_span_context, 0); - } - - return 0; -} \ No newline at end of file diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_arm64.go deleted file mode 100644 index 489bb8978..000000000 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_arm64.go +++ /dev/null @@ -1,163 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build arm64 - -package grpc - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfGrpcRequestT struct { - StartTime uint64 - EndTime uint64 - Sc bpfSpanContext - Psc bpfSpanContext - Method [50]int8 - Target [50]int8 - _ [4]byte -} - -type bpfHeadersBuff struct{ Buff [500]uint8 } - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeClientConnInvoke *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke"` - UprobeClientConnInvokeReturns *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke_Returns"` - UprobeLoopyWriterHeaderHandler *ebpf.ProgramSpec `ebpf:"uprobe_LoopyWriter_HeaderHandler"` - UprobeHttp2ClientNewStream *ebpf.ProgramSpec `ebpf:"uprobe_http2Client_NewStream"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - Events *ebpf.MapSpec `ebpf:"events"` - GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` - HeadersBuffMap *ebpf.MapSpec `ebpf:"headers_buff_map"` - StreamidToSpanContexts *ebpf.MapSpec `ebpf:"streamid_to_span_contexts"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - AllocMap *ebpf.Map `ebpf:"alloc_map"` - Events *ebpf.Map `ebpf:"events"` - GrpcEvents *ebpf.Map `ebpf:"grpc_events"` - HeadersBuffMap *ebpf.Map `ebpf:"headers_buff_map"` - StreamidToSpanContexts *ebpf.Map `ebpf:"streamid_to_span_contexts"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.AllocMap, - m.Events, - m.GrpcEvents, - m.HeadersBuffMap, - m.StreamidToSpanContexts, - m.TrackedSpans, - m.TrackedSpansBySc, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeClientConnInvoke *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke"` - UprobeClientConnInvokeReturns *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke_Returns"` - UprobeLoopyWriterHeaderHandler *ebpf.Program `ebpf:"uprobe_LoopyWriter_HeaderHandler"` - UprobeHttp2ClientNewStream *ebpf.Program `ebpf:"uprobe_http2Client_NewStream"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeClientConnInvoke, - p.UprobeClientConnInvokeReturns, - p.UprobeLoopyWriterHeaderHandler, - p.UprobeHttp2ClientNewStream, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel_arm64.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_x86.go deleted file mode 100644 index f26a8e07e..000000000 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_x86.go +++ /dev/null @@ -1,163 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build 386 || amd64 - -package grpc - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfGrpcRequestT struct { - StartTime uint64 - EndTime uint64 - Sc bpfSpanContext - Psc bpfSpanContext - Method [50]int8 - Target [50]int8 - _ [4]byte -} - -type bpfHeadersBuff struct{ Buff [500]uint8 } - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeClientConnInvoke *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke"` - UprobeClientConnInvokeReturns *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke_Returns"` - UprobeLoopyWriterHeaderHandler *ebpf.ProgramSpec `ebpf:"uprobe_LoopyWriter_HeaderHandler"` - UprobeHttp2ClientNewStream *ebpf.ProgramSpec `ebpf:"uprobe_http2Client_NewStream"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - Events *ebpf.MapSpec `ebpf:"events"` - GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` - HeadersBuffMap *ebpf.MapSpec `ebpf:"headers_buff_map"` - StreamidToSpanContexts *ebpf.MapSpec `ebpf:"streamid_to_span_contexts"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - AllocMap *ebpf.Map `ebpf:"alloc_map"` - Events *ebpf.Map `ebpf:"events"` - GrpcEvents *ebpf.Map `ebpf:"grpc_events"` - HeadersBuffMap *ebpf.Map `ebpf:"headers_buff_map"` - StreamidToSpanContexts *ebpf.Map `ebpf:"streamid_to_span_contexts"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.AllocMap, - m.Events, - m.GrpcEvents, - m.HeadersBuffMap, - m.StreamidToSpanContexts, - m.TrackedSpans, - m.TrackedSpansBySc, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeClientConnInvoke *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke"` - UprobeClientConnInvokeReturns *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke_Returns"` - UprobeLoopyWriterHeaderHandler *ebpf.Program `ebpf:"uprobe_LoopyWriter_HeaderHandler"` - UprobeHttp2ClientNewStream *ebpf.Program `ebpf:"uprobe_http2Client_NewStream"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeClientConnInvoke, - p.UprobeClientConnInvokeReturns, - p.UprobeLoopyWriterHeaderHandler, - p.UprobeHttp2ClientNewStream, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel_x86.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go deleted file mode 100644 index 9d2f745d0..000000000 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go +++ /dev/null @@ -1,279 +0,0 @@ -// 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 grpc provides an instrumentor for the client in the -// google.golang.org/grpc package. -// -// Deprecated: This package is no longer supported. -package grpc - -import ( - "bytes" - "encoding/binary" - "errors" - "os" - "strings" - - "github.com/cilium/ebpf" - - "go.opentelemetry.io/auto/pkg/instrumentors/bpffs" // nolint:staticcheck // Atomic deprecation. - - "github.com/cilium/ebpf/link" - "github.com/cilium/ebpf/perf" - "golang.org/x/sys/unix" - - "go.opentelemetry.io/auto/pkg/inject" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/context" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/events" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/utils" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/otel/attribute" - semconv "go.opentelemetry.io/otel/semconv/v1.18.0" - "go.opentelemetry.io/otel/trace" -) - -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c - -// Event represents an event in the gRPC client during a gRPC request. -type Event struct { - context.BaseSpanProperties - Method [50]byte - Target [50]byte -} - -// Instrumentor is the gRPC client instrumentor. -type Instrumentor struct { - bpfObjects *bpfObjects - uprobes []link.Link - eventsReader *perf.Reader -} - -// New returns a new [Instrumentor]. -func New() *Instrumentor { - return &Instrumentor{} -} - -// LibraryName returns the gRPC package import path. -func (g *Instrumentor) LibraryName() string { - return "google.golang.org/grpc" -} - -// FuncNames returns the function names from "google.golang.org/grpc" that are -// instrumented. -func (g *Instrumentor) FuncNames() []string { - return []string{"google.golang.org/grpc.(*ClientConn).Invoke", - "google.golang.org/grpc/internal/transport.(*http2Client).NewStream", - "google.golang.org/grpc/internal/transport.(*loopyWriter).headerHandler"} -} - -// Load loads all instrumentation offsets. -func (g *Instrumentor) Load(ctx *context.InstrumentorContext) error { - libVersion, exists := ctx.TargetDetails.Libraries[g.LibraryName()] - if !exists { - libVersion = "" - } - spec, err := ctx.Injector.Inject(loadBpf, g.LibraryName(), libVersion, []*inject.StructField{ - { - VarName: "clientconn_target_ptr_pos", - StructName: "google.golang.org/grpc.ClientConn", - Field: "target", - }, - { - VarName: "httpclient_nextid_pos", - StructName: "google.golang.org/grpc/internal/transport.http2Client", - Field: "nextID", - }, - { - VarName: "headerFrame_hf_pos", - StructName: "google.golang.org/grpc/internal/transport.headerFrame", - Field: "hf", - }, - { - VarName: "headerFrame_streamid_pos", - StructName: "google.golang.org/grpc/internal/transport.headerFrame", - Field: "streamID", - }, - }, nil, true) - - if err != nil { - return err - } - - g.bpfObjects = &bpfObjects{} - err = utils.LoadEBPFObjects(spec, g.bpfObjects, &ebpf.CollectionOptions{ - Maps: ebpf.MapOptions{ - PinPath: bpffs.PathForTargetApplication(ctx.TargetDetails), - }, - }) - - if err != nil { - return err - } - - offset, err := ctx.TargetDetails.GetFunctionOffset(g.FuncNames()[0]) - if err != nil { - return err - } - - up, err := ctx.Executable.Uprobe("", g.bpfObjects.UprobeClientConnInvoke, &link.UprobeOptions{ - Address: offset, - }) - if err != nil { - return err - } - - g.uprobes = append(g.uprobes, up) - - retOffsets, err := ctx.TargetDetails.GetFunctionReturns(g.FuncNames()[0]) - if err != nil { - return err - } - - for _, ret := range retOffsets { - retProbe, err := ctx.Executable.Uprobe("", g.bpfObjects.UprobeClientConnInvokeReturns, &link.UprobeOptions{ - Address: ret, - }) - if err != nil { - return err - } - g.uprobes = append(g.uprobes, retProbe) - } - - // SendMsg probe - sendMsgOffset, err := ctx.TargetDetails.GetFunctionOffset(g.FuncNames()[1]) - if err != nil { - return err - } - sendMsgProbe, err := ctx.Executable.Uprobe("", g.bpfObjects.UprobeHttp2ClientNewStream, &link.UprobeOptions{ - Address: sendMsgOffset, - }) - if err != nil { - return err - } - g.uprobes = append(g.uprobes, sendMsgProbe) - - // Write headers probe - whOffset, err := ctx.TargetDetails.GetFunctionOffset(g.FuncNames()[2]) - if err != nil { - return err - } - - whProbe, err := ctx.Executable.Uprobe("", g.bpfObjects.UprobeLoopyWriterHeaderHandler, &link.UprobeOptions{ - Address: whOffset, - }) - if err != nil { - return err - } - - g.uprobes = append(g.uprobes, whProbe) - - rd, err := perf.NewReader(g.bpfObjects.Events, os.Getpagesize()) - if err != nil { - return err - } - g.eventsReader = rd - return nil -} - -// Run runs the events processing loop. -func (g *Instrumentor) Run(eventsChan chan<- *events.Event) { - logger := log.Logger.WithName("grpc-instrumentor") - var event Event - for { - record, err := g.eventsReader.Read() - if err != nil { - if errors.Is(err, perf.ErrClosed) { - return - } - logger.Error(err, "error reading from perf reader") - continue - } - - if record.LostSamples != 0 { - logger.V(0).Info("perf event ring buffer full", "dropped", record.LostSamples) - continue - } - - if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.LittleEndian, &event); err != nil { - logger.Error(err, "error parsing perf event") - continue - } - - eventsChan <- g.convertEvent(&event) - } -} - -// According to https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/rpc.md -func (g *Instrumentor) convertEvent(e *Event) *events.Event { - method := unix.ByteSliceToString(e.Method[:]) - target := unix.ByteSliceToString(e.Target[:]) - var attrs []attribute.KeyValue - - // remove port - if parts := strings.Split(target, ":"); len(parts) > 1 { - target = parts[0] - attrs = append(attrs, semconv.NetPeerPortKey.String(parts[1])) - } - - attrs = append(attrs, semconv.RPCSystemKey.String("grpc"), - semconv.RPCServiceKey.String(method), - semconv.NetPeerNameKey.String(target)) - - sc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: e.SpanContext.TraceID, - SpanID: e.SpanContext.SpanID, - TraceFlags: trace.FlagsSampled, - }) - - var pscPtr *trace.SpanContext - if e.ParentSpanContext.TraceID.IsValid() { - psc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: e.ParentSpanContext.TraceID, - SpanID: e.ParentSpanContext.SpanID, - TraceFlags: trace.FlagsSampled, - Remote: true, - }) - pscPtr = &psc - } else { - pscPtr = nil - } - - log.Logger.V(0).Info("got spancontext", "trace_id", e.SpanContext.TraceID.String(), "span_id", e.SpanContext.SpanID.String()) - return &events.Event{ - Library: g.LibraryName(), - Name: method, - Kind: trace.SpanKindClient, - StartTime: int64(e.StartTime), - EndTime: int64(e.EndTime), - Attributes: attrs, - SpanContext: &sc, - ParentSpanContext: pscPtr, - } -} - -// Close stops the Instrumentor. -func (g *Instrumentor) Close() { - log.Logger.V(0).Info("closing gRPC instrumentor") - if g.eventsReader != nil { - g.eventsReader.Close() - } - - for _, r := range g.uprobes { - r.Close() - } - - if g.bpfObjects != nil { - g.bpfObjects.Close() - } -} diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf/probe.bpf.c b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf/probe.bpf.c deleted file mode 100644 index 274c5de3a..000000000 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf/probe.bpf.c +++ /dev/null @@ -1,158 +0,0 @@ -// 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. - -#include "arguments.h" -#include "go_types.h" -#include "span_context.h" -#include "go_context.h" -#include "uprobe.h" - -char __license[] SEC("license") = "Dual MIT/GPL"; - -#define MAX_SIZE 100 -#define MAX_CONCURRENT 50 -#define MAX_HEADERS 20 -#define MAX_HEADER_STRING 50 -#define W3C_KEY_LENGTH 11 -#define W3C_VAL_LENGTH 55 - -struct grpc_request_t -{ - BASE_SPAN_PROPERTIES - char method[MAX_SIZE]; -}; - -struct -{ - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, void *); - __type(value, struct grpc_request_t); - __uint(max_entries, MAX_CONCURRENT); -} grpc_events SEC(".maps"); - -struct -{ - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, u32); - __type(value, struct grpc_request_t); - __uint(max_entries, MAX_CONCURRENT); -} streamid_to_grpc_events SEC(".maps"); - -struct -{ - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); -} events SEC(".maps"); - -struct hpack_header_field -{ - struct go_string name; - struct go_string value; - bool sensitive; -}; - -// Injected in init -volatile const u64 stream_method_ptr_pos; -volatile const u64 frame_fields_pos; -volatile const u64 frame_stream_id_pod; -volatile const u64 stream_id_pos; -volatile const u64 stream_ctx_pos; - -// This instrumentation attaches uprobe to the following function: -// func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream, trInfo *traceInfo) { -SEC("uprobe/server_handleStream") -int uprobe_server_handleStream(struct pt_regs *ctx) -{ - u64 stream_pos = 4; - void *stream_ptr = get_argument(ctx, stream_pos); - - // Get parent context if exists - u32 stream_id = 0; - bpf_probe_read(&stream_id, sizeof(stream_id), (void *)(stream_ptr + stream_id_pos)); - void *grpcReq_ptr = bpf_map_lookup_elem(&streamid_to_grpc_events, &stream_id); - struct grpc_request_t grpcReq = {}; - if (grpcReq_ptr != NULL) - { - bpf_probe_read(&grpcReq, sizeof(grpcReq), grpcReq_ptr); - bpf_map_delete_elem(&streamid_to_grpc_events, &stream_id); - copy_byte_arrays(grpcReq.psc.TraceID, grpcReq.sc.TraceID, TRACE_ID_SIZE); - generate_random_bytes(grpcReq.sc.SpanID, SPAN_ID_SIZE); - } - else - { - grpcReq.sc = generate_span_context(); - } - - // Set attributes - grpcReq.start_time = bpf_ktime_get_ns(); - void *method_ptr = 0; - bpf_probe_read(&method_ptr, sizeof(method_ptr), (void *)(stream_ptr + stream_method_ptr_pos)); - u64 method_len = 0; - bpf_probe_read(&method_len, sizeof(method_len), (void *)(stream_ptr + (stream_method_ptr_pos + 8))); - u64 method_size = sizeof(grpcReq.method); - method_size = method_size < method_len ? method_size : method_len; - bpf_probe_read(&grpcReq.method, method_size, method_ptr); - - // Get key - void *ctx_iface = 0; - bpf_probe_read(&ctx_iface, sizeof(ctx_iface), (void *)(stream_ptr + stream_ctx_pos)); - void *key = get_consistent_key(ctx, (void *)(stream_ptr + stream_ctx_pos)); - - // Write event - bpf_map_update_elem(&grpc_events, &key, &grpcReq, 0); - start_tracking_span(ctx_iface, &grpcReq.sc); - return 0; -} - -UPROBE_RETURN(server_handleStream, struct grpc_request_t, 4, stream_ctx_pos, grpc_events, events) - -// func (d *decodeState) decodeHeader(frame *http2.MetaHeadersFrame) error -SEC("uprobe/decodeState_decodeHeader") -int uprobe_decodeState_decodeHeader(struct pt_regs *ctx) -{ - u64 frame_pos = 2; - void *frame_ptr = get_argument(ctx, frame_pos); - struct go_slice header_fields = {}; - bpf_probe_read(&header_fields, sizeof(header_fields), (void *)(frame_ptr + frame_fields_pos)); - char key[W3C_KEY_LENGTH] = "traceparent"; - for (s32 i = 0; i < MAX_HEADERS; i++) - { - if (i >= header_fields.len) - { - break; - } - struct hpack_header_field hf = {}; - long res = bpf_probe_read(&hf, sizeof(hf), (void *)(header_fields.array + (i * sizeof(hf)))); - if (hf.name.len == W3C_KEY_LENGTH && hf.value.len == W3C_VAL_LENGTH) - { - char current_key[W3C_KEY_LENGTH]; - bpf_probe_read(current_key, sizeof(current_key), hf.name.str); - if (bpf_memcmp(key, current_key, sizeof(key))) - { - char val[W3C_VAL_LENGTH]; - bpf_probe_read(val, W3C_VAL_LENGTH, hf.value.str); - - // Get stream id - void *headers_frame = NULL; - bpf_probe_read(&headers_frame, sizeof(headers_frame), frame_ptr); - u32 stream_id = 0; - bpf_probe_read(&stream_id, sizeof(stream_id), (void *)(headers_frame + frame_stream_id_pod)); - struct grpc_request_t grpcReq = {}; - w3c_string_to_span_context(val, &grpcReq.psc); - bpf_map_update_elem(&streamid_to_grpc_events, &stream_id, &grpcReq, 0); - } - } - } - - return 0; -} \ No newline at end of file diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_arm64.go deleted file mode 100644 index 8002c33ab..000000000 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_arm64.go +++ /dev/null @@ -1,154 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build arm64 - -package server - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfGrpcRequestT struct { - StartTime uint64 - EndTime uint64 - Sc bpfSpanContext - Psc bpfSpanContext - Method [100]int8 - _ [4]byte -} - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeDecodeStateDecodeHeader *ebpf.ProgramSpec `ebpf:"uprobe_decodeState_decodeHeader"` - UprobeServerHandleStream *ebpf.ProgramSpec `ebpf:"uprobe_server_handleStream"` - UprobeServerHandleStreamReturns *ebpf.ProgramSpec `ebpf:"uprobe_server_handleStream_Returns"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - Events *ebpf.MapSpec `ebpf:"events"` - GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` - StreamidToGrpcEvents *ebpf.MapSpec `ebpf:"streamid_to_grpc_events"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - AllocMap *ebpf.Map `ebpf:"alloc_map"` - Events *ebpf.Map `ebpf:"events"` - GrpcEvents *ebpf.Map `ebpf:"grpc_events"` - StreamidToGrpcEvents *ebpf.Map `ebpf:"streamid_to_grpc_events"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.AllocMap, - m.Events, - m.GrpcEvents, - m.StreamidToGrpcEvents, - m.TrackedSpans, - m.TrackedSpansBySc, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeDecodeStateDecodeHeader *ebpf.Program `ebpf:"uprobe_decodeState_decodeHeader"` - UprobeServerHandleStream *ebpf.Program `ebpf:"uprobe_server_handleStream"` - UprobeServerHandleStreamReturns *ebpf.Program `ebpf:"uprobe_server_handleStream_Returns"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeDecodeStateDecodeHeader, - p.UprobeServerHandleStream, - p.UprobeServerHandleStreamReturns, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel_arm64.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_x86.go deleted file mode 100644 index db9a7611c..000000000 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_x86.go +++ /dev/null @@ -1,154 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build 386 || amd64 - -package server - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfGrpcRequestT struct { - StartTime uint64 - EndTime uint64 - Sc bpfSpanContext - Psc bpfSpanContext - Method [100]int8 - _ [4]byte -} - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeDecodeStateDecodeHeader *ebpf.ProgramSpec `ebpf:"uprobe_decodeState_decodeHeader"` - UprobeServerHandleStream *ebpf.ProgramSpec `ebpf:"uprobe_server_handleStream"` - UprobeServerHandleStreamReturns *ebpf.ProgramSpec `ebpf:"uprobe_server_handleStream_Returns"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - Events *ebpf.MapSpec `ebpf:"events"` - GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` - StreamidToGrpcEvents *ebpf.MapSpec `ebpf:"streamid_to_grpc_events"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - AllocMap *ebpf.Map `ebpf:"alloc_map"` - Events *ebpf.Map `ebpf:"events"` - GrpcEvents *ebpf.Map `ebpf:"grpc_events"` - StreamidToGrpcEvents *ebpf.Map `ebpf:"streamid_to_grpc_events"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.AllocMap, - m.Events, - m.GrpcEvents, - m.StreamidToGrpcEvents, - m.TrackedSpans, - m.TrackedSpansBySc, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeDecodeStateDecodeHeader *ebpf.Program `ebpf:"uprobe_decodeState_decodeHeader"` - UprobeServerHandleStream *ebpf.Program `ebpf:"uprobe_server_handleStream"` - UprobeServerHandleStreamReturns *ebpf.Program `ebpf:"uprobe_server_handleStream_Returns"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeDecodeStateDecodeHeader, - p.UprobeServerHandleStream, - p.UprobeServerHandleStreamReturns, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel_x86.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go deleted file mode 100644 index 1f0bda610..000000000 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go +++ /dev/null @@ -1,263 +0,0 @@ -// 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 server provides an instrumentor for the server in the -// google.golang.org/grpc package. -// -// Deprecated: This package is no longer supported. -package server - -import ( - "bytes" - "encoding/binary" - "errors" - "os" - - "go.opentelemetry.io/auto/pkg/instrumentors/bpffs" // nolint:staticcheck // Atomic deprecation. - - "github.com/cilium/ebpf" - "github.com/cilium/ebpf/link" - "github.com/cilium/ebpf/perf" - "golang.org/x/sys/unix" - - "go.opentelemetry.io/auto/pkg/inject" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/context" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/events" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/utils" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/otel/attribute" - semconv "go.opentelemetry.io/otel/semconv/v1.18.0" - "go.opentelemetry.io/otel/trace" -) - -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c - -// Event represents an event in the gRPC server during a gRPC request. -type Event struct { - context.BaseSpanProperties - Method [100]byte -} - -// Instrumentor is the gRPC server instrumentor. -type Instrumentor struct { - bpfObjects *bpfObjects - uprobe link.Link - returnProbs []link.Link - headersProbe link.Link - eventsReader *perf.Reader -} - -// New returns a new [Instrumentor]. -func New() *Instrumentor { - return &Instrumentor{} -} - -// LibraryName returns the gRPC server package import path. -func (g *Instrumentor) LibraryName() string { - return "google.golang.org/grpc/server" -} - -// FuncNames returns the function names from "google.golang.org/grpc" that are -// instrumented. -func (g *Instrumentor) FuncNames() []string { - return []string{"google.golang.org/grpc.(*Server).handleStream", - "google.golang.org/grpc/internal/transport.(*http2Server).operateHeaders"} -} - -// Load loads all instrumentation offsets. -func (g *Instrumentor) Load(ctx *context.InstrumentorContext) error { - targetLib := "google.golang.org/grpc" - libVersion, exists := ctx.TargetDetails.Libraries[targetLib] - if !exists { - libVersion = "" - } - spec, err := ctx.Injector.Inject(loadBpf, "google.golang.org/grpc", libVersion, []*inject.StructField{ - { - VarName: "stream_method_ptr_pos", - StructName: "google.golang.org/grpc/internal/transport.Stream", - Field: "method", - }, - { - VarName: "stream_id_pos", - StructName: "google.golang.org/grpc/internal/transport.Stream", - Field: "id", - }, - { - VarName: "stream_ctx_pos", - StructName: "google.golang.org/grpc/internal/transport.Stream", - Field: "ctx", - }, - { - VarName: "frame_fields_pos", - StructName: "golang.org/x/net/http2.MetaHeadersFrame", - Field: "Fields", - }, - { - VarName: "frame_stream_id_pod", - StructName: "golang.org/x/net/http2.FrameHeader", - Field: "StreamID", - }, - }, nil, true) - - if err != nil { - return err - } - - g.bpfObjects = &bpfObjects{} - err = utils.LoadEBPFObjects(spec, g.bpfObjects, &ebpf.CollectionOptions{ - Maps: ebpf.MapOptions{ - PinPath: bpffs.PathForTargetApplication(ctx.TargetDetails), - }, - }) - if err != nil { - return err - } - - offset, err := ctx.TargetDetails.GetFunctionOffset(g.FuncNames()[0]) - if err != nil { - return err - } - - up, err := ctx.Executable.Uprobe("", g.bpfObjects.UprobeServerHandleStream, &link.UprobeOptions{ - Address: offset, - }) - if err != nil { - return err - } - - g.uprobe = up - retOffsets, err := ctx.TargetDetails.GetFunctionReturns(g.FuncNames()[0]) - if err != nil { - return err - } - - for _, ret := range retOffsets { - retProbe, err := ctx.Executable.Uprobe("", g.bpfObjects.UprobeServerHandleStreamReturns, &link.UprobeOptions{ - Address: ret, - }) - if err != nil { - return err - } - g.returnProbs = append(g.returnProbs, retProbe) - } - - headerOffset, err := ctx.TargetDetails.GetFunctionOffset(g.FuncNames()[1]) - if err != nil { - return err - } - hProbe, err := ctx.Executable.Uprobe("", g.bpfObjects.UprobeDecodeStateDecodeHeader, &link.UprobeOptions{ - Address: headerOffset, - }) - if err != nil { - return err - } - g.headersProbe = hProbe - - rd, err := perf.NewReader(g.bpfObjects.Events, os.Getpagesize()) - if err != nil { - return err - } - g.eventsReader = rd - - return nil -} - -// Run runs the events processing loop. -func (g *Instrumentor) Run(eventsChan chan<- *events.Event) { - logger := log.Logger.WithName("grpc-server-instrumentor") - var event Event - for { - record, err := g.eventsReader.Read() - if err != nil { - if errors.Is(err, perf.ErrClosed) { - return - } - logger.Error(err, "error reading from perf reader") - continue - } - - if record.LostSamples != 0 { - logger.V(0).Info("perf event ring buffer full", "dropped", record.LostSamples) - continue - } - - if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.LittleEndian, &event); err != nil { - logger.Error(err, "error parsing perf event") - continue - } - - eventsChan <- g.convertEvent(&event) - } -} - -func (g *Instrumentor) convertEvent(e *Event) *events.Event { - method := unix.ByteSliceToString(e.Method[:]) - - sc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: e.SpanContext.TraceID, - SpanID: e.SpanContext.SpanID, - TraceFlags: trace.FlagsSampled, - }) - - var pscPtr *trace.SpanContext - if e.ParentSpanContext.TraceID.IsValid() { - psc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: e.ParentSpanContext.TraceID, - SpanID: e.ParentSpanContext.SpanID, - TraceFlags: trace.FlagsSampled, - Remote: true, - }) - pscPtr = &psc - } else { - pscPtr = nil - } - - return &events.Event{ - Library: g.LibraryName(), - Name: method, - Kind: trace.SpanKindServer, - StartTime: int64(e.StartTime), - EndTime: int64(e.EndTime), - Attributes: []attribute.KeyValue{ - semconv.RPCSystemKey.String("grpc"), - semconv.RPCServiceKey.String(method), - }, - ParentSpanContext: pscPtr, - SpanContext: &sc, - } -} - -// Close stops the Instrumentor. -func (g *Instrumentor) Close() { - log.Logger.V(0).Info("closing gRPC server instrumentor") - if g.eventsReader != nil { - g.eventsReader.Close() - } - - if g.uprobe != nil { - g.uprobe.Close() - } - - for _, r := range g.returnProbs { - r.Close() - } - - if g.headersProbe != nil { - g.headersProbe.Close() - } - - if g.bpfObjects != nil { - g.bpfObjects.Close() - } -} diff --git a/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c deleted file mode 100644 index 61a692bcc..000000000 --- a/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ /dev/null @@ -1,202 +0,0 @@ -#include "arguments.h" -#include "span_context.h" -#include "go_context.h" -#include "go_types.h" -#include "uprobe.h" - -char __license[] SEC("license") = "Dual MIT/GPL"; - -#define MAX_PATH_SIZE 100 -#define MAX_METHOD_SIZE 10 -#define W3C_KEY_LENGTH 11 -#define W3C_VAL_LENGTH 55 -#define MAX_CONCURRENT 50 - -struct http_request_t { - BASE_SPAN_PROPERTIES - char method[MAX_METHOD_SIZE]; - char path[MAX_PATH_SIZE]; -}; - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, void*); - __type(value, struct http_request_t); - __uint(max_entries, MAX_CONCURRENT); -} http_events SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); - __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(struct map_bucket)); - __uint(max_entries, 1); -} golang_mapbucket_storage_map SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); -} events SEC(".maps"); - -// Injected in init -volatile const u64 method_ptr_pos; -volatile const u64 url_ptr_pos; -volatile const u64 path_ptr_pos; -volatile const u64 headers_ptr_pos; -volatile const u64 ctx_ptr_pos; - -static __always_inline long inject_header(void* headers_ptr, struct span_context* propagated_ctx) { - - // Read headers map count - u64 map_keyvalue_count = 0; - bpf_probe_read(&map_keyvalue_count, sizeof(map_keyvalue_count), headers_ptr); - - // Currently only maps with less than 8 keys are supported for injection - if (map_keyvalue_count >= 8) { - bpf_printk("Map size is bigger than 8, skipping context propagation"); - return 0; - } - - long res; - if (map_keyvalue_count == 0) { - u32 map_id = 0; - struct map_bucket *map_value = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id); - if (!map_value) { - return -1; - } - void *bucket_ptr = write_target_data(map_value, sizeof(struct map_bucket)); - res = bpf_probe_write_user(headers_ptr + 16, &bucket_ptr, sizeof(bucket_ptr)); - - if(res < 0) { - bpf_printk("Failed to write bucket ptr, return code: %d", res); - return -1; - } - - } - - void *map_keyvalues_ptr = NULL; - bpf_probe_read(&map_keyvalues_ptr, sizeof(map_keyvalues_ptr), headers_ptr + 16); - void *injected_key_ptr = map_keyvalues_ptr + 8 + (16 * map_keyvalue_count); - char traceparent_tophash = 0xee; - void *tophashes_ptr = map_keyvalues_ptr + map_keyvalue_count; - res = bpf_probe_write_user(tophashes_ptr, &traceparent_tophash, 1); - - if(res < 0) { - bpf_printk("Failed to write tophash, return code: %d", res); - return -1; - } - - char key[W3C_KEY_LENGTH] = "traceparent"; - void *ptr = write_target_data(key, W3C_KEY_LENGTH); - - res = bpf_probe_write_user(injected_key_ptr, &ptr, sizeof(ptr)); - if(res < 0) { - return -1; - } - - u64 header_key_length = W3C_KEY_LENGTH; - res = bpf_probe_write_user(injected_key_ptr + 8, &header_key_length, sizeof(header_key_length)); - - if(res < 0) { - return -1; - } - - void *injected_value_ptr = injected_key_ptr + (16 * (8 - map_keyvalue_count)) + 24 * map_keyvalue_count; - char val[W3C_VAL_LENGTH]; - span_context_to_w3c_string(propagated_ctx, val); - - ptr = write_target_data(val, sizeof(val)); - struct go_string header_value = {}; - header_value.str = ptr; - header_value.len = W3C_VAL_LENGTH; - - ptr = write_target_data((void*)&header_value, sizeof(header_value)); - - if(ptr == NULL) { - return -1; - } - - struct go_slice values_slice = {}; - values_slice.array = ptr; - values_slice.len = 1; - values_slice.cap = 1; - - res = bpf_probe_write_user(injected_value_ptr, &values_slice, sizeof(values_slice)); - - if(res < 0) { - return -1; - } - - map_keyvalue_count += 1; - res = bpf_probe_write_user(headers_ptr, &map_keyvalue_count, sizeof(map_keyvalue_count)); - - if(res < 0) { - return -1; - } - - return 0; -} - -// This instrumentation attaches uprobe to the following function: -// func net/http/client.Do(req *Request) -SEC("uprobe/HttpClient_Do") -int uprobe_HttpClient_Do(struct pt_regs *ctx) { - struct http_request_t httpReq = {}; - httpReq.start_time = bpf_ktime_get_ns(); - - u64 request_pos = 2; - void *req_ptr = get_argument(ctx, request_pos); - - // Get parent if exists - void *context_ptr = (void *)(req_ptr+ctx_ptr_pos); - void *context_ptr_val = 0; - bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); - struct span_context *parent_span_ctx = get_parent_span_context(context_ptr_val); - if (parent_span_ctx != NULL) { - bpf_probe_read(&httpReq.psc, sizeof(httpReq.psc), parent_span_ctx); - copy_byte_arrays(httpReq.psc.TraceID, httpReq.sc.TraceID, TRACE_ID_SIZE); - generate_random_bytes(httpReq.sc.SpanID, SPAN_ID_SIZE); - } else { - httpReq.sc = generate_span_context(); - } - - void *method_ptr = 0; - bpf_probe_read(&method_ptr, sizeof(method_ptr), (void *)(req_ptr+method_ptr_pos)); - u64 method_len = 0; - bpf_probe_read(&method_len, sizeof(method_len), (void *)(req_ptr+(method_ptr_pos+8))); - u64 method_size = sizeof(httpReq.method); - method_size = method_size < method_len ? method_size : method_len; - bpf_probe_read(&httpReq.method, method_size, method_ptr); - - // get path from Request.URL - void *url_ptr = 0; - bpf_probe_read(&url_ptr, sizeof(url_ptr), (void *)(req_ptr+url_ptr_pos)); - void *path_ptr = 0; - bpf_probe_read(&path_ptr, sizeof(path_ptr), (void *)(url_ptr+path_ptr_pos)); - - u64 path_len = 0; - bpf_probe_read(&path_len, sizeof(path_len), (void *)(url_ptr+(path_ptr_pos+8))); - u64 path_size = sizeof(httpReq.path); - path_size = path_size < path_len ? path_size : path_len; - bpf_probe_read(&httpReq.path, path_size, path_ptr); - - // get headers from Request - void *headers_ptr = 0; - bpf_probe_read(&headers_ptr, sizeof(headers_ptr), (void *)(req_ptr+headers_ptr_pos)); - u64 map_keyvalue_count = 0; - bpf_probe_read(&map_keyvalue_count, sizeof(map_keyvalue_count), headers_ptr); - long res = inject_header(headers_ptr, &httpReq.sc); - if (res < 0) { - bpf_printk("uprobe_HttpClient_Do: Failed to inject header"); - } - - // Get key - void *key = get_consistent_key(ctx, context_ptr); - - // Write event - bpf_map_update_elem(&http_events, &key, &httpReq, 0); - start_tracking_span(context_ptr_val, &httpReq.sc); - return 0; -} - -// This instrumentation attaches uretprobe to the following function: -// func net/http/client.Do(req *Request) -UPROBE_RETURN(HttpClient_Do, struct http_request_t, 2, ctx_ptr_pos, http_events, events) \ No newline at end of file diff --git a/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go deleted file mode 100644 index 6846ab481..000000000 --- a/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go +++ /dev/null @@ -1,152 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build arm64 - -package client - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfHttpRequestT struct { - StartTime uint64 - EndTime uint64 - Sc bpfSpanContext - Psc bpfSpanContext - Method [10]int8 - Path [100]int8 - _ [2]byte -} - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeHttpClientDo *ebpf.ProgramSpec `ebpf:"uprobe_HttpClient_Do"` - UprobeHttpClientDoReturns *ebpf.ProgramSpec `ebpf:"uprobe_HttpClient_Do_Returns"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - Events *ebpf.MapSpec `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` - HttpEvents *ebpf.MapSpec `ebpf:"http_events"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - AllocMap *ebpf.Map `ebpf:"alloc_map"` - Events *ebpf.Map `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` - HttpEvents *ebpf.Map `ebpf:"http_events"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.AllocMap, - m.Events, - m.GolangMapbucketStorageMap, - m.HttpEvents, - m.TrackedSpans, - m.TrackedSpansBySc, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeHttpClientDo *ebpf.Program `ebpf:"uprobe_HttpClient_Do"` - UprobeHttpClientDoReturns *ebpf.Program `ebpf:"uprobe_HttpClient_Do_Returns"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeHttpClientDo, - p.UprobeHttpClientDoReturns, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel_arm64.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go deleted file mode 100644 index 6352e91da..000000000 --- a/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go +++ /dev/null @@ -1,152 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build 386 || amd64 - -package client - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfHttpRequestT struct { - StartTime uint64 - EndTime uint64 - Sc bpfSpanContext - Psc bpfSpanContext - Method [10]int8 - Path [100]int8 - _ [2]byte -} - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeHttpClientDo *ebpf.ProgramSpec `ebpf:"uprobe_HttpClient_Do"` - UprobeHttpClientDoReturns *ebpf.ProgramSpec `ebpf:"uprobe_HttpClient_Do_Returns"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - Events *ebpf.MapSpec `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` - HttpEvents *ebpf.MapSpec `ebpf:"http_events"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - AllocMap *ebpf.Map `ebpf:"alloc_map"` - Events *ebpf.Map `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` - HttpEvents *ebpf.Map `ebpf:"http_events"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.AllocMap, - m.Events, - m.GolangMapbucketStorageMap, - m.HttpEvents, - m.TrackedSpans, - m.TrackedSpansBySc, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeHttpClientDo *ebpf.Program `ebpf:"uprobe_HttpClient_Do"` - UprobeHttpClientDoReturns *ebpf.Program `ebpf:"uprobe_HttpClient_Do_Returns"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeHttpClientDo, - p.UprobeHttpClientDoReturns, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel_x86.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/net/http/client/probe.go b/pkg/instrumentors/bpf/net/http/client/probe.go deleted file mode 100644 index cfb30cb20..000000000 --- a/pkg/instrumentors/bpf/net/http/client/probe.go +++ /dev/null @@ -1,246 +0,0 @@ -// 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 client provides an instrumentor for the client in the net/http -// package. -// -// Deprecated: This package is no longer supported. -package client - -import ( - "bytes" - "encoding/binary" - "errors" - "os" - - "go.opentelemetry.io/auto/pkg/instrumentors/bpffs" // nolint:staticcheck // Atomic deprecation. - - "github.com/cilium/ebpf" - "github.com/cilium/ebpf/link" - "github.com/cilium/ebpf/perf" - "golang.org/x/sys/unix" - - "go.opentelemetry.io/auto/pkg/inject" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/context" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/events" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/otel/attribute" - semconv "go.opentelemetry.io/otel/semconv/v1.7.0" - "go.opentelemetry.io/otel/trace" -) - -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c - -// Event represents an event in an HTTP server during an HTTP -// request-response. -type Event struct { - context.BaseSpanProperties - Method [10]byte - Path [100]byte -} - -// Instrumentor is the net/http instrumentor. -type Instrumentor struct { - bpfObjects *bpfObjects - uprobes []link.Link - returnProbs []link.Link - eventsReader *perf.Reader -} - -// New returns a new [Instrumentor]. -func New() *Instrumentor { - return &Instrumentor{} -} - -// LibraryName returns the net/http package name. -func (h *Instrumentor) LibraryName() string { - return "net/http/client" -} - -// FuncNames returns the function names from "net/http" that are instrumented. -func (h *Instrumentor) FuncNames() []string { - return []string{"net/http.(*Client).do"} -} - -// Load loads all instrumentation offsets. -func (h *Instrumentor) Load(ctx *context.InstrumentorContext) error { - spec, err := ctx.Injector.Inject(loadBpf, "go", ctx.TargetDetails.GoVersion.Original(), []*inject.StructField{ - { - VarName: "method_ptr_pos", - StructName: "net/http.Request", - Field: "Method", - }, - { - VarName: "url_ptr_pos", - StructName: "net/http.Request", - Field: "URL", - }, - { - VarName: "path_ptr_pos", - StructName: "net/url.URL", - Field: "Path", - }, - { - VarName: "headers_ptr_pos", - StructName: "net/http.Request", - Field: "Header", - }, - { - VarName: "ctx_ptr_pos", - StructName: "net/http.Request", - Field: "ctx", - }, - }, nil, true) - - if err != nil { - return err - } - - h.bpfObjects = &bpfObjects{} - err = spec.LoadAndAssign(h.bpfObjects, &ebpf.CollectionOptions{ - Maps: ebpf.MapOptions{ - PinPath: bpffs.PathForTargetApplication(ctx.TargetDetails), - }, - }) - - if err != nil { - return err - } - - offset, err := ctx.TargetDetails.GetFunctionOffset(h.FuncNames()[0]) - - if err != nil { - return err - } - - up, err := ctx.Executable.Uprobe("", h.bpfObjects.UprobeHttpClientDo, &link.UprobeOptions{ - Address: offset, - }) - - if err != nil { - return err - } - - h.uprobes = append(h.uprobes, up) - - retOffsets, err := ctx.TargetDetails.GetFunctionReturns(h.FuncNames()[0]) - - if err != nil { - return err - } - - for _, ret := range retOffsets { - retProbe, err := ctx.Executable.Uprobe("", h.bpfObjects.UprobeHttpClientDoReturns, &link.UprobeOptions{ - Address: ret, - }) - if err != nil { - return err - } - h.returnProbs = append(h.returnProbs, retProbe) - } - - rd, err := perf.NewReader(h.bpfObjects.Events, os.Getpagesize()) - if err != nil { - return err - } - h.eventsReader = rd - - return nil -} - -// Run runs the events processing loop. -func (h *Instrumentor) Run(eventsChan chan<- *events.Event) { - logger := log.Logger.WithName("net/http/client-instrumentor") - var event Event - for { - record, err := h.eventsReader.Read() - if err != nil { - if errors.Is(err, perf.ErrClosed) { - return - } - logger.Error(err, "error reading from perf reader") - continue - } - - if record.LostSamples != 0 { - logger.V(0).Info("perf event ring buffer full", "dropped", record.LostSamples) - continue - } - - if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.LittleEndian, &event); err != nil { - logger.Error(err, "error parsing perf event") - continue - } - - eventsChan <- h.convertEvent(&event) - } -} - -func (h *Instrumentor) convertEvent(e *Event) *events.Event { - method := unix.ByteSliceToString(e.Method[:]) - path := unix.ByteSliceToString(e.Path[:]) - - sc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: e.SpanContext.TraceID, - SpanID: e.SpanContext.SpanID, - TraceFlags: trace.FlagsSampled, - }) - - var pscPtr *trace.SpanContext - if e.ParentSpanContext.TraceID.IsValid() { - psc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: e.ParentSpanContext.TraceID, - SpanID: e.ParentSpanContext.SpanID, - TraceFlags: trace.FlagsSampled, - Remote: true, - }) - pscPtr = &psc - } else { - pscPtr = nil - } - - return &events.Event{ - Library: h.LibraryName(), - Name: path, - Kind: trace.SpanKindClient, - StartTime: int64(e.StartTime), - EndTime: int64(e.EndTime), - SpanContext: &sc, - Attributes: []attribute.KeyValue{ - semconv.HTTPMethodKey.String(method), - semconv.HTTPTargetKey.String(path), - }, - ParentSpanContext: pscPtr, - } -} - -// Close stops the Instrumentor. -func (h *Instrumentor) Close() { - log.Logger.V(0).Info("closing net/http/client instrumentor") - if h.eventsReader != nil { - h.eventsReader.Close() - } - - for _, r := range h.uprobes { - r.Close() - } - - for _, r := range h.returnProbs { - r.Close() - } - - if h.bpfObjects != nil { - h.bpfObjects.Close() - } -} diff --git a/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c deleted file mode 100644 index 5d1c23a6f..000000000 --- a/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ /dev/null @@ -1,225 +0,0 @@ -// 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. - -#include "arguments.h" -#include "span_context.h" -#include "go_context.h" -#include "go_types.h" -#include "uprobe.h" - -char __license[] SEC("license") = "Dual MIT/GPL"; - -#define PATH_MAX_LEN 100 -#define MAX_BUCKETS 8 -#define METHOD_MAX_LEN 7 -#define MAX_CONCURRENT 50 -#define W3C_KEY_LENGTH 11 -#define W3C_VAL_LENGTH 55 - -struct http_request_t -{ - BASE_SPAN_PROPERTIES - char method[METHOD_MAX_LEN]; - char path[PATH_MAX_LEN]; -}; - -struct -{ - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, void *); - __type(value, struct http_request_t); - __uint(max_entries, MAX_CONCURRENT); -} http_events SEC(".maps"); - -struct -{ - __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); - __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(struct map_bucket)); - __uint(max_entries, 1); -} golang_mapbucket_storage_map SEC(".maps"); - -struct -{ - __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); - __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(struct span_context)); - __uint(max_entries, 1); -} parent_span_context_storage_map SEC(".maps"); - -struct -{ - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); -} events SEC(".maps"); - -// Injected in init -volatile const u64 method_ptr_pos; -volatile const u64 url_ptr_pos; -volatile const u64 path_ptr_pos; -volatile const u64 ctx_ptr_pos; -volatile const u64 headers_ptr_pos; - -static __always_inline struct span_context *extract_context_from_req_headers(void *headers_ptr_ptr) -{ - void *headers_ptr; - long res; - res = bpf_probe_read(&headers_ptr, sizeof(headers_ptr), headers_ptr_ptr); - if (res < 0) - { - return NULL; - } - u64 headers_count = 0; - res = bpf_probe_read(&headers_count, sizeof(headers_count), headers_ptr); - if (res < 0) - { - return NULL; - } - if (headers_count == 0) - { - return NULL; - } - unsigned char log_2_bucket_count; - res = bpf_probe_read(&log_2_bucket_count, sizeof(log_2_bucket_count), headers_ptr + 9); - if (res < 0) - { - return NULL; - } - u64 bucket_count = 1 << log_2_bucket_count; - void *header_buckets; - res = bpf_probe_read(&header_buckets, sizeof(header_buckets), headers_ptr + 16); - if (res < 0) - { - return NULL; - } - u32 map_id = 0; - struct map_bucket *map_value = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id); - if (!map_value) - { - return NULL; - } - - for (u64 j = 0; j < MAX_BUCKETS; j++) - { - if (j >= bucket_count) - { - break; - } - res = bpf_probe_read(map_value, sizeof(struct map_bucket), header_buckets + (j * sizeof(struct map_bucket))); - if (res < 0) - { - continue; - } - for (u64 i = 0; i < 8; i++) - { - if (map_value->tophash[i] == 0) - { - continue; - } - if (map_value->keys[i].len != W3C_KEY_LENGTH) - { - continue; - } - char current_header_key[W3C_KEY_LENGTH]; - bpf_probe_read(current_header_key, sizeof(current_header_key), map_value->keys[i].str); - if (!bpf_memcmp(current_header_key, "traceparent", W3C_KEY_LENGTH) && !bpf_memcmp(current_header_key, "Traceparent", W3C_KEY_LENGTH)) - { - continue; - } - void *traceparent_header_value_ptr = map_value->values[i].array; - struct go_string traceparent_header_value_go_str; - res = bpf_probe_read(&traceparent_header_value_go_str, sizeof(traceparent_header_value_go_str), traceparent_header_value_ptr); - if (res < 0) - { - return NULL; - } - if (traceparent_header_value_go_str.len != W3C_VAL_LENGTH) - { - continue; - } - char traceparent_header_value[W3C_VAL_LENGTH]; - res = bpf_probe_read(&traceparent_header_value, sizeof(traceparent_header_value), traceparent_header_value_go_str.str); - if (res < 0) - { - return NULL; - } - struct span_context *parent_span_context = bpf_map_lookup_elem(&parent_span_context_storage_map, &map_id); - if (!parent_span_context) - { - return NULL; - } - w3c_string_to_span_context(traceparent_header_value, parent_span_context); - return parent_span_context; - } - } - return NULL; -} - -// This instrumentation attaches uprobe to the following function: -// func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) -SEC("uprobe/ServerMux_ServeHTTP") -int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) -{ - u64 request_pos = 4; - struct http_request_t httpReq = {}; - httpReq.start_time = bpf_ktime_get_ns(); - - // Get request struct - void *req_ptr = get_argument(ctx, request_pos); - - // Get method from request - void *method_ptr = 0; - bpf_probe_read(&method_ptr, sizeof(method_ptr), (void *)(req_ptr + method_ptr_pos)); - u64 method_len = 0; - bpf_probe_read(&method_len, sizeof(method_len), (void *)(req_ptr + (method_ptr_pos + 8))); - u64 method_size = sizeof(httpReq.method); - method_size = method_size < method_len ? method_size : method_len; - bpf_probe_read(&httpReq.method, method_size, method_ptr); - - // get path from Request.URL - void *url_ptr = 0; - bpf_probe_read(&url_ptr, sizeof(url_ptr), (void *)(req_ptr + url_ptr_pos)); - void *path_ptr = 0; - bpf_probe_read(&path_ptr, sizeof(path_ptr), (void *)(url_ptr + path_ptr_pos)); - u64 path_len = 0; - bpf_probe_read(&path_len, sizeof(path_len), (void *)(url_ptr + (path_ptr_pos + 8))); - u64 path_size = sizeof(httpReq.path); - path_size = path_size < path_len ? path_size : path_len; - bpf_probe_read(&httpReq.path, path_size, path_ptr); - - // Propagate context - struct span_context *parent_ctx = extract_context_from_req_headers(req_ptr + headers_ptr_pos); - if (parent_ctx != NULL) - { - httpReq.psc = *parent_ctx; - copy_byte_arrays(httpReq.psc.TraceID, httpReq.sc.TraceID, TRACE_ID_SIZE); - generate_random_bytes(httpReq.sc.SpanID, SPAN_ID_SIZE); - } - else - { - httpReq.sc = generate_span_context(); - } - - // Get key - void *req_ctx_ptr = 0; - bpf_probe_read(&req_ctx_ptr, sizeof(req_ctx_ptr), (void *)(req_ptr + ctx_ptr_pos)); - void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_ptr_pos)); - - // Write event - httpReq.sc = generate_span_context(); - bpf_map_update_elem(&http_events, &key, &httpReq, 0); - start_tracking_span(req_ctx_ptr, &httpReq.sc); - return 0; -} - -UPROBE_RETURN(ServerMux_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events) \ No newline at end of file diff --git a/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go deleted file mode 100644 index 9ae25dca9..000000000 --- a/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go +++ /dev/null @@ -1,155 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build arm64 - -package server - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfHttpRequestT struct { - StartTime uint64 - EndTime uint64 - Sc bpfSpanContext - Psc bpfSpanContext - Method [7]int8 - Path [100]int8 - _ [5]byte -} - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeServerMuxServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_ServerMux_ServeHTTP"` - UprobeServerMuxServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_ServerMux_ServeHTTP_Returns"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - Events *ebpf.MapSpec `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` - HttpEvents *ebpf.MapSpec `ebpf:"http_events"` - ParentSpanContextStorageMap *ebpf.MapSpec `ebpf:"parent_span_context_storage_map"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - AllocMap *ebpf.Map `ebpf:"alloc_map"` - Events *ebpf.Map `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` - HttpEvents *ebpf.Map `ebpf:"http_events"` - ParentSpanContextStorageMap *ebpf.Map `ebpf:"parent_span_context_storage_map"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.AllocMap, - m.Events, - m.GolangMapbucketStorageMap, - m.HttpEvents, - m.ParentSpanContextStorageMap, - m.TrackedSpans, - m.TrackedSpansBySc, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeServerMuxServeHTTP *ebpf.Program `ebpf:"uprobe_ServerMux_ServeHTTP"` - UprobeServerMuxServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_ServerMux_ServeHTTP_Returns"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeServerMuxServeHTTP, - p.UprobeServerMuxServeHTTP_Returns, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel_arm64.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go deleted file mode 100644 index 1bb9e8c04..000000000 --- a/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go +++ /dev/null @@ -1,155 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build 386 || amd64 - -package server - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfHttpRequestT struct { - StartTime uint64 - EndTime uint64 - Sc bpfSpanContext - Psc bpfSpanContext - Method [7]int8 - Path [100]int8 - _ [5]byte -} - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeServerMuxServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_ServerMux_ServeHTTP"` - UprobeServerMuxServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_ServerMux_ServeHTTP_Returns"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - Events *ebpf.MapSpec `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` - HttpEvents *ebpf.MapSpec `ebpf:"http_events"` - ParentSpanContextStorageMap *ebpf.MapSpec `ebpf:"parent_span_context_storage_map"` - TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - AllocMap *ebpf.Map `ebpf:"alloc_map"` - Events *ebpf.Map `ebpf:"events"` - GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` - HttpEvents *ebpf.Map `ebpf:"http_events"` - ParentSpanContextStorageMap *ebpf.Map `ebpf:"parent_span_context_storage_map"` - TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` - TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.AllocMap, - m.Events, - m.GolangMapbucketStorageMap, - m.HttpEvents, - m.ParentSpanContextStorageMap, - m.TrackedSpans, - m.TrackedSpansBySc, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeServerMuxServeHTTP *ebpf.Program `ebpf:"uprobe_ServerMux_ServeHTTP"` - UprobeServerMuxServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_ServerMux_ServeHTTP_Returns"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeServerMuxServeHTTP, - p.UprobeServerMuxServeHTTP_Returns, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel_x86.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/net/http/server/probe.go b/pkg/instrumentors/bpf/net/http/server/probe.go deleted file mode 100644 index 83fb99c8d..000000000 --- a/pkg/instrumentors/bpf/net/http/server/probe.go +++ /dev/null @@ -1,263 +0,0 @@ -// 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 server provides an instrumentor for the server in the net/http -// package. -// -// Deprecated: This package is no longer supported. -package server - -import ( - "bytes" - "encoding/binary" - "errors" - "os" - - "go.opentelemetry.io/auto/pkg/instrumentors/bpffs" // nolint:staticcheck // Atomic deprecation. - - "github.com/cilium/ebpf" - "github.com/cilium/ebpf/link" - "github.com/cilium/ebpf/perf" - "golang.org/x/sys/unix" - - "go.opentelemetry.io/auto/pkg/inject" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/context" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/events" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/utils" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/otel/attribute" - semconv "go.opentelemetry.io/otel/semconv/v1.18.0" - "go.opentelemetry.io/otel/trace" -) - -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c - -const instrumentedPkg = "net/http" - -// Event represents an event in an HTTP server during an HTTP -// request-response. -type Event struct { - context.BaseSpanProperties - Method [7]byte - Path [100]byte -} - -// Instrumentor is the net/http instrumentor. -type Instrumentor struct { - bpfObjects *bpfObjects - uprobes []link.Link - returnProbs []link.Link - eventsReader *perf.Reader -} - -// New returns a new [Instrumentor]. -func New() *Instrumentor { - return &Instrumentor{} -} - -// LibraryName returns the net/http package name. -func (h *Instrumentor) LibraryName() string { - return instrumentedPkg -} - -// FuncNames returns the function names from "net/http" that are instrumented. -func (h *Instrumentor) FuncNames() []string { - return []string{"net/http.HandlerFunc.ServeHTTP"} -} - -// Load loads all instrumentation offsets. -func (h *Instrumentor) Load(ctx *context.InstrumentorContext) error { - spec, err := ctx.Injector.Inject(loadBpf, "go", ctx.TargetDetails.GoVersion.Original(), []*inject.StructField{ - { - VarName: "method_ptr_pos", - StructName: "net/http.Request", - Field: "Method", - }, - { - VarName: "url_ptr_pos", - StructName: "net/http.Request", - Field: "URL", - }, - { - VarName: "ctx_ptr_pos", - StructName: "net/http.Request", - Field: "ctx", - }, - { - VarName: "path_ptr_pos", - StructName: "net/url.URL", - Field: "Path", - }, - { - VarName: "ctx_ptr_pos", - StructName: "net/http.Request", - Field: "ctx", - }, - { - VarName: "headers_ptr_pos", - StructName: "net/http.Request", - Field: "Header", - }, - }, nil, false) - - if err != nil { - return err - } - - h.bpfObjects = &bpfObjects{} - err = utils.LoadEBPFObjects(spec, h.bpfObjects, &ebpf.CollectionOptions{ - Maps: ebpf.MapOptions{ - PinPath: bpffs.PathForTargetApplication(ctx.TargetDetails), - }, - }) - if err != nil { - return err - } - - for _, funcName := range h.FuncNames() { - h.registerProbes(ctx, funcName) - } - - rd, err := perf.NewReader(h.bpfObjects.Events, os.Getpagesize()) - if err != nil { - return err - } - h.eventsReader = rd - - return nil -} - -func (h *Instrumentor) registerProbes(ctx *context.InstrumentorContext, funcName string) { - logger := log.Logger.WithName("net/http-instrumentor").WithValues("function", funcName) - offset, err := ctx.TargetDetails.GetFunctionOffset(funcName) - if err != nil { - logger.Error(err, "could not find function start offset. Skipping") - return - } - retOffsets, err := ctx.TargetDetails.GetFunctionReturns(funcName) - if err != nil { - logger.Error(err, "could not find function end offsets. Skipping") - return - } - - up, err := ctx.Executable.Uprobe("", h.bpfObjects.UprobeServerMuxServeHTTP, &link.UprobeOptions{ - Address: offset, - }) - if err != nil { - logger.V(1).Info("could not insert start uprobe. Skipping", - "error", err.Error()) - return - } - - h.uprobes = append(h.uprobes, up) - - for _, ret := range retOffsets { - retProbe, err := ctx.Executable.Uprobe("", h.bpfObjects.UprobeServerMuxServeHTTP_Returns, &link.UprobeOptions{ - Address: ret, - }) - if err != nil { - logger.Error(err, "could not insert return uprobe. Skipping") - return - } - h.returnProbs = append(h.returnProbs, retProbe) - } -} - -// Run runs the events processing loop. -func (h *Instrumentor) Run(eventsChan chan<- *events.Event) { - logger := log.Logger.WithName("net/http-instrumentor") - var event Event - for { - record, err := h.eventsReader.Read() - if err != nil { - if errors.Is(err, perf.ErrClosed) { - return - } - logger.Error(err, "error reading from perf reader") - continue - } - - if record.LostSamples != 0 { - logger.V(0).Info("perf event ring buffer full", "dropped", record.LostSamples) - continue - } - - if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.LittleEndian, &event); err != nil { - logger.Error(err, "error parsing perf event") - continue - } - - eventsChan <- h.convertEvent(&event) - } -} - -func (h *Instrumentor) convertEvent(e *Event) *events.Event { - method := unix.ByteSliceToString(e.Method[:]) - path := unix.ByteSliceToString(e.Path[:]) - - sc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: e.SpanContext.TraceID, - SpanID: e.SpanContext.SpanID, - TraceFlags: trace.FlagsSampled, - }) - - var pscPtr *trace.SpanContext - if e.ParentSpanContext.TraceID.IsValid() { - psc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: e.ParentSpanContext.TraceID, - SpanID: e.ParentSpanContext.SpanID, - TraceFlags: trace.FlagsSampled, - Remote: true, - }) - pscPtr = &psc - } else { - pscPtr = nil - } - - return &events.Event{ - Library: h.LibraryName(), - // Do not include the high-cardinality path here (there is no - // templatized path manifest to reference). - Name: method, - Kind: trace.SpanKindServer, - StartTime: int64(e.StartTime), - EndTime: int64(e.EndTime), - SpanContext: &sc, - ParentSpanContext: pscPtr, - Attributes: []attribute.KeyValue{ - semconv.HTTPMethodKey.String(method), - semconv.HTTPTargetKey.String(path), - }, - } -} - -// Close stops the Instrumentor. -func (h *Instrumentor) Close() { - log.Logger.V(0).Info("closing net/http instrumentor") - if h.eventsReader != nil { - h.eventsReader.Close() - } - - for _, r := range h.uprobes { - r.Close() - } - - for _, r := range h.returnProbs { - r.Close() - } - - if h.bpfObjects != nil { - h.bpfObjects.Close() - } -} diff --git a/pkg/instrumentors/bpf/net/http/server/probe_test.go b/pkg/instrumentors/bpf/net/http/server/probe_test.go deleted file mode 100644 index 8fc0879c5..000000000 --- a/pkg/instrumentors/bpf/net/http/server/probe_test.go +++ /dev/null @@ -1,68 +0,0 @@ -// 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 server - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "go.opentelemetry.io/auto/pkg/instrumentors/context" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/events" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/otel/attribute" - semconv "go.opentelemetry.io/otel/semconv/v1.7.0" - "go.opentelemetry.io/otel/trace" -) - -func TestInstrumentorConvertEvent(t *testing.T) { - start := time.Now() - end := start.Add(1 * time.Second) - - traceID := trace.TraceID{1} - spanID := trace.SpanID{1} - - i := New() - got := i.convertEvent(&Event{ - BaseSpanProperties: context.BaseSpanProperties{ - StartTime: uint64(start.UnixNano()), - EndTime: uint64(end.UnixNano()), - SpanContext: context.EBPFSpanContext{TraceID: traceID, SpanID: spanID}, - }, - // "GET" - Method: [7]byte{0x47, 0x45, 0x54}, - // "/foo/bar" - Path: [100]byte{0x2f, 0x66, 0x6f, 0x6f, 0x2f, 0x62, 0x61, 0x72}, - }) - - sc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - }) - want := &events.Event{ - Library: instrumentedPkg, - Name: "GET", - Kind: trace.SpanKindServer, - StartTime: int64(start.UnixNano()), - EndTime: int64(end.UnixNano()), - SpanContext: &sc, - Attributes: []attribute.KeyValue{ - semconv.HTTPMethodKey.String("GET"), - semconv.HTTPTargetKey.String("/foo/bar"), - }, - } - assert.Equal(t, want, got) -} diff --git a/pkg/instrumentors/bpffs/bpfsfs.go b/pkg/instrumentors/bpffs/bpfsfs.go deleted file mode 100644 index 9ab1b1c4a..000000000 --- a/pkg/instrumentors/bpffs/bpfsfs.go +++ /dev/null @@ -1,71 +0,0 @@ -// 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 bpffs provides the path to bpf on unix systems. -// -// Deprecated: This package is no longer supported. -package bpffs - -import ( - "fmt" - "os" - - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. - - "golang.org/x/sys/unix" - - "go.opentelemetry.io/auto/pkg/process" // nolint:staticcheck // Atomic deprecation. -) - -// BPFFsPath is the system path to the BPF file-system. -const bpfFsPath = "/sys/fs/bpf" - -// PathForTargetApplication returns the path to the BPF file-system for the given target. -func PathForTargetApplication(target *process.TargetDetails) string { - return fmt.Sprintf("%s/%d", bpfFsPath, target.PID) -} - -// Mount mounts the BPF file-system for the given target. -func Mount(target *process.TargetDetails) error { - if !isBPFFSMounted() { - // Directory does not exist, create it and mount - if err := os.MkdirAll(bpfFsPath, 0755); err != nil { - return err - } - - err := unix.Mount(bpfFsPath, bpfFsPath, "bpf", 0, "") - if err != nil { - return err - } - } - - // create directory with read, write and execute permissions - return os.Mkdir(PathForTargetApplication(target), 0755) -} - -func isBPFFSMounted() bool { - var stat unix.Statfs_t - err := unix.Statfs(bpfFsPath, &stat) - if err != nil { - log.Logger.Error(err, "failed to statfs bpf filesystem") - return false - } - - return stat.Type == unix.BPF_FS_MAGIC -} - -// Cleanup removes the BPF file-system for the given target. -func Cleanup(target *process.TargetDetails) error { - return os.RemoveAll(PathForTargetApplication(target)) -} diff --git a/pkg/instrumentors/context/inst_context.go b/pkg/instrumentors/context/inst_context.go deleted file mode 100644 index de9abc50e..000000000 --- a/pkg/instrumentors/context/inst_context.go +++ /dev/null @@ -1,32 +0,0 @@ -// 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 context provides context utilities. -// -// Deprecated: This package is no longer supported. -package context - -import ( - "github.com/cilium/ebpf/link" - - "go.opentelemetry.io/auto/pkg/inject" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/process" // nolint:staticcheck // Atomic deprecation. -) - -// InstrumentorContext holds the state of the auto-instrumentation system. -type InstrumentorContext struct { - TargetDetails *process.TargetDetails - Executable *link.Executable - Injector *inject.Injector -} diff --git a/pkg/instrumentors/context/span_context.go b/pkg/instrumentors/context/span_context.go deleted file mode 100644 index bd943b841..000000000 --- a/pkg/instrumentors/context/span_context.go +++ /dev/null @@ -1,32 +0,0 @@ -// 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 context - -import "go.opentelemetry.io/otel/trace" - -// BaseSpanProperties contains the basic attributes filled by all instrumentors. -type BaseSpanProperties struct { - StartTime uint64 - EndTime uint64 - SpanContext EBPFSpanContext - ParentSpanContext EBPFSpanContext -} - -// EBPFSpanContext is the the span context representation within the eBPF -// instrumentation system. -type EBPFSpanContext struct { - TraceID trace.TraceID - SpanID trace.SpanID -} diff --git a/pkg/instrumentors/events/event.go b/pkg/instrumentors/events/event.go deleted file mode 100644 index 3f0fc24fc..000000000 --- a/pkg/instrumentors/events/event.go +++ /dev/null @@ -1,35 +0,0 @@ -// 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 events provides span event types and functionality. -// -// Deprecated: This package is no longer supported. -package events - -import ( - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" -) - -// Event is a telemetry event that happens within an instrumented package. -type Event struct { - Library string - Name string - Attributes []attribute.KeyValue - Kind trace.SpanKind - StartTime int64 - EndTime int64 - SpanContext *trace.SpanContext - ParentSpanContext *trace.SpanContext -} diff --git a/pkg/instrumentors/manager.go b/pkg/instrumentors/manager.go deleted file mode 100644 index b60c1e0e7..000000000 --- a/pkg/instrumentors/manager.go +++ /dev/null @@ -1,133 +0,0 @@ -// 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 instrumentors provides instrumentors that instrument Go packages. -// -// Deprecated: This package is no longer supported. -package instrumentors - -import ( - "fmt" - - "go.opentelemetry.io/auto/pkg/instrumentors/allocator" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/bpf/github.com/gin-gonic/gin" // nolint:staticcheck // Atomic deprecation. - gorillaMux "go.opentelemetry.io/auto/pkg/instrumentors/bpf/github.com/gorilla/mux" // nolint:staticcheck // TODO: remove in #263 - "go.opentelemetry.io/auto/pkg/instrumentors/bpf/google/golang/org/grpc" // nolint:staticcheck // Atomic deprecation. - grpcServer "go.opentelemetry.io/auto/pkg/instrumentors/bpf/google/golang/org/grpc/server" // nolint:staticcheck // Atomic deprecation. - httpClient "go.opentelemetry.io/auto/pkg/instrumentors/bpf/net/http/client" // nolint:staticcheck // Atomic deprecation. - httpServer "go.opentelemetry.io/auto/pkg/instrumentors/bpf/net/http/server" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/events" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/opentelemetry" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/process" // nolint:staticcheck // Atomic deprecation. -) - -var ( - // Error message returned when unable to find all instrumentation functions. - errNotAllFuncsFound = fmt.Errorf("not all functions found for instrumentation") -) - -// Manager handles the management of [Instrumentor] instances. -type Manager struct { - instrumentors map[string]Instrumentor - done chan bool - incomingEvents chan *events.Event - otelController *opentelemetry.Controller - allocator *allocator.Allocator -} - -// NewManager returns a new [Manager]. -func NewManager(otelController *opentelemetry.Controller) (*Manager, error) { - m := &Manager{ - instrumentors: make(map[string]Instrumentor), - done: make(chan bool, 1), - incomingEvents: make(chan *events.Event), - otelController: otelController, - allocator: allocator.New(), - } - - err := registerInstrumentors(m) - if err != nil { - return nil, err - } - - return m, nil -} - -func (m *Manager) registerInstrumentor(instrumentor Instrumentor) error { - if _, exists := m.instrumentors[instrumentor.LibraryName()]; exists { - return fmt.Errorf("library %s registered twice, aborting", instrumentor.LibraryName()) - } - - m.instrumentors[instrumentor.LibraryName()] = instrumentor - return nil -} - -// GetRelevantFuncs returns the instrumented functions for all managed -// Instrumentors. -func (m *Manager) GetRelevantFuncs() map[string]interface{} { - funcsMap := make(map[string]interface{}) - for _, i := range m.instrumentors { - for _, f := range i.FuncNames() { - funcsMap[f] = nil - } - } - - return funcsMap -} - -// FilterUnusedInstrumentors filterers Instrumentors whose functions are -// already instrumented out of the Manager. -func (m *Manager) FilterUnusedInstrumentors(target *process.TargetDetails) { - existingFuncMap := make(map[string]interface{}) - for _, f := range target.Functions { - existingFuncMap[f.Name] = nil - } - - for name, inst := range m.instrumentors { - funcsFound := 0 - for _, instF := range inst.FuncNames() { - if _, exists := existingFuncMap[instF]; exists { - funcsFound++ - } - } - - if funcsFound != len(inst.FuncNames()) { - if funcsFound > 0 { - log.Logger.Error(errNotAllFuncsFound, "some of expected functions not found - check instrumented functions", "instrumentation_name", name, "funcs_found", funcsFound, "funcs_expected", len(inst.FuncNames())) - } - delete(m.instrumentors, name) - } - } -} - -func registerInstrumentors(m *Manager) error { - insts := []Instrumentor{ - grpc.New(), - grpcServer.New(), - httpServer.New(), - httpClient.New(), - gorillaMux.New(), - gin.New(), - } - - for _, i := range insts { - err := m.registerInstrumentor(i) - if err != nil { - return err - } - } - - return nil -} diff --git a/pkg/instrumentors/runner.go b/pkg/instrumentors/runner.go deleted file mode 100644 index 5d6f19b49..000000000 --- a/pkg/instrumentors/runner.go +++ /dev/null @@ -1,108 +0,0 @@ -// 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 instrumentors - -import ( - "fmt" - - "github.com/cilium/ebpf/link" - "github.com/cilium/ebpf/rlimit" - - "go.opentelemetry.io/auto/pkg/inject" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/instrumentors/context" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/process" // nolint:staticcheck // Atomic deprecation. -) - -// Run runs the event processing loop for all managed Instrumentors. -func (m *Manager) Run(target *process.TargetDetails) error { - if len(m.instrumentors) == 0 { - log.Logger.V(0).Info("there are no available instrumentations for target process") - return nil - } - - err := m.load(target) - if err != nil { - return err - } - - for _, i := range m.instrumentors { - go i.Run(m.incomingEvents) - } - - for { - select { - case <-m.done: - log.Logger.V(0).Info("shutting down all instrumentors due to signal") - m.cleanup() - return nil - case e := <-m.incomingEvents: - m.otelController.Trace(e) - } - } -} - -func (m *Manager) load(target *process.TargetDetails) error { - // Allow the current process to lock memory for eBPF resources. - if err := rlimit.RemoveMemlock(); err != nil { - return err - } - - injector, err := inject.New(target) - if err != nil { - return err - } - - exe, err := link.OpenExecutable(fmt.Sprintf("/proc/%d/exe", target.PID)) - if err != nil { - return err - } - ctx := &context.InstrumentorContext{ - TargetDetails: target, - Executable: exe, - Injector: injector, - } - - if err := m.allocator.Load(ctx); err != nil { - log.Logger.Error(err, "failed to load allocator") - return err - } - - // Load instrumentors - for name, i := range m.instrumentors { - log.Logger.V(0).Info("loading instrumentor", "name", name) - err := i.Load(ctx) - if err != nil { - log.Logger.Error(err, "error while loading instrumentors, cleaning up", "name", name) - m.cleanup() - return err - } - } - - log.Logger.V(0).Info("loaded instrumentors to memory", "total_instrumentors", len(m.instrumentors)) - return nil -} - -func (m *Manager) cleanup() { - close(m.incomingEvents) - for _, i := range m.instrumentors { - i.Close() - } -} - -// Close closes m. -func (m *Manager) Close() { - m.done <- true -} diff --git a/pkg/instrumentors/utils/ebpf.go b/pkg/instrumentors/utils/ebpf.go deleted file mode 100644 index c770f7cd3..000000000 --- a/pkg/instrumentors/utils/ebpf.go +++ /dev/null @@ -1,65 +0,0 @@ -// 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 utils provides eBPF utilities. -// -// Deprecated: This package is no longer supported. -package utils - -import ( - "errors" - "fmt" - "os" - "strconv" - - "github.com/cilium/ebpf" -) - -const ( - showVerifierLogEnvVar = "OTEL_GO_AUTO_SHOW_VERIFIER_LOG" -) - -// LoadEBPFObjects loads eBPF objects from the given spec into the given interface. -// If the environment variable OTEL_GO_AUTO_SHOW_VERIFIER_LOG is set to true, the verifier log will be printed. -func LoadEBPFObjects(spec *ebpf.CollectionSpec, to interface{}, opts *ebpf.CollectionOptions) error { - // Getting full verifier log is expensive, so we only do it if the user explicitly asks for it. - showVerifierLogs := shouldShowVerifierLogs() - if showVerifierLogs { - opts.Programs.LogSize = ebpf.DefaultVerifierLogSize * 100 - opts.Programs.LogLevel = ebpf.LogLevelInstruction | ebpf.LogLevelBranch | ebpf.LogLevelStats - } - - err := spec.LoadAndAssign(to, opts) - if err != nil && showVerifierLogs { - var ve *ebpf.VerifierError - if errors.As(err, &ve) { - fmt.Printf("Verifier log: %+v\n", ve) - } - } - - return err -} - -// shouldShowVerifierLogs returns if the user has configured verifier logs to be emitted. -func shouldShowVerifierLogs() bool { - val, exists := os.LookupEnv(showVerifierLogEnvVar) - if exists { - boolVal, err := strconv.ParseBool(val) - if err == nil { - return boolVal - } - } - - return false -} diff --git a/pkg/log/logger.go b/pkg/log/logger.go deleted file mode 100644 index 9825b4a98..000000000 --- a/pkg/log/logger.go +++ /dev/null @@ -1,38 +0,0 @@ -// 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 log provides a unified logger. -// -// Deprecated: This package is no longer supported. -package log - -import ( - "github.com/go-logr/logr" - "github.com/go-logr/zapr" - "go.uber.org/zap" -) - -// Logger is a global logger used for internal logging. -var Logger logr.Logger - -// Init initializes [Logger] to be a production Zap logger. -func Init() error { - zapLog, err := zap.NewProduction() - if err != nil { - return err - } - - Logger = zapr.NewLogger(zapLog) - return nil -} diff --git a/pkg/opentelemetry/controller.go b/pkg/opentelemetry/controller.go deleted file mode 100644 index de2ffed8e..000000000 --- a/pkg/opentelemetry/controller.go +++ /dev/null @@ -1,195 +0,0 @@ -// 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 opentelemetry provides a controller for auto-instrumentation. -// -// Deprecated: This package is no longer supported. -package opentelemetry - -import ( - "context" - "fmt" - "os" - "runtime" - "strings" - "time" - - "golang.org/x/sys/unix" - "google.golang.org/grpc" - - "go.opentelemetry.io/auto" - "go.opentelemetry.io/auto/pkg/instrumentors/events" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/otel/exporters/otlp/otlptrace" - "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" - "go.opentelemetry.io/otel/sdk/resource" - sdktrace "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.18.0" - "go.opentelemetry.io/otel/trace" -) - -const ( - otelServiceNameEnvVar = "OTEL_SERVICE_NAME" -) - -var ( - // Controller-local reference to the auto-instrumentation release version. - releaseVersion = auto.Version() - // Start of this auto-instrumentation's exporter User-Agent header, e.g. ""OTel-Go-Auto-Instrumentation/1.2.3". - baseUserAgent = fmt.Sprintf("OTel-Go-Auto-Instrumentation/%s", releaseVersion) - // Information about the runtime environment for inclusion in User-Agent, e.g. "go/1.18.2 (linux/amd64)". - runtimeInfo = fmt.Sprintf("%s (%s/%s)", strings.Replace(runtime.Version(), "go", "go/", 1), runtime.GOOS, runtime.GOARCH) - // Combined User-Agent identifying this auto-instrumentation and its runtime environment, see RFC7231 for format considerations. - autoinstUserAgent = fmt.Sprintf("%s %s", baseUserAgent, runtimeInfo) -) - -// Controller handles OpenTelemetry telemetry generation for events. -type Controller struct { - tracerProvider trace.TracerProvider - tracersMap map[string]trace.Tracer - bootTime int64 -} - -func (c *Controller) getTracer(libName string) trace.Tracer { - t, exists := c.tracersMap[libName] - if exists { - return t - } - - newTracer := c.tracerProvider.Tracer(libName) - c.tracersMap[libName] = newTracer - return newTracer -} - -// Trace creates a trace span for event. -func (c *Controller) Trace(event *events.Event) { - log.Logger.V(0).Info("got event", "attrs", event.Attributes) - ctx := context.Background() - - if event.SpanContext == nil { - log.Logger.V(0).Info("got event without context - dropping") - return - } - - // TODO: handle remote parent - if event.ParentSpanContext != nil { - ctx = trace.ContextWithSpanContext(ctx, *event.ParentSpanContext) - } - - ctx = ContextWithEBPFEvent(ctx, *event) - _, span := c.getTracer(event.Library). - Start(ctx, event.Name, - trace.WithAttributes(event.Attributes...), - trace.WithSpanKind(event.Kind), - trace.WithTimestamp(c.convertTime(event.StartTime))) - span.End(trace.WithTimestamp(c.convertTime(event.EndTime))) -} - -func (c *Controller) convertTime(t int64) time.Time { - return time.Unix(0, c.bootTime+t) -} - -// NewController returns a new initialized [Controller]. -func NewController() (*Controller, error) { - serviceName, exists := os.LookupEnv(otelServiceNameEnvVar) - if !exists { - return nil, fmt.Errorf("%s env var must be set", otelServiceNameEnvVar) - } - - ctx := context.Background() - res, err := resource.New(ctx, - resource.WithAttributes( - semconv.ServiceNameKey.String(serviceName), - semconv.TelemetrySDKLanguageGo, - semconv.TelemetryAutoVersionKey.String(releaseVersion), - ), - ) - if err != nil { - return nil, err - } - - log.Logger.V(0).Info("Establishing connection to OTLP receiver ...") - otlpTraceClient := otlptracegrpc.NewClient( - otlptracegrpc.WithDialOption(grpc.WithUserAgent(autoinstUserAgent)), - ) - traceExporter, err := otlptrace.New(ctx, otlpTraceClient) - if err != nil { - log.Logger.Error(err, "unable to connect to OTLP endpoint") - return nil, err - } - - bsp := sdktrace.NewBatchSpanProcessor(traceExporter) - tracerProvider := sdktrace.NewTracerProvider( - sdktrace.WithSampler(sdktrace.AlwaysSample()), - sdktrace.WithResource(res), - sdktrace.WithSpanProcessor(bsp), - sdktrace.WithIDGenerator(newEBPFSourceIDGenerator()), - ) - - bt, err := estimateBootTimeOffset() - if err != nil { - return nil, err - } - - return &Controller{ - tracerProvider: tracerProvider, - tracersMap: make(map[string]trace.Tracer), - bootTime: bt, - }, nil -} - -func estimateBootTimeOffset() (bootTimeOffset int64, err error) { - // The datapath is currently using ktime_get_boot_ns for the pcap timestamp, - // which corresponds to CLOCK_BOOTTIME. To be able to convert the the - // CLOCK_BOOTTIME to CLOCK_REALTIME (i.e. a unix timestamp). - - // There can be an arbitrary amount of time between the execution of - // time.Now() and unix.ClockGettime() below, especially under scheduler - // pressure during program startup. To reduce the error introduced by these - // delays, we pin the current Go routine to its OS thread and measure the - // clocks multiple times, taking only the smallest observed difference - // between the two values (which implies the smallest possible delay - // between the two snapshots). - var minDiff int64 = 1<<63 - 1 - estimationRounds := 25 - runtime.LockOSThread() - defer runtime.UnlockOSThread() - for round := 0; round < estimationRounds; round++ { - var bootTimespec unix.Timespec - - // Ideally we would use __vdso_clock_gettime for both clocks here, - // to have as little overhead as possible. - // time.Now() will actually use VDSO on Go 1.9+, but calling - // unix.ClockGettime to obtain CLOCK_BOOTTIME is a regular system call - // for now. - unixTime := time.Now() - err = unix.ClockGettime(unix.CLOCK_BOOTTIME, &bootTimespec) - if err != nil { - return 0, err - } - - offset := unixTime.UnixNano() - bootTimespec.Nano() - diff := offset - if diff < 0 { - diff = -diff - } - - if diff < minDiff { - minDiff = diff - bootTimeOffset = offset - } - } - - return bootTimeOffset, nil -} diff --git a/pkg/opentelemetry/controller_test.go b/pkg/opentelemetry/controller_test.go deleted file mode 100644 index f6bef3538..000000000 --- a/pkg/opentelemetry/controller_test.go +++ /dev/null @@ -1,28 +0,0 @@ -// 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 opentelemetry - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - - "go.opentelemetry.io/auto" -) - -func TestUserAgent(t *testing.T) { - assert.Contains(t, autoinstUserAgent, fmt.Sprintf("OTel-Go-Auto-Instrumentation/%s", auto.Version())) -} diff --git a/pkg/opentelemetry/id_generator.go b/pkg/opentelemetry/id_generator.go deleted file mode 100644 index 828c6b9dc..000000000 --- a/pkg/opentelemetry/id_generator.go +++ /dev/null @@ -1,68 +0,0 @@ -// 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 opentelemetry - -import ( - "context" - - "go.opentelemetry.io/auto/pkg/instrumentors/events" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/otel/trace" -) - -type eBPFSourceIDGenerator struct{} - -type eBPFEventKey struct{} - -func newEBPFSourceIDGenerator() *eBPFSourceIDGenerator { - return &eBPFSourceIDGenerator{} -} - -// ContextWithEBPFEvent returns a copy of parent in which event is stored. -func ContextWithEBPFEvent(parent context.Context, event events.Event) context.Context { - return context.WithValue(parent, eBPFEventKey{}, event) -} - -// EventFromContext returns the event within ctx if one exists. -func EventFromContext(ctx context.Context) *events.Event { - val := ctx.Value(eBPFEventKey{}) - if val == nil { - return nil - } - - event, ok := val.(events.Event) - if !ok { - return nil - } - - return &event -} - -func (e *eBPFSourceIDGenerator) NewIDs(ctx context.Context) (trace.TraceID, trace.SpanID) { - event := EventFromContext(ctx) - if event == nil || event.SpanContext == nil { - return trace.TraceID{}, trace.SpanID{} - } - - return event.SpanContext.TraceID(), event.SpanContext.SpanID() -} - -func (e *eBPFSourceIDGenerator) NewSpanID(ctx context.Context, traceID trace.TraceID) trace.SpanID { - event := EventFromContext(ctx) - if event == nil { - return trace.SpanID{} - } - - return event.SpanContext.SpanID() -} diff --git a/pkg/process/analyze.go b/pkg/process/analyze.go deleted file mode 100644 index 67f05ef17..000000000 --- a/pkg/process/analyze.go +++ /dev/null @@ -1,246 +0,0 @@ -// 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 process - -import ( - "debug/elf" - "errors" - "fmt" - "os" - - "github.com/hashicorp/go-version" - - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/process/ptrace" // nolint:staticcheck // Atomic deprecation. -) - -const ( - // The concurrent trace & span ID pairs lookup size in bytes. Currently set to 24mb. - // TODO: Review map size. - mapSize = 25165824 -) - -// TargetDetails are the details about a target function. -type TargetDetails struct { - PID int - Functions []*Func - GoVersion *version.Version - Libraries map[string]string - AllocationDetails *AllocationDetails -} - -// AllocationDetails are the details about allocated memory. -type AllocationDetails struct { - StartAddr uint64 - EndAddr uint64 -} - -// Func represents a function target. -type Func struct { - Name string - Offset uint64 - ReturnOffsets []uint64 -} - -// IsRegistersABI returns if t is supported. -func (t *TargetDetails) IsRegistersABI() bool { - regAbiMinVersion, _ := version.NewVersion("1.17") - return t.GoVersion.GreaterThanOrEqual(regAbiMinVersion) -} - -// GetFunctionOffset returns the offset for of the function with name. -func (t *TargetDetails) GetFunctionOffset(name string) (uint64, error) { - for _, f := range t.Functions { - if f.Name == name { - return f.Offset, nil - } - } - - return 0, fmt.Errorf("could not find offset for function %s", name) -} - -// GetFunctionReturns returns the return value of the call for the function -// with name. -func (t *TargetDetails) GetFunctionReturns(name string) ([]uint64, error) { - for _, f := range t.Functions { - if f.Name == name { - return f.ReturnOffsets, nil - } - } - - return nil, fmt.Errorf("could not find returns for function %s", name) -} - -func (a *Analyzer) remoteMmap(pid int, mapSize uint64) (uint64, error) { - program, err := ptrace.NewTracedProgram(pid, log.Logger) - if err != nil { - log.Logger.Error(err, "Failed to attach ptrace", "pid", pid) - return 0, err - } - - defer func() { - log.Logger.V(0).Info("Detaching from process", "pid", pid) - err := program.Detach() - if err != nil { - log.Logger.Error(err, "Failed to detach ptrace", "pid", pid) - } - }() - fd := -1 - addr, err := program.Mmap(mapSize, uint64(fd)) - if err != nil { - log.Logger.Error(err, "Failed to mmap", "pid", pid) - return 0, err - } - - return addr, nil -} - -// Analyze returns the target details for an actively running process. -func (a *Analyzer) Analyze(pid int, relevantFuncs map[string]interface{}) (*TargetDetails, error) { - result := &TargetDetails{ - PID: pid, - } - - f, err := os.Open(fmt.Sprintf("/proc/%d/exe", pid)) - if err != nil { - return nil, err - } - - defer f.Close() - elfF, err := elf.NewFile(f) - if err != nil { - return nil, err - } - - goVersion, modules, err := a.getModuleDetails(elfF) - if err != nil { - return nil, err - } - result.GoVersion = goVersion - result.Libraries = modules - - addr, err := a.remoteMmap(pid, mapSize) - if err != nil { - log.Logger.Error(err, "Failed to mmap") - return nil, err - } - log.Logger.V(0).Info("mmaped remote memory", "start_addr", fmt.Sprintf("%X", addr), - "end_addr", fmt.Sprintf("%X", addr+mapSize)) - - result.AllocationDetails = &AllocationDetails{ - StartAddr: addr, - EndAddr: addr + mapSize, - } - - if err != nil { - return nil, err - } - symbols, err := elfF.Symbols() - if err != nil { - return nil, err - } - - for _, f := range symbols { - if _, exists := relevantFuncs[f.Name]; exists { - offset, err := getFuncOffset(elfF, f) - if err != nil { - return nil, err - } - - returns, err := findFuncReturns(elfF, f, offset) - if err != nil { - log.Logger.V(1).Info("can't find function offset. Skipping", "function", f.Name) - continue - } - - log.Logger.V(0).Info("found relevant function for instrumentation", - "function", f.Name, - "start", offset, - "returns", returns) - function := &Func{ - Name: f.Name, - Offset: offset, - ReturnOffsets: returns, - } - - result.Functions = append(result.Functions, function) - } - } - if len(result.Functions) == 0 { - return nil, errors.New("could not find function offsets for instrumenter") - } - - return result, nil -} - -func getFuncOffset(f *elf.File, symbol elf.Symbol) (uint64, error) { - var sections []*elf.Section - - for i := range f.Sections { - if f.Sections[i].Flags == elf.SHF_ALLOC+elf.SHF_EXECINSTR { - sections = append(sections, f.Sections[i]) - } - } - - if len(sections) == 0 { - return 0, fmt.Errorf("function %q not found in file", symbol) - } - - var execSection *elf.Section - for m := range sections { - sectionStart := sections[m].Addr - sectionEnd := sectionStart + sections[m].Size - if symbol.Value >= sectionStart && symbol.Value < sectionEnd { - execSection = sections[m] - break - } - } - - if execSection == nil { - return 0, errors.New("could not find symbol in executable sections of binary") - } - - return uint64(symbol.Value - execSection.Addr + execSection.Offset), nil -} - -func findFuncReturns(elfFile *elf.File, sym elf.Symbol, functionOffset uint64) ([]uint64, error) { - textSection := elfFile.Section(".text") - if textSection == nil { - return nil, errors.New("could not find .text section in binary") - } - - lowPC := sym.Value - highPC := lowPC + sym.Size - offset := lowPC - textSection.Addr - buf := make([]byte, int(highPC-lowPC)) - - readBytes, err := textSection.ReadAt(buf, int64(offset)) - if err != nil { - return nil, fmt.Errorf("could not read text section: %w", err) - } - data := buf[:readBytes] - instructionIndices, err := findRetInstructions(data) - if err != nil { - return nil, fmt.Errorf("error while scanning instructions: %w", err) - } - - // Add the function lowPC to each index to obtain the actual locations - newLocations := make([]uint64, len(instructionIndices)) - for i, instructionIndex := range instructionIndices { - newLocations[i] = instructionIndex + functionOffset - } - - return newLocations, nil -} diff --git a/pkg/process/args.go b/pkg/process/args.go deleted file mode 100644 index ad0c60e9a..000000000 --- a/pkg/process/args.go +++ /dev/null @@ -1,51 +0,0 @@ -// 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 process - -import ( - "errors" - "os" -) - -// ExePathEnvVar is the environment variable key whose value points to the -// instrumented executable. -const ExePathEnvVar = "OTEL_GO_AUTO_TARGET_EXE" - -// TargetArgs are the binary target information. -type TargetArgs struct { - ExePath string -} - -// Validate validates t and returns an error if not valid. -func (t *TargetArgs) Validate() error { - if t.ExePath == "" { - return errors.New("target binary path not specified, please specify " + ExePathEnvVar + " env variable") - } - - return nil -} - -// ParseTargetArgs returns TargetArgs for the target pointed to by the -// environment variable OTEL_GO_AUTO_TARGET_EXE. -func ParseTargetArgs() *TargetArgs { - result := &TargetArgs{} - - val, exists := os.LookupEnv(ExePathEnvVar) - if exists { - result.ExePath = val - } - - return result -} diff --git a/pkg/process/discover.go b/pkg/process/discover.go deleted file mode 100644 index 30b0a3f17..000000000 --- a/pkg/process/discover.go +++ /dev/null @@ -1,120 +0,0 @@ -// 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 process - -import ( - "io" - "io/ioutil" - "os" - "path" - "strconv" - "strings" - "time" - - "go.opentelemetry.io/auto/pkg/errors" // nolint:staticcheck // Atomic deprecation. - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. -) - -// Analyzer is used to find actively running processes. -type Analyzer struct { - done chan bool - pidTickerChan <-chan time.Time -} - -// NewAnalyzer returns a new [ProcessAnalyzer]. -func NewAnalyzer() *Analyzer { - return &Analyzer{ - done: make(chan bool, 1), - pidTickerChan: time.NewTicker(2 * time.Second).C, - } -} - -// DiscoverProcessID searches for the target as an actively running process, -// returning its PID if found. -func (a *Analyzer) DiscoverProcessID(target *TargetArgs) (int, error) { - for { - select { - case <-a.done: - log.Logger.V(0).Info("stopping process id discovery due to kill signal") - return 0, errors.ErrInterrupted - case <-a.pidTickerChan: - pid, err := a.findProcessID(target) - if err == nil { - log.Logger.V(0).Info("found process", "pid", pid) - return pid, nil - } - if err == errors.ErrProcessNotFound { - log.Logger.V(0).Info("process not found yet, trying again soon", "exe_path", target.ExePath) - } else { - log.Logger.Error(err, "error while searching for process", "exe_path", target.ExePath) - } - } - } -} - -func (a *Analyzer) findProcessID(target *TargetArgs) (int, error) { - proc, err := os.Open("/proc") - if err != nil { - return 0, err - } - - for { - dirs, err := proc.Readdir(15) - if err == io.EOF { - break - } - if err != nil { - return 0, err - } - - for _, di := range dirs { - if !di.IsDir() { - continue - } - - dname := di.Name() - if dname[0] < '0' || dname[0] > '9' { - continue - } - - pid, err := strconv.Atoi(dname) - if err != nil { - return 0, err - } - - exeName, err := os.Readlink(path.Join("/proc", dname, "exe")) - if err != nil { - // Read link may fail if target process runs not as root - cmdLine, err := ioutil.ReadFile(path.Join("/proc", dname, "cmdline")) - if err != nil { - return 0, err - } - - if strings.Contains(string(cmdLine), target.ExePath) { - return pid, nil - } - } else if exeName == target.ExePath { - return pid, nil - } - } - } - - return 0, errors.ErrProcessNotFound -} - -// Close closes the analyzer. -func (a *Analyzer) Close() { - a.done <- true -} diff --git a/pkg/process/module.go b/pkg/process/module.go deleted file mode 100644 index a2a9b2319..000000000 --- a/pkg/process/module.go +++ /dev/null @@ -1,205 +0,0 @@ -// 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 process provides utilities to instrument processes. -// -// Deprecated: This package is no longer supported. -package process - -import ( - "bytes" - "debug/elf" - "encoding/binary" - "errors" - "fmt" - "strings" - - "github.com/hashicorp/go-version" - - "go.opentelemetry.io/auto/pkg/log" // nolint:staticcheck // Atomic deprecation. -) - -// The build info blob left by the linker is identified by -// a 16-byte header, consisting of buildInfoMagic (14 bytes), -// the binary's pointer size (1 byte), -// and whether the binary is big endian (1 byte). -var buildInfoMagic = []byte("\xff Go buildinf:") -var errNotGoExe = errors.New("not a Go executable") - -func (a *Analyzer) getModuleDetails(f *elf.File) (*version.Version, map[string]string, error) { - goVersion, modules, err := getGoDetails(f) - if err != nil { - return nil, nil, err - } - - v, err := parseGoVersion(goVersion) - if err != nil { - return nil, nil, err - } - - log.Logger.V(1).Info("go version detected", "version", goVersion) - modsMap := parseModules(modules) - return v, modsMap, nil -} - -func parseGoVersion(vers string) (*version.Version, error) { - vers = strings.ReplaceAll(vers, "go", "") - return version.NewVersion(vers) -} - -func getGoDetails(f *elf.File) (string, string, error) { - // Read the first 64kB of text to find the build info blob. - text := dataStart(f) - data, err := readData(f, text, 64*1024) - if err != nil { - return "", "", err - } - const ( - buildInfoAlign = 16 - buildInfoSize = 32 - ) - for { - i := bytes.Index(data, buildInfoMagic) - if i < 0 || len(data)-i < buildInfoSize { - return "", "", errNotGoExe - } - if i%buildInfoAlign == 0 && len(data)-i >= buildInfoSize { - data = data[i:] - break - } - data = data[(i+buildInfoAlign-1)&^buildInfoAlign:] - } - - // Decode the blob. - // The first 14 bytes are buildInfoMagic. - // The next two bytes indicate pointer size in bytes (4 or 8) and endianness - // (0 for little, 1 for big). - // Two virtual addresses to Go strings follow that: runtime.buildVersion, - // and runtime.modinfo. - // On 32-bit platforms, the last 8 bytes are unused. - // If the endianness has the 2 bit set, then the pointers are zero - // and the 32-byte header is followed by varint-prefixed string data - // for the two string values we care about. - ptrSize := int(data[14]) - var vers, mod string - if data[15]&2 != 0 { - vers, data = decodeString(data[32:]) - mod, _ = decodeString(data) - } else { - bigEndian := data[15] != 0 - var bo binary.ByteOrder - if bigEndian { - bo = binary.BigEndian - } else { - bo = binary.LittleEndian - } - var readPtr func([]byte) uint64 - if ptrSize == 4 { - readPtr = func(b []byte) uint64 { return uint64(bo.Uint32(b)) } - } else { - readPtr = bo.Uint64 - } - vers = readString(f, ptrSize, readPtr, readPtr(data[16:])) - mod = readString(f, ptrSize, readPtr, readPtr(data[16+ptrSize:])) - } - if vers == "" { - return "", "", errNotGoExe - } - if len(mod) >= 33 && mod[len(mod)-17] == '\n' { - // Strip module framing: sentinel strings delimiting the module info. - // These are cmd/go/internal/modload.infoStart and infoEnd. - mod = mod[16 : len(mod)-16] - } else { - mod = "" - } - - return vers, mod, nil -} - -func dataStart(f *elf.File) uint64 { - for _, s := range f.Sections { - if s.Name == ".go.buildinfo" { - return s.Addr - } - } - for _, p := range f.Progs { - if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W { - return p.Vaddr - } - } - return 0 -} - -func readData(f *elf.File, addr, size uint64) ([]byte, error) { - for _, prog := range f.Progs { - if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 { - n := prog.Vaddr + prog.Filesz - addr - if n > size { - n = size - } - data := make([]byte, n) - _, err := prog.ReadAt(data, int64(addr-prog.Vaddr)) - if err != nil { - return nil, err - } - return data, nil - } - } - return nil, fmt.Errorf("address not mapped") -} - -// readString returns the string at address addr in the executable x. -func readString(f *elf.File, ptrSize int, readPtr func([]byte) uint64, addr uint64) string { - hdr, err := readData(f, addr, uint64(2*ptrSize)) - if err != nil || len(hdr) < 2*ptrSize { - return "" - } - dataAddr := readPtr(hdr) - dataLen := readPtr(hdr[ptrSize:]) - data, err := readData(f, dataAddr, dataLen) - if err != nil || uint64(len(data)) < dataLen { - return "" - } - return string(data) -} - -func parseModules(mod string) map[string]string { - lines := strings.Split(mod, "\n") - result := make(map[string]string) - for _, line := range lines { - parts := strings.Fields(line) - if len(parts) > 1 { - modType := parts[0] - modPackage := parts[1] - if modType == "dep" { - v := "" - if len(parts) > 2 { - v = parts[2] - } - - result[modPackage] = v - } - } - } - - return result -} - -func decodeString(data []byte) (s string, rest []byte) { - u, n := binary.Uvarint(data) - if n <= 0 || u >= uint64(len(data)-n) { - return "", nil - } - return string(data[n : uint64(n)+u]), data[uint64(n)+u:] -} diff --git a/pkg/process/ptrace/cwrapper_linux.go b/pkg/process/ptrace/cwrapper_linux.go deleted file mode 100644 index f05f8015e..000000000 --- a/pkg/process/ptrace/cwrapper_linux.go +++ /dev/null @@ -1,29 +0,0 @@ -// 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. - -//go:build cgo - -package ptrace - -/* -#define _GNU_SOURCE -#include -#include -#include -*/ -import "C" - -func waitpid(pid int) int { - return int(C.waitpid(C.int(pid), nil, C.__WALL)) -} diff --git a/pkg/process/ptrace/ptrace_linux.go b/pkg/process/ptrace/ptrace_linux.go deleted file mode 100644 index a0dbe1d78..000000000 --- a/pkg/process/ptrace/ptrace_linux.go +++ /dev/null @@ -1,215 +0,0 @@ -// 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 ptrace provides process tracing utilities. -// -// Deprecated: This package is no longer supported. -package ptrace - -import ( - "fmt" - "os" - "strconv" - "strings" - "syscall" - - "github.com/go-logr/logr" - "github.com/pkg/errors" -) - -const waitPidErrorMessage = "waitpid ret value: %d" - -var threadRetryLimit = 10 - -// TracedProgram is a program traced by ptrace. -type TracedProgram struct { - pid int - tids []int - - backupRegs *syscall.PtraceRegs - backupCode []byte - - logger logr.Logger -} - -// Pid return the pid of traced program. -func (p *TracedProgram) Pid() int { - return p.pid -} - -func waitPid(pid int) error { - ret := waitpid(pid) - if ret == pid { - return nil - } - - return errors.Errorf(waitPidErrorMessage, ret) -} - -// NewTracedProgram ptrace all threads of a process. -func NewTracedProgram(pid int, logger logr.Logger) (*TracedProgram, error) { - tidMap := make(map[int]bool) - retryCount := make(map[int]int) - - // iterate over the thread group, until it doens't change - // - // we have tried several ways to ensure that we have stopped all the tasks: - // 1. iterating over and over again to make sure all of them are tracee - // 2. send `SIGSTOP` signal - // ... - // only the first way finally worked for every situations - for { - threads, err := os.ReadDir(fmt.Sprintf("/proc/%d/task", pid)) - if err != nil { - return nil, errors.WithStack(err) - } - - // judge whether `threads` is a subset of `tidMap` - subset := true - - tids := make(map[int]bool) - for _, thread := range threads { - tid64, err := strconv.ParseInt(thread.Name(), 10, 32) - if err != nil { - return nil, errors.WithStack(err) - } - tid := int(tid64) - - _, ok := tidMap[tid] - if ok { - tids[tid] = true - continue - } - subset = false - - err = syscall.PtraceAttach(tid) - if err != nil { - _, ok := retryCount[tid] - if !ok { - retryCount[tid] = 1 - } else { - retryCount[tid]++ - } - if retryCount[tid] < threadRetryLimit { - logger.Info("retry attaching thread", "tid", tid, "retryCount", retryCount[tid], "limit", threadRetryLimit) - continue - } - - if !strings.Contains(err.Error(), "no such process") { - return nil, errors.WithStack(err) - } - continue - } - - err = waitPid(tid) - if err != nil { - e := syscall.PtraceDetach(tid) - if e != nil && !strings.Contains(e.Error(), "no such process") { - logger.Error(e, "detach failed", "tid", tid) - } - return nil, errors.WithStack(err) - } - - logger.Info("attach successfully", "tid", tid) - tids[tid] = true - tidMap[tid] = true - } - - if subset { - tidMap = tids - break - } - } - - var tids []int - for key := range tidMap { - tids = append(tids, key) - } - - program := &TracedProgram{ - pid: pid, - tids: tids, - backupRegs: &syscall.PtraceRegs{}, - backupCode: make([]byte, syscallInstrSize), - logger: logger, - } - - return program, nil -} - -// Detach detaches from all threads of the processes. -func (p *TracedProgram) Detach() error { - for _, tid := range p.tids { - err := syscall.PtraceDetach(tid) - - if err != nil { - if !strings.Contains(err.Error(), "no such process") { - return errors.WithStack(err) - } - } - } - - return nil -} - -// Protect will backup regs and rip into fields. -func (p *TracedProgram) Protect() error { - err := getRegs(p.pid, p.backupRegs) - if err != nil { - return errors.WithStack(err) - } - - _, err = syscall.PtracePeekData(p.pid, getIP(p.backupRegs), p.backupCode) - if err != nil { - return errors.WithStack(err) - } - - return nil -} - -// Restore will restore regs and rip from fields. -func (p *TracedProgram) Restore() error { - err := setRegs(p.pid, p.backupRegs) - if err != nil { - return errors.WithStack(err) - } - - _, err = syscall.PtracePokeData(p.pid, getIP(p.backupRegs), p.backupCode) - if err != nil { - return errors.WithStack(err) - } - - return nil -} - -// Wait waits until the process stops. -func (p *TracedProgram) Wait() error { - _, err := syscall.Wait4(p.pid, nil, 0, nil) - return err -} - -// Step moves one step forward. -func (p *TracedProgram) Step() error { - err := syscall.PtraceSingleStep(p.pid) - if err != nil { - return errors.WithStack(err) - } - - return p.Wait() -} - -// Mmap runs mmap syscall. -func (p *TracedProgram) Mmap(length uint64, fd uint64) (uint64, error) { - return p.Syscall(syscall.SYS_MMAP, 0, length, syscall.PROT_READ|syscall.PROT_WRITE|syscall.PROT_EXEC, syscall.MAP_ANON|syscall.MAP_PRIVATE|syscall.MAP_POPULATE, fd, 0) -} diff --git a/pkg/process/ptrace/ptrace_linux_amd64.go b/pkg/process/ptrace/ptrace_linux_amd64.go deleted file mode 100644 index 7b7911b66..000000000 --- a/pkg/process/ptrace/ptrace_linux_amd64.go +++ /dev/null @@ -1,115 +0,0 @@ -// 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 ptrace - -import ( - "encoding/binary" - "syscall" - - "github.com/pkg/errors" -) - -const syscallInstrSize = 2 - -func getIP(regs *syscall.PtraceRegs) uintptr { - return uintptr(regs.Rip) -} - -func getRegs(pid int, regsout *syscall.PtraceRegs) error { - err := syscall.PtraceGetRegs(pid, regsout) - if err != nil { - return errors.Wrapf(err, "get registers of process %d", pid) - } - - return nil -} - -func setRegs(pid int, regs *syscall.PtraceRegs) error { - err := syscall.PtraceSetRegs(pid, regs) - if err != nil { - return errors.Wrapf(err, "set registers of process %d", pid) - } - - return nil -} - -// Syscall runs a syscall at main thread of process. -func (p *TracedProgram) Syscall(number uint64, args ...uint64) (uint64, error) { - // save the original registers and the current instructions - err := p.Protect() - if err != nil { - return 0, err - } - - var regs syscall.PtraceRegs - - err = getRegs(p.pid, ®s) - if err != nil { - return 0, err - } - // set the registers according to the syscall convention. Learn more about - // it in `man 2 syscall`. In x86_64 the syscall nr is stored in rax - // register, and the arguments are stored in rdi, rsi, rdx, r10, r8, r9 in - // order - regs.Rax = number - for index, arg := range args { - // All these registers are hard coded for x86 platform - if index == 0 { - regs.Rdi = arg - } else if index == 1 { - regs.Rsi = arg - } else if index == 2 { - regs.Rdx = arg - } else if index == 3 { - regs.R10 = arg - } else if index == 4 { - regs.R8 = arg - } else if index == 5 { - regs.R9 = arg - } else { - return 0, errors.New("too many arguments for a syscall") - } - } - err = setRegs(p.pid, ®s) - if err != nil { - return 0, err - } - - instruction := make([]byte, syscallInstrSize) - ip := getIP(p.backupRegs) - - // set the current instruction (the ip register points to) to the `syscall` - // instruction. In x86_64, the `syscall` instruction is 0x050f. - binary.LittleEndian.PutUint16(instruction, 0x050f) - _, err = syscall.PtracePokeData(p.pid, ip, instruction) - if err != nil { - return 0, errors.Wrapf(err, "writing data %v to %x", instruction, ip) - } - - // run one instruction, and stop - err = p.Step() - if err != nil { - return 0, err - } - - // read registers, the return value of syscall is stored inside rax register - err = getRegs(p.pid, ®s) - if err != nil { - return 0, err - } - - // restore the state saved at beginning. - return regs.Rax, p.Restore() -} diff --git a/pkg/process/ptrace/ptrace_linux_arm64.go b/pkg/process/ptrace/ptrace_linux_arm64.go deleted file mode 100644 index bbfc77928..000000000 --- a/pkg/process/ptrace/ptrace_linux_arm64.go +++ /dev/null @@ -1,105 +0,0 @@ -// 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 ptrace - -import ( - "encoding/binary" - "syscall" - - "github.com/pkg/errors" - "golang.org/x/sys/unix" -) - -var endian = binary.LittleEndian - -const syscallInstrSize = 4 - -// see kernel source /include/uapi/linux/elf.h. -const nrPRStatus = 1 - -func getIP(regs *syscall.PtraceRegs) uintptr { - return uintptr(regs.Pc) -} - -func getRegs(pid int, regsout *syscall.PtraceRegs) error { - err := unix.PtraceGetRegSetArm64(pid, nrPRStatus, (*unix.PtraceRegsArm64)(regsout)) - if err != nil { - return errors.Wrapf(err, "get registers of process %d", pid) - } - return nil -} - -func setRegs(pid int, regs *syscall.PtraceRegs) error { - err := unix.PtraceSetRegSetArm64(pid, nrPRStatus, (*unix.PtraceRegsArm64)(regs)) - if err != nil { - return errors.Wrapf(err, "set registers of process %d", pid) - } - return nil -} - -// Syscall runs a syscall at main thread of process. -func (p *TracedProgram) Syscall(number uint64, args ...uint64) (uint64, error) { - if len(args) > 7 { - return 0, errors.New("too many arguments for a syscall") - } - - // save the original registers and the current instructions - err := p.Protect() - if err != nil { - return 0, err - } - - var regs syscall.PtraceRegs - - err = getRegs(p.pid, ®s) - if err != nil { - return 0, err - } - // set the registers according to the syscall convention. Learn more about - // it in `man 2 syscall`. In aarch64 the syscall nr is stored in w8, and the - // arguments are stored in x0, x1, x2, x3, x4, x5 in order - regs.Regs[8] = number - copy(regs.Regs[:len(args)], args) - - err = setRegs(p.pid, ®s) - if err != nil { - return 0, err - } - - instruction := make([]byte, syscallInstrSize) - ip := getIP(p.backupRegs) - - // most aarch64 devices are little endian - // 0xd4000001 is `svc #0` to call the system call - endian.PutUint32(instruction, 0xd4000001) - _, err = syscall.PtracePokeData(p.pid, ip, instruction) - if err != nil { - return 0, errors.Wrapf(err, "writing data %v to %x", instruction, ip) - } - - // run one instruction, and stop - err = p.Step() - if err != nil { - return 0, err - } - - // read registers, the return value of syscall is stored inside x0 register - err = getRegs(p.pid, ®s) - if err != nil { - return 0, err - } - - return regs.Regs[0], p.Restore() -} diff --git a/pkg/process/ret_linux_amd64.go b/pkg/process/ret_linux_amd64.go deleted file mode 100644 index ccbddb094..000000000 --- a/pkg/process/ret_linux_amd64.go +++ /dev/null @@ -1,42 +0,0 @@ -// 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. -//go:build 386 || amd64 -// +build 386 amd64 - -package process - -import ( - "fmt" - - "golang.org/x/arch/x86/x86asm" -) - -func findRetInstructions(data []byte) ([]uint64, error) { - var returnOffsets []uint64 - index := 0 - for index < len(data) { - instruction, err := x86asm.Decode(data[index:], 64) - if err != nil { - return nil, fmt.Errorf("failed to decode x64 instruction at offset %d: %w", index, err) - } - - if instruction.Op == x86asm.RET { - returnOffsets = append(returnOffsets, uint64(index)) - } - - index += instruction.Len - } - - return returnOffsets, nil -} diff --git a/pkg/process/ret_linux_arm64.go b/pkg/process/ret_linux_arm64.go deleted file mode 100644 index 0a28bb287..000000000 --- a/pkg/process/ret_linux_arm64.go +++ /dev/null @@ -1,41 +0,0 @@ -// 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. -//go:build arm64 -// +build arm64 - -package process - -import ( - "golang.org/x/arch/arm64/arm64asm" -) - -const ( - // In ARM64 each instruction is 4 bytes in length. - armInstructionSize = 4 -) - -func findRetInstructions(data []byte) ([]uint64, error) { - var returnOffsets []uint64 - index := 0 - for index < len(data) { - instruction, err := arm64asm.Decode(data[index:]) - if err == nil && instruction.Op == arm64asm.RET { - returnOffsets = append(returnOffsets, uint64(index)) - } - - index += armInstructionSize - } - - return returnOffsets, nil -} diff --git a/test/e2e/databasesql/Dockerfile b/test/e2e/databasesql/Dockerfile deleted file mode 100644 index 646ec7a43..000000000 --- a/test/e2e/databasesql/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM golang:1.20 -WORKDIR /sample-app -COPY . . -RUN go build -o main diff --git a/test/e2e/databasesql/go.mod b/test/e2e/databasesql/go.mod deleted file mode 100644 index a95c57552..000000000 --- a/test/e2e/databasesql/go.mod +++ /dev/null @@ -1,13 +0,0 @@ -module main - -go 1.20 - -require ( - github.com/mattn/go-sqlite3 v1.14.17 - go.uber.org/zap v1.24.0 -) - -require ( - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.6.0 // indirect -) diff --git a/test/e2e/databasesql/go.sum b/test/e2e/databasesql/go.sum deleted file mode 100644 index 94e89795c..000000000 --- a/test/e2e/databasesql/go.sum +++ /dev/null @@ -1,20 +0,0 @@ -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= -github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/test/e2e/databasesql/main.go b/test/e2e/databasesql/main.go deleted file mode 100644 index b119c2ec2..000000000 --- a/test/e2e/databasesql/main.go +++ /dev/null @@ -1,150 +0,0 @@ -// 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 main - -import ( - "database/sql" - "fmt" - "io" - "net/http" - "os" - "time" - - _ "github.com/mattn/go-sqlite3" - "go.uber.org/zap" -) - -const sqlQuery = "SELECT * FROM contacts" -const dbName = "test.db" -const tableDefinition = `CREATE TABLE contacts ( - contact_id INTEGER PRIMARY KEY, - first_name TEXT NOT NULL, - last_name TEXT NOT NULL, - email TEXT NOT NULL UNIQUE, - phone TEXT NOT NULL UNIQUE);` -const tableInsertion = `INSERT INTO 'contacts' - ('first_name', 'last_name', 'email', 'phone') VALUES - ('Moshe', 'Levi', 'moshe@gmail.com', '052-1234567');` - -// Server is Http server that exposes multiple endpoints. -type Server struct { - db *sql.DB -} - -// Create the db file. -func CreateDb() { - file, err := os.Create(dbName) - if err != nil { - panic(err) - } - err = file.Close() - if err != nil { - panic(err) - } -} - -// NewServer creates a server struct after initialing rand. -func NewServer() *Server { - CreateDb() - - database, err := sql.Open("sqlite3", dbName) - - if err != nil { - panic(err) - } - - _, err = database.Exec(tableDefinition) - - if err != nil { - panic(err) - } - - _, err = database.Exec(tableInsertion) - - if err != nil { - panic(err) - } - - return &Server{ - db: database, - } -} - -func (s *Server) queryDb(w http.ResponseWriter, req *http.Request) { - ctx := req.Context() - - conn, err := s.db.Conn(ctx) - - if err != nil { - panic(err) - } - - rows, err := conn.QueryContext(req.Context(), sqlQuery) - if err != nil { - panic(err) - } - - logger.Info("queryDb called") - for rows.Next() { - var id int - var firstName string - var lastName string - var email string - var phone string - err := rows.Scan(&id, &firstName, &lastName, &email, &phone) - if err != nil { - panic(err) - } - fmt.Fprintf(w, "ID: %d, firstName: %s, lastName: %s, email: %s, phone: %s\n", id, firstName, lastName, email, phone) - } -} - -var logger *zap.Logger - -func main() { - var err error - logger, err = zap.NewDevelopment() - if err != nil { - fmt.Printf("error creating zap logger, error:%v", err) - return - } - port := fmt.Sprintf(":%d", 8080) - logger.Info("starting http server", zap.String("port", port)) - - s := NewServer() - - http.HandleFunc("/query_db", s.queryDb) - go func() { - _ = http.ListenAndServe(":8080", nil) - }() - - // give time for auto-instrumentation to start up - time.Sleep(5 * time.Second) - - resp, err := http.Get("http://localhost:8080/query_db") - if err != nil { - logger.Error("Error performing GET", zap.Error(err)) - } - body, err := io.ReadAll(resp.Body) - if err != nil { - logger.Error("Error reading http body", zap.Error(err)) - } - - logger.Info("Body:\n", zap.String("body", string(body[:]))) - _ = resp.Body.Close() - - // give time for auto-instrumentation to report signal - time.Sleep(5 * time.Second) -} diff --git a/test/e2e/databasesql/traces.json b/test/e2e/databasesql/traces.json deleted file mode 100644 index 96c9f398e..000000000 --- a/test/e2e/databasesql/traces.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "resourceSpans": [ - { - "resource": { - "attributes": [ - { - "key": "service.name", - "value": { - "stringValue": "sample-app" - } - }, - { - "key": "telemetry.auto.version", - "value": { - "stringValue": "v0.3.0-alpha" - } - }, - { - "key": "telemetry.sdk.language", - "value": { - "stringValue": "go" - } - } - ] - }, - "scopeSpans": [ - { - "scope": { - "name": "database/sql" - }, - "spans": [ - { - "attributes": [ - { - "key": "db.statement", - "value": { - "stringValue": "SELECT * FROM contacts" - } - } - ], - "kind": 3, - "name": "DB", - "parentSpanId": "xxxxx", - "spanId": "xxxxx", - "status": {}, - "traceId": "xxxxx" - } - ] - }, - { - "scope": { - "name": "net/http" - }, - "spans": [ - { - "attributes": [ - { - "key": "http.method", - "value": { - "stringValue": "GET" - } - }, - { - "key": "http.target", - "value": { - "stringValue": "/query_db" - } - } - ], - "kind": 2, - "name": "GET", - "parentSpanId": "xxxxx", - "spanId": "xxxxx", - "status": {}, - "traceId": "xxxxx" - } - ] - }, - { - "scope": { - "name": "net/http/client" - }, - "spans": [ - { - "attributes": [ - { - "key": "http.method", - "value": { - "stringValue": "GET" - } - }, - { - "key": "http.target", - "value": { - "stringValue": "/query_db" - } - } - ], - "kind": 3, - "name": "/query_db", - "parentSpanId": "", - "spanId": "xxxxx", - "status": {}, - "traceId": "xxxxx" - } - ] - } - ] - } - ] -} diff --git a/test/e2e/databasesql/verify.bats b/test/e2e/databasesql/verify.bats deleted file mode 100644 index 306d66b76..000000000 --- a/test/e2e/databasesql/verify.bats +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bats - -load ../../test_helpers/utilities - -LIBRARY_NAME="database/sql" - -@test "${LIBRARY_NAME} :: includes db.statement attribute" { - result=$(span_attributes_for ${LIBRARY_NAME} | jq "select(.key == \"db.statement\").value.stringValue") - assert_equal "$result" '"SELECT * FROM contacts"' -} - -@test "${LIBRARY_NAME} :: trace ID present and valid in all spans" { - trace_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".traceId") - assert_regex "$trace_id" ${MATCH_A_TRACE_ID} -} - -@test "${LIBRARY_NAME} :: span ID present and valid in all spans" { - span_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") - assert_regex "$span_id" ${MATCH_A_SPAN_ID} -} - -@test "${LIBRARY_NAME} :: parent span ID present and valid in all spans" { - parent_span_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".parentSpanId") - assert_regex "$parent_span_id" ${MATCH_A_SPAN_ID} -} - -@test "${LIBRARY_NAME} :: expected (redacted) trace output" { - redact_json - assert_equal "$(git --no-pager diff ${BATS_TEST_DIRNAME}/traces.json)" "" -} diff --git a/test/e2e/gin/Dockerfile b/test/e2e/gin/Dockerfile deleted file mode 100644 index 646ec7a43..000000000 --- a/test/e2e/gin/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM golang:1.20 -WORKDIR /sample-app -COPY . . -RUN go build -o main diff --git a/test/e2e/gin/go.mod b/test/e2e/gin/go.mod deleted file mode 100644 index ac1381f37..000000000 --- a/test/e2e/gin/go.mod +++ /dev/null @@ -1,32 +0,0 @@ -// Deprecated: This module is no longer supported. -module go.opentelemetry.io/auto/test/e2e/gin - -go 1.20 - -require github.com/gin-gonic/gin v1.9.0 - -require ( - github.com/bytedance/sonic v1.8.0 // indirect - github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect - github.com/gin-contrib/sse v0.1.0 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.11.2 // indirect - github.com/goccy/go-json v0.10.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/cpuid/v2 v2.0.9 // indirect - github.com/leodido/go-urn v1.2.1 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect - github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.0.6 // indirect - github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.2.9 // indirect - golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect - golang.org/x/crypto v0.5.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/test/e2e/gin/go.sum b/test/e2e/gin/go.sum deleted file mode 100644 index bfad1c04d..000000000 --- a/test/e2e/gin/go.sum +++ /dev/null @@ -1,81 +0,0 @@ -github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA= -github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= -github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8= -github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k= -github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU= -github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s= -github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= -github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= -github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= -github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= -github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU= -github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -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= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/test/e2e/gin/main.go b/test/e2e/gin/main.go deleted file mode 100644 index 9072099be..000000000 --- a/test/e2e/gin/main.go +++ /dev/null @@ -1,52 +0,0 @@ -// 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 main - -import ( - "io" - "log" - "net/http" - "time" - - "github.com/gin-gonic/gin" -) - -func main() { - r := gin.Default() - r.GET("/hello-gin", func(c *gin.Context) { - c.String(http.StatusOK, "hello\n") - }) - go func() { - _ = r.Run() - }() - - // give time for auto-instrumentation to start up - time.Sleep(5 * time.Second) - - resp, err := http.Get("http://localhost:8080/hello-gin") - if err != nil { - log.Fatal(err) - } - body, err := io.ReadAll(resp.Body) - if err != nil { - log.Fatal(err) - } - - log.Printf("Body: %s\n", string(body)) - _ = resp.Body.Close() - - // give time for auto-instrumentation to report signal - time.Sleep(5 * time.Second) -} diff --git a/test/e2e/gin/traces.json b/test/e2e/gin/traces.json deleted file mode 100644 index 3daf1ae00..000000000 --- a/test/e2e/gin/traces.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "resourceSpans": [ - { - "resource": { - "attributes": [ - { - "key": "service.name", - "value": { - "stringValue": "sample-app" - } - }, - { - "key": "telemetry.auto.version", - "value": { - "stringValue": "v0.3.0-alpha" - } - }, - { - "key": "telemetry.sdk.language", - "value": { - "stringValue": "go" - } - } - ] - }, - "scopeSpans": [ - { - "scope": { - "name": "github.com/gin-gonic/gin" - }, - "spans": [ - { - "attributes": [ - { - "key": "http.method", - "value": { - "stringValue": "GET" - } - }, - { - "key": "http.target", - "value": { - "stringValue": "/hello-gin" - } - } - ], - "kind": 2, - "name": "GET", - "parentSpanId": "", - "spanId": "xxxxx", - "status": {}, - "traceId": "xxxxx" - } - ] - }, - { - "scope": { - "name": "net/http/client" - }, - "spans": [ - { - "attributes": [ - { - "key": "http.method", - "value": { - "stringValue": "GET" - } - }, - { - "key": "http.target", - "value": { - "stringValue": "/hello-gin" - } - } - ], - "kind": 3, - "name": "/hello-gin", - "parentSpanId": "", - "spanId": "xxxxx", - "status": {}, - "traceId": "xxxxx" - } - ] - } - ] - } - ] -} diff --git a/test/e2e/gin/verify.bats b/test/e2e/gin/verify.bats deleted file mode 100644 index 08e9dc321..000000000 --- a/test/e2e/gin/verify.bats +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bats - -load ../../test_helpers/utilities - -LIBRARY_NAME="github.com/gin-gonic/gin" - -@test "go-auto :: includes service.name in resource attributes" { - result=$(resource_attributes_received | jq "select(.key == \"service.name\").value.stringValue") - assert_equal "$result" '"sample-app"' -} - -@test "${LIBRARY_NAME} :: emits a span name '{http.method}' (per semconv)" { - result=$(span_names_for ${LIBRARY_NAME}) - assert_equal "$result" '"GET"' -} - -@test "${LIBRARY_NAME} :: includes http.method attribute" { - result=$(span_attributes_for ${LIBRARY_NAME} | jq "select(.key == \"http.method\").value.stringValue") - assert_equal "$result" '"GET"' -} - -@test "${LIBRARY_NAME} :: includes http.target attribute" { - result=$(span_attributes_for ${LIBRARY_NAME} | jq "select(.key == \"http.target\").value.stringValue") - assert_equal "$result" '"/hello-gin"' -} - -@test "${LIBRARY_NAME} :: trace ID present and valid in all spans" { - trace_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".traceId") - assert_regex "$trace_id" ${MATCH_A_TRACE_ID} -} - -@test "${LIBRARY_NAME} :: span ID present and valid in all spans" { - span_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") - assert_regex "$span_id" ${MATCH_A_SPAN_ID} -} - -@test "${LIBRARY_NAME} :: expected (redacted) trace output" { - redact_json - assert_equal "$(git --no-pager diff ${BATS_TEST_DIRNAME}/traces.json)" "" -} diff --git a/test/e2e/gorillamux/Dockerfile b/test/e2e/gorillamux/Dockerfile deleted file mode 100644 index 646ec7a43..000000000 --- a/test/e2e/gorillamux/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM golang:1.20 -WORKDIR /sample-app -COPY . . -RUN go build -o main diff --git a/test/e2e/gorillamux/go.mod b/test/e2e/gorillamux/go.mod deleted file mode 100644 index f87970487..000000000 --- a/test/e2e/gorillamux/go.mod +++ /dev/null @@ -1,6 +0,0 @@ -// Deprecated: This module will be removed in the next release. -module go.opentelemetry.io/auto/test/e2e/gorillamux - -go 1.20 - -require github.com/gorilla/mux v1.8.0 diff --git a/test/e2e/gorillamux/go.sum b/test/e2e/gorillamux/go.sum deleted file mode 100644 index 535028803..000000000 --- a/test/e2e/gorillamux/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= diff --git a/test/e2e/gorillamux/main.go b/test/e2e/gorillamux/main.go deleted file mode 100644 index 403e0cabf..000000000 --- a/test/e2e/gorillamux/main.go +++ /dev/null @@ -1,56 +0,0 @@ -// 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 main - -import ( - "fmt" - "io" - "log" - "net/http" - "time" - - "github.com/gorilla/mux" -) - -func main() { - r := mux.NewRouter() - - r.HandleFunc("/users/{user}", func(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - user := vars["user"] - fmt.Fprintf(w, "Hello user %s\n", user) - }) - go func() { - _ = http.ListenAndServe(":8080", r) - }() - - // give time for auto-instrumentation to start up - time.Sleep(5 * time.Second) - - resp, err := http.Get("http://localhost:8080/users/foo") - if err != nil { - log.Fatal(err) - } - body, err := io.ReadAll(resp.Body) - if err != nil { - log.Fatal(err) - } - - log.Printf("Body: %s\n", string(body)) - _ = resp.Body.Close() - - // give time for auto-instrumentation to report signal - time.Sleep(5 * time.Second) -} diff --git a/test/e2e/gorillamux/traces.json b/test/e2e/gorillamux/traces.json deleted file mode 100644 index 8307fe3bd..000000000 --- a/test/e2e/gorillamux/traces.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "resourceSpans": [ - { - "resource": { - "attributes": [ - { - "key": "service.name", - "value": { - "stringValue": "sample-app" - } - }, - { - "key": "telemetry.auto.version", - "value": { - "stringValue": "v0.3.0-alpha" - } - }, - { - "key": "telemetry.sdk.language", - "value": { - "stringValue": "go" - } - } - ] - }, - "scopeSpans": [ - { - "scope": { - "name": "github.com/gorilla/mux" - }, - "spans": [ - { - "attributes": [ - { - "key": "http.method", - "value": { - "stringValue": "GET" - } - }, - { - "key": "http.target", - "value": { - "stringValue": "/users/foo" - } - } - ], - "kind": 2, - "name": "GET", - "parentSpanId": "", - "spanId": "xxxxx", - "status": {}, - "traceId": "xxxxx" - } - ] - }, - { - "scope": { - "name": "net/http" - }, - "spans": [ - { - "attributes": [ - { - "key": "http.method", - "value": { - "stringValue": "GET" - } - }, - { - "key": "http.target", - "value": { - "stringValue": "/users/foo" - } - } - ], - "kind": 2, - "name": "GET", - "parentSpanId": "xxxxx", - "spanId": "xxxxx", - "status": {}, - "traceId": "xxxxx" - } - ] - }, - { - "scope": { - "name": "net/http/client" - }, - "spans": [ - { - "attributes": [ - { - "key": "http.method", - "value": { - "stringValue": "GET" - } - }, - { - "key": "http.target", - "value": { - "stringValue": "/users/foo" - } - } - ], - "kind": 3, - "name": "/users/foo", - "parentSpanId": "", - "spanId": "xxxxx", - "status": {}, - "traceId": "xxxxx" - } - ] - } - ] - } - ] -} diff --git a/test/e2e/gorillamux/verify.bats b/test/e2e/gorillamux/verify.bats deleted file mode 100644 index 9b0624218..000000000 --- a/test/e2e/gorillamux/verify.bats +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bats - -load ../../test_helpers/utilities - -LIBRARY_NAME="github.com/gorilla/mux" - -@test "go-auto :: includes service.name in resource attributes" { - result=$(resource_attributes_received | jq "select(.key == \"service.name\").value.stringValue") - assert_equal "$result" '"sample-app"' -} - -@test "${LIBRARY_NAME} :: emits a span name '{http.method}' (per semconv)" { - result=$(span_names_for ${LIBRARY_NAME}) - assert_equal "$result" '"GET"' -} - -@test "${LIBRARY_NAME} :: includes http.method attribute" { - result=$(span_attributes_for ${LIBRARY_NAME} | jq "select(.key == \"http.method\").value.stringValue") - assert_equal "$result" '"GET"' -} - -@test "${LIBRARY_NAME} :: includes http.target attribute" { - result=$(span_attributes_for ${LIBRARY_NAME} | jq "select(.key == \"http.target\").value.stringValue") - assert_equal "$result" '"/users/foo"' -} - -@test "${LIBRARY_NAME} :: trace ID present and valid in all spans" { - trace_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".traceId") - assert_regex "$trace_id" ${MATCH_A_TRACE_ID} -} - -@test "${LIBRARY_NAME} :: span ID present and valid in all spans" { - span_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") - assert_regex "$span_id" ${MATCH_A_SPAN_ID} -} - -@test "${LIBRARY_NAME} :: expected (redacted) trace output" { - redact_json - assert_equal "$(git --no-pager diff ${BATS_TEST_DIRNAME}/traces.json)" "" -} diff --git a/test/e2e/nethttp/Dockerfile b/test/e2e/nethttp/Dockerfile deleted file mode 100644 index 646ec7a43..000000000 --- a/test/e2e/nethttp/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM golang:1.20 -WORKDIR /sample-app -COPY . . -RUN go build -o main diff --git a/test/e2e/nethttp/go.mod b/test/e2e/nethttp/go.mod deleted file mode 100644 index 76ca0a022..000000000 --- a/test/e2e/nethttp/go.mod +++ /dev/null @@ -1,4 +0,0 @@ -// Deprecated: This module is no longer supported. -module go.opentelemetry.io/auto/test/e2e/nethttp - -go 1.20 diff --git a/test/e2e/nethttp/main.go b/test/e2e/nethttp/main.go deleted file mode 100644 index 38488ee40..000000000 --- a/test/e2e/nethttp/main.go +++ /dev/null @@ -1,52 +0,0 @@ -// 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 main - -import ( - "fmt" - "io" - "log" - "net/http" - "time" -) - -func hello(w http.ResponseWriter, _ *http.Request) { - fmt.Fprintf(w, "hello\n") -} - -func main() { - http.HandleFunc("/hello", hello) - go func() { - _ = http.ListenAndServe(":8080", nil) - }() - - // give time for auto-instrumentation to start up - time.Sleep(5 * time.Second) - - resp, err := http.Get("http://localhost:8080/hello") - if err != nil { - log.Fatal(err) - } - body, err := io.ReadAll(resp.Body) - if err != nil { - log.Fatal(err) - } - - log.Printf("Body: %s\n", string(body)) - _ = resp.Body.Close() - - // give time for auto-instrumentation to report signal - time.Sleep(5 * time.Second) -} diff --git a/test/e2e/nethttp/traces.json b/test/e2e/nethttp/traces.json deleted file mode 100644 index 76a8b0865..000000000 --- a/test/e2e/nethttp/traces.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "resourceSpans": [ - { - "resource": { - "attributes": [ - { - "key": "service.name", - "value": { - "stringValue": "sample-app" - } - }, - { - "key": "telemetry.auto.version", - "value": { - "stringValue": "v0.3.0-alpha" - } - }, - { - "key": "telemetry.sdk.language", - "value": { - "stringValue": "go" - } - } - ] - }, - "scopeSpans": [ - { - "scope": { - "name": "net/http" - }, - "spans": [ - { - "attributes": [ - { - "key": "http.method", - "value": { - "stringValue": "GET" - } - }, - { - "key": "http.target", - "value": { - "stringValue": "/hello" - } - } - ], - "kind": 2, - "name": "GET", - "parentSpanId": "xxxxx", - "spanId": "xxxxx", - "status": {}, - "traceId": "xxxxx" - } - ] - }, - { - "scope": { - "name": "net/http/client" - }, - "spans": [ - { - "attributes": [ - { - "key": "http.method", - "value": { - "stringValue": "GET" - } - }, - { - "key": "http.target", - "value": { - "stringValue": "/hello" - } - } - ], - "kind": 3, - "name": "/hello", - "parentSpanId": "", - "spanId": "xxxxx", - "status": {}, - "traceId": "xxxxx" - } - ] - } - ] - } - ] -} diff --git a/test/e2e/nethttp/verify.bats b/test/e2e/nethttp/verify.bats deleted file mode 100644 index 7e51561c3..000000000 --- a/test/e2e/nethttp/verify.bats +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bats - -load ../../test_helpers/utilities - -LIBRARY_NAME="net/http" - -@test "go-auto :: includes service.name in resource attributes" { - result=$(resource_attributes_received | jq "select(.key == \"service.name\").value.stringValue") - assert_equal "$result" '"sample-app"' -} - -@test "${LIBRARY_NAME} :: emits a span name '{http.method}' (per semconv)" { - result=$(span_names_for ${LIBRARY_NAME}) - assert_equal "$result" '"GET"' -} - -@test "${LIBRARY_NAME} :: includes http.method attribute" { - result=$(span_attributes_for ${LIBRARY_NAME} | jq "select(.key == \"http.method\").value.stringValue") - assert_equal "$result" '"GET"' -} - -@test "${LIBRARY_NAME} :: includes http.target attribute" { - result=$(span_attributes_for ${LIBRARY_NAME} | jq "select(.key == \"http.target\").value.stringValue") - assert_equal "$result" '"/hello"' -} - -@test "${LIBRARY_NAME} :: trace ID present and valid in all spans" { - trace_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".traceId") - assert_regex "$trace_id" ${MATCH_A_TRACE_ID} -} - -@test "${LIBRARY_NAME} :: span ID present and valid in all spans" { - span_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") - assert_regex "$span_id" ${MATCH_A_SPAN_ID} -} - -@test "${LIBRARY_NAME} :: parent span ID present and valid in all spans" { - parent_span_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".parentSpanId") - assert_regex "$parent_span_id" ${MATCH_A_SPAN_ID} -} - -@test "${LIBRARY_NAME} :: expected (redacted) trace output" { - redact_json - assert_equal "$(git --no-pager diff ${BATS_TEST_DIRNAME}/traces.json)" "" -} diff --git a/test/test_helpers/utilities.bash b/test/test_helpers/utilities.bash deleted file mode 100644 index 1fa921f63..000000000 --- a/test/test_helpers/utilities.bash +++ /dev/null @@ -1,112 +0,0 @@ -# DATA RETRIEVERS - -# Returns a list of span names emitted by a given library/scope - # $1 - library/scope name -span_names_for() { - spans_from_scope_named $1 | jq '.name' -} - -# Returns a list of attributes emitted by a given library/scope -span_attributes_for() { - # $1 - library/scope name - - spans_from_scope_named $1 | \ - jq ".attributes[]" -} - -# Returns a list of all resource attributes -resource_attributes_received() { - spans_received | jq ".resource.attributes[]?" -} - -# Returns an array of all spans emitted by a given library/scope - # $1 - library/scope name -spans_from_scope_named() { - spans_received | jq ".scopeSpans[] | select(.scope.name == \"$1\").spans[]" -} - -# Returns an array of all spans received -spans_received() { - json_output | jq ".resourceSpans[]?" -} - -# Returns the content of the log file produced by a collector -# and located in the same directory as the BATS test file -# loading this helper script. -json_output() { - cat "${BATS_TEST_DIRNAME}/traces-orig.json" -} - -redact_json() { - json_output | \ - jq --sort-keys ' - del( - .resourceSpans[].scopeSpans[].spans[].startTimeUnixNano, - .resourceSpans[].scopeSpans[].spans[].endTimeUnixNano - ) - | .resourceSpans[].scopeSpans[].spans[].traceId|= (if - . // "" | test("^[A-Fa-f0-9]{32}$") then "xxxxx" else (. + "<-INVALID") - end) - | .resourceSpans[].scopeSpans[].spans[].spanId|= (if - . // "" | test("^[A-Fa-f0-9]{16}$") then "xxxxx" else (. + "<-INVALID") - end) - | .resourceSpans[].scopeSpans[].spans[].parentSpanId|= (if - . // "" | test("^[A-Fa-f0-9]{16}$") then "xxxxx" else (. + "") - end) - | .resourceSpans[].scopeSpans|=sort_by(.scope.name) - ' > ${BATS_TEST_DIRNAME}/traces.json -} - -# ASSERTION HELPERS - -# expect a 32-digit hexadecimal string (in quotes) -MATCH_A_TRACE_ID=^"\"[A-Fa-f0-9]{32}\"$" - -# expect a 16-digit hexadecimal string (in quotes) -MATCH_A_SPAN_ID=^"\"[A-Fa-f0-9]{16}\"$" - -# Fail and display details if the expected and actual values do not -# equal. Details include both values. -# -# Inspired by bats-assert * bats-support, but dramatically simplified -assert_equal() { - if [[ $1 != "$2" ]]; then - { - echo - echo "-- 💥 values are not equal 💥 --" - echo "expected : $2" - echo "actual : $1" - echo "--" - echo - } >&2 # output error to STDERR - return 1 - fi -} - -assert_regex() { - if ! [[ $1 =~ $2 ]]; then - { - echo - echo "-- 💥 value does not match regular expression 💥 --" - echo "value : $1" - echo "pattern : $2" - echo "--" - echo - } >&2 # output error to STDERR - return 1 - fi -} - -assert_not_empty() { - EMPTY=(\"\") - if [[ "$1" == "${EMPTY}" ]]; then - { - echo - echo "-- 💥 value is empty 💥 --" - echo "value : $1" - echo "--" - echo - } >&2 # output error to STDERR - return 1 - fi -} diff --git a/versions.yaml b/versions.yaml index 8492e15aa..0e18978fc 100644 --- a/versions.yaml +++ b/versions.yaml @@ -18,9 +18,6 @@ module-sets: modules: - go.opentelemetry.io/auto - go.opentelemetry.io/auto/examples/rolldice - - go.opentelemetry.io/auto/offsets-tracker - - go.opentelemetry.io/auto/test/e2e/gin - - go.opentelemetry.io/auto/test/e2e/nethttp excluded-modules: - github.com/hashicorp/go-version - go.opentelemetry.io/auto/internal/tools