Repository: open-telemetry/opentelemetry-go-contrib
Pull request #3108 (2022-12-19 14:24:00)

Add instrgen implementation

codecov[bot]: # [Codecov](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) Report
> Merging [#3108](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (1844910) into [main](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/commit/54f0bc5c0fd347cd6db9b7bc14c9f0c00dfcb36b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (54f0bc5) will **increase** coverage by `0.0%`.
> The diff coverage is `n/a`.

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/graphs/tree.svg?width=650&height=150&src=pr&token=P6F3W9WA7Q&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)

```diff
@@          Coverage Diff          @@
##            main   #3108   +/-   ##
=====================================
  Coverage   69.0%   69.1%           
=====================================
  Files        147     147           
  Lines       6884    6884           
=====================================
+ Hits        4754    4757    +3     
+ Misses      2011    2009    -2     
+ Partials     119     118    -1     
```


| [Impacted Files](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) | Coverage Δ | |
|---|---|---|
| [...ion/google.golang.org/grpc/otelgrpc/interceptor.go](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-aW5zdHJ1bWVudGF0aW9uL2dvb2dsZS5nb2xhbmcub3JnL2dycGMvb3RlbGdycGMvaW50ZXJjZXB0b3IuZ28=) | `83.9% <0.0%> (+0.9%)` | :arrow_up: |

</details>
codecov[bot]: # [Codecov](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) Report
> Merging [#3108](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (c6a2fc8) into [main](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/commit/54f0bc5c0fd347cd6db9b7bc14c9f0c00dfcb36b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (54f0bc5) will **increase** coverage by `0.0%`.
> The diff coverage is `n/a`.

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/graphs/tree.svg?width=650&height=150&src=pr&token=P6F3W9WA7Q&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)

```diff
@@          Coverage Diff          @@
##            main   #3108   +/-   ##
=====================================
  Coverage   69.0%   69.1%           
=====================================
  Files        147     147           
  Lines       6884    6884           
=====================================
+ Hits        4754    4757    +3     
+ Misses      2011    2009    -2     
+ Partials     119     118    -1     
```


| [Impacted Files](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) | Coverage Δ | |
|---|---|---|
| [...ion/google.golang.org/grpc/otelgrpc/interceptor.go](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-aW5zdHJ1bWVudGF0aW9uL2dvb2dsZS5nb2xhbmcub3JnL2dycGMvb3RlbGdycGMvaW50ZXJjZXB0b3IuZ28=) | `83.9% <0.0%> (+0.9%)` | :arrow_up: |

</details>
codecov[bot]: # [Codecov](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) Report
> Merging [#3108](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (a764782) into [main](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/commit/92e0588b124b2b8208a753333855544759bf049d?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (92e0588) will **decrease** coverage by `0.0%`.
> The diff coverage is `n/a`.

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/graphs/tree.svg?width=650&height=150&src=pr&token=P6F3W9WA7Q&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)

```diff
@@           Coverage Diff           @@
##            main   #3108     +/-   ##
=======================================
- Coverage   69.1%   69.0%   -0.1%     
=======================================
  Files        147     147             
  Lines       6884    6884             
=======================================
- Hits        4757    4754      -3     
- Misses      2009    2011      +2     
- Partials     118     119      +1     
```


| [Impacted Files](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) | Coverage Δ | |
|---|---|---|
| [...ion/google.golang.org/grpc/otelgrpc/interceptor.go](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-aW5zdHJ1bWVudGF0aW9uL2dvb2dsZS5nb2xhbmcub3JnL2dycGMvb3RlbGdycGMvaW50ZXJjZXB0b3IuZ28=) | `83.0% <0.0%> (-1.0%)` | :arrow_down: |

</details>
codecov[bot]: # [Codecov](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) Report
> Merging [#3108](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (491af78) into [main](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/commit/92e0588b124b2b8208a753333855544759bf049d?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (92e0588) will **increase** coverage by `0.0%`.
> The diff coverage is `71.4%`.

> :exclamation: Current head 491af78 differs from pull request most recent head 9f34cf9. Consider uploading reports for the commit 9f34cf9 to get more accurate results

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/graphs/tree.svg?width=650&height=150&src=pr&token=P6F3W9WA7Q&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)

```diff
@@          Coverage Diff           @@
##            main   #3108    +/-   ##
======================================
  Coverage   69.1%   69.1%            
======================================
  Files        147     149     +2     
  Lines       6884    7017   +133     
======================================
+ Hits        4757    4852    +95     
- Misses      2009    2038    +29     
- Partials     118     127     +9     
```


