From 7d7606c6523471ebd284ac3e37c07f23055cfda2 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 23 Jan 2025 14:41:18 -0800 Subject: [PATCH] Remove the instrgen module (#6671) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Robert PajÄ…k --- .github/ISSUE_TEMPLATE/bug_report_instrgen.md | 29 -- .../feature_request_instrgen.md | 30 -- .gitignore | 2 - CODEOWNERS | 1 - CONTRIBUTING.md | 8 +- instrgen/README.md | 40 -- instrgen/doc.go | 8 - instrgen/docs/flow.png | Bin 81837 -> 0 bytes instrgen/docs/how-it-works.md | 12 - instrgen/driver/go.mod | 19 - instrgen/driver/go.sum | 18 - instrgen/driver/instrgen_test.go | 106 ----- instrgen/driver/main.go | 173 -------- instrgen/driver/passes.go | 41 -- instrgen/driver/testdata/basic/fib.go | 41 -- instrgen/driver/testdata/basic/goroutines.go | 23 -- instrgen/driver/testdata/basic/main.go | 28 -- instrgen/driver/testdata/basic/methods.go | 46 --- instrgen/driver/testdata/basic/package.go | 22 - instrgen/driver/testdata/dummy/main.go | 8 - .../driver/testdata/expected/basic/fib.go | 51 --- .../testdata/expected/basic/goroutines.go | 29 -- .../driver/testdata/expected/basic/main.go | 38 -- .../driver/testdata/expected/basic/methods.go | 59 --- .../driver/testdata/expected/basic/package.go | 26 -- .../driver/testdata/expected/basic/traces.txt | 148 ------- .../testdata/expected/interface/app/impl.go | 22 - .../testdata/expected/interface/main.go | 29 -- .../interface/serializer/interface.go | 11 - .../driver/testdata/expected/selector/main.go | 42 -- .../testdata/funwithoutpathtoroot/driver.go | 22 - .../driver/testdata/interface/app/impl.go | 17 - instrgen/driver/testdata/interface/go.mod | 20 - instrgen/driver/testdata/interface/go.sum | 31 -- instrgen/driver/testdata/interface/main.go | 20 - .../interface/serializer/interface.go | 9 - instrgen/driver/testdata/selector/main.go | 32 -- instrgen/go.mod | 22 - instrgen/go.sum | 37 -- instrgen/lib/analysis.go | 130 ------ instrgen/lib/callgraph.go | 385 ------------------ instrgen/lib/context_propagation.go | 202 --------- instrgen/lib/instrumentation.go | 370 ----------------- instrgen/lib/otel_pruning.go | 146 ------- instrgen/lib/tools.go | 60 --- instrgen/rtlib/rtlib.go | 81 ---- renovate.json | 1 - versions.yaml | 3 - 48 files changed, 2 insertions(+), 2696 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report_instrgen.md delete mode 100644 .github/ISSUE_TEMPLATE/feature_request_instrgen.md delete mode 100644 instrgen/README.md delete mode 100644 instrgen/doc.go delete mode 100644 instrgen/docs/flow.png delete mode 100644 instrgen/docs/how-it-works.md delete mode 100644 instrgen/driver/go.mod delete mode 100644 instrgen/driver/go.sum delete mode 100644 instrgen/driver/instrgen_test.go delete mode 100644 instrgen/driver/main.go delete mode 100644 instrgen/driver/passes.go delete mode 100644 instrgen/driver/testdata/basic/fib.go delete mode 100644 instrgen/driver/testdata/basic/goroutines.go delete mode 100644 instrgen/driver/testdata/basic/main.go delete mode 100644 instrgen/driver/testdata/basic/methods.go delete mode 100644 instrgen/driver/testdata/basic/package.go delete mode 100644 instrgen/driver/testdata/dummy/main.go delete mode 100644 instrgen/driver/testdata/expected/basic/fib.go delete mode 100644 instrgen/driver/testdata/expected/basic/goroutines.go delete mode 100644 instrgen/driver/testdata/expected/basic/main.go delete mode 100644 instrgen/driver/testdata/expected/basic/methods.go delete mode 100644 instrgen/driver/testdata/expected/basic/package.go delete mode 100644 instrgen/driver/testdata/expected/basic/traces.txt delete mode 100644 instrgen/driver/testdata/expected/interface/app/impl.go delete mode 100644 instrgen/driver/testdata/expected/interface/main.go delete mode 100644 instrgen/driver/testdata/expected/interface/serializer/interface.go delete mode 100644 instrgen/driver/testdata/expected/selector/main.go delete mode 100644 instrgen/driver/testdata/funwithoutpathtoroot/driver.go delete mode 100644 instrgen/driver/testdata/interface/app/impl.go delete mode 100644 instrgen/driver/testdata/interface/go.mod delete mode 100644 instrgen/driver/testdata/interface/go.sum delete mode 100644 instrgen/driver/testdata/interface/main.go delete mode 100644 instrgen/driver/testdata/interface/serializer/interface.go delete mode 100644 instrgen/driver/testdata/selector/main.go delete mode 100644 instrgen/go.mod delete mode 100644 instrgen/go.sum delete mode 100644 instrgen/lib/analysis.go delete mode 100644 instrgen/lib/callgraph.go delete mode 100644 instrgen/lib/context_propagation.go delete mode 100644 instrgen/lib/instrumentation.go delete mode 100644 instrgen/lib/otel_pruning.go delete mode 100644 instrgen/lib/tools.go delete mode 100644 instrgen/rtlib/rtlib.go diff --git a/.github/ISSUE_TEMPLATE/bug_report_instrgen.md b/.github/ISSUE_TEMPLATE/bug_report_instrgen.md deleted file mode 100644 index 531b4cbcc5c..00000000000 --- a/.github/ISSUE_TEMPLATE/bug_report_instrgen.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -name: '[instrgen] Bug report' -about: Create a report of invalid behavior about the instrgen package to help us improve -title: '' -labels: 'bug, area: instrgen' -assignees: '@open-telemetry/go-instrumentation-approvers' - ---- - -### Description - -A clear and concise description of what the bug is. - -### Environment - -- OS: [e.g. iOS] -- Architecture: [e.g. x86, i386] -- Go Version: [e.g. 1.15] -- `instrgen` version: [e.g. v0.14.0, 3c7face] - -### Steps To Reproduce - -1. Using this code ... -2. Run ... -3. See error ... - -### Expected behavior - -A clear and concise description of what you expected to happen. diff --git a/.github/ISSUE_TEMPLATE/feature_request_instrgen.md b/.github/ISSUE_TEMPLATE/feature_request_instrgen.md deleted file mode 100644 index d5ac8fa5ce9..00000000000 --- a/.github/ISSUE_TEMPLATE/feature_request_instrgen.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -name: '[instrgen] Feature request' -about: Suggest an idea for the instrgen package -title: '' -labels: enhancement -labels: 'enhancement, area: instrgen' -assignees: '@open-telemetry/go-instrumentation-approvers' - ---- - -### Problem Statement - -A clear and concise description of what the problem is. -Ex. I'm always frustrated when [...] - -### Proposed Solution - -A clear and concise description of what you want to happen. - -#### Alternatives - -A clear and concise description of any alternative solutions or features you've considered. - -#### Prior Art - -A clear and concise list of any similar and existing solutions from other projects that provide context to possible solutions. - -### Additional Context - -Add any other context or screenshots about the feature request here. diff --git a/.gitignore b/.gitignore index 1172e25e803..4cd7cf08649 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,4 @@ examples/zipkin/zipkin instrumentation/google.golang.org/grpc/otelgrpc/example/server/server instrumentation/google.golang.org/grpc/otelgrpc/example/client/client -instrgen/driver/testdata/**/*.go_pass_* - tmp diff --git a/CODEOWNERS b/CODEOWNERS index ecbb7a36ab8..5481e8170e5 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -70,4 +70,3 @@ samplers/jaegerremote/ @open-te samplers/probability/consistent/ @open-telemetry/go-approvers zpages/ @open-telemetry/go-approvers @dashpole -instrgen/ @open-telemetry/go-approvers @open-telemetry/go-instrumentation-approvers @MrAlias @pdelewski diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 956a6878bf2..7bd42f2e9d5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -88,14 +88,14 @@ Changes should be made using [the GitHub flow](https://guides.github.com/introdu A pull request is considered ready to merge when the following criteria are meet. -* It has received two approvals from Code Owners/Approvers/Maintainers (at different companies), unless the change is for an exempt module[^1]. +* It has received two approvals from Code Owners/Approvers/Maintainers (at different companies). * All feedback has been addressed. Be sure to "Resolve" all comments that have been addressed to signal this. * Any substantive changes submitted after an Approval removes that Approval. You will need to manually clear these prior Approval reviews to indicate to the reviewer that they need to resubmit their review. This includes changes resulting from other feedback. Unless the approver explicitly stated that their approval will persist across changes it should be assumed that the pull request needs their review again. Other project members (e.g. approvers, maintainers) can help with this if there are any questions or if you forget to clear reviews. -* If the changes are not trivial, cosmetic, exempt[^1], or for documentation or dependencies only, the pull request will need to be open for review for at least one working day. +* If the changes are not trivial, cosmetic, exempt, or for documentation or dependencies only, the pull request will need to be open for review for at least one working day. This gives people reasonable time to review. * `CHANGELOG.md` has been updated to reflect what has been added, changed, removed, or fixed from the end users perspective. See [how to keep a changelog](https://keepachangelog.com/en/1.0.0/). @@ -103,10 +103,6 @@ A pull request is considered ready to merge when the following criteria are meet Any Maintainer can merge the pull request once it is ready to merge. -[^1]: The `go.opentelemetry.io/contrib/instrgen` module is exempt from the two approvals and one day requirement. - Only one approval is needed to merge a Pull Request for that module and there is no minimum amount of time required for the PR to be open before merging. - This exemption is to be removed when that package makes its first tagged release. - ### Draft Pull Requests It can be helpful at times to publish your incomplete changes. diff --git a/instrgen/README.md b/instrgen/README.md deleted file mode 100644 index c40627a57c8..00000000000 --- a/instrgen/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# OpenTelemetry Go Source Automatic Instrumentation - -This package provides a code generation utility that instruments existing source code with [OpenTelemetry]. -If you are looking for more details about internal working, see [How it works](./docs/how-it-works.md). - -## Project Status - -:construction: This package is currently work in progress. - -## How to use it - -In order to instrument your project you have to add following call in your entry point function, usually main -(you can look at testdata directory for reference) and invoke instrgen tool. - -``` -func main() { - rtlib.AutotelEntryPoint() -``` - -Instrgen requires three parameters: command, path to project and package(s) pattern we -would like to instrument. - -``` -./instrgen --inject [path to your go project] [package(s) pattern] -``` - -Below concrete example with one of test instrumentation that is part of the project. - -``` -./instrgen --inject ./testdata/basic ./... -``` - -```./...``` works like wildcard in this case and it will instrument all packages in this path, but it can be invoked with -specific package as well. - -### Compatibility - -The `instrgen` utility is based on the Go standard library and is platform agnostic. - -[OpenTelemetry]: https://opentelemetry.io/ diff --git a/instrgen/doc.go b/instrgen/doc.go deleted file mode 100644 index b0cce8ad80b..00000000000 --- a/instrgen/doc.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -/* -Package instrgen provides a code generation utility that instruments existing -source code with OpenTelemetry. -*/ -package instrgen // import "go.opentelemetry.io/contrib/instrgen" diff --git a/instrgen/docs/flow.png b/instrgen/docs/flow.png deleted file mode 100644 index 3f519e41f70992bec9c90c36f27beb350f1d2f35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81837 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�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 diff --git a/instrgen/docs/how-it-works.md b/instrgen/docs/how-it-works.md deleted file mode 100644 index f59475d7dfa..00000000000 --- a/instrgen/docs/how-it-works.md +++ /dev/null @@ -1,12 +0,0 @@ -## OpenTelemetry Go Source Automatic Instrumentation - How it works - -`instrgen` adds OpenTelemetry instrumentation to source code by directly modifying it. -It uses the AST (Abstract Syntax Tree) representation of the code to determine its operational flow and injects necessary OpenTelemetry functionality into the AST. - -The AST modification algorithm is the following: -1. Search for the entry point: a function definition with `AutotelEntryPoint()`. -2. Build the call graph. Traverse all calls from the entry point through all function definitions. -3. Inject OpenTelemetry instrumentation into functions bodies. -4. Context propagation. Adding an additional context parameter to all function declarations and function call expressions that are visible - (it will not add a context argument to call expressions if they are not reachable from the entry point). -![image info](./flow.png) \ No newline at end of file diff --git a/instrgen/driver/go.mod b/instrgen/driver/go.mod deleted file mode 100644 index ef5572819ee..00000000000 --- a/instrgen/driver/go.mod +++ /dev/null @@ -1,19 +0,0 @@ -module go.opentelemetry.io/contrib/instrgen/driver - -go 1.22.0 - -replace go.opentelemetry.io/contrib/instrgen => ../ - -require ( - github.com/stretchr/testify v1.10.0 - go.opentelemetry.io/contrib/instrgen v0.0.0-00010101000000-000000000000 -) - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/mod v0.22.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/tools v0.29.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/instrgen/driver/go.sum b/instrgen/driver/go.sum deleted file mode 100644 index cb075b2eefb..00000000000 --- a/instrgen/driver/go.sum +++ /dev/null @@ -1,18 +0,0 @@ -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/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -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/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= -golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/instrgen/driver/instrgen_test.go b/instrgen/driver/instrgen_test.go deleted file mode 100644 index 3871eb06e39..00000000000 --- a/instrgen/driver/instrgen_test.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//go:build !windows - -package main - -import ( - "bytes" - "fmt" - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - alib "go.opentelemetry.io/contrib/instrgen/lib" -) - -var testcases = map[string]string{ - "./testdata/basic": "./testdata/expected/basic", - "./testdata/selector": "./testdata/expected/selector", - "./testdata/interface": "./testdata/expected/interface", -} - -var failures []string - -func inject(t *testing.T, root string, packagePattern string) { - err := executeCommand("--inject-dump-ir", root, packagePattern) - require.NoError(t, err) -} - -func TestCommands(t *testing.T) { - err := executeCommand("--dumpcfg", "./testdata/dummy", "./...") - require.NoError(t, err) - err = executeCommand("--rootfunctions", "./testdata/dummy", "./...") - require.NoError(t, err) - err = executeCommand("--prune", "./testdata/dummy", "./...") - require.NoError(t, err) - err = executeCommand("--inject", "./testdata/dummy", "./...") - require.NoError(t, err) - err = usage() - require.NoError(t, err) -} - -func TestCallGraph(t *testing.T) { - cg := makeCallGraph("./testdata/dummy", "./...") - dumpCallGraph(cg) - assert.Empty(t, cg, "callgraph should contain 0 elems") - rf := makeRootFunctions("./testdata/dummy", "./...") - dumpRootFunctions(rf) - assert.Empty(t, rf, "rootfunctions set should be empty") -} - -func TestArgs(t *testing.T) { - err := checkArgs(nil) - require.Error(t, err) - args := []string{"driver", "--inject", "", "./..."} - err = checkArgs(args) - require.NoError(t, err) -} - -func TestUnknownCommand(t *testing.T) { - err := executeCommand("unknown", "a", "b") - require.Error(t, err) -} - -func TestInstrumentation(t *testing.T) { - for k, v := range testcases { - inject(t, k, "./...") - files := alib.SearchFiles(k, ".go_pass_tracing") - expectedFiles := alib.SearchFiles(v, ".go") - numOfFiles := len(expectedFiles) - fmt.Println("Go Files:", len(files)) - fmt.Println("Expected Go Files:", len(expectedFiles)) - numOfComparisons := 0 - for _, file := range files { - fmt.Println(filepath.Base(file)) - for _, expectedFile := range expectedFiles { - fmt.Println(filepath.Base(expectedFile)) - if filepath.Base(file) == filepath.Base(expectedFile+"_pass_tracing") { - f1, err1 := os.ReadFile(file) - require.NoError(t, err1) - f2, err2 := os.ReadFile(expectedFile) - require.NoError(t, err2) - if !assert.True(t, bytes.Equal(f1, f2), file) { - failures = append(failures, file) - } - numOfComparisons = numOfComparisons + 1 - } - } - } - if numOfFiles != numOfComparisons { - fmt.Println("numberOfComparisons:", numOfComparisons) - panic("not all files were compared") - } - _, err := Prune(k, "./...", false) - if err != nil { - fmt.Println("Prune failed") - } - } - for _, f := range failures { - fmt.Println("FAILURE : ", f) - } -} diff --git a/instrgen/driver/main.go b/instrgen/driver/main.go deleted file mode 100644 index c5b38642710..00000000000 --- a/instrgen/driver/main.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package main - -import ( - "errors" - "fmt" - "go/ast" - "log" - "os" - - alib "go.opentelemetry.io/contrib/instrgen/lib" -) - -func usage() error { - fmt.Println("\nusage driver --command [path to go project] [package pattern]") - fmt.Println("\tcommand:") - fmt.Println("\t\tinject (injects open telemetry calls into project code)") - fmt.Println("\t\tinject-dump-ir (injects open telemetry calls into project code and intermediate passes)") - fmt.Println("\t\tprune (prune open telemetry calls") - fmt.Println("\t\tdumpcfg (dumps control flow graph)") - fmt.Println("\t\trootfunctions (dumps root functions)") - return nil -} - -func makeAnalysis(projectPath string, packagePattern string, debug bool) *alib.PackageAnalysis { - var rootFunctions []alib.FuncDescriptor - - interfaces := alib.FindInterfaces(projectPath, packagePattern) - rootFunctions = append(rootFunctions, alib.FindRootFunctions(projectPath, packagePattern, "AutotelEntryPoint")...) - funcDecls := alib.FindFuncDecls(projectPath, packagePattern, interfaces) - backwardCallGraph := alib.BuildCallGraph(projectPath, packagePattern, funcDecls, interfaces) - fmt.Println("\n\tchild parent") - for k, v := range backwardCallGraph { - fmt.Print("\n\t", k) - fmt.Print(" ", v) - } - fmt.Println("") - analysis := &alib.PackageAnalysis{ - ProjectPath: projectPath, - PackagePattern: packagePattern, - RootFunctions: rootFunctions, - FuncDecls: funcDecls, - Callgraph: backwardCallGraph, - Interfaces: interfaces, - Debug: debug, - } - return analysis -} - -// Prune. -func Prune(projectPath string, packagePattern string, debug bool) ([]*ast.File, error) { - analysis := makeAnalysis(projectPath, packagePattern, debug) - return analysis.Execute(&alib.OtelPruner{}, otelPrunerPassSuffix) -} - -func makeCallGraph(projectPath string, packagePattern string) map[alib.FuncDescriptor][]alib.FuncDescriptor { - var funcDecls map[alib.FuncDescriptor]bool - var backwardCallGraph map[alib.FuncDescriptor][]alib.FuncDescriptor - - interfaces := alib.FindInterfaces(projectPath, packagePattern) - funcDecls = alib.FindFuncDecls(projectPath, packagePattern, interfaces) - backwardCallGraph = alib.BuildCallGraph(projectPath, packagePattern, funcDecls, interfaces) - return backwardCallGraph -} - -func makeRootFunctions(projectPath string, packagePattern string) []alib.FuncDescriptor { - var rootFunctions []alib.FuncDescriptor - rootFunctions = append(rootFunctions, alib.FindRootFunctions(projectPath, packagePattern, "AutotelEntryPoint")...) - return rootFunctions -} - -func dumpCallGraph(callGraph map[alib.FuncDescriptor][]alib.FuncDescriptor) { - fmt.Println("\n\tchild parent") - for k, v := range callGraph { - fmt.Print("\n\t", k) - fmt.Print(" ", v) - } -} - -func dumpRootFunctions(rootFunctions []alib.FuncDescriptor) { - fmt.Println("rootfunctions:") - for _, fun := range rootFunctions { - fmt.Println("\t" + fun.TypeHash()) - } -} - -func isDirectory(path string) (bool, error) { - fileInfo, err := os.Stat(path) - if err != nil { - return false, err - } - - return fileInfo.IsDir(), err -} - -// Parsing algorithm works as follows. It goes through all function -// decls and infer function bodies to find call to AutotelEntryPoint -// A parent function of this call will become root of instrumentation -// Each function call from this place will be instrumented automatically. -func executeCommand(command string, projectPath string, packagePattern string) error { - isDir, err := isDirectory(projectPath) - if !isDir { - _ = usage() - return errors.New("[path to go project] argument must be directory") - } - if err != nil { - return err - } - switch command { - case "--inject": - _, err := Prune(projectPath, packagePattern, false) - if err != nil { - return err - } - analysis := makeAnalysis(projectPath, packagePattern, false) - err = ExecutePasses(analysis) - if err != nil { - return err - } - fmt.Println("\tinstrumentation done") - return nil - case "--inject-dump-ir": - _, err := Prune(projectPath, packagePattern, true) - if err != nil { - return err - } - analysis := makeAnalysis(projectPath, packagePattern, true) - err = ExecutePassesDumpIr(analysis) - if err != nil { - return err - } - fmt.Println("\tinstrumentation done") - return nil - case "--dumpcfg": - backwardCallGraph := makeCallGraph(projectPath, packagePattern) - dumpCallGraph(backwardCallGraph) - return nil - case "--rootfunctions": - rootFunctions := makeRootFunctions(projectPath, packagePattern) - dumpRootFunctions(rootFunctions) - return nil - case "--prune": - _, err := Prune(projectPath, packagePattern, false) - if err != nil { - return err - } - return nil - default: - return errors.New("unknown command") - } -} - -func checkArgs(args []string) error { - if len(args) != 4 { - _ = usage() - return errors.New("wrong arguments") - } - return nil -} - -func main() { - fmt.Println("autotel compiler") - err := checkArgs(os.Args) - if err != nil { - return - } - err = executeCommand(os.Args[1], os.Args[2], os.Args[3]) - if err != nil { - log.Fatal(err) - } -} diff --git a/instrgen/driver/passes.go b/instrgen/driver/passes.go deleted file mode 100644 index 42777431175..00000000000 --- a/instrgen/driver/passes.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package main - -import ( - "fmt" - - "go.opentelemetry.io/contrib/instrgen/lib" -) - -const ( - otelPrunerPassSuffix = "_pass_pruner" - contextPassFileSuffix = "_pass_ctx" - instrumentationPassFileSuffix = "_pass_tracing" -) - -// ExecutePassesDumpIr. -func ExecutePassesDumpIr(analysis *lib.PackageAnalysis) error { - fmt.Println("Instrumentation") - _, err := analysis.Execute(&lib.InstrumentationPass{}, "") - if err != nil { - return err - } - - fmt.Println("ContextPropagation") - _, err = analysis.Execute(&lib.ContextPropagationPass{}, instrumentationPassFileSuffix) - return err -} - -// ExecutePasses. -func ExecutePasses(analysis *lib.PackageAnalysis) error { - fmt.Println("Instrumentation") - _, err := analysis.Execute(&lib.InstrumentationPass{}, instrumentationPassFileSuffix) - if err != nil { - return err - } - fmt.Println("ContextPropagation") - _, err = analysis.Execute(&lib.ContextPropagationPass{}, contextPassFileSuffix) - return err -} diff --git a/instrgen/driver/testdata/basic/fib.go b/instrgen/driver/testdata/basic/fib.go deleted file mode 100644 index fd17e41ee99..00000000000 --- a/instrgen/driver/testdata/basic/fib.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -import ( - "fmt" -) - -func foo() { - - fmt.Println("foo") -} - -func FibonacciHelper(n uint) (uint64, error) { - - func() { - - foo() - }() - return Fibonacci(n) -} - -func Fibonacci(n uint) (uint64, error) { - - if n <= 1 { - return uint64(n), nil - } - - if n > 93 { - return 0, fmt.Errorf("unsupported fibonacci number %d: too large", n) - } - - var n2, n1 uint64 = 0, 1 - for i := uint(2); i < n; i++ { - n2, n1 = n1, n1+n2 - } - - return n2 + n1, nil -} diff --git a/instrgen/driver/testdata/basic/goroutines.go b/instrgen/driver/testdata/basic/goroutines.go deleted file mode 100644 index c295df56c61..00000000000 --- a/instrgen/driver/testdata/basic/goroutines.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -import ( - "fmt" -) - -func goroutines() { - - messages := make(chan string) - - go func() { - - messages <- "ping" - }() - - msg := <-messages - fmt.Println(msg) - -} diff --git a/instrgen/driver/testdata/basic/main.go b/instrgen/driver/testdata/basic/main.go deleted file mode 100644 index c8bd88b0487..00000000000 --- a/instrgen/driver/testdata/basic/main.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -import ( - "fmt" - - "go.opentelemetry.io/contrib/instrgen/rtlib" -) - -func recur(n int) { - - if n > 0 { - recur(n - 1) - } -} - -func main() { - - rtlib.AutotelEntryPoint() - fmt.Println(FibonacciHelper(10)) - recur(5) - goroutines() - pack() - methods() -} diff --git a/instrgen/driver/testdata/basic/methods.go b/instrgen/driver/testdata/basic/methods.go deleted file mode 100644 index 2d07bab8381..00000000000 --- a/instrgen/driver/testdata/basic/methods.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -type element struct { -} - -type driver struct { - e element -} - -type i interface { - anotherfoo(p int) int -} - -type impl struct { -} - -func (i impl) anotherfoo(p int) int { - - return 5 -} - -func anotherfoo(p int) int { - return 1 -} - -func (d driver) process(a int) { - -} - -func (e element) get(a int) { - -} - -func methods() { - - d := driver{} - d.process(10) - d.e.get(5) - var in i - in = impl{} - in.anotherfoo(10) -} diff --git a/instrgen/driver/testdata/basic/package.go b/instrgen/driver/testdata/basic/package.go deleted file mode 100644 index a09c94312c4..00000000000 --- a/instrgen/driver/testdata/basic/package.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -import ( - "os" -) - -func Close() error { - return nil -} - -func pack() { - - f, e := os.Create("temp") - defer f.Close() - if e != nil { - - } -} diff --git a/instrgen/driver/testdata/dummy/main.go b/instrgen/driver/testdata/dummy/main.go deleted file mode 100644 index 37c97482101..00000000000 --- a/instrgen/driver/testdata/dummy/main.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -func main() { -} diff --git a/instrgen/driver/testdata/expected/basic/fib.go b/instrgen/driver/testdata/expected/basic/fib.go deleted file mode 100644 index f5ea42c5251..00000000000 --- a/instrgen/driver/testdata/expected/basic/fib.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -import ( - "fmt" - __atel_context "context" - __atel_otel "go.opentelemetry.io/otel" -) - -func foo(__atel_tracing_ctx __atel_context.Context,) { - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("foo").Start(__atel_tracing_ctx, "foo") - _ = __atel_child_tracing_ctx - defer __atel_span.End() - fmt.Println("foo") -} - -func FibonacciHelper(__atel_tracing_ctx __atel_context.Context, n uint) (uint64, error) { - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("FibonacciHelper").Start(__atel_tracing_ctx, "FibonacciHelper") - _ = __atel_child_tracing_ctx - defer __atel_span.End() - func() { - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("anonymous").Start(__atel_child_tracing_ctx, "anonymous") - _ = __atel_child_tracing_ctx - defer __atel_span.End() - foo(__atel_child_tracing_ctx) - }() - return Fibonacci(__atel_child_tracing_ctx, n) -} - -func Fibonacci(__atel_tracing_ctx __atel_context.Context, n uint) (uint64, error) { - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("Fibonacci").Start(__atel_tracing_ctx, "Fibonacci") - _ = __atel_child_tracing_ctx - defer __atel_span.End() - if n <= 1 { - return uint64(n), nil - } - - if n > 93 { - return 0, fmt.Errorf("unsupported fibonacci number %d: too large", n) - } - - var n2, n1 uint64 = 0, 1 - for i := uint(2); i < n; i++ { - n2, n1 = n1, n1+n2 - } - - return n2 + n1, nil -} diff --git a/instrgen/driver/testdata/expected/basic/goroutines.go b/instrgen/driver/testdata/expected/basic/goroutines.go deleted file mode 100644 index 513874d215f..00000000000 --- a/instrgen/driver/testdata/expected/basic/goroutines.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -import ( - "fmt" - __atel_context "context" - __atel_otel "go.opentelemetry.io/otel" -) - -func goroutines(__atel_tracing_ctx __atel_context.Context,) { - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("goroutines").Start(__atel_tracing_ctx, "goroutines") - _ = __atel_child_tracing_ctx - defer __atel_span.End() - messages := make(chan string) - - go func() { - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("anonymous").Start(__atel_child_tracing_ctx, "anonymous") - _ = __atel_child_tracing_ctx - defer __atel_span.End() - messages <- "ping" - }() - - msg := <-messages - fmt.Println(msg) - -} diff --git a/instrgen/driver/testdata/expected/basic/main.go b/instrgen/driver/testdata/expected/basic/main.go deleted file mode 100644 index bd6cf7f951a..00000000000 --- a/instrgen/driver/testdata/expected/basic/main.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -import ( - "fmt" - __atel_context "context" - - "go.opentelemetry.io/contrib/instrgen/rtlib" - __atel_otel "go.opentelemetry.io/otel" -) - -func recur(__atel_tracing_ctx __atel_context.Context, n int) { - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("recur").Start(__atel_tracing_ctx, "recur") - _ = __atel_child_tracing_ctx - defer __atel_span.End() - if n > 0 { - recur(__atel_child_tracing_ctx, n-1) - } -} - -func main() { - __atel_ts := rtlib.NewTracingState() - defer rtlib.Shutdown(__atel_ts) - __atel_otel.SetTracerProvider(__atel_ts.Tp) - __atel_ctx := __atel_context.Background() - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("main").Start(__atel_ctx, "main") - _ = __atel_child_tracing_ctx - defer __atel_span.End() - rtlib.AutotelEntryPoint() - fmt.Println(FibonacciHelper(__atel_child_tracing_ctx, 10)) - recur(__atel_child_tracing_ctx, 5) - goroutines(__atel_child_tracing_ctx) - pack(__atel_child_tracing_ctx) - methods(__atel_child_tracing_ctx) -} diff --git a/instrgen/driver/testdata/expected/basic/methods.go b/instrgen/driver/testdata/expected/basic/methods.go deleted file mode 100644 index 081d85a2fde..00000000000 --- a/instrgen/driver/testdata/expected/basic/methods.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -import ( - __atel_context "context" - __atel_otel "go.opentelemetry.io/otel" -) - -type element struct { -} - -type driver struct { - e element -} - -type i interface { - anotherfoo(__atel_tracing_ctx __atel_context.Context, p int) int -} - -type impl struct { -} - -func (i impl) anotherfoo(__atel_tracing_ctx __atel_context.Context, p int) int { - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("anotherfoo").Start(__atel_tracing_ctx, "anotherfoo") - _ = __atel_child_tracing_ctx - defer __atel_span.End() - return 5 -} - -func anotherfoo(p int) int { - return 1 -} - -func (d driver) process(__atel_tracing_ctx __atel_context.Context, a int) { - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("process").Start(__atel_tracing_ctx, "process") - _ = __atel_child_tracing_ctx - defer __atel_span.End() -} - -func (e element) get(__atel_tracing_ctx __atel_context.Context, a int) { - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("get").Start(__atel_tracing_ctx, "get") - _ = __atel_child_tracing_ctx - defer __atel_span.End() -} - -func methods(__atel_tracing_ctx __atel_context.Context,) { - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("methods").Start(__atel_tracing_ctx, "methods") - _ = __atel_child_tracing_ctx - defer __atel_span.End() - d := driver{} - d.process(__atel_child_tracing_ctx, 10) - d.e.get(__atel_child_tracing_ctx, 5) - var in i - in = impl{} - in.anotherfoo(__atel_child_tracing_ctx, 10) -} diff --git a/instrgen/driver/testdata/expected/basic/package.go b/instrgen/driver/testdata/expected/basic/package.go deleted file mode 100644 index 1e2e34024d2..00000000000 --- a/instrgen/driver/testdata/expected/basic/package.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -import ( - "os" - __atel_context "context" - __atel_otel "go.opentelemetry.io/otel" -) - -func Close() error { - return nil -} - -func pack(__atel_tracing_ctx __atel_context.Context,) { - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("pack").Start(__atel_tracing_ctx, "pack") - _ = __atel_child_tracing_ctx - defer __atel_span.End() - f, e := os.Create("temp") - defer f.Close() - if e != nil { - - } -} diff --git a/instrgen/driver/testdata/expected/basic/traces.txt b/instrgen/driver/testdata/expected/basic/traces.txt deleted file mode 100644 index ecf2f9e541f..00000000000 --- a/instrgen/driver/testdata/expected/basic/traces.txt +++ /dev/null @@ -1,148 +0,0 @@ -{ - "Name": "foo", - "SpanContext": { - "TraceID": "374c11217817c32b01876bb2e2aceae8", - "SpanID": "8c982b3e435c56e0", - "TraceFlags": "01", - "TraceState": "", - "Remote": false - }, - "Parent": { - "TraceID": "374c11217817c32b01876bb2e2aceae8", - "SpanID": "65c37661e2869798", - "TraceFlags": "01", - "TraceState": "", - "Remote": false - }, - "SpanKind": 1, - "StartTime": "0001-01-01T00:00:00Z", - "EndTime": "0001-01-01T00:00:00Z", - "Attributes": null, - "Events": null, - "Links": null, - "Status": { - "Code": "Unset", - "Description": "" - }, - "DroppedAttributes": 0, - "DroppedEvents": 0, - "DroppedLinks": 0, - "ChildSpanCount": 0, - "Resource": null, - "InstrumentationLibrary": { - "Name": "foo", - "Version": "", - "SchemaURL": "" - } -} -{ - "Name": "Fibonacci", - "SpanContext": { - "TraceID": "374c11217817c32b01876bb2e2aceae8", - "SpanID": "6676950f24fe09e2", - "TraceFlags": "01", - "TraceState": "", - "Remote": false - }, - "Parent": { - "TraceID": "374c11217817c32b01876bb2e2aceae8", - "SpanID": "65c37661e2869798", - "TraceFlags": "01", - "TraceState": "", - "Remote": false - }, - "SpanKind": 1, - "StartTime": "0001-01-01T00:00:00Z", - "EndTime": "0001-01-01T00:00:00Z", - "Attributes": null, - "Events": null, - "Links": null, - "Status": { - "Code": "Unset", - "Description": "" - }, - "DroppedAttributes": 0, - "DroppedEvents": 0, - "DroppedLinks": 0, - "ChildSpanCount": 0, - "Resource": null, - "InstrumentationLibrary": { - "Name": "Fibonacci", - "Version": "", - "SchemaURL": "" - } -} -{ - "Name": "FibonacciHelper", - "SpanContext": { - "TraceID": "374c11217817c32b01876bb2e2aceae8", - "SpanID": "65c37661e2869798", - "TraceFlags": "01", - "TraceState": "", - "Remote": false - }, - "Parent": { - "TraceID": "374c11217817c32b01876bb2e2aceae8", - "SpanID": "89a2f3b8fc474d6a", - "TraceFlags": "01", - "TraceState": "", - "Remote": false - }, - "SpanKind": 1, - "StartTime": "0001-01-01T00:00:00Z", - "EndTime": "0001-01-01T00:00:00Z", - "Attributes": null, - "Events": null, - "Links": null, - "Status": { - "Code": "Unset", - "Description": "" - }, - "DroppedAttributes": 0, - "DroppedEvents": 0, - "DroppedLinks": 0, - "ChildSpanCount": 2, - "Resource": null, - "InstrumentationLibrary": { - "Name": "FibonacciHelper", - "Version": "", - "SchemaURL": "" - } -} -{ - "Name": "main", - "SpanContext": { - "TraceID": "374c11217817c32b01876bb2e2aceae8", - "SpanID": "89a2f3b8fc474d6a", - "TraceFlags": "01", - "TraceState": "", - "Remote": false - }, - "Parent": { - "TraceID": "00000000000000000000000000000000", - "SpanID": "0000000000000000", - "TraceFlags": "00", - "TraceState": "", - "Remote": false - }, - "SpanKind": 1, - "StartTime": "0001-01-01T00:00:00Z", - "EndTime": "0001-01-01T00:00:00Z", - "Attributes": null, - "Events": null, - "Links": null, - "Status": { - "Code": "Unset", - "Description": "" - }, - "DroppedAttributes": 0, - "DroppedEvents": 0, - "DroppedLinks": 0, - "ChildSpanCount": 1, - "Resource": null, - "InstrumentationLibrary": { - "Name": "main", - "Version": "", - "SchemaURL": "" - } -} diff --git a/instrgen/driver/testdata/expected/interface/app/impl.go b/instrgen/driver/testdata/expected/interface/app/impl.go deleted file mode 100644 index 9b7bb311626..00000000000 --- a/instrgen/driver/testdata/expected/interface/app/impl.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package app - -import ( - "fmt" - __atel_context "context" - __atel_otel "go.opentelemetry.io/otel" -) - -type BasicSerializer struct { -} - -func (b BasicSerializer) Serialize(__atel_tracing_ctx __atel_context.Context,) { - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("Serialize").Start(__atel_tracing_ctx, "Serialize") - _ = __atel_child_tracing_ctx - defer __atel_span.End() - - fmt.Println("Serialize") -} diff --git a/instrgen/driver/testdata/expected/interface/main.go b/instrgen/driver/testdata/expected/interface/main.go deleted file mode 100644 index 0d33e3e08d7..00000000000 --- a/instrgen/driver/testdata/expected/interface/main.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -import ( - . "go.opentelemetry.io/contrib/instrgen/testdata/interface/app" - __atel_otel "go.opentelemetry.io/otel" - __atel_context "context" - . "go.opentelemetry.io/contrib/instrgen/testdata/interface/serializer" - "go.opentelemetry.io/contrib/instrgen/rtlib" -) - -func main() { - __atel_ts := rtlib.NewTracingState() - defer rtlib.Shutdown(__atel_ts) - __atel_otel.SetTracerProvider(__atel_ts.Tp) - __atel_ctx := __atel_context.Background() - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("main").Start(__atel_ctx, "main") - _ = __atel_child_tracing_ctx - defer __atel_span.End() - - rtlib.AutotelEntryPoint() - bs := BasicSerializer{} - var s Serializer - s = bs - s.Serialize(__atel_child_tracing_ctx) -} diff --git a/instrgen/driver/testdata/expected/interface/serializer/interface.go b/instrgen/driver/testdata/expected/interface/serializer/interface.go deleted file mode 100644 index 09f6c131b13..00000000000 --- a/instrgen/driver/testdata/expected/interface/serializer/interface.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package serializer - -import __atel_context "context" - -type Serializer interface { - Serialize(__atel_tracing_ctx __atel_context.Context,) -} diff --git a/instrgen/driver/testdata/expected/selector/main.go b/instrgen/driver/testdata/expected/selector/main.go deleted file mode 100644 index 74d8c092fd9..00000000000 --- a/instrgen/driver/testdata/expected/selector/main.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -import ( - "go.opentelemetry.io/contrib/instrgen/rtlib" - __atel_otel "go.opentelemetry.io/otel" - __atel_context "context" -) - -type Driver interface { - Foo(__atel_tracing_ctx __atel_context.Context, i int) -} - -type Impl struct { -} - -func (impl Impl) Foo(__atel_tracing_ctx __atel_context.Context, i int) { - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("Foo").Start(__atel_tracing_ctx, "Foo") - _ = __atel_child_tracing_ctx - defer __atel_span.End() -} - -func main() { - __atel_ts := rtlib.NewTracingState() - defer rtlib.Shutdown(__atel_ts) - __atel_otel.SetTracerProvider(__atel_ts.Tp) - __atel_ctx := __atel_context.Background() - __atel_child_tracing_ctx, __atel_span := __atel_otel.Tracer("main").Start(__atel_ctx, "main") - _ = __atel_child_tracing_ctx - defer __atel_span.End() - rtlib.AutotelEntryPoint() - a := []Driver{ - Impl{}, - } - var d Driver - d = Impl{} - d.Foo(__atel_child_tracing_ctx, 3) - a[0].Foo(__atel_child_tracing_ctx, 4) -} diff --git a/instrgen/driver/testdata/funwithoutpathtoroot/driver.go b/instrgen/driver/testdata/funwithoutpathtoroot/driver.go deleted file mode 100644 index e5a7515dac5..00000000000 --- a/instrgen/driver/testdata/funwithoutpathtoroot/driver.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -import ( - "go.opentelemetry.io/contrib/instrgen/rtlib" -) - -func bar() { - -} - -func foo() { - bar() -} - -func main() { - rtlib.AutotelEntryPoint() - bar() -} diff --git a/instrgen/driver/testdata/interface/app/impl.go b/instrgen/driver/testdata/interface/app/impl.go deleted file mode 100644 index 22de2cb7cde..00000000000 --- a/instrgen/driver/testdata/interface/app/impl.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package app - -import ( - "fmt" -) - -type BasicSerializer struct { -} - -func (b BasicSerializer) Serialize() { - - fmt.Println("Serialize") -} diff --git a/instrgen/driver/testdata/interface/go.mod b/instrgen/driver/testdata/interface/go.mod deleted file mode 100644 index fe72551538c..00000000000 --- a/instrgen/driver/testdata/interface/go.mod +++ /dev/null @@ -1,20 +0,0 @@ -module go.opentelemetry.io/contrib/instrgen/testdata/interface - -go 1.22.0 - -replace go.opentelemetry.io/contrib/instrgen => ../../.. - -require go.opentelemetry.io/contrib/instrgen v0.0.0-20221228173227-92e0588b124b - -require ( - github.com/go-logr/logr v1.4.2 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/google/uuid v1.6.0 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/otel v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 // indirect - go.opentelemetry.io/otel/metric v1.34.0 // indirect - go.opentelemetry.io/otel/sdk v1.34.0 // indirect - go.opentelemetry.io/otel/trace v1.34.0 // indirect - golang.org/x/sys v0.29.0 // indirect -) diff --git a/instrgen/driver/testdata/interface/go.sum b/instrgen/driver/testdata/interface/go.sum deleted file mode 100644 index a86b4405ba9..00000000000 --- a/instrgen/driver/testdata/interface/go.sum +++ /dev/null @@ -1,31 +0,0 @@ -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/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 h1:jBpDk4HAUsrnVO1FsfCfCOTEc/MkInJmvfCHYLFiT80= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0/go.mod h1:H9LUIM1daaeZaz91vZcfeM0fejXPmgCYE8ZhzqfJuiU= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= -go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/instrgen/driver/testdata/interface/main.go b/instrgen/driver/testdata/interface/main.go deleted file mode 100644 index 88bb4607957..00000000000 --- a/instrgen/driver/testdata/interface/main.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -import ( - . "go.opentelemetry.io/contrib/instrgen/testdata/interface/app" - . "go.opentelemetry.io/contrib/instrgen/testdata/interface/serializer" - "go.opentelemetry.io/contrib/instrgen/rtlib" -) - -func main() { - - rtlib.AutotelEntryPoint() - bs := BasicSerializer{} - var s Serializer - s = bs - s.Serialize() -} diff --git a/instrgen/driver/testdata/interface/serializer/interface.go b/instrgen/driver/testdata/interface/serializer/interface.go deleted file mode 100644 index d856760e1e0..00000000000 --- a/instrgen/driver/testdata/interface/serializer/interface.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package serializer - -type Serializer interface { - Serialize() -} diff --git a/instrgen/driver/testdata/selector/main.go b/instrgen/driver/testdata/selector/main.go deleted file mode 100644 index ecbb1725bca..00000000000 --- a/instrgen/driver/testdata/selector/main.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -//nolint:all // Linter is executed at the same time as tests which leads to race conditions and failures. -package main - -import ( - "go.opentelemetry.io/contrib/instrgen/rtlib" -) - -type Driver interface { - Foo(i int) -} - -type Impl struct { -} - -func (impl Impl) Foo(i int) { - -} - -func main() { - - rtlib.AutotelEntryPoint() - a := []Driver{ - Impl{}, - } - var d Driver - d = Impl{} - d.Foo(3) - a[0].Foo(4) -} diff --git a/instrgen/go.mod b/instrgen/go.mod deleted file mode 100644 index f6750a96b40..00000000000 --- a/instrgen/go.mod +++ /dev/null @@ -1,22 +0,0 @@ -module go.opentelemetry.io/contrib/instrgen - -go 1.22.0 - -require ( - go.opentelemetry.io/otel v1.34.0 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 - go.opentelemetry.io/otel/sdk v1.34.0 - golang.org/x/tools v0.29.0 -) - -require ( - github.com/go-logr/logr v1.4.2 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/google/uuid v1.6.0 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/otel/metric v1.34.0 // indirect - go.opentelemetry.io/otel/trace v1.34.0 // indirect - golang.org/x/mod v0.22.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.29.0 // indirect -) diff --git a/instrgen/go.sum b/instrgen/go.sum deleted file mode 100644 index c1fe3e3338c..00000000000 --- a/instrgen/go.sum +++ /dev/null @@ -1,37 +0,0 @@ -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/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 h1:jBpDk4HAUsrnVO1FsfCfCOTEc/MkInJmvfCHYLFiT80= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0/go.mod h1:H9LUIM1daaeZaz91vZcfeM0fejXPmgCYE8ZhzqfJuiU= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= -go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= -golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/instrgen/lib/analysis.go b/instrgen/lib/analysis.go deleted file mode 100644 index f13d9f10121..00000000000 --- a/instrgen/lib/analysis.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package lib // import "go.opentelemetry.io/contrib/instrgen/lib" - -import ( - "fmt" - "go/ast" - "go/printer" - "go/token" - "os" - - "golang.org/x/tools/go/ast/astutil" - "golang.org/x/tools/go/packages" -) - -// PackageAnalysis analyze all package set according to passed -// pattern. It requires an information about path, pattern, -// root functions - entry points, function declarations, -// and so on. -type PackageAnalysis struct { - ProjectPath string - PackagePattern string - RootFunctions []FuncDescriptor - FuncDecls map[FuncDescriptor]bool - Callgraph map[FuncDescriptor][]FuncDescriptor - Interfaces map[string]bool - Debug bool -} - -type importaction int - -const ( - // const that tells whether package should be imported. - Add importaction = iota - // or removed. - Remove -) - -// Stores an information about operations on packages. -// Currently packages can be imported with an aliases -// or without. -type Import struct { - NamedPackage string - Package string - ImportAction importaction -} - -// FileAnalysisPass executes an analysis for -// specific file node - translation unit. -type FileAnalysisPass interface { - Execute(node *ast.File, - analysis *PackageAnalysis, - pkg *packages.Package, - pkgs []*packages.Package) []Import -} - -func createFile(name string) (*os.File, error) { - var out *os.File - out, err := os.Create(name) - if err != nil { - defer out.Close() - } - return out, err -} - -func addImports(imports []Import, fset *token.FileSet, fileNode *ast.File) { - for _, imp := range imports { - if imp.ImportAction == Add { - if len(imp.NamedPackage) > 0 { - astutil.AddNamedImport(fset, fileNode, imp.NamedPackage, imp.Package) - } else { - astutil.AddImport(fset, fileNode, imp.Package) - } - } else { - if len(imp.NamedPackage) > 0 { - astutil.DeleteNamedImport(fset, fileNode, imp.NamedPackage, imp.Package) - } else { - astutil.DeleteImport(fset, fileNode, imp.Package) - } - } - } -} - -// Execute function, main entry point to analysis process. -func (analysis *PackageAnalysis) Execute(pass FileAnalysisPass, fileSuffix string) ([]*ast.File, error) { - fset := token.NewFileSet() - cfg := &packages.Config{Fset: fset, Mode: LoadMode, Dir: analysis.ProjectPath} - pkgs, err := packages.Load(cfg, analysis.PackagePattern) - if err != nil { - return nil, err - } - var fileNodeSet []*ast.File - for _, pkg := range pkgs { - fmt.Println("\t", pkg) - // fileNode represents a translationUnit - var fileNode *ast.File - for _, fileNode = range pkg.Syntax { - fmt.Println("\t\t", fset.File(fileNode.Pos()).Name()) - var out *os.File - out, err = createFile(fset.File(fileNode.Pos()).Name() + fileSuffix) - if err != nil { - return nil, err - } - if len(analysis.RootFunctions) == 0 { - e := printer.Fprint(out, fset, fileNode) - if e != nil { - return nil, e - } - continue - } - imports := pass.Execute(fileNode, analysis, pkg, pkgs) - addImports(imports, fset, fileNode) - e := printer.Fprint(out, fset, fileNode) - if e != nil { - return nil, e - } - if !analysis.Debug { - oldFileName := fset.File(fileNode.Pos()).Name() + fileSuffix - newFileName := fset.File(fileNode.Pos()).Name() - e = os.Rename(oldFileName, newFileName) - if e != nil { - return nil, e - } - } - fileNodeSet = append(fileNodeSet, fileNode) - } - } - return fileNodeSet, nil -} diff --git a/instrgen/lib/callgraph.go b/instrgen/lib/callgraph.go deleted file mode 100644 index ae273d21cb3..00000000000 --- a/instrgen/lib/callgraph.go +++ /dev/null @@ -1,385 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package lib // import "go.opentelemetry.io/contrib/instrgen/lib" - -import ( - "fmt" - "go/ast" - "go/token" - "go/types" - "strings" - - "golang.org/x/tools/go/packages" -) - -// FuncDescriptor stores an information about -// id, type and if function requires custom instrumentation. -type FuncDescriptor struct { - Id string - DeclType string - CustomInjection bool -} - -// Function TypeHash. Each function is itentified by its -// id and type. -func (fd FuncDescriptor) TypeHash() string { - return fd.Id + fd.DeclType -} - -// LoadMode. Tells about needed information during analysis. -const LoadMode packages.LoadMode = packages.NeedName | - packages.NeedTypes | - packages.NeedSyntax | - packages.NeedTypesInfo | - packages.NeedFiles - -func getPkgs(projectPath string, packagePattern string, fset *token.FileSet) ([]*packages.Package, error) { - cfg := &packages.Config{Fset: fset, Mode: LoadMode, Dir: projectPath} - pkgs, err := packages.Load(cfg, packagePattern) - var packageSet []*packages.Package - if err != nil { - return nil, err - } - for _, pkg := range pkgs { - fmt.Println("\t", pkg) - packageSet = append(packageSet, pkg) - } - return packageSet, nil -} - -// FindRootFunctions looks for all root functions eg. entry points. -// Currently an entry point is a function that contains call of function -// passed as functionLabel paramaterer. -func FindRootFunctions(projectPath string, packagePattern string, functionLabel string) []FuncDescriptor { - fset := token.NewFileSet() - pkgs, _ := getPkgs(projectPath, packagePattern, fset) - var currentFun FuncDescriptor - var rootFunctions []FuncDescriptor - for _, pkg := range pkgs { - for _, node := range pkg.Syntax { - ast.Inspect(node, func(n ast.Node) bool { - switch xNode := n.(type) { - case *ast.CallExpr: - selector, ok := xNode.Fun.(*ast.SelectorExpr) - if ok { - if selector.Sel.Name == functionLabel { - rootFunctions = append(rootFunctions, currentFun) - } - } - case *ast.FuncDecl: - if pkg.TypesInfo.Defs[xNode.Name] != nil { - funId := pkg.TypesInfo.Defs[xNode.Name].Pkg().Path() + "." + pkg.TypesInfo.Defs[xNode.Name].Name() - currentFun = FuncDescriptor{funId, pkg.TypesInfo.Defs[xNode.Name].Type().String(), false} - fmt.Println("\t\t\tFuncDecl:", funId, pkg.TypesInfo.Defs[xNode.Name].Type().String()) - } - } - return true - }) - } - } - return rootFunctions -} - -// GetMostInnerAstIdent takes most inner identifier used for -// function call. For a.b.foo(), `b` will be the most inner identifier. -func GetMostInnerAstIdent(inSel *ast.SelectorExpr) *ast.Ident { - var l []*ast.Ident - var e ast.Expr - e = inSel - for e != nil { - if _, ok := e.(*ast.Ident); ok { - l = append(l, e.(*ast.Ident)) - break - } else if _, ok := e.(*ast.SelectorExpr); ok { - l = append(l, e.(*ast.SelectorExpr).Sel) - e = e.(*ast.SelectorExpr).X - } else if _, ok := e.(*ast.CallExpr); ok { - e = e.(*ast.CallExpr).Fun - } else if _, ok := e.(*ast.IndexExpr); ok { - e = e.(*ast.IndexExpr).X - } else if _, ok := e.(*ast.UnaryExpr); ok { - e = e.(*ast.UnaryExpr).X - } else if _, ok := e.(*ast.ParenExpr); ok { - e = e.(*ast.ParenExpr).X - } else if _, ok := e.(*ast.SliceExpr); ok { - e = e.(*ast.SliceExpr).X - } else if _, ok := e.(*ast.IndexListExpr); ok { - e = e.(*ast.IndexListExpr).X - } else if _, ok := e.(*ast.StarExpr); ok { - e = e.(*ast.StarExpr).X - } else if _, ok := e.(*ast.TypeAssertExpr); ok { - e = e.(*ast.TypeAssertExpr).X - } else if _, ok := e.(*ast.CompositeLit); ok { - // TODO dummy implementation - if len(e.(*ast.CompositeLit).Elts) == 0 { - e = e.(*ast.CompositeLit).Type - } else { - e = e.(*ast.CompositeLit).Elts[0] - } - } else if _, ok := e.(*ast.KeyValueExpr); ok { - e = e.(*ast.KeyValueExpr).Value - } else { - // TODO this is uncaught expression - panic("uncaught expression") - } - } - if len(l) < 2 { - panic("selector list should have at least 2 elems") - } - // caller or receiver is always - // at position 1, function is at 0 - return l[1] -} - -// GetPkgPathFromRecvInterface builds package path taking -// receiver interface into account. -func GetPkgPathFromRecvInterface(pkg *packages.Package, - pkgs []*packages.Package, funDeclNode *ast.FuncDecl, interfaces map[string]bool, -) string { - var pkgPath string - for _, v := range funDeclNode.Recv.List { - for _, dependentpkg := range pkgs { - for _, defs := range dependentpkg.TypesInfo.Defs { - if defs == nil { - continue - } - if _, ok := defs.Type().Underlying().(*types.Interface); !ok { - continue - } - if len(v.Names) == 0 || pkg.TypesInfo.Defs[v.Names[0]] == nil { - continue - } - funType := pkg.TypesInfo.Defs[v.Names[0]].Type() - - if types.Implements(funType, defs.Type().Underlying().(*types.Interface)) { - interfaceExists := interfaces[defs.Type().String()] - if interfaceExists { - pkgPath = defs.Type().String() - } - break - } - } - } - } - return pkgPath -} - -// GetPkgPathFromFunctionRecv build package path taking function receiver parameters. -func GetPkgPathFromFunctionRecv(pkg *packages.Package, - pkgs []*packages.Package, funDeclNode *ast.FuncDecl, interfaces map[string]bool, -) string { - pkgPath := GetPkgPathFromRecvInterface(pkg, pkgs, funDeclNode, interfaces) - if len(pkgPath) != 0 { - return pkgPath - } - for _, v := range funDeclNode.Recv.List { - if len(v.Names) == 0 { - continue - } - funType := pkg.TypesInfo.Defs[v.Names[0]].Type() - pkgPath = funType.String() - // We don't care if that's pointer, remove it from - // type id - if _, ok := funType.(*types.Pointer); ok { - pkgPath = strings.TrimPrefix(pkgPath, "*") - } - // We don't care if called via index, remove it from - // type id - if _, ok := funType.(*types.Slice); ok { - pkgPath = strings.TrimPrefix(pkgPath, "[]") - } - } - - return pkgPath -} - -// GetSelectorPkgPath builds packages path according to selector expr. -func GetSelectorPkgPath(sel *ast.SelectorExpr, pkg *packages.Package, pkgPath string) string { - caller := GetMostInnerAstIdent(sel) - if caller != nil && pkg.TypesInfo.Uses[caller] != nil { - if !strings.Contains(pkg.TypesInfo.Uses[caller].Type().String(), "invalid") { - pkgPath = pkg.TypesInfo.Uses[caller].Type().String() - // We don't care if that's pointer, remove it from - // type id - if _, ok := pkg.TypesInfo.Uses[caller].Type().(*types.Pointer); ok { - pkgPath = strings.TrimPrefix(pkgPath, "*") - } - // We don't care if called via index, remove it from - // type id - if _, ok := pkg.TypesInfo.Uses[caller].Type().(*types.Slice); ok { - pkgPath = strings.TrimPrefix(pkgPath, "[]") - } - } - } - return pkgPath -} - -// GetPkgNameFromUsesTable gets package name from uses table. -func GetPkgNameFromUsesTable(pkg *packages.Package, ident *ast.Ident) string { - var pkgPath string - if pkg.TypesInfo.Uses[ident].Pkg() != nil { - pkgPath = pkg.TypesInfo.Uses[ident].Pkg().Path() - } - return pkgPath -} - -// GetPkgNameFromDefsTable gets package name from uses table. -func GetPkgNameFromDefsTable(pkg *packages.Package, ident *ast.Ident) string { - var pkgPath string - if pkg.TypesInfo.Defs[ident] == nil { - return pkgPath - } - if pkg.TypesInfo.Defs[ident].Pkg() != nil { - pkgPath = pkg.TypesInfo.Defs[ident].Pkg().Path() - } - return pkgPath -} - -// GetPkgPathForFunction builds package path, delegates work to -// other helper functions defined above. -func GetPkgPathForFunction(pkg *packages.Package, - pkgs []*packages.Package, funDecl *ast.FuncDecl, interfaces map[string]bool, -) string { - if funDecl.Recv != nil { - return GetPkgPathFromFunctionRecv(pkg, pkgs, funDecl, interfaces) - } - return GetPkgNameFromDefsTable(pkg, funDecl.Name) -} - -// BuildCallGraph builds an information about flow graph -// in the following form child->parent. -func BuildCallGraph( - projectPath string, - packagePattern string, - funcDecls map[FuncDescriptor]bool, - interfaces map[string]bool, -) map[FuncDescriptor][]FuncDescriptor { - fset := token.NewFileSet() - pkgs, _ := getPkgs(projectPath, packagePattern, fset) - fmt.Println("BuildCallGraph") - currentFun := FuncDescriptor{"nil", "", false} - backwardCallGraph := make(map[FuncDescriptor][]FuncDescriptor) - for _, pkg := range pkgs { - fmt.Println("\t", pkg) - for _, node := range pkg.Syntax { - fmt.Println("\t\t", fset.File(node.Pos()).Name()) - ast.Inspect(node, func(n ast.Node) bool { - switch xNode := n.(type) { - case *ast.CallExpr: - if id, ok := xNode.Fun.(*ast.Ident); ok { - pkgPath := GetPkgNameFromUsesTable(pkg, id) - funId := pkgPath + "." + pkg.TypesInfo.Uses[id].Name() - fmt.Println("\t\t\tFuncCall:", funId, pkg.TypesInfo.Uses[id].Type().String(), - " @called : ", - fset.File(node.Pos()).Name()) - fun := FuncDescriptor{funId, pkg.TypesInfo.Uses[id].Type().String(), false} - if !Contains(backwardCallGraph[fun], currentFun) { - if funcDecls[fun] { - backwardCallGraph[fun] = append(backwardCallGraph[fun], currentFun) - } - } - } - if sel, ok := xNode.Fun.(*ast.SelectorExpr); ok { - if pkg.TypesInfo.Uses[sel.Sel] != nil { - pkgPath := GetPkgNameFromUsesTable(pkg, sel.Sel) - if sel.X != nil { - pkgPath = GetSelectorPkgPath(sel, pkg, pkgPath) - } - funId := pkgPath + "." + pkg.TypesInfo.Uses[sel.Sel].Name() - fmt.Println("\t\t\tFuncCall via selector:", funId, pkg.TypesInfo.Uses[sel.Sel].Type().String(), - " @called : ", - fset.File(node.Pos()).Name()) - fun := FuncDescriptor{funId, pkg.TypesInfo.Uses[sel.Sel].Type().String(), false} - if !Contains(backwardCallGraph[fun], currentFun) { - if funcDecls[fun] { - backwardCallGraph[fun] = append(backwardCallGraph[fun], currentFun) - } - } - } - } - case *ast.FuncDecl: - if pkg.TypesInfo.Defs[xNode.Name] != nil { - pkgPath := GetPkgPathForFunction(pkg, pkgs, xNode, interfaces) - funId := pkgPath + "." + pkg.TypesInfo.Defs[xNode.Name].Name() - funcDecls[FuncDescriptor{funId, pkg.TypesInfo.Defs[xNode.Name].Type().String(), false}] = true - currentFun = FuncDescriptor{funId, pkg.TypesInfo.Defs[xNode.Name].Type().String(), false} - fmt.Println("\t\t\tFuncDecl:", funId, pkg.TypesInfo.Defs[xNode.Name].Type().String()) - } - } - return true - }) - } - } - return backwardCallGraph -} - -// FindFuncDecls looks for all function declarations. -func FindFuncDecls(projectPath string, packagePattern string, interfaces map[string]bool) map[FuncDescriptor]bool { - fset := token.NewFileSet() - pkgs, _ := getPkgs(projectPath, packagePattern, fset) - fmt.Println("FindFuncDecls") - funcDecls := make(map[FuncDescriptor]bool) - for _, pkg := range pkgs { - fmt.Println("\t", pkg) - for _, node := range pkg.Syntax { - fmt.Println("\t\t", fset.File(node.Pos()).Name()) - ast.Inspect(node, func(n ast.Node) bool { - if funDeclNode, ok := n.(*ast.FuncDecl); ok { - pkgPath := GetPkgPathForFunction(pkg, pkgs, funDeclNode, interfaces) - if pkg.TypesInfo.Defs[funDeclNode.Name] != nil { - funId := pkgPath + "." + pkg.TypesInfo.Defs[funDeclNode.Name].Name() - fmt.Println("\t\t\tFuncDecl:", funId, pkg.TypesInfo.Defs[funDeclNode.Name].Type().String()) - funcDecls[FuncDescriptor{funId, pkg.TypesInfo.Defs[funDeclNode.Name].Type().String(), false}] = true - } - } - return true - }) - } - } - return funcDecls -} - -// FindInterfaces looks for all interfaces. -func FindInterfaces(projectPath string, packagePattern string) map[string]bool { - fset := token.NewFileSet() - pkgs, _ := getPkgs(projectPath, packagePattern, fset) - fmt.Println("FindInterfaces") - interaceTable := make(map[string]bool) - for _, pkg := range pkgs { - fmt.Println("\t", pkg) - for _, node := range pkg.Syntax { - fmt.Println("\t\t", fset.File(node.Pos()).Name()) - ast.Inspect(node, func(n ast.Node) bool { - if typeSpecNode, ok := n.(*ast.TypeSpec); ok { - if _, ok := typeSpecNode.Type.(*ast.InterfaceType); ok { - fmt.Println("\t\t\tInterface:", pkg.TypesInfo.Defs[typeSpecNode.Name].Type().String()) - interaceTable[pkg.TypesInfo.Defs[typeSpecNode.Name].Type().String()] = true - } - } - return true - }) - } - } - return interaceTable -} - -// InferRootFunctionsFromGraph tries to infer entry points from passed call graph. -func InferRootFunctionsFromGraph(callgraph map[FuncDescriptor][]FuncDescriptor) []FuncDescriptor { - var allFunctions map[FuncDescriptor]bool - var rootFunctions []FuncDescriptor - allFunctions = make(map[FuncDescriptor]bool) - for k, v := range callgraph { - allFunctions[k] = true - for _, childFun := range v { - allFunctions[childFun] = true - } - } - for k := range allFunctions { - _, exists := callgraph[k] - if !exists { - rootFunctions = append(rootFunctions, k) - } - } - return rootFunctions -} diff --git a/instrgen/lib/context_propagation.go b/instrgen/lib/context_propagation.go deleted file mode 100644 index de4f5907be1..00000000000 --- a/instrgen/lib/context_propagation.go +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package lib // import "go.opentelemetry.io/contrib/instrgen/lib" - -import ( - "fmt" - "go/ast" - - "golang.org/x/tools/go/packages" -) - -func isFunPartOfCallGraph(fun FuncDescriptor, callgraph map[FuncDescriptor][]FuncDescriptor) bool { - // TODO this is not optimap o(n) - for k, v := range callgraph { - if k.TypeHash() == fun.TypeHash() { - return true - } - for _, e := range v { - if fun.TypeHash() == e.TypeHash() { - return true - } - } - } - return false -} - -// ContextPropagationPass. -type ContextPropagationPass struct{} - -// Execute. -func (pass *ContextPropagationPass) Execute( - node *ast.File, - analysis *PackageAnalysis, - pkg *packages.Package, - pkgs []*packages.Package, -) []Import { - var imports []Import - addImports := false - // below variable is used - // when callexpr is inside var decl - // instead of functiondecl - currentFun := FuncDescriptor{} - emitEmptyContext := func(callExpr *ast.CallExpr, ctxArg *ast.Ident) { - addImports = true - if currentFun != (FuncDescriptor{}) { - visited := map[FuncDescriptor]bool{} - if isPath(analysis.Callgraph, currentFun, analysis.RootFunctions[0], visited) { - callExpr.Args = append([]ast.Expr{ctxArg}, callExpr.Args...) - } else { - contextTodo := &ast.CallExpr{ - Fun: &ast.SelectorExpr{ - X: &ast.Ident{ - Name: "__atel_context", - }, - Sel: &ast.Ident{ - Name: "TODO", - }, - }, - Lparen: 62, - Ellipsis: 0, - } - callExpr.Args = append([]ast.Expr{contextTodo}, callExpr.Args...) - } - return - } - contextTodo := &ast.CallExpr{ - Fun: &ast.SelectorExpr{ - X: &ast.Ident{ - Name: "__atel_context", - }, - Sel: &ast.Ident{ - Name: "TODO", - }, - }, - Lparen: 62, - Ellipsis: 0, - } - callExpr.Args = append([]ast.Expr{contextTodo}, callExpr.Args...) - } - emitCallExpr := func(ident *ast.Ident, n ast.Node, ctxArg *ast.Ident, pkgPath string) { - if callExpr, ok := n.(*ast.CallExpr); ok { - funId := pkgPath + "." + pkg.TypesInfo.Uses[ident].Name() - fun := FuncDescriptor{ - Id: funId, - DeclType: pkg.TypesInfo.Uses[ident].Type().String(), - CustomInjection: false, - } - found := analysis.FuncDecls[fun] - - // inject context parameter only - // to these functions for which function decl - // exists - - if found { - visited := map[FuncDescriptor]bool{} - if isPath(analysis.Callgraph, fun, analysis.RootFunctions[0], visited) { - fmt.Println("\t\t\tContextPropagation FuncCall:", funId, pkg.TypesInfo.Uses[ident].Type().String()) - emitEmptyContext(callExpr, ctxArg) - } - } - } - } - ast.Inspect(node, func(n ast.Node) bool { - ctxArg := &ast.Ident{ - Name: "__atel_child_tracing_ctx", - } - ctxField := &ast.Field{ - Names: []*ast.Ident{ - { - Name: "__atel_tracing_ctx", - }, - }, - Type: &ast.SelectorExpr{ - X: &ast.Ident{ - Name: "__atel_context", - }, - Sel: &ast.Ident{ - Name: "Context", - }, - }, - } - switch xNode := n.(type) { - case *ast.FuncDecl: - pkgPath := GetPkgPathForFunction(pkg, pkgs, xNode, analysis.Interfaces) - funId := pkgPath + "." + pkg.TypesInfo.Defs[xNode.Name].Name() - fun := FuncDescriptor{ - Id: funId, - DeclType: pkg.TypesInfo.Defs[xNode.Name].Type().String(), - CustomInjection: false, - } - currentFun = fun - // inject context only - // functions available in the call graph - if !isFunPartOfCallGraph(fun, analysis.Callgraph) { - break - } - - if Contains(analysis.RootFunctions, fun) { - break - } - visited := map[FuncDescriptor]bool{} - - if isPath(analysis.Callgraph, fun, analysis.RootFunctions[0], visited) { - fmt.Println("\t\t\tContextPropagation FuncDecl:", funId, - pkg.TypesInfo.Defs[xNode.Name].Type().String()) - addImports = true - xNode.Type.Params.List = append([]*ast.Field{ctxField}, xNode.Type.Params.List...) - } - case *ast.CallExpr: - if ident, ok := xNode.Fun.(*ast.Ident); ok { - if pkg.TypesInfo.Uses[ident] == nil { - return false - } - pkgPath := GetPkgNameFromUsesTable(pkg, ident) - emitCallExpr(ident, n, ctxArg, pkgPath) - } - - if sel, ok := xNode.Fun.(*ast.SelectorExpr); ok { - if pkg.TypesInfo.Uses[sel.Sel] == nil { - return false - } - pkgPath := GetPkgNameFromUsesTable(pkg, sel.Sel) - if sel.X != nil { - pkgPath = GetSelectorPkgPath(sel, pkg, pkgPath) - } - emitCallExpr(sel.Sel, n, ctxArg, pkgPath) - } - - case *ast.TypeSpec: - iname := xNode.Name - iface, ok := xNode.Type.(*ast.InterfaceType) - if !ok { - return true - } - for _, method := range iface.Methods.List { - funcType, ok := method.Type.(*ast.FuncType) - if !ok { - return true - } - visited := map[FuncDescriptor]bool{} - pkgPath := GetPkgNameFromDefsTable(pkg, method.Names[0]) - funId := pkgPath + "." + iname.Name + "." + pkg.TypesInfo.Defs[method.Names[0]].Name() - fun := FuncDescriptor{ - Id: funId, - DeclType: pkg.TypesInfo.Defs[method.Names[0]].Type().String(), - CustomInjection: false, - } - if isPath(analysis.Callgraph, fun, analysis.RootFunctions[0], visited) { - fmt.Println("\t\t\tContext Propagation InterfaceType", fun.Id, fun.DeclType) - addImports = true - funcType.Params.List = append([]*ast.Field{ctxField}, funcType.Params.List...) - } - } - } - return true - }) - if addImports { - imports = append(imports, Import{"__atel_context", "context", Add}) - } - return imports -} diff --git a/instrgen/lib/instrumentation.go b/instrgen/lib/instrumentation.go deleted file mode 100644 index 7c8b1d7583c..00000000000 --- a/instrgen/lib/instrumentation.go +++ /dev/null @@ -1,370 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package lib // import "go.opentelemetry.io/contrib/instrgen/lib" - -import ( - "fmt" - "go/ast" - "go/token" - - "golang.org/x/tools/go/packages" -) - -// InstrumentationPass. -type InstrumentationPass struct{} - -func makeInitStmts(name string) []ast.Stmt { - childTracingSupress := &ast.AssignStmt{ - Lhs: []ast.Expr{ - &ast.Ident{ - Name: "_", - }, - }, - Tok: token.ASSIGN, - Rhs: []ast.Expr{ - &ast.Ident{ - Name: "__atel_child_tracing_ctx", - }, - }, - } - s1 := &ast.AssignStmt{ - Lhs: []ast.Expr{ - &ast.Ident{ - Name: "__atel_ts", - }, - }, - Tok: token.DEFINE, - - Rhs: []ast.Expr{ - &ast.CallExpr{ - Fun: &ast.SelectorExpr{ - X: &ast.Ident{ - Name: "rtlib", - }, - Sel: &ast.Ident{ - Name: "NewTracingState", - }, - }, - Lparen: 54, - Ellipsis: 0, - }, - }, - } - s2 := &ast.DeferStmt{ - Defer: 27, - Call: &ast.CallExpr{ - Fun: &ast.SelectorExpr{ - X: &ast.Ident{ - Name: "rtlib", - }, - Sel: &ast.Ident{ - Name: "Shutdown", - }, - }, - Lparen: 48, - Args: []ast.Expr{ - &ast.Ident{ - Name: "__atel_ts", - }, - }, - Ellipsis: 0, - }, - } - - s3 := &ast.ExprStmt{ - X: &ast.CallExpr{ - Fun: &ast.SelectorExpr{ - X: &ast.Ident{ - Name: "__atel_otel", - }, - Sel: &ast.Ident{ - Name: "SetTracerProvider", - }, - }, - Lparen: 49, - Args: []ast.Expr{ - &ast.SelectorExpr{ - X: &ast.Ident{ - Name: "__atel_ts", - }, - Sel: &ast.Ident{ - Name: "Tp", - }, - }, - }, - Ellipsis: 0, - }, - } - s4 := &ast.AssignStmt{ - Lhs: []ast.Expr{ - &ast.Ident{ - Name: "__atel_ctx", - }, - }, - Tok: token.DEFINE, - Rhs: []ast.Expr{ - &ast.CallExpr{ - Fun: &ast.SelectorExpr{ - X: &ast.Ident{ - Name: "__atel_context", - }, - Sel: &ast.Ident{ - Name: "Background", - }, - }, - Lparen: 52, - Ellipsis: 0, - }, - }, - } - s5 := &ast.AssignStmt{ - Lhs: []ast.Expr{ - &ast.Ident{ - Name: "__atel_child_tracing_ctx", - }, - &ast.Ident{ - Name: "__atel_span", - }, - }, - Tok: token.DEFINE, - Rhs: []ast.Expr{ - &ast.CallExpr{ - Fun: &ast.SelectorExpr{ - X: &ast.CallExpr{ - Fun: &ast.SelectorExpr{ - X: &ast.Ident{ - Name: "__atel_otel", - }, - Sel: &ast.Ident{ - Name: "Tracer", - }, - }, - Lparen: 50, - Args: []ast.Expr{ - &ast.Ident{ - Name: `"` + name + `"`, - }, - }, - Ellipsis: 0, - }, - Sel: &ast.Ident{ - Name: "Start", - }, - }, - Lparen: 62, - Args: []ast.Expr{ - &ast.Ident{ - Name: "__atel_ctx", - }, - &ast.Ident{ - Name: `"` + name + `"`, - }, - }, - Ellipsis: 0, - }, - }, - } - - s6 := &ast.DeferStmt{ - Defer: 27, - Call: &ast.CallExpr{ - Fun: &ast.SelectorExpr{ - X: &ast.Ident{ - Name: "__atel_span", - }, - Sel: &ast.Ident{ - Name: "End", - }, - }, - Lparen: 41, - Ellipsis: 0, - }, - } - stmts := []ast.Stmt{s1, s2, s3, s4, s5, childTracingSupress, s6} - return stmts -} - -func makeSpanStmts(name string, paramName string) []ast.Stmt { - s1 := &ast.AssignStmt{ - Lhs: []ast.Expr{ - &ast.Ident{ - Name: "__atel_child_tracing_ctx", - }, - &ast.Ident{ - Name: "__atel_span", - }, - }, - Tok: token.DEFINE, - Rhs: []ast.Expr{ - &ast.CallExpr{ - Fun: &ast.SelectorExpr{ - X: &ast.CallExpr{ - Fun: &ast.SelectorExpr{ - X: &ast.Ident{ - Name: "__atel_otel", - }, - Sel: &ast.Ident{ - Name: "Tracer", - }, - }, - Lparen: 50, - Args: []ast.Expr{ - &ast.Ident{ - Name: `"` + name + `"`, - }, - }, - Ellipsis: 0, - }, - Sel: &ast.Ident{ - Name: "Start", - }, - }, - Lparen: 62, - Args: []ast.Expr{ - &ast.Ident{ - Name: paramName, - }, - &ast.Ident{ - Name: `"` + name + `"`, - }, - }, - Ellipsis: 0, - }, - }, - } - - s2 := &ast.AssignStmt{ - Lhs: []ast.Expr{ - &ast.Ident{ - Name: "_", - }, - }, - Tok: token.ASSIGN, - Rhs: []ast.Expr{ - &ast.Ident{ - Name: "__atel_child_tracing_ctx", - }, - }, - } - - s3 := &ast.DeferStmt{ - Defer: 27, - Call: &ast.CallExpr{ - Fun: &ast.SelectorExpr{ - X: &ast.Ident{ - Name: "__atel_span", - }, - Sel: &ast.Ident{ - Name: "End", - }, - }, - Lparen: 41, - Ellipsis: 0, - }, - } - stmts := []ast.Stmt{s1, s2, s3} - return stmts -} - -// Execute. -func (pass *InstrumentationPass) Execute( - node *ast.File, - analysis *PackageAnalysis, - pkg *packages.Package, - pkgs []*packages.Package, -) []Import { - var imports []Import - addImports := false - addContext := false - // store all function literals positions - // that are part of assignment statement - // it's used to avoid injection into literal - // more than once - var functionLiteralPositions []token.Pos - ast.Inspect(node, func(n ast.Node) bool { - switch x := n.(type) { - case *ast.FuncDecl: - pkgPath := GetPkgPathForFunction(pkg, pkgs, x, analysis.Interfaces) - fundId := pkgPath + "." + pkg.TypesInfo.Defs[x.Name].Name() - fun := FuncDescriptor{ - Id: fundId, - DeclType: pkg.TypesInfo.Defs[x.Name].Type().String(), - CustomInjection: false, - } - // check if it's root function or - // one of function in call graph - // and emit proper ast nodes - _, exists := analysis.Callgraph[fun] - if !exists { - if !Contains(analysis.RootFunctions, fun) { - return false - } - } - for _, root := range analysis.RootFunctions { - visited := map[FuncDescriptor]bool{} - fmt.Println("\t\t\tInstrumentation FuncDecl:", fundId, pkg.TypesInfo.Defs[x.Name].Type().String()) - if isPath(analysis.Callgraph, fun, root, visited) && fun.TypeHash() != root.TypeHash() { - x.Body.List = append(makeSpanStmts(x.Name.Name, "__atel_tracing_ctx"), x.Body.List...) - addContext = true - addImports = true - } else { - // check whether this function is root function - if !Contains(analysis.RootFunctions, fun) { - return false - } - x.Body.List = append(makeInitStmts(x.Name.Name), x.Body.List...) - addContext = true - addImports = true - } - } - case *ast.AssignStmt: - for _, e := range x.Lhs { - if ident, ok := e.(*ast.Ident); ok { - _ = ident - pkgPath := "" - pkgPath = GetPkgNameFromDefsTable(pkg, ident) - if pkg.TypesInfo.Defs[ident] == nil { - return false - } - fundId := pkgPath + "." + pkg.TypesInfo.Defs[ident].Name() - fun := FuncDescriptor{ - Id: fundId, - DeclType: pkg.TypesInfo.Defs[ident].Type().String(), - CustomInjection: true, - } - _, exists := analysis.Callgraph[fun] - if exists { - return false - } - } - } - for _, e := range x.Rhs { - if funLit, ok := e.(*ast.FuncLit); ok { - functionLiteralPositions = append(functionLiteralPositions, funLit.Pos()) - funLit.Body.List = append(makeSpanStmts("anonymous", "__atel_child_tracing_ctx"), funLit.Body.List...) - addImports = true - addContext = true - } - } - case *ast.FuncLit: - for _, pos := range functionLiteralPositions { - if pos == x.Pos() { - return false - } - } - x.Body.List = append(makeSpanStmts("anonymous", "__atel_child_tracing_ctx"), x.Body.List...) - addImports = true - addContext = true - } - - return true - }) - if addContext { - imports = append(imports, Import{"__atel_context", "context", Add}) - } - if addImports { - imports = append(imports, Import{"__atel_otel", "go.opentelemetry.io/otel", Add}) - } - return imports -} diff --git a/instrgen/lib/otel_pruning.go b/instrgen/lib/otel_pruning.go deleted file mode 100644 index 6e2ce3e71ec..00000000000 --- a/instrgen/lib/otel_pruning.go +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package lib // import "go.opentelemetry.io/contrib/instrgen/lib" - -import ( - "go/ast" - "strings" - - "golang.org/x/tools/go/packages" -) - -func removeStmt(slice []ast.Stmt, s int) []ast.Stmt { - return append(slice[:s], slice[s+1:]...) -} - -func removeField(slice []*ast.Field, s int) []*ast.Field { - return append(slice[:s], slice[s+1:]...) -} - -func removeExpr(slice []ast.Expr, s int) []ast.Expr { - return append(slice[:s], slice[s+1:]...) -} - -// OtelPruner. -type OtelPruner struct{} - -func inspectFuncContent(fType *ast.FuncType, fBody *ast.BlockStmt) { - for index := 0; index < len(fType.Params.List); index++ { - param := fType.Params.List[index] - for _, ident := range param.Names { - if strings.Contains(ident.Name, "__atel_") { - fType.Params.List = removeField(fType.Params.List, index) - index-- - } - } - } - for index := 0; index < len(fBody.List); index++ { - stmt := fBody.List[index] - switch bodyStmt := stmt.(type) { - case *ast.AssignStmt: - if ident, ok := bodyStmt.Lhs[0].(*ast.Ident); ok { - if strings.Contains(ident.Name, "__atel_") { - fBody.List = removeStmt(fBody.List, index) - index-- - } - } - if ident, ok := bodyStmt.Rhs[0].(*ast.Ident); ok { - if strings.Contains(ident.Name, "__atel_") { - fBody.List = removeStmt(fBody.List, index) - index-- - } - } - case *ast.ExprStmt: - if call, ok := bodyStmt.X.(*ast.CallExpr); ok { - if sel, ok := call.Fun.(*ast.SelectorExpr); ok { - if strings.Contains(sel.Sel.Name, "SetTracerProvider") { - fBody.List = removeStmt(fBody.List, index) - index-- - } - } - } - case *ast.DeferStmt: - if sel, ok := bodyStmt.Call.Fun.(*ast.SelectorExpr); ok { - if strings.Contains(sel.Sel.Name, "Shutdown") { - if ident, ok := sel.X.(*ast.Ident); ok { - if strings.Contains(ident.Name, "rtlib") { - fBody.List = removeStmt(fBody.List, index) - index-- - } - } - } - if ident, ok := sel.X.(*ast.Ident); ok { - if strings.Contains(ident.Name, "__atel_") { - fBody.List = removeStmt(fBody.List, index) - index-- - } - } - } - } - } -} - -// Execute. -func (pass *OtelPruner) Execute( - node *ast.File, - analysis *PackageAnalysis, - pkg *packages.Package, - pkgs []*packages.Package, -) []Import { - var imports []Import - ast.Inspect(node, func(n ast.Node) bool { - switch x := n.(type) { - case *ast.FuncDecl: - inspectFuncContent(x.Type, x.Body) - case *ast.CallExpr: - for argIndex := 0; argIndex < len(x.Args); argIndex++ { - if ident, ok := x.Args[argIndex].(*ast.Ident); ok { - if strings.Contains(ident.Name, "__atel_") { - x.Args = removeExpr(x.Args, argIndex) - argIndex-- - } - } - } - for argIndex := 0; argIndex < len(x.Args); argIndex++ { - if c, ok := x.Args[argIndex].(*ast.CallExpr); ok { - if sel, ok := c.Fun.(*ast.SelectorExpr); ok { - if ident, ok := sel.X.(*ast.Ident); ok { - if strings.Contains(ident.Name, "__atel_") { - x.Args = removeExpr(x.Args, argIndex) - argIndex-- - } - } - } - } - } - case *ast.FuncLit: - inspectFuncContent(x.Type, x.Body) - case *ast.TypeSpec: - iface, ok := x.Type.(*ast.InterfaceType) - if !ok { - return true - } - for _, method := range iface.Methods.List { - funcType, ok := method.Type.(*ast.FuncType) - if !ok { - continue - } - for argIndex := 0; argIndex < len(funcType.Params.List); argIndex++ { - for _, ident := range funcType.Params.List[argIndex].Names { - if strings.Contains(ident.Name, "__atel_") { - funcType.Params.List = removeField(funcType.Params.List, argIndex) - argIndex-- - } - } - } - } - } - return true - }) - imports = append(imports, Import{"__atel_context", "context", Remove}) - imports = append(imports, Import{"__atel_otel", "go.opentelemetry.io/otel", Remove}) - imports = append(imports, Import{"__atel_otelhttp", "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp", Remove}) - - return imports -} diff --git a/instrgen/lib/tools.go b/instrgen/lib/tools.go deleted file mode 100644 index 1473a11ddc5..00000000000 --- a/instrgen/lib/tools.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package lib // import "go.opentelemetry.io/contrib/instrgen/lib" - -import ( - "os" - "path/filepath" -) - -// SearchFiles. -func SearchFiles(root string, ext string) []string { - var files []string - err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { - if filepath.Ext(path) == ext { - files = append(files, path) - } - return nil - }) - if err != nil { - panic(err) - } - return files -} - -func isPath( - callGraph map[FuncDescriptor][]FuncDescriptor, - current FuncDescriptor, - goal FuncDescriptor, - visited map[FuncDescriptor]bool, -) bool { - if current == goal { - return true - } - - value, ok := callGraph[current] - if ok { - for _, child := range value { - exists := visited[child] - if exists { - continue - } - visited[child] = true - if isPath(callGraph, child, goal, visited) { - return true - } - } - } - return false -} - -// Contains. -func Contains(a []FuncDescriptor, x FuncDescriptor) bool { - for _, n := range a { - if x.TypeHash() == n.TypeHash() { - return true - } - } - return false -} diff --git a/instrgen/rtlib/rtlib.go b/instrgen/rtlib/rtlib.go deleted file mode 100644 index bec1d0df5bb..00000000000 --- a/instrgen/rtlib/rtlib.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Basic runtime library - -package rtlib // import "go.opentelemetry.io/contrib/instrgen/rtlib" - -import ( - "context" - "io" - "log" - "os" - - "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" - "go.opentelemetry.io/otel/sdk/resource" - trace "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.4.0" -) - -// TracingState type. -type TracingState struct { - Logger *log.Logger - File *os.File - Tp *trace.TracerProvider -} - -// NewTracingState. -func NewTracingState() TracingState { - var tracingState TracingState - tracingState.Logger = log.New(os.Stdout, "", 0) - - // Write telemetry data to a file. - var err error - tracingState.File, err = os.Create("traces.txt") - if err != nil { - tracingState.Logger.Fatal(err) - } - var exp trace.SpanExporter - exp, err = NewExporter(tracingState.File) - if err != nil { - tracingState.Logger.Fatal(err) - } - tracingState.Tp = trace.NewTracerProvider( - trace.WithBatcher(exp), - trace.WithResource(NewResource()), - ) - return tracingState -} - -// NewExporter returns a console exporter. -func NewExporter(w io.Writer) (trace.SpanExporter, error) { - return stdouttrace.New( - stdouttrace.WithWriter(w), - // Use human readable output. - stdouttrace.WithPrettyPrint(), - // Do not print timestamps for the demo. - stdouttrace.WithoutTimestamps(), - ) -} - -// NewResource returns a resource describing this application. -func NewResource() *resource.Resource { - r, _ := resource.Merge( - resource.Default(), - resource.NewWithAttributes( - semconv.SchemaURL, - ), - ) - return r -} - -// Shutdown. -func Shutdown(ts TracingState) { - if err := ts.Tp.Shutdown(context.Background()); err != nil { - ts.Logger.Fatal(err) - } -} - -// AutoEntryPoint. -func AutotelEntryPoint() { -} diff --git a/renovate.json b/renovate.json index c10c4687fdd..f5054c3e2e9 100644 --- a/renovate.json +++ b/renovate.json @@ -4,7 +4,6 @@ "config:recommended" ], "ignorePaths": [], - "ignoreDeps": [ "go.opentelemetry.io/contrib/instrgen" ], "labels": ["Skip Changelog", "dependencies"], "separateMajorMinor": true, "postUpdateOptions" : [ diff --git a/versions.yaml b/versions.yaml index 2a406783801..1b5981bc110 100644 --- a/versions.yaml +++ b/versions.yaml @@ -94,6 +94,3 @@ excluded-modules: - go.opentelemetry.io/contrib/examples/passthrough - go.opentelemetry.io/contrib/examples/prometheus - go.opentelemetry.io/contrib/examples/zipkin - - go.opentelemetry.io/contrib/instrgen - - go.opentelemetry.io/contrib/instrgen/driver - - go.opentelemetry.io/contrib/instrgen/testdata/interface