GoWrap is a command line tool for generating decorators for Go interfaces

Overview

GoWrap

License Build Status Coverage Status Go Report Card GoDoc Awesome Release

GoWrap is a command line tool that generates decorators for Go interface types using simple templates. With GoWrap you can easily add metrics, tracing, fallbacks, pools, and many other features into your existing code in a few seconds.

Demo

demo

Installation

go get -u github.com/hexdigest/gowrap/cmd/gowrap

Usage of gowrap

Usage: gowrap gen -p package -i interfaceName -t template -o output_file.go
  -g	don't put //go:generate instruction into the generated code
  -i string
    	the source interface name, i.e. "Reader"
  -o string
    	the output file name
  -p string
    	the source package import path, i.e. "io", "github.com/hexdigest/gowrap" or
    	a relative import path like "./generator"
  -t template
    	the template to use, it can be an HTTPS URL a local file or a
    	reference to one of the templates in the gowrap repository
  -v value
    	a key-value pair to parametrize the template,
    	arguments without an equal sign are treated as a bool values,
    	i.e. -v DecoratorName=MyDecorator -v disableChecks

This will generate an implementation of the io.Reader interface wrapped with prometheus metrics

  $ gowrap gen -p io -i Reader -t prometheus -o reader_with_metrics.go

This will generate a fallback decorator for the Connector interface that can be found in the ./connector subpackage:

  $ gowrap gen -p ./connector -i Connector -t fallback -o ./connector/with_metrics.go

Run gowrap help for more options

Hosted templates

When you specify a template with the "-t" flag, gowrap will first search for and use the local file with this name. If the file is not found, gowrap will look for the template here and use it if found.

List of available templates:

  • circuitbreaker stops executing methods of the wrapped interface after the specified number of consecutive errors and resumes execution after the specified delay
  • fallback takes several implementations of the source interface and concurrently runs each implementation if the previous attempt didn't return the result in a specified period of time, it returns the first non-error result
  • log instruments the source interface with logging using standard logger from the "log" package
  • logrus instruments the source interface with logging using popular sirupsen/logrus logger
  • opentracing instruments the source interface with opentracing spans
  • prometheus instruments the source interface with prometheus metrics
  • ratelimit instruments the source interface with RPS limit and concurrent calls limit
  • retry instruments the source interface with retries
  • robinpool puts several implementations of the source interface to the slice and for every method call it picks one implementation from the slice using the Round-robin algorithm
  • syncpool puts several implementations of the source interface to the sync.Pool and for every method call it gets one implementation from the pool and puts it back once finished
  • timeout instruments each method that accepts context with configurable timeout
  • validate runs func Validate() error method on each argument if it's present
  • twirp_error inject request data into twirp.Error as metadata
  • twirp_validate runs func Validate() error method on each argument if it's present and wraps returned error with twirp.Malformed error
  • grpc_validate runs func Validate() error method on each argument if it's present and returns InvalidArgument error in case when validation failed

By default GoWrap places the //go:generate instruction into the generated code. This allows you to regenerate decorators' code just by typing go generate ./... when you change the source interface type declaration. However if you used a remote template, the //go:generate instruction will contain the HTTPS URL of the template and therefore you will need to have internet connection in order to regenerate decorators. In order to avoid this, you can copy templates from the GoWrap repository to local files and add them to your version control system:

$ gowrap template copy fallback templates/fallback

The above command will fetch the fallback template and copy it to the templates/fallback local file. After template is copied, you can generate decorators using this local template:

$ gowrap gen -p io -i Reader -t templates/fallback reader_with_fallback.go

Custom templates

You can always write your own template that will provide the desired functionality to your interfaces. If you think that your template might be useful to others, please consider adding it to our template repository.

The structure of information passed to templates is documented with the TemplateInputs struct.

