github.com/sacloud/iaas-api-go@v1.12.0/internal/tools/gen-otel-tracer/main.go (about) 1 // Copyright 2022-2023 The sacloud/iaas-api-go Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "log" 19 "path/filepath" 20 21 "github.com/sacloud/iaas-api-go/internal/define" 22 "github.com/sacloud/iaas-api-go/internal/dsl" 23 "github.com/sacloud/iaas-api-go/internal/tools" 24 ) 25 26 const destination = "trace/otel/zz_api_tracer.go" 27 28 func init() { 29 log.SetFlags(0) 30 log.SetPrefix("gen-otel-tracer: ") 31 } 32 33 func main() { 34 dsl.IsOutOfSacloudPackage = true 35 36 tools.WriteFileWithTemplate(&tools.TemplateConfig{ 37 OutputPath: filepath.Join(tools.ProjectRootPath(), destination), 38 Template: tmpl, 39 Parameter: define.APIs, 40 }) 41 log.Printf("generated: %s\n", filepath.Join(tools.ProjectRootPath(), destination)) 42 } 43 44 const tmpl = `// generated by 'github.com/sacloud/iaas-api-go/internal/tools/gen-otel-tracer'; DO NOT EDIT 45 46 package otel 47 48 import ( 49 "github.com/sacloud/iaas-api-go" 50 "go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace" 51 "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" 52 "go.opentelemetry.io/otel" 53 "go.opentelemetry.io/otel/codes" 54 "go.opentelemetry.io/otel/attribute" 55 "go.opentelemetry.io/otel/trace" 56 ) 57 58 func addClientFactoryHooks(cnf *config) { 59 {{ range . -}} 60 iaas.AddClientFacotyHookFunc("{{.TypeName}}", func(in interface{}) interface{} { 61 return new{{.TypeName}}Tracer(in.(iaas.{{.TypeName}}API), cnf) 62 }) 63 {{ end -}} 64 } 65 66 {{ range . }} {{$typeName := .TypeName}} {{ $resource := . }} 67 /************************************************* 68 * {{ $typeName }}Tracer 69 *************************************************/ 70 71 // {{ $typeName }}Tracer is for trace {{ $typeName }}Op operations 72 type {{ $typeName }}Tracer struct { 73 Internal iaas.{{$typeName}}API 74 config *config 75 } 76 77 // New{{ $typeName}}Tracer creates new {{ $typeName}}Tracer instance 78 func new{{ $typeName}}Tracer(in iaas.{{$typeName}}API, cnf *config) iaas.{{$typeName}}API { 79 return &{{ $typeName}}Tracer { 80 Internal: in, 81 config: cnf, 82 } 83 } 84 85 {{ range .Operations }}{{$returnErrStatement := .ReturnErrorStatement}}{{ $operationName := .MethodName }} 86 // {{ .MethodName }} is API call with trace log 87 func (t *{{ $typeName }}Tracer) {{ .MethodName }}(ctx context.Context{{if not $resource.IsGlobal}}, zone string{{end}}{{ range .Arguments }}, {{ .ArgName }} {{ .TypeName }}{{ end }}) {{.ResultsStatement}} { 88 var span trace.Span 89 options := append(t.config.SpanStartOptions, trace.WithAttributes( 90 {{if not $resource.IsGlobal -}} 91 attribute.String("sacloud.api.arguments.zone", zone), 92 {{ end -}} 93 {{ range .Arguments -}} 94 attribute.String("sacloud.api.arguments.{{.ArgName}}", forceString({{.ArgName}})), 95 {{ end -}} 96 )) 97 ctx, span = t.config.Tracer.Start(ctx, "{{ $typeName }}API.{{ .MethodName }}", options...) 98 defer func() { 99 span.End() 100 }() 101 102 // for http trace 103 ctx = httptrace.WithClientTrace(ctx, otelhttptrace.NewClientTrace(ctx)) 104 {{range .ResultsTypeInfo}}{{.VarName}}, {{end}}err := t.Internal.{{ .MethodName }}(ctx{{if not $resource.IsGlobal}}, zone{{end}}{{ range .Arguments }}, {{ .ArgName }}{{ end }}) 105 106 if err != nil { 107 span.SetStatus(codes.Error, err.Error()) 108 }else { 109 span.SetStatus(codes.Ok, "") 110 {{range .ResultsTypeInfo}}span.SetAttributes(attribute.String("libiaas.api.results.{{.VarName}}", forceString({{.VarName}}))) 111 {{ end }} 112 } 113 return {{range .ResultsTypeInfo}}{{.VarName}}, {{end}}err 114 } 115 {{- end -}} 116 117 {{ end }} 118 `