| [Impacted Files](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) | Coverage Δ | |
|---|---|---|
| [instrgen/driver/passes.go](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-aW5zdHJnZW4vZHJpdmVyL3Bhc3Nlcy5nbw==) | `66.6% <66.6%> (ø)` | |
| [instrgen/driver/main.go](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-aW5zdHJnZW4vZHJpdmVyL21haW4uZ28=) | `72.1% <72.1%> (ø)` | |

</details>
codecov[bot]: # [Codecov](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) Report
> Merging [#3108](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (6acc3b4) into [main](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/commit/92e0588b124b2b8208a753333855544759bf049d?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (92e0588) will **decrease** coverage by `0.0%`.
> The diff coverage is `n/a`.

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/graphs/tree.svg?width=650&height=150&src=pr&token=P6F3W9WA7Q&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)

```diff
@@           Coverage Diff           @@
##            main   #3108     +/-   ##
=======================================
- Coverage   69.1%   69.0%   -0.1%     
=======================================
  Files        147     147             
  Lines       6884    6884             
=======================================
- Hits        4757    4754      -3     
- Misses      2009    2011      +2     
- Partials     118     119      +1     
```


| [Impacted Files](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) | Coverage Δ | |
|---|---|---|
| [...ion/google.golang.org/grpc/otelgrpc/interceptor.go](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-aW5zdHJ1bWVudGF0aW9uL2dvb2dsZS5nb2xhbmcub3JnL2dycGMvb3RlbGdycGMvaW50ZXJjZXB0b3IuZ28=) | `83.0% <0.0%> (-1.0%)` | :arrow_down: |

</details>
codecov[bot]: # [Codecov](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) Report
> Merging [#3108](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (09d562b) into [main](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/commit/537f38a110f0437a68eaa021c88e47c68f2ed211?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (537f38a) will **decrease** coverage by `0.0%`.
> The diff coverage is `n/a`.

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/graphs/tree.svg?width=650&height=150&src=pr&token=P6F3W9WA7Q&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)

```diff
@@           Coverage Diff           @@
##            main   #3108     +/-   ##
=======================================
- Coverage   69.2%   69.2%   -0.1%     
=======================================
  Files        147     147             
  Lines       6884    6884             
=======================================
- Hits        4768    4765      -3     
- Misses      2000    2002      +2     
- Partials     116     117      +1     
```


| [Impacted Files](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) | Coverage Δ | |
|---|---|---|
| [...ion/google.golang.org/grpc/otelgrpc/interceptor.go](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-aW5zdHJ1bWVudGF0aW9uL2dvb2dsZS5nb2xhbmcub3JnL2dycGMvb3RlbGdycGMvaW50ZXJjZXB0b3IuZ28=) | `83.0% <0.0%> (-1.0%)` | :arrow_down: |

</details>
pdelewski: > Can you please add how to run this instrument ? And please trim printlns.
> 
> When i run in macos or linux am getting this error ( go version go1.19.5 darwin/arm64 )
> 
> ```
>` ./instrgen --inject ./testdata/basic/fib.go ./  `                                                                                                                                                                                                                                                                                                                                                                                                                                 ─╯
> autotel compiler
> FindInterfaces
> FindFuncDecls
> BuildCallGraph
> 
>         child parent
> 
> 2023/02/05 07:29:29 err: fork/exec /opt/homebrew/bin/go: not a directory: stderr:
> ```

@dineshg13 works on packages so second parameter must be path not file, so in this case ` ./instrgen --inject ./testdata/basic/ ./  ` will work, however it will inject into all files in this directory. I grouped few simple programs under one sub-directory due to test execution speedup
codecov[bot]: # [Codecov](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) Report
> Merging [#3108](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (c3f00ca) into [main](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/commit/e31186a9c26cf4b70b4598b225508af76d25b6c4?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (e31186a) will **decrease** coverage by `0.2%`.
> The diff coverage is `n/a`.

> :exclamation: Current head c3f00ca differs from pull request most recent head 21c7ac9. Consider uploading reports for the commit 21c7ac9 to get more accurate results

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/graphs/tree.svg?width=650&height=150&src=pr&token=P6F3W9WA7Q&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)

```diff
@@           Coverage Diff           @@
##            main   #3108     +/-   ##
=======================================
- Coverage   69.6%   69.5%   -0.2%     
=======================================
  Files        147     147             
  Lines       6910    6890     -20     
=======================================
- Hits        4812    4789     -23     
- Misses      1978    1980      +2     
- Partials     120     121      +1     
```