Issues
  • Imports of modules with custom names are not included into generated code

    Imports of modules with custom names are not included into generated code

    The generator does not work with the case when the name of the package imported into source file does not match last import path segment.

    For example, source file like

    package authz
    
    import (
    	"mymodulename/pkg/api/iam/v1" // Go package name is "iamv1"
    )
    
    type Enforcer interface {
    	Enforce(ctx context.Context, request *iamv1.Request) ([]string, error)
    }
    

    Will result generated code that is using *iamv1.Request type in method signatures, however mymodulename/pkg/api/iam/v1 will not be added to the imports section.

    I tried all sorts of aliases for this module, however, nothing helps. Generator only works if I rename imported package to v1.

    opened by kop 8
  • Fixing

    Fixing "printChan" method for bidirectional channels

    Hi,

    I believe it will fix this issue https://github.com/gojuno/minimock/issues/41 The previous commit https://github.com/hexdigest/gowrap/commit/e0c4708e933c42ae3c0abc414cc4ed8391bd9767 didn't fix that.

    I've modified chanTypes map because of this line https://github.com/golang/go/blob/go1.14.4/src/go/parser/parser.go#L1012

    I added this line Channels(chA chan bool, chB chan<- bool, chanC <-chan bool) to the tests to make sure that it works now. Hope I didn't miss anything in terms of testing.

    opened by beono 7
  • Allowing specifying custom package

    Allowing specifying custom package

    When generating tests, the package inferred by gowrap is incorrect, and there doesn't seem to be a way to override it.

    opened by Varriount 6
  • Added TemplateInputInterface MethodsList method

    Added TemplateInputInterface MethodsList method

    This method allow iterate by methods with indexes. Use in templates example:

    {{range $i, $method := .Interface.MethodsList}}
    // something: arr[{{$i}}].Do()
    {{end}}
    

    Range over map not provided indexing in go templates.

    opened by androndo 6
  • Access to Package Name in Body Template

    Access to Package Name in Body Template

    We need access to the interface’s package name in a template.
    We can see this is available when the header template is executed, but don’t think it is available to body templates.
    Could this be made available in the map?

    Also, is there any way to customise the header template?

    opened by sjames-iberis 6
  • feat(template): add opencensus

    feat(template): add opencensus

    opened by damianopetrungaro 5
  • Make it possible for template to output imports

    Make it possible for template to output imports

    Sometimes, especially in large projects, goimports cannot properly resolve the imports by itself. This adds a helper function that can be used in templates, which outputs the imports from the original file as well as any additional imports required by the template itself.

    I believe this also fixes #21.

    opened by recht 5
  • Reason for errUnexportableType error

    Reason for errUnexportableType error

    I am curious to know why the use of an unexported type should abort decorator generation (line 138 of printer.go).

    I want to generate decorators for an interface that is only used in the context of the package in which it is defined, but this error blocks me from doing that.

    If I comment out the check, everything is generated as I need.

    opened by sjames-iberis 4
  • add logrus template.

    add logrus template.

    This adds a template similar to the log template but uses logrus with field annotations for

    • component (name of the interface)
    • method
    • parameters
    • results

    This makes it easier to retrieve these values out of the structured output of logrus' formats.

    opened by trusch 4
  • Implement concurrency limit template

    Implement concurrency limit template

    Sometimes it is required to limit concurrency without RPS limitation. Let's consider a situation we have a function which takes 100 ms and we want to have 3 or less calls of the function at any moment. We may use ratelimit template with parameters {concurrentRequests: 3, rps: 30}. Let's consider a situation we have a function which takes 1 s and we want to have 3 or less calls of the function at any moment. We may use ratelimit template with parameters {concurrentRequests: 3, rps: 3}. The problem here is that rps parameter depends on the time of the function's execution which is usually unknown and is not a constant. In other words if we don't want to limit RPS an interface instrumented with ratelimit template doesn't limit concurrency. Take a look at https://github.com/masim05/gowrap/blob/concurrency-limit-motivation/templates_tests/interface_with_ratelimit_test.go#L37 (which fails) for more details.

    Since the change will be backward incompatible with current implementation of ratelimit template (in terms of runtime behaviour) it is worth having a separate template for concurrency limitation. This PR provides the implementation.

    opened by masim05 5
  • Wrong position of package comment if template has no own `import`

    Wrong position of package comment if template has no own `import`

    If template has own import section (e.g. with github.com/prometheus/client_golang/prometheus) then the generated file header looks correct :

    package name
    
    // DO NOT EDIT!
    // This code is generated with http://github.com/hexdigest/gowrap tool
    // using templates/metrics template
    
    import (
    	"context"
    	
    	"github.com/prometheus/client_golang/prometheus"
    )
    

    But if template doesn't have own import section then package comment goes after import in generated file. It looks bad:

    package name
    
    import (
    	"context"
    )
    
    // DO NOT EDIT!
    // This code is generated with http://github.com/hexdigest/gowrap tool
    // using templates/metrics template
    

    import() in the beginning of template fixes it but looks weird.

    opened by vpbarb 1
