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

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.

Owner
Max Chechel
Program or be programmed
Max Chechel
Comments
  • 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.

  • 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.

  • 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.

  • 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?

  • 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.

  • 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.

  • 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.

  • Allow overlapping methods

    Allow overlapping methods

    Since golang allows overlapping methods in embedded interfaces, do not fail if overlapping methods are found when merging embedded interfaces.

    This will unfortunately pull Doc and Comment fields from an arbitrary overlapping method, but in my opinion that's better than returning an error.

  • Load source package with imports

    Load source package with imports

    This way the generator won't have to load the same packages multiple times while processing interfaces.

    With the project I'm working on at the moment, gowrap takes almost 30 seconds to load an interface. After profiling with pprof, I noticed most of that time is spend inside pkg.Load.

    image

    In the current implementation while, processing interfaces, for every method and embedded interface, the same packages are loaded multiple times. If the package is loaded with imports and import paths are searched from the first loaded package struct the same interface is loaded in less than two seconds.

  • Unable to install this package

    Unable to install this package

    I'm trying to install gowrap using command go get -u github.com/hexdigest/gowrap/cmd/gowrap And receiving an error:

    go get: github.com/cavaliercoder/[email protected] updating to github.com/cavaliercoder/[email protected]: parsing go.mod: module declares its path as: github.com/cavaliergopher/cpio but was required as: github.com/cavaliercoder/go-cpio

  • add twirp_error template

    add twirp_error template

    Added template twirp_error. Which inject request data into twirp.Error as metadata. This allows ServerHooks.Error to access the request data for more detailed logging.

  • 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.

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

Dec 24, 2022
randstr is a module that contains functions for generating random strings.

randstr is a module that contains functions for generating random strings. The functions in this module uses the crypto/rand package. Installa

Nov 13, 2021
Template repo for generating your own workflow executor for Azure Orkestra

Orkestra Workflow Executor Template Repo This is a template repository for a new workflow executor Usage Generate your repository from this template b

Oct 22, 2021
Generating sitemap using goLang

This Go Module will generate the sitemap for any given URL. We will travese the all pages of the website and creates the sitemap We will use the 'net/

Dec 9, 2021
Tiny lib to manipulate the .line format (.rm in the reMarkable2) in Go

linestogo Tiny lib to manipulate the .line format

Apr 30, 2021
Continuous profiling for analysis of CPU, memory usage over time, and down to the line number. Saving infrastructure cost, improving performance, and increasing reliability.
Continuous profiling for analysis of CPU, memory usage over time, and down to the line number. Saving infrastructure cost, improving performance, and increasing reliability.

Continuous profiling for analysis of CPU, memory usage over time, and down to the line number. Saving infrastructure cost, improving performance, and increasing reliability.

Jan 2, 2023
tail a text file and trigger an action if a new line occurs [wip]

Tailpipe Synopsis Config Help Synopsis Tail a file and trigger an action if a new line occurs. Currently only mailing the new line somewhere is suppor

Dec 23, 2021
go-i18n is a Go package and a command that helps you translate Go programs into multiple languages.

go-i18n is a Go package and a command that helps you translate Go programs into multiple languages.

Jan 2, 2023
📚 Clone all your repositories from GitHub with one command!

An utility to clone easily all your repositories from GitHub. The process is done concurrently so it is quite fast.

Apr 6, 2022
efaceconv - Code generation tool for high performance conversion from interface{} to immutable type without allocations.

efaceconv High performance conversion from interface{} to immutable types without additional allocations This is tool for go generate and common lib (

May 14, 2022
Perforator is a tool for recording performance metrics over subregions of a program using the Linux "perf" interface.

Perforator Perforator is a tool for recording performance metrics over subregions of a program (e.g., functions) using the Linux "perf" interface.

Dec 15, 2022
a tool for creating exploited media files for discord

Discord-Exploits A program for creating exploited media files for discord written in Go. Usage discord-exploits is a command line utility, meaning you

Dec 29, 2021
A full-featured license tool to check and fix license headers and resolve dependencies' licenses.
A full-featured license tool to check and fix license headers and resolve dependencies' licenses.

SkyWalking Eyes A full-featured license tool to check and fix license headers and resolve dependencies' licenses. Usage You can use License-Eye in Git

Dec 26, 2022
sigurls is a reconnaissance tool, it fetches URLs from AlienVault's OTX, Common Crawl, URLScan, Github and the Wayback Machine.

sigurls is a reconnaissance tool, it fetches URLs from AlienVault's OTX, Common Crawl, URLScan, Github and the Wayback Machine. DiSCLAIMER: fe

May 22, 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).

Dec 7, 2022
TUI grep tool respect for IntelliJ
TUI grep tool respect for IntelliJ

ilse TUI grep tool respect for IntelliJ Requirements ripgrep for fast grep bat for beautiful preview Features support HeadMatch(FirstMatch), WordMatch

Sep 27, 2022
A tool to check problems about meta files of Unity
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.

Dec 22, 2022
A tool to find redirection chains in multiple URLs
A tool to find redirection chains in multiple URLs

UnChain A tool to find redirection chains in multiple URLs Introduction UnChain automates process of finding and following `30X` redirects by extracti

Dec 12, 2022
⚖️ A tool for transpiling C to Go.

A tool for converting C to Go. The goals of this project are: To create a generic tool that can convert C to Go. To be cross platform (linux and mac)

Dec 29, 2022