| [Impacted Files](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) | Coverage Δ | |
|---|---|---|
| [samplers/jaegerremote/sampler\_remote.go](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-c2FtcGxlcnMvamFlZ2VycmVtb3RlL3NhbXBsZXJfcmVtb3RlLmdv) | `87.4% <0.0%> (-2.3%)` | :arrow_down: |
| [...om/aws/aws-sdk-go-v2/otelaws/dynamodbattributes.go](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-aW5zdHJ1bWVudGF0aW9uL2dpdGh1Yi5jb20vYXdzL2F3cy1zZGstZ28tdjIvb3RlbGF3cy9keW5hbW9kYmF0dHJpYnV0ZXMuZ28=) | `100.0% <0.0%> (ø)` | |

</details>
MrAlias: SIG meeting: plan is to add a readme to this.
codecov[bot]: # [Codecov](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) Report
> Merging [#3108](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (21c7ac9) into [main](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/commit/284c610a61120835f5789a9551273a370abddf87?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (284c610) will **decrease** coverage by `0.4%`.
> The diff coverage is `n/a`.

> :exclamation: Current head 21c7ac9 differs from pull request most recent head 3b18a67. Consider uploading reports for the commit 3b18a67 to get more accurate results

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/graphs/tree.svg?width=650&height=150&src=pr&token=P6F3W9WA7Q&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)

```diff
@@           Coverage Diff           @@
##            main   #3108     +/-   ##
=======================================
- Coverage   69.9%   69.6%   -0.4%     
=======================================
  Files        147     147             
  Lines       6934    6910     -24     
=======================================
- Hits        4851    4812     -39     
- Misses      1959    1978     +19     
+ Partials     124     120      -4     
```


| [Impacted Files](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) | Coverage Δ | |
|---|---|---|
| [detectors/aws/ecs/ecs.go](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-ZGV0ZWN0b3JzL2F3cy9lY3MvZWNzLmdv) | `18.0% <0.0%> (-21.7%)` | :arrow_down: |
| [...ation/github.com/gin-gonic/gin/otelgin/gintrace.go](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-aW5zdHJ1bWVudGF0aW9uL2dpdGh1Yi5jb20vZ2luLWdvbmljL2dpbi9vdGVsZ2luL2dpbnRyYWNlLmdv) | `82.5% <0.0%> (-1.0%)` | :arrow_down: |
| [...ntation/github.com/gin-gonic/gin/otelgin/option.go](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-aW5zdHJ1bWVudGF0aW9uL2dpdGh1Yi5jb20vZ2luLWdvbmljL2dpbi9vdGVsZ2luL29wdGlvbi5nbw==) | `100.0% <0.0%> (ø)` | |

</details>
codecov[bot]: ## [Codecov](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) Report
> Merging [#3108](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (4bd3b5d) into [main](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/commit/83b942ad88a86e3a3d0c92579122597854d2f2ff?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (83b942a) will **decrease** coverage by `0.1%`.
> The diff coverage is `n/a`.

> :exclamation: Current head 4bd3b5d differs from pull request most recent head 4a77b50. Consider uploading reports for the commit 4a77b50 to get more accurate results

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/graphs/tree.svg?width=650&height=150&src=pr&token=P6F3W9WA7Q&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)

```diff
@@           Coverage Diff           @@
##            main   #3108     +/-   ##
=======================================
- Coverage   70.0%   69.9%   -0.1%     
=======================================
  Files        147     147             
  Lines       6956    6934     -22     
=======================================
- Hits        4870    4851     -19     
+ Misses      1961    1959      -2     
+ Partials     125     124      -1     
```