Releases(v1.2.1)
Owner
Max Chechel
Program or be programmed
Max Chechel
Code generation tools for Go.

interfaces Code generation tools for Go's interfaces. Tools available in this repository: cmd/interfacer cmd/structer cmd/interfacer Generates an inte

Rafal Jeczalik 305 Jul 15, 2021
Discover internet-wide misconfigurations while drinking coffee

netz ?? ?? The purpose of this project is to discover an internet-wide misconfiguration of network components like web-servers/databases/cache-service

null 259 Jun 24, 2021
A tool and library for using structural regular expressions.

Structural Regular Expressions sregx is a package and tool for using structural regular expressions as described by Rob Pike (link).

Zachary Yedidia 22 Jun 18, 2021
Go tool to modify struct field tags

Go tool to modify/update field tags in structs. gomodifytags makes it easy to update, add or delete the tags in a struct field. You can easily add new tags, update existing tags (such as appending a new key, i.e: db, xml, etc..) or remove existing tags

Fatih Arslan 1.5k Jul 16, 2021
Go package to generate and manage color palettes & schemes 🎨

Go package to generate and manage color palettes & schemes

Christian Muehlhaeuser 437 Jul 19, 2021
bebop is a bebop parser written in Go, for generating Go code.

bebop is a bebop parser written in Go, for generating Go code. bebop can read .bop files and output .go files representing them: package main i

Patrick Stephen 24 Jul 14, 2021
A Golang tool to whitelist ASN's based on organization name

A Golang tool to whitelist ASN's based on organization name. This works by providing a list of ASN org names. This tool uses goPacket to monitor incoming traffic, capturing the IP's and checking the IP to see if it is a part of a whitelisted ASN. If it is not, it blocks that connection and future connections using iptables.

JP 10 Jul 14, 2021
Code Generation for Functional Programming, Concurrency and Generics in Golang

goderive goderive derives mundane golang functions that you do not want to maintain and keeps them up to date. It does this by parsing your go code fo

Walter Schulze 901 Jul 22, 2021
Type-driven code generation for Go

What’s this? gen is a code-generation tool for Go. It’s intended to offer generics-like functionality on your types. Out of the box, it offers offers

Matt Sherman 1.3k Jul 21, 2021
go-sysinfo is a library for collecting system information.

go-sysinfo go-sysinfo is a library for collecting system information. This includes information about the host machine and processes running on the ho

elastic 148 Jun 29, 2021
Reload Go code in a running process at function/method level granularity

got reload? Function/method-level stateful hot reloading for Go! Status Very much work in progress.

null 32 Jul 14, 2021
Simple profiling for Go

profile Simple profiling for Go. Easy management of Go's built-in profiling and tracing Based on the widely-used pkg/profile: mostly-compatible API Su

Michael McLoughlin 67 Jul 14, 2021
提供能简单处理服务熔断逻辑的工具包。

circuit 简介 提供能简单处理服务熔断逻辑的工具包。

Rui Zhong 3 Jul 19, 2021
A tool to check problems about meta files of Unity

A tool to check problems about meta files of Unity on Git repositories, and also the tool can do limited autofix for meta files of auto-generated files.

DeNA 38 Jul 14, 2021