Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea
/gtrace
/pinger
/buildtags
Expand Down
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,41 @@ func (c *Client) ping(ctx context.Context) error {
}
```

**gtrace** can export **shortcuts** by using comment like `//gtrace:set Shortcut` or `//gtrace:set SHORTCUT`.
This may need if traces placed in external package (for example `trace`):

```go
package trace

//go:generate gtrace

//gtrace:gen
//gtrace:set Shortcut
type Client struct {
OnPing func(ClientPingStart) func(ClientPingDone)
}
```

Code snippet bellow exclude `Trace` prefix from struct names because `trace` is a package name.
This allows transform code from `ClientTrace` to `trace.Client`.
After `go generate` we able to call exported _hooks_ like this:

```go
package lib

import (
"context"
"trace"
)

func (c *Client) ClientTracePing(ctx context.Context) error {
done := trace.ClientOnPing(c.Trace, 1, 2, 3)
err := doPing(ctx, c.conn)
done(1, 2, 3, err)
return err
}
```

### Build Tags

**gtrace** can generate zero-cost tracing helpers when tracing of your app is optional. That is, your client code will remain the same -- composing traces with needed callbacks, calling non-exported versions of _hooks_ (or _shortcuts_) etc. But after compilation calling the tracing helpers would take no CPU time.
Expand Down
6 changes: 6 additions & 0 deletions cmd/gtrace/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ func main() {
for i, item := range items {
t := p.Traces[i]
for _, field := range item.StructType.Fields.List {
if _, ok := field.Type.(*ast.FuncType); !ok {
continue
}
name := field.Names[0].Name
fn, ok := field.Type.(*ast.FuncType)
if !ok {
Expand Down Expand Up @@ -489,6 +492,7 @@ func (f GenFlag) Has(x GenFlag) bool {
const (
GenZero GenFlag = 1 << iota >> 1
GenShortcut
GenShortcutPublic
GenContext

GenAll = ^GenFlag(0)
Expand Down Expand Up @@ -527,6 +531,8 @@ func (g *GenConfig) ParseParameter(text string) (err error) {
switch param {
case "shortcut":
g.Flag |= GenShortcut
case "Shortcut", "SHORTCUT":
g.Flag |= GenShortcutPublic
case "context":
g.Flag |= GenContext
default:
Expand Down
24 changes: 16 additions & 8 deletions cmd/gtrace/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,13 @@ func (w *Writer) Write(p Package) error {
}
for _, trace := range p.Traces {
for _, hook := range trace.Hooks {
if !hook.Flag.Has(GenShortcut) {
if !hook.Flag.Has(GenShortcut) && !hook.Flag.Has(GenShortcutPublic) {
continue
}
if w.Stub {
w.stubHookShortcut(trace, hook)
w.stubHookShortcut(trace, hook, hook.Flag.Has(GenShortcutPublic))
} else {
w.hookShortcut(trace, hook)
w.hookShortcut(trace, hook, hook.Flag.Has(GenShortcutPublic))
}
}
}
Expand Down Expand Up @@ -209,7 +209,7 @@ func unwrapStruct(t types.Type) (n *types.Named, s *types.Struct) {
func (w *Writer) funcImports(dst []dep, flag GenFlag, fn *Func) []dep {
for _, p := range fn.Params {
dst = w.typeImports(dst, p.Type)
if !flag.Has(GenShortcut) {
if !flag.Has(GenShortcut) && !flag.Has(GenShortcutPublic) {
continue
}
if _, s := unwrapStruct(p.Type); s != nil {
Expand Down Expand Up @@ -597,9 +597,13 @@ func (w *Writer) stubShortcutFunc(id string, f *Func) (name string) {
return name
}

func (w *Writer) stubHookShortcut(trace *Trace, hook Hook) {
func (w *Writer) stubHookShortcut(trace *Trace, hook Hook, export bool) {
name := tempName(trace.Name, hook.Name)
name = unexported(name)
if export {
name = exported(name)
} else {
name = unexported(name)
}
w.mustDeclare(name)

id := uniqueTraceHookID(trace, hook)
Expand Down Expand Up @@ -877,9 +881,13 @@ func (w *Writer) constructStruct(n *types.Named, s *types.Struct, vars []string)
return p, vars
}

func (w *Writer) hookShortcut(trace *Trace, hook Hook) {
func (w *Writer) hookShortcut(trace *Trace, hook Hook, export bool) {
name := tempName(trace.Name, hook.Name)
name = unexported(name)
if export {
name = exported(name)
} else {
name = unexported(name)
}
w.mustDeclare(name)

w.newScope(func() {
Expand Down