[see 11 files with indirect coverage changes](https://codecov.io/gh/open-telemetry/opentelemetry-go-contrib/pull/3108/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)

</details>
pdelewski: @MrAlias Seems that we can merge it.
MrAlias: Merging as this has 2 reviews from the @open-telemetry/go-instrumentation-approvers group.

Patch:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index d69473429..6129c4d06 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -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:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2d257a493..0e7903315 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
 
diff --git a/instrgen/README.md b/instrgen/README.md
index c60f0d25e..0afe79cea 100644
--- a/instrgen/README.md
+++ b/instrgen/README.md
@@ -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.
diff --git a/instrgen/driver/go.mod b/instrgen/driver/go.mod
new file mode 100644
index 000000000..c796007c1
--- /dev/null
+++ b/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
+)
diff --git a/instrgen/driver/go.sum b/instrgen/driver/go.sum
new file mode 100644
index 000000000..bf8140031
--- /dev/null
+++ b/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=
diff --git a/instrgen/driver/main.go b/instrgen/driver/main.go
new file mode 100644
index 000000000..0f5b4ddf9
--- /dev/null
+++ b/instrgen/driver/main.go
@@ -0,0 +1,183 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"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
new file mode 100644
index 000000000..6c3f81f2b
--- /dev/null
+++ b/instrgen/driver/passes.go
@@ -0,0 +1,52 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"fmt"
+
+	"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/go.mod b/instrgen/go.mod
index f15e39186..b8429b11a 100644
--- a/instrgen/go.mod
+++ b/instrgen/go.mod
@@ -1,3 +1,18 @@
 module go.opentelemetry.io/contrib/instrgen
 
 go 1.19
+
+require (
+	go.opentelemetry.io/otel v1.11.2
+	go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.11.2
+	go.opentelemetry.io/otel/sdk v1.11.2
+	golang.org/x/tools v0.4.0
+)
+
+require (
+	github.com/go-logr/logr v1.2.3 // indirect
+	github.com/go-logr/stdr v1.2.2 // indirect
+	go.opentelemetry.io/otel/trace v1.11.2 // indirect
+	golang.org/x/mod v0.7.0 // indirect
+	golang.org/x/sys v0.3.0 // indirect
+)
diff --git a/instrgen/go.sum b/instrgen/go.sum
new file mode 100644
index 000000000..34de4a69a
--- /dev/null
+++ b/instrgen/go.sum
@@ -0,0 +1,25 @@
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
+github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+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.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+go.opentelemetry.io/otel v1.11.2 h1:YBZcQlsVekzFsFbjygXMOXSs6pialIZxcjfO/mBDmR0=
+go.opentelemetry.io/otel v1.11.2/go.mod h1:7p4EUV+AqgdlNV9gL97IgUZiVR3yrFXYo53f9BM3tRI=
+go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.11.2 h1:BhEVgvuE1NWLLuMLvC6sif791F45KFHi5GhOs1KunZU=
+go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.11.2/go.mod h1:bx//lU66dPzNT+Y0hHA12ciKoMOH9iixEwCqC1OeQWQ=
+go.opentelemetry.io/otel/sdk v1.11.2 h1:GF4JoaEx7iihdMFu30sOyRx52HDHOkl9xQ8SMqNXUiU=
+go.opentelemetry.io/otel/sdk v1.11.2/go.mod h1:wZ1WxImwpq+lVRo4vsmSOxdd+xwoUJ6rqyLc3SyX9aU=
+go.opentelemetry.io/otel/trace v1.11.2 h1:Xf7hWSF2Glv0DE3MH7fBHvtpSBsjcBUe5MYAmZM/+y0=
+go.opentelemetry.io/otel/trace v1.11.2/go.mod h1:4N+yC7QEz7TTsG9BSRLNAa63eg5E06ObSbKPmxQ/pKA=
+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/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/instrgen/lib/analysis.go b/instrgen/lib/analysis.go
new file mode 100644
index 000000000..53ecf8688
--- /dev/null
+++ b/instrgen/lib/analysis.go
@@ -0,0 +1,141 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package 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 accrding 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
new file mode 100644
index 000000000..e655d1d41
--- /dev/null
+++ b/instrgen/lib/callgraph.go
@@ -0,0 +1,392 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package 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
new file mode 100644
index 000000000..e75588524
--- /dev/null
+++ b/instrgen/lib/context_propagation.go
@@ -0,0 +1,210 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package 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, fun FuncDescriptor, 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, fun, 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
new file mode 100644
index 000000000..c59ff2a6c
--- /dev/null
+++ b/instrgen/lib/instrumentation.go
@@ -0,0 +1,380 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package 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
new file mode 100644
index 000000000..29362a397
--- /dev/null
+++ b/instrgen/lib/otel_pruning.go
@@ -0,0 +1,157 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package 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
new file mode 100644
index 000000000..c09007dca
--- /dev/null
+++ b/instrgen/lib/tools.go
@@ -0,0 +1,70 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package 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
new file mode 100644
index 000000000..67a368f7a
--- /dev/null
+++ b/instrgen/rtlib/rtlib.go
@@ -0,0 +1,94 @@
+// 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.
+
+// 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() {
+
+}


