Remove the instrgen module (#6671)

Co-authored-by: Robert Pająk <pellared@hotmail.com>
This commit is contained in:
Tyler Yahn 2025-01-23 14:41:18 -08:00 committed by GitHub
parent 0746da0ac7
commit 7d7606c652
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
48 changed files with 2 additions and 2696 deletions

View File

@ -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.

View File

@ -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.

2
.gitignore vendored
View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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/

View File

@ -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"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

View File

@ -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)

View File

@ -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
)

View File

@ -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=

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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()
}

View File

@ -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)
}

View File

@ -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 {
}
}

View File

@ -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() {
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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 {
}
}

View File

@ -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": ""
}
}

View File

@ -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")
}

View File

@ -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)
}

View File

@ -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,)
}

View File

@ -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)
}

View File

@ -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()
}

View File

@ -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")
}

View File

@ -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
)

View File

@ -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=

View File

@ -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()
}

View File

@ -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()
}

View File

@ -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)
}

View File

@ -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
)

View File

@ -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=

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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() {
}

View File

@ -4,7 +4,6 @@
"config:recommended"
],
"ignorePaths": [],
"ignoreDeps": [ "go.opentelemetry.io/contrib/instrgen" ],
"labels": ["Skip Changelog", "dependencies"],
"separateMajorMinor": true,
"postUpdateOptions" : [

View File

@ -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