Skip to content

Commit

Permalink
Add instrgen implementation (#3108)
Browse files Browse the repository at this point in the history
* Add instrgen implementation

* check whether projectPath is directory

* use switch instead of if statement

* remove some attributes

* adding usage to readme

* update CHANGELOG.md

---------

Co-authored-by: Przemek Delewski <pdelewski@users.noreply.github.com>
  • Loading branch information
pdelewski and pdelewski committed Mar 24, 2023
1 parent 81f1a7e commit e65f090
Show file tree
Hide file tree
Showing 40 changed files with 2,921 additions and 1 deletion.
18 changes: 18 additions & 0 deletions .github/dependabot.yml
Expand Up @@ -199,6 +199,24 @@ updates:
schedule:
interval: weekly
day: sunday
- package-ecosystem: gomod
directory: /instrgen/driver
labels:
- dependencies
- go
- Skip Changelog
schedule:
interval: weekly
day: sunday
- package-ecosystem: gomod
directory: /instrgen/driver/testdata/interface
labels:
- dependencies
- go
- Skip Changelog
schedule:
interval: weekly
day: sunday
- package-ecosystem: gomod
directory: /instrumentation/github.com/Shopify/sarama/otelsarama
labels:
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -10,7 +10,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

### Added

- Add the new `go.opentelemetry.io/contrib/instrgen` package to provide auto-generated source code instrumentation. (#3068)
- Add the new `go.opentelemetry.io/contrib/instrgen` package to provide auto-generated source code instrumentation. (#3068, #3108)

## [1.16.0-rc.2/0.41.0-rc.2/0.10.0-rc.2] - 2023-03-23

Expand Down
26 changes: 26 additions & 0 deletions instrgen/README.md
Expand Up @@ -6,6 +6,32 @@ This package provides a code generation utility that instruments existing source

: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.
Expand Down
19 changes: 19 additions & 0 deletions instrgen/driver/go.mod
@@ -0,0 +1,19 @@
module go.opentelemetry.io/contrib/instrgen/instrgen

go 1.19

replace go.opentelemetry.io/contrib/instrgen => ../

require (
github.com/stretchr/testify v1.8.1
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.7.0 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/tools v0.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
24 changes: 24 additions & 0 deletions instrgen/driver/go.sum
@@ -0,0 +1,24 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
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.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
118 changes: 118 additions & 0 deletions instrgen/driver/instrgen_test.go
@@ -0,0 +1,118 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build !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 Test(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)) {
fmt.Println(k)
failures = append(failures, k)
}
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)
}
}

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.Equal(t, len(cg), 0, "callgraph should contain 0 elems")
rf := makeRootFunctions("./testdata/dummy", "./...")
dumpRootFunctions(rf)
assert.Equal(t, len(rf), 0, "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 TestUnknown(t *testing.T) {
err := executeCommand("unknown", "a", "b")
require.Error(t, err)
}

0 comments on commit e65f090

Please sign in to comment.