Test patch:
diff --git a/instrgen/driver/instrgen_test.go b/instrgen/driver/instrgen_test.go
new file mode 100644
index 000000000..79b310109
--- /dev/null
+++ b/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)
+}
diff --git a/instrgen/driver/testdata/basic/fib.go b/instrgen/driver/testdata/basic/fib.go
new file mode 100644
index 000000000..835a4899a
--- /dev/null
+++ b/instrgen/driver/testdata/basic/fib.go
@@ -0,0 +1,52 @@
+// 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.
+
+//nolint:all
+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
new file mode 100644
index 000000000..47d913c03
--- /dev/null
+++ b/instrgen/driver/testdata/basic/goroutines.go
@@ -0,0 +1,36 @@
+// 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.
+
+//nolint:all
+package main
+
+import (
+	"fmt"
+
+	"go.opentelemetry.io/contrib/instrgen/rtlib"
+)
+
+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
new file mode 100644
index 000000000..6bb99a5db
--- /dev/null
+++ b/instrgen/driver/testdata/basic/main.go
@@ -0,0 +1,39 @@
+// 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.
+
+//nolint:all
+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
new file mode 100644
index 000000000..6152e0bdd
--- /dev/null
+++ b/instrgen/driver/testdata/basic/methods.go
@@ -0,0 +1,61 @@
+// 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.
+
+//nolint:all
+package main
+
+import (
+	"go.opentelemetry.io/contrib/instrgen/rtlib"
+)
+
+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
new file mode 100644
index 000000000..03e721c94
--- /dev/null
+++ b/instrgen/driver/testdata/basic/package.go
@@ -0,0 +1,35 @@
+// 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.
+
+//nolint:all
+package main
+
+import (
+	"os"
+
+	"go.opentelemetry.io/contrib/instrgen/rtlib"
+)
+
+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
new file mode 100644
index 000000000..5b2192947
--- /dev/null
+++ b/instrgen/driver/testdata/dummy/main.go
@@ -0,0 +1,19 @@
+// 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.
+
+//nolint:all
+package main
+
+func main() {
+}
diff --git a/instrgen/driver/testdata/expected/basic/fib.go b/instrgen/driver/testdata/expected/basic/fib.go
new file mode 100644
index 000000000..700cc037e
--- /dev/null
+++ b/instrgen/driver/testdata/expected/basic/fib.go
@@ -0,0 +1,62 @@
+// 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.
+
+//nolint:all
+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
new file mode 100644
index 000000000..5579749a3
--- /dev/null
+++ b/instrgen/driver/testdata/expected/basic/goroutines.go
@@ -0,0 +1,42 @@
+// 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.
+
+//nolint:all
+package main
+
+import (
+	"fmt"
+	__atel_context "context"
+
+	"go.opentelemetry.io/contrib/instrgen/rtlib"
+	__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
new file mode 100644
index 000000000..4314e8e62
--- /dev/null
+++ b/instrgen/driver/testdata/expected/basic/main.go
@@ -0,0 +1,49 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//nolint:all
+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
new file mode 100644
index 000000000..5f0d60c97
--- /dev/null
+++ b/instrgen/driver/testdata/expected/basic/methods.go
@@ -0,0 +1,74 @@
+// 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.
+
+//nolint:all
+package main
+
+import (
+	"go.opentelemetry.io/contrib/instrgen/rtlib"
+	__atel_otel "go.opentelemetry.io/otel"
+	__atel_context "context"
+)
+
+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
new file mode 100644
index 000000000..5e990d62f
--- /dev/null
+++ b/instrgen/driver/testdata/expected/basic/package.go
@@ -0,0 +1,39 @@
+// 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.
+
+//nolint:all
+package main
+
+import (
+	"os"
+	__atel_context "context"
+
+	"go.opentelemetry.io/contrib/instrgen/rtlib"
+	__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
new file mode 100644
index 000000000..ecf2f9e54
--- /dev/null
+++ b/instrgen/driver/testdata/expected/basic/traces.txt
@@ -0,0 +1,148 @@
+{
+	"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
new file mode 100644
index 000000000..19433eaeb
--- /dev/null
+++ b/instrgen/driver/testdata/expected/interface/app/impl.go
@@ -0,0 +1,33 @@
+// 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.
+
+//nolint:all
+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
new file mode 100644
index 000000000..01b73a741
--- /dev/null
+++ b/instrgen/driver/testdata/expected/interface/main.go
@@ -0,0 +1,40 @@
+// 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.
+
+//nolint:all
+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
new file mode 100644
index 000000000..be7ae9e4d
--- /dev/null
+++ b/instrgen/driver/testdata/expected/interface/serializer/interface.go
@@ -0,0 +1,22 @@
+// 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.
+
+//nolint:all
+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
new file mode 100644
index 000000000..ea7cf370b
--- /dev/null
+++ b/instrgen/driver/testdata/expected/selector/main.go
@@ -0,0 +1,53 @@
+// 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.
+
+//nolint:all
+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
new file mode 100644
index 000000000..c1499f2b3
--- /dev/null
+++ b/instrgen/driver/testdata/funwithoutpathtoroot/driver.go
@@ -0,0 +1,33 @@
+// 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.
+
+//nolint:all
+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
new file mode 100644
index 000000000..9e186959e
--- /dev/null
+++ b/instrgen/driver/testdata/interface/app/impl.go
@@ -0,0 +1,28 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//nolint:all
+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
new file mode 100644
index 000000000..2c23d008b
--- /dev/null
+++ b/instrgen/driver/testdata/interface/go.mod
@@ -0,0 +1,17 @@
+module go.opentelemetry.io/contrib/instrgen/testdata/interface
+
+go 1.18
+
+replace go.opentelemetry.io/contrib/instrgen => ../../..
+
+require go.opentelemetry.io/contrib/instrgen v0.0.0-20221228173227-92e0588b124b
+
+require (
+	github.com/go-logr/logr v1.2.3 // indirect
+	github.com/go-logr/stdr v1.2.2 // indirect
+	go.opentelemetry.io/otel v1.11.2 // indirect
+	go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.11.2 // indirect
+	go.opentelemetry.io/otel/sdk v1.11.2 // indirect
+	go.opentelemetry.io/otel/trace v1.11.2 // indirect
+	golang.org/x/sys v0.3.0 // indirect
+)
diff --git a/instrgen/driver/testdata/interface/go.sum b/instrgen/driver/testdata/interface/go.sum
new file mode 100644
index 000000000..3bce30861
--- /dev/null
+++ b/instrgen/driver/testdata/interface/go.sum
@@ -0,0 +1,20 @@
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
+github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+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.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+go.opentelemetry.io/otel v1.11.2 h1:YBZcQlsVekzFsFbjygXMOXSs6pialIZxcjfO/mBDmR0=
+go.opentelemetry.io/otel v1.11.2/go.mod h1:7p4EUV+AqgdlNV9gL97IgUZiVR3yrFXYo53f9BM3tRI=
+go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.11.2 h1:BhEVgvuE1NWLLuMLvC6sif791F45KFHi5GhOs1KunZU=
+go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.11.2/go.mod h1:bx//lU66dPzNT+Y0hHA12ciKoMOH9iixEwCqC1OeQWQ=
+go.opentelemetry.io/otel/sdk v1.11.2 h1:GF4JoaEx7iihdMFu30sOyRx52HDHOkl9xQ8SMqNXUiU=
+go.opentelemetry.io/otel/sdk v1.11.2/go.mod h1:wZ1WxImwpq+lVRo4vsmSOxdd+xwoUJ6rqyLc3SyX9aU=
+go.opentelemetry.io/otel/trace v1.11.2 h1:Xf7hWSF2Glv0DE3MH7fBHvtpSBsjcBUe5MYAmZM/+y0=
+go.opentelemetry.io/otel/trace v1.11.2/go.mod h1:4N+yC7QEz7TTsG9BSRLNAa63eg5E06ObSbKPmxQ/pKA=
+golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
+golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/instrgen/driver/testdata/interface/main.go b/instrgen/driver/testdata/interface/main.go
new file mode 100644
index 000000000..5ec2cf865
--- /dev/null
+++ b/instrgen/driver/testdata/interface/main.go
@@ -0,0 +1,31 @@
+// 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.
+
+//nolint:all
+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
new file mode 100644
index 000000000..83ff55d22
--- /dev/null
+++ b/instrgen/driver/testdata/interface/serializer/interface.go
@@ -0,0 +1,20 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//nolint:all
+package serializer
+
+type Serializer interface {
+	Serialize()
+}
diff --git a/instrgen/driver/testdata/selector/main.go b/instrgen/driver/testdata/selector/main.go
new file mode 100644
index 000000000..696e0a363
--- /dev/null
+++ b/instrgen/driver/testdata/selector/main.go
@@ -0,0 +1,43 @@
+// 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.
+
+//nolint:all
+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)
+}