Skip to content

Commit 8e6ec46

Browse files
authored
Merge pull request #1114 from anatoly32322/codegen_function_id
Add codegeneration for stack.FunctionID
2 parents 0e4cf0a + ffd3ee0 commit 8e6ec46

File tree

35 files changed

+521
-103
lines changed

35 files changed

+521
-103
lines changed

.github/workflows/check-codegen.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ jobs:
3232
- name: Build
3333
run: |
3434
go install ./internal/cmd/gtrace
35+
go install ./internal/cmd/gstack
3536
go install go.uber.org/mock/[email protected]
3637
3738
- name: Clean and re-generate *_gtrace.go files
@@ -40,5 +41,9 @@ jobs:
4041
go generate ./trace
4142
go generate ./...
4243
44+
- name: Re-generate stack.FunctionID calls
45+
run: |
46+
gstack .
47+
4348
- name: Check repository diff
4449
run: bash ./.github/scripts/check-work-copy-equals-to-committed.sh "code-generation not equal with committed"

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
* Added internal `gstack` codegen tool for filling `stack.FunctionID` with value from call stack
2+
13
## v3.59.1
24
* Fixed updating last usage timestamp for smart parking of the conns
35

driver.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ func (d *Driver) trace() *trace.Driver {
115115
//
116116
//nolint:nonamedreturns
117117
func (d *Driver) Close(ctx context.Context) (finalErr error) {
118-
onDone := trace.DriverOnClose(d.trace(), &ctx, stack.FunctionID(""))
118+
onDone := trace.DriverOnClose(d.trace(), &ctx,
119+
stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/3/ydb.(*Driver).Close"))
119120
defer func() {
120121
onDone(finalErr)
121122
}()
@@ -248,7 +249,7 @@ func Open(ctx context.Context, dsn string, opts ...Option) (_ *Driver, err error
248249

249250
onDone := trace.DriverOnInit(
250251
d.trace(), &ctx,
251-
stack.FunctionID(""),
252+
stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/3/ydb.Open"),
252253
d.config.Endpoint(), d.config.Database(), d.config.Secure(),
253254
)
254255
defer func() {
@@ -284,7 +285,7 @@ func New(ctx context.Context, opts ...Option) (_ *Driver, err error) {
284285

285286
onDone := trace.DriverOnInit(
286287
d.trace(), &ctx,
287-
stack.FunctionID(""),
288+
stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/3/ydb.New"),
288289
d.config.Endpoint(), d.config.Database(), d.config.Secure(),
289290
)
290291
defer func() {

internal/balancer/balancer.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ func (b *Balancer) clusterDiscoveryAttempt(ctx context.Context) (err error) {
9797
address = "ydb:///" + b.driverConfig.Endpoint()
9898
onDone = trace.DriverOnBalancerClusterDiscoveryAttempt(
9999
b.driverConfig.Trace(), &ctx,
100-
stack.FunctionID(""),
100+
stack.FunctionID(
101+
"github.com/ydb-platform/ydb-go-sdk/3/internal/balancer.(*Balancer).clusterDiscoveryAttempt"),
101102
address,
102103
)
103104
endpoints []endpoint.Endpoint
@@ -173,7 +174,8 @@ func (b *Balancer) applyDiscoveredEndpoints(ctx context.Context, endpoints []end
173174
var (
174175
onDone = trace.DriverOnBalancerUpdate(
175176
b.driverConfig.Trace(), &ctx,
176-
stack.FunctionID(""),
177+
stack.FunctionID(
178+
"github.com/ydb-platform/ydb-go-sdk/3/internal/balancer.(*Balancer).applyDiscoveredEndpoints"),
177179
b.config.DetectLocalDC,
178180
)
179181
previousConns []conn.Conn
@@ -211,7 +213,7 @@ func (b *Balancer) applyDiscoveredEndpoints(ctx context.Context, endpoints []end
211213
func (b *Balancer) Close(ctx context.Context) (err error) {
212214
onDone := trace.DriverOnBalancerClose(
213215
b.driverConfig.Trace(), &ctx,
214-
stack.FunctionID(""),
216+
stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/3/internal/balancer.(*Balancer).Close"),
215217
)
216218
defer func() {
217219
onDone(err)
@@ -237,7 +239,7 @@ func New(
237239
var (
238240
onDone = trace.DriverOnBalancerInit(
239241
driverConfig.Trace(), &ctx,
240-
stack.FunctionID(""),
242+
stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/3/internal/balancer.New"),
241243
driverConfig.Balancer().String(),
242244
)
243245
discoveryConfig = discoveryConfig.New(append(opts,
@@ -371,7 +373,7 @@ func (b *Balancer) connections() *connectionsState {
371373
func (b *Balancer) getConn(ctx context.Context) (c conn.Conn, err error) {
372374
onDone := trace.DriverOnBalancerChooseEndpoint(
373375
b.driverConfig.Trace(), &ctx,
374-
stack.FunctionID(""),
376+
stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/3/internal/balancer.(*Balancer).getConn"),
375377
)
376378
defer func() {
377379
if err == nil {

internal/cmd/gstack/main.go

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"flag"
6+
"fmt"
7+
"go/ast"
8+
"go/parser"
9+
"go/token"
10+
"io/fs"
11+
"os"
12+
"path/filepath"
13+
14+
"github.com/ydb-platform/ydb-go-sdk/v3/internal/cmd/gstack/utils"
15+
)
16+
17+
func usage() {
18+
fmt.Fprintf(os.Stderr, "usage: gstack [path]\n")
19+
flag.PrintDefaults()
20+
}
21+
22+
func getCallExpressionsFromExpr(expr ast.Expr) (listOfCalls []*ast.CallExpr) {
23+
switch expr := expr.(type) {
24+
case *ast.SelectorExpr:
25+
listOfCalls = getCallExpressionsFromExpr(expr.X)
26+
case *ast.IndexExpr:
27+
listOfCalls = getCallExpressionsFromExpr(expr.X)
28+
case *ast.StarExpr:
29+
listOfCalls = getCallExpressionsFromExpr(expr.X)
30+
case *ast.BinaryExpr:
31+
listOfCalls = getCallExpressionsFromExpr(expr.X)
32+
listOfCalls = append(listOfCalls, getCallExpressionsFromExpr(expr.Y)...)
33+
case *ast.CallExpr:
34+
listOfCalls = append(listOfCalls, expr)
35+
listOfCalls = append(listOfCalls, getCallExpressionsFromExpr(expr.Fun)...)
36+
for _, arg := range expr.Args {
37+
listOfCalls = append(listOfCalls, getCallExpressionsFromExpr(arg)...)
38+
}
39+
case *ast.CompositeLit:
40+
for _, elt := range expr.Elts {
41+
listOfCalls = append(listOfCalls, getCallExpressionsFromExpr(elt)...)
42+
}
43+
case *ast.UnaryExpr:
44+
listOfCalls = append(listOfCalls, getCallExpressionsFromExpr(expr.X)...)
45+
case *ast.KeyValueExpr:
46+
listOfCalls = append(listOfCalls, getCallExpressionsFromExpr(expr.Value)...)
47+
case *ast.FuncLit:
48+
listOfCalls = append(listOfCalls, getListOfCallExpressionsFromBlockStmt(expr.Body)...)
49+
}
50+
51+
return listOfCalls
52+
}
53+
54+
func getExprFromDeclStmt(statement *ast.DeclStmt) (listOfExpressions []ast.Expr) {
55+
decl, ok := statement.Decl.(*ast.GenDecl)
56+
if !ok {
57+
return listOfExpressions
58+
}
59+
for _, spec := range decl.Specs {
60+
if spec, ok := spec.(*ast.ValueSpec); ok {
61+
listOfExpressions = append(listOfExpressions, spec.Values...)
62+
}
63+
}
64+
65+
return listOfExpressions
66+
}
67+
68+
func getCallExpressionsFromStmt(statement ast.Stmt) (listOfCallExpressions []*ast.CallExpr) {
69+
var body *ast.BlockStmt
70+
var listOfExpressions []ast.Expr
71+
switch stmt := statement.(type) {
72+
case *ast.IfStmt:
73+
body = stmt.Body
74+
case *ast.SwitchStmt:
75+
body = stmt.Body
76+
case *ast.TypeSwitchStmt:
77+
body = stmt.Body
78+
case *ast.SelectStmt:
79+
body = stmt.Body
80+
case *ast.ForStmt:
81+
body = stmt.Body
82+
case *ast.RangeStmt:
83+
body = stmt.Body
84+
case *ast.DeclStmt:
85+
listOfExpressions = append(listOfExpressions, getExprFromDeclStmt(stmt)...)
86+
for _, expr := range listOfExpressions {
87+
listOfCallExpressions = append(listOfCallExpressions, getCallExpressionsFromExpr(expr)...)
88+
}
89+
case *ast.CommClause:
90+
stmts := stmt.Body
91+
for _, stmt := range stmts {
92+
listOfCallExpressions = append(listOfCallExpressions, getCallExpressionsFromStmt(stmt)...)
93+
}
94+
case *ast.ExprStmt:
95+
listOfCallExpressions = append(listOfCallExpressions, getCallExpressionsFromExpr(stmt.X)...)
96+
}
97+
if body != nil {
98+
listOfCallExpressions = append(
99+
listOfCallExpressions,
100+
getListOfCallExpressionsFromBlockStmt(body)...,
101+
)
102+
}
103+
104+
return listOfCallExpressions
105+
}
106+
107+
func getListOfCallExpressionsFromBlockStmt(block *ast.BlockStmt) (listOfCallExpressions []*ast.CallExpr) {
108+
for _, statement := range block.List {
109+
switch expr := statement.(type) {
110+
case *ast.ExprStmt:
111+
listOfCallExpressions = append(listOfCallExpressions, getCallExpressionsFromExpr(expr.X)...)
112+
case *ast.ReturnStmt:
113+
for _, result := range expr.Results {
114+
listOfCallExpressions = append(listOfCallExpressions, getCallExpressionsFromExpr(result)...)
115+
}
116+
case *ast.AssignStmt:
117+
for _, rh := range expr.Rhs {
118+
listOfCallExpressions = append(listOfCallExpressions, getCallExpressionsFromExpr(rh)...)
119+
}
120+
default:
121+
listOfCallExpressions = append(listOfCallExpressions, getCallExpressionsFromStmt(statement)...)
122+
}
123+
}
124+
125+
return listOfCallExpressions
126+
}
127+
128+
func format(src []byte, path string, fset *token.FileSet, file *ast.File) ([]byte, error) {
129+
var listOfArgs []utils.FunctionIDArg
130+
for _, f := range file.Decls {
131+
var listOfCalls []*ast.CallExpr
132+
fn, ok := f.(*ast.FuncDecl)
133+
if !ok {
134+
continue
135+
}
136+
listOfCalls = getListOfCallExpressionsFromBlockStmt(fn.Body)
137+
for _, call := range listOfCalls {
138+
if function, ok := call.Fun.(*ast.SelectorExpr); ok && function.Sel.Name == "FunctionID" {
139+
pack, ok := function.X.(*ast.Ident)
140+
if !ok {
141+
continue
142+
}
143+
if pack.Name == "stack" && len(call.Args) == 1 {
144+
listOfArgs = append(listOfArgs, utils.FunctionIDArg{
145+
FuncDecl: fn,
146+
ArgPos: call.Args[0].Pos(),
147+
ArgEnd: call.Args[0].End(),
148+
})
149+
}
150+
}
151+
}
152+
}
153+
if len(listOfArgs) != 0 {
154+
fixed, err := utils.FixSource(fset, path, src, listOfArgs)
155+
if err != nil {
156+
return nil, err
157+
}
158+
159+
return fixed, nil
160+
}
161+
162+
return src, nil
163+
}
164+
165+
func processFile(src []byte, path string, fset *token.FileSet, file *ast.File, info os.FileInfo) error {
166+
formatted, err := format(src, path, fset, file)
167+
if err != nil {
168+
return err
169+
}
170+
if !bytes.Equal(src, formatted) {
171+
err = utils.WriteFile(path, formatted, info.Mode().Perm())
172+
if err != nil {
173+
return err
174+
}
175+
}
176+
177+
return nil
178+
}
179+
180+
func main() {
181+
flag.Usage = usage
182+
flag.Parse()
183+
args := flag.Args()
184+
185+
if len(args) != 1 {
186+
flag.Usage()
187+
188+
return
189+
}
190+
_, err := os.Stat(args[0])
191+
if err != nil {
192+
panic(err)
193+
}
194+
195+
fileSystem := os.DirFS(args[0])
196+
197+
err = fs.WalkDir(fileSystem, ".", func(path string, d fs.DirEntry, err error) error {
198+
fset := token.NewFileSet()
199+
if err != nil {
200+
return err
201+
}
202+
if d.IsDir() {
203+
return nil
204+
}
205+
if filepath.Ext(path) == ".go" {
206+
info, err := os.Stat(path)
207+
if err != nil {
208+
return err
209+
}
210+
src, err := utils.ReadFile(path, info)
211+
if err != nil {
212+
return err
213+
}
214+
file, err := parser.ParseFile(fset, path, nil, 0)
215+
if err != nil {
216+
return err
217+
}
218+
219+
return processFile(src, path, fset, file, info)
220+
}
221+
222+
return nil
223+
})
224+
if err != nil {
225+
panic(err)
226+
}
227+
}

0 commit comments

Comments
 (0)