Giter VIP home page Giter VIP logo

gizmo's Introduction

Gizmo Microservice Toolkit GoDoc Build Status Coverage Status

As of late April, 2021 Gizmo has been placed in maintenance mode.

This toolkit provides packages to put together server and pubsub daemons with the following features:

  • Standardized configuration and logging
  • Health check endpoints with configurable strategies
  • Configuration for managing pprof endpoints and log levels
  • Basic interfaces to define expectations and vocabulary
  • Structured logging containing basic request information
  • Useful metrics for endpoints
  • Graceful shutdowns

Install

Notice the capitalization!

go get github.com/NYTimes/gizmo/...

Import Path Change Notice

The New York Times recently changed the github organization from NYTimes to nytimes. This should not affect the installation as long as you use the proper casing NYTimes and not nytimes per installation instructions above.

However, the intention is to migrate the import paths to be consistent with how it's shown on GitHub. This will be a breaking change and we will introduce a major tag when we update the code. Therefore, the import path will go from github.com/NYTimes/gizmo/server to github.com/nytimes/gizmo/v2/server. This ensures that people will not have type-mismatches between import path changes.

Packages

The server package is the bulk of the toolkit and relies on server.Config to manage Server implementations.

It offers 1 server implementation:

SimpleServer, which is capable of handling basic HTTP and JSON requests via 5 of the available Service implementations: SimpleService, JSONService, ContextService, MixedService and a MixedContextService.

The server/kit package embodies Gizmo's goals to combine with go-kit.

  • In this package you'll find:
    • A more opinionated server with fewer choices.
    • go-kit used for serving HTTP/JSON & gRPC used for serving HTTP2/RPC
    • Monitoring, traces and metrics are automatically registered if running within App Engine, Cloud Run, Kubernetes Engine, Compute Engine or AWS EC2 Instances.
      • to change the name and version for Error reporting and Traces use SERVICE_NAME and SERVICE_VERSION environment variables.
    • Logs go to stdout locally or directly to Stackdriver when in GCP.
    • Using Go's 1.8 graceful HTTP shutdown.
    • Services using this package are expected to deploy to GCP.

The observe package provides observability helpers for metrics and tracing through OpenCensus

  • server/kit (and soon SimpleServer) utilizes this package to create a StackDriver exporter with sane defaults
  • GoogleProjectID, IsGAE, and IsCloudRun can help you make decisions about the underlying platform

The auth package provides primitives for verifying inbound authentication tokens:

  • The PublicKeySource interface is meant to provide *rsa.PublicKeys from JSON Web Key Sets.
  • The Verifier struct composes key source implementations with custom decoders and verifier functions to streamline server side token verification.

The auth/gcp package provides 2 Google Cloud Platform based auth.PublicKeySource and oauth2.TokenSource implementations:

  • The "Identity" key source and token source rely on GCP's identity JWT mechanism for asserting instance identities. This is the preferred method for asserting instance identity on GCP.
  • The "IAM" key source and token source rely on GCP's IAM services for signing and verifying JWTs. This method can be used outside of GCP, if needed and can provide a bridge for users transitioning from the 1st generation App Engine (where Identity tokens are not available) runtime to the 2nd.

The auth/gcp package also includes an Authenticator, which encapsulates a Google Identity verifier and oauth2 credentials to manage a basic web auth flow.

The config package contains a handful of useful functions to load to configuration structs from JSON files or environment variables.

There are also many structs for common configuration options and credentials of different Cloud Services and Databases.

The pubsub package contains two (publisher and subscriber) generic interfaces for publishing data to queues as well as subscribing and consuming data from those queues.

There are 4 implementations of pubsub interfaces:

  • For pubsub via Amazon's SNS/SQS, you can use the pubsub/aws package

  • For pubsub via Google's Pubsub, you can use the pubsub/gcp package

  • For pubsub via Kafka topics, you can use the pubsub/kafka package

  • For publishing via HTTP, you can use the pubsub/http package

The pubsub/pubsubtest package contains test implementations of the pubsub.Publisher, pubsub.MultiPublisher, and pubsub.Subscriber interfaces that will allow developers to easily mock out and test their pubsub implementations.

Examples

  • Several reference implementations utilizing server and pubsub are available in the examples subdirectory.
  • There are also examples within the GoDoc: here

If you experience any issues please create an issue and/or reach out on the #gizmo channel in the Gophers Slack Workspace with what you've found.

The Gizmo logo was based on the Go mascot designed by Renée French and copyrighted under the Creative Commons Attribution 3.0 license.

gizmo's People

Contributors

adammck avatar avepr avatar buddhamagnet avatar bufdev avatar cristiangraz avatar ctborg avatar darrenmcc avatar dependabot-preview[bot] avatar edgulczynski avatar fsouza avatar gaplyk avatar joemadeus avatar jprobinson avatar konomaxi avatar marcotroisi avatar marwan-at-work avatar marzagao avatar mixedmessages avatar mk6i avatar nathanbwaters avatar oliver-nyt avatar saranrapjs avatar scentless-apprentice avatar scottefein avatar surajbarkale avatar taraspos avatar tiagorlampert avatar tonglil avatar weilandia avatar wild-endeavor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gizmo's Issues

Unable to build minimal example

I don't write a lot of go. I feel like there's something critical I'm missing in being unable to run this program, it doesn't even include a service. Any help would be appreciated.

I installed go from brew

❯ go version
go version go1.9.1 darwin/amd64

I'm attempting to use dep to install dependencies. So I ran dep init and dep ensure with the example below.

package main

import (
	"github.com/NYTimes/gizmo/server"
)

func main() {
	server.Init("test-server", nil)
	if err = server.Run(); err != nil {
		server.Log.Fatal("unable to run server: ", err)
	}
}
❯ go build main.go
# test/vendor/github.com/NYTimes/gizmo/server
vendor/github.com/NYTimes/gizmo/server/router.go:87:17: cannot use h (type http.Handler) as type http.HandlerFunc in assignment: need type assertion

Is there anything I can do on my end to fix this or is this really an issue in gizmo?

GRPC server fails when Prometheus metrics are enabled

panic: descriptor Desc{fqName: "rpc.Data.DURATION", help: "rpc.Data.DURATION", constLabels: {}, variableLabels: []} is invalid: "rpc.Data.DURATION" is not a valid metric name

goroutine 1 [running]:
github.com/prometheus/client_golang/prometheus.(*Registry).MustRegister(0xc420078980, 0xc4201e35a0, 0x1, 0x1)
	/Users/207269/go/src/github.com/prometheus/client_golang/prometheus/registry.go:353 +0x92
github.com/prometheus/client_golang/prometheus.MustRegister(0xc4201e35a0, 0x1, 0x1)
	/Users/207269/go/src/github.com/prometheus/client_golang/prometheus/registry.go:152 +0x53
github.com/go-kit/kit/metrics/prometheus.NewSummaryFrom(0x0, 0x0, 0x0, 0x0, 0xc4201e6fc0, 0x11, 0xc4201e6fc0, 0x11, 0x0, 0x0, ...)
	/Users/207269/go/src/github.com/go-kit/kit/metrics/prometheus/prometheus.go:99 +0xe8
github.com/go-kit/kit/metrics/provider.(*prometheusProvider).NewHistogram(0xc4201e6580, 0xc4201e6fc0, 0x11, 0x32, 0x9, 0xc4201e6fc0)
	/Users/207269/go/src/github.com/go-kit/kit/metrics/provider/prometheus.go:59 +0x107
github.com/NYTimes/gizmo/server.registerRPCMetrics(0xc4201e3548, 0x8, 0x17eb2c0, 0xc4201e6580)
	/Users/207269/go/src/github.com/NYTimes/gizmo/server/rpc_server.go:298 +0x102
github.com/NYTimes/gizmo/server.(*RPCServer).Register(0xc42006e9b0, 0x17e7340, 0xc4201e3550, 0xc4201e3088, 0xc4201e3090)
	/Users/207269/go/src/github.com/NYTimes/gizmo/server/rpc_server.go:78 +0x123
github.com/NYTimes/gizmo/server.Register(0x17e7340, 0xc4201e3550, 0xc420061380, 0xc420082098)
	/Users/207269/go/src/github.com/NYTimes/gizmo/server/server.go:130 +0x49
main.main()

Needs similar fixing like we did here: #69

Add support for IAM Roles in the publisher and subscriber

Currently in NewSubscriber(cfg SQSConfig) (pubsub.Subscriber, error) there are only 2 ways the Credentials are set: Static and from the Environment.

I would need to use the AssumeRoleProvider in order to be able to switch to the role authorised to use the service

Add example on integrate pubsub to service

Currently, I am implementing kind of message bus for each service.
I would like to see some example on how we should integrate pubsub into Service such as JSONService
If anyone can provide some sort of README or example. I would very much appreciate it :D

Logrus case-insensitive import collision

Hi,

Since logrus changed it's case (github.com/Sirupsen/logrus to github.com/sirupsen/logrus) using Gizmo can cause a case-insensitive import collision. This happens when both github.com/Sirupsen/logrus and github.com/sirupsen/logrus are imported.

As stated on the logrus github page:

Seeing weird case-sensitive problems? Unfortunately, the author failed to realize the consequences of renaming to lower-case. Due to the Go package environment, this caused issues. Regretfully, there's no turning back now. Everything using logrus will need to use the lower-case: github.com/sirupsen/logrus. Any package that isn't, should be changed.

I'll submit a pull request with the simple fix of renaming Sirupsen to sirupsen.

Drop support for Go <1.9

The next release should drop support for anything below 1.9 now that 1.12 is about to be released. This way we can clean up SimpleServer a little bit to get rid of the build tags.

FastSimpleServer for using Julien Schmidt’s httprouter

I am developing an API with gizmo microservice toolkit. One of use cases is a sudden load spike for short period of time like 4 hours 2 days per week. For the use case, I am trying to optimize performance of the API in various parts as much as I can. A a part of the optimization, I would like to incorporate HttpRouter in gizmo Sever. Based on the benchmarks of various Go http routers (https://github.com/julienschmidt/go-http-routing-benchmark), HttpRouter shows very good performance with very low heap allocation rate. At this point, SimpleServer uses Gorilla mux as a http router. To use HttpRouter, it needs FastSimpleServer , which is planned this year per http://open.blogs.nytimes.com/2015/12/17/introducing-gizmo. I am looking forward to adding FastSimpleServer with HttpRouter to gizmo for those who want HttpRouter as a http router.

Error When i use MYSQL config out of appengine sdk

GOROOT=/usr/local/Cellar/go/1.7/libexec
GOPATH=/Users/felipeweb/Code/go
/usr/local/Cellar/go/1.7/libexec/bin/go build -o "/private/var/folders/3x/ydvg5kjn6pvgwmp21lhytpcw0000gn/T/Build main.go and rungo" /Users/felipeweb/Code/go/src/bitbucket.org/lebre/lebre/main.go
package main
    imports bitbucket.org/lebre/lebre/service
    imports github.com/NYTimes/gizmo/server
    imports google.golang.org/appengine
    imports google.golang.org/appengine/internal
    imports google.golang.org/appengine/internal/log: use of internal package not allowed

PubSub GCP MaxExtension not changeable

Hi,

I'm trying to use the GCP Pubsub throught github.com/NYTimes/gizmo/pubsub/gcp but my receiver is running an import with a long duration surpassing the defaultMaxExtension = 60 * time.Second as defined on gcp.go:51. Causing the message to be resend because the receiver failed to Ack() the message.

Maybe i'm missing something but i don't see a way to change the MaxExtension on the underlying subscription's ReceiveSettings

I guess this requires a change in the code to make customisable? I'm happy to send in a pull request but would like to hear if it's needed an how you would like to see it implemented?

Make server `Endpoints` methods return arrays instead of maps

Maps do not allow users to declare the order in which their endpoints are registered against our routers, which can force developers to compromise how their URIs are constructed or even force users to build custom router implementations.

By switching to an array, users will be allowed to declare the order in which routes will be registered. Long term goal here is to eventually open up a path for us to remove any custom routing options in the future and purely rely on gorilla/mux.

I haven't figured out exactly what this API will look like, but I hope the change to be simple enough that minimal refactoring is required for the upgrade.

Using 1.7 with Gorilla Mux causes memory leak

gorilla/mux has build tags that opt to use the new/native context package for 1.7.

Unfortunately, Gizmo's server.Router implementation uses gorilla/context under the hood to allow httprouter to pass parameters. This leads to a massive memory leak when running with 1.7 as the gorilla/context never gets cleared.

update Google Cloud API client import paths and more

The Google Cloud API client libraries for Go are making some breaking changes:

  • The import paths are changing from google.golang.org/cloud/... to
    cloud.google.com/go/.... For example, if your code imports the BigQuery client
    it currently reads
    import "google.golang.org/cloud/bigquery"
    It should be changed to
    import "cloud.google.com/go/bigquery"
  • Client options are also moving, from google.golang.org/cloud to
    google.golang.org/api/option. Two have also been renamed:
    • WithBaseGRPC is now WithGRPCConn
    • WithBaseHTTP is now WithHTTPClient
  • The cloud.WithContext and cloud.NewContext methods are gone, as are the
    deprecated pubsub and container functions that required them. Use the Client
    methods of these packages instead.

You should make these changes before September 12, 2016, when the packages at
google.golang.org/cloud will go away.

Extract App Engine From server/kit

The App Engine Set Up (such as tracing, metrics, and logging) does not have to be locked with server/kit, this way you can use it with the SimpleServer

Labels for metrics for service endpoints are wrong

As a result of #129 the Prometheus metrics for an endpoint are now recorded with the actual URL accessed, not the URL path that was registered.
This is a problem when the registered URL path contains regular expressions like id:[0-9]+ cause the label will contain the actual ID and the stats won't get collapsed into the same time series.

Actually, if I'm not mistaken then #129 broke all metric recording, not only Prometheus style metrics, because the fullPath is also used in the default section here: https://github.com/NYTimes/gizmo/blob/73db46d2c901dfd0cb3f45d67bc75c1a248eb685/server/metrics.go#L145-L147

proposal: integrate Go CDK pubsub

The Go Cloud Development Kit, an open-source product of Google's Go team, is a set of high-level APIs that are designed to work across multiple cloud and on-prem providers. For example, our blob package lets the same code read and write data to Amazon S3, Google Cloud Storage, Azure Storage or a local filesystem.

We'd like to integrate our Go CDK pubsub API with Gizmo. We'd add a pubsub/gocdk directory with implementations of the four pubsub interfaces and config support. Gizmo would immediately gain two pubsub implementations—Azure and RabbitMQ—and would benefit from any future Go CDK integrations.

Create new custom `HealthCheckHandler` implementation

To allow users to inject a custom health check handler, we should add a CustomHealthCheckHandler http.Handler attribute to config.Server.

If the config.Server.HealthCheckType is "custom", the NewHealthCheckHandler should look for the CustomHealthCheckHandler function and use it.

Tag releases please

It would be nice if you can add tag releases. We are using dep but I don't want to vendor the master branch. Thanks.

go.sum mismatch at head

I cloned this repo and ran make build. It failed with

verifying github.com/influxdata/[email protected]: checksum mismatch
        downloaded: h1:L2DsZmSjI2ySLb1AaYtUkBjMcgRZC1DsL9fcagszDv4=
        go.sum:     h1:ekuRYg65KyXed1eWHMYKBNfa8Zw57UbBef4RTKPxiLY=

Allow to specify the MessageAttributes when publishing an event

In order to be able to use the attribute based filtering, would be nice if the Publisher allowed to specify the MessageAttributes field in sns.PublishInput so basically have something like:

// PublishRaw will emit the byte array to the SNS topic.
// The key will be used as the SNS message subject.
func (p *publisher) PublishRaw(_ context.Context, key string, m []byte, messageAttributes map[string]*MessageAttributeValue) error {
	msg := &sns.PublishInput{
		TopicArn: &p.topic,
		Subject:  &key,
		Message:  aws.String(base64.StdEncoding.EncodeToString(m)),
		MessageAttributes: messageAttributes,
	}

	_, err := p.sns.Publish(msg)
	return err
}

ref. https://aws.amazon.com/blogs/compute/simplify-pubsub-messaging-with-amazon-sns-message-filtering/

server.Register should error if it is called more than once

#18 brought up the issue that there is nothing to prevent users from registering multiple services on a single Gizmo server, which I think is against the microservice philosophy.

To force users to only have 1 Service per Server, we should change the 'Register' methods to error if a service has already been registered.

Clean up README.md

We have far too much documentation in the README, which makes keeping things up to date rather difficult.

We should trim down the README to just cover the highlights and purpose of gizmo.

Allow a more global style of middleware

Hi,

When trying to implement a CORS handler that catches all OPTIONS requests I noticed that the current Middleware wraps all requests that are defined in the Endpoints function. Would it be possible to allow wrapping of the mux.ServeHTTP func somehow?

When using httprouter instead of Gorilla at least the OPTIONS requests are handled by the router itself but there is no way of adding allowed origins to that response.

Prehaps a RouterMiddleware function that allows you to wrap the mux's ServeHTTP.

What are your thoughts on this?

Add Read Preference and Tags to Mongo config

Rather than rely on a MasterHost config value, which can change during elections, it would be more flexible to use Mongo's built in support for read preference and tags to constrain which nodes in the Hosts field can be used.

If these configurations are set, the MongoDB object can supply these to the mgo Session object before returning it to the client via:

https://godoc.org/gopkg.in/mgo.v2#Session.SetMode (Read Preference)
https://godoc.org/gopkg.in/mgo.v2#Session.SelectServers (Tags)

Connecting to subscriber results in 404

While trying to run the sqs-sub pubsub example, I keep encountering this error:

InvalidAddress: The address https://sqs.us-east-1.amazonaws.com/ is not valid for this endpoint.
status code: 404, request id: 14c12121-5d1c-5583-a35d-73d68936cbf6dmcdonald@dmcdonald-mbp15:~/go/src/dmcdonald/pubsubspike/

This traces to the s.sqs.GetQueueUrl call. I tried calling this api method myself with the following code, and got success:

	cfg := aws.NewConfig().WithCredentials(
		awscredentials.NewEnvCredentials(),
	).WithRegion(region)
	sqsClient := sqs.New(session.New(cfg))
	if resp, err := sqsClient.GetQueueUrl(&sqs.GetQueueUrlInput{QueueName: &queueName}); err != nil {
		fmt.Printf("failed to get queue url: \n%v\n", err)
	} else {
		fmt.Println(resp)
	}

I'm using the same permissions, region and queuename with both the gizmo example and my own test code.

The error response indicates possibly a permissions issue, but I can't seem to reproduce it outside of the gizmo codebase. Any suggestions on how to troubleshoot this further?

PubSub GCP Attributes (keys)

Hi,

One more thing i came across: the gcp.Publish and gcp.PublishRaw have a param key string.

However this is converted to Attributes: map[string]string{"key": key} here. Wouldn't it be better to allow a map in the params of those functions?

Would of course mean a breaking change, but the functionality is partially broken now anyways?

RPC service does not expose HTTP endpoints

I just cloned the RPC example but the HTTP endpoints are not exposed.

I also had to modify the code because in newer versions of gRPC you have to add grpc.WithInsecure() when calling grpc.Dial(...)

Any clue why the http endpoints are not being exposed ?

COC?

Hi,

I'm just wondering what your code of conduct is for this project?

Thanks,
Alison

Update tag

Would it be possible to up the tag of Gizmo to v0.0.2? Would love to “properly” update our dependencies to fix the panic on 404s. Thanks

Remove Prefix() from `server.Service`, add it to `config.Server`

Since a prefix can an optional value for services, we should not force everyone to implement it, especially since the value is likely to be immutable.

We should remove the method from the server.Service interface, include it's value as an attribute in config.Server and then change the server.Register implementations to utilize it.

THIS WILL BE A BREAKING CHANGE!
If possible, it'd be nice if we could provide a small utility that would see a Prefix() implementation, remove it and then add a line about server.Init(...) in main.go to do a config.Server.Prefix = "xyz" on the line above.

Add README to examples/pubsub

We should have notes in the examples/pubsub README to detail how to:

  1. Creating an SNS, SQS, subscribing one to the other and enabling 'raw delivery'.
  2. Setting up a local Kafka instance.

Allow ServerOption(s) to be passed into grpc Server

grpc supports various configurable options when creating a new rpc server.

func NewServer(opt ...ServerOption) *Server

It would be nice if these options can be managed via a new Config type or some other solution.

I can work on this if it sounds reasonable.

Add an HTTP request tracing header

I'm not sure how many folks at the Times are using gizmo but if you think it would be useful maybe we could add a request id header (X-NYT-Request-Id) to gizmo? If that's too Times specific maybe we could use X-Request-ID like Heroku does (https://devcenter.heroku.com/articles/http-request-id)? This header would be parsed from requests coming into a service and passed by the service to other services in HTTP requests that it makes. It would also be logged with all log statements related to a particular web transaction.

Allow AWS endpoint override for SQS

In #156 functionality was added to be able to override the AWS endpoint so that a mock AWS implementation could be used.

The SNS constructor was updated but it looks like the SQS constructor was not.

It looks like a pretty simple change so will open a PR with a proposed fix soon

Question: how can I organize folders for multiple services?

Hello,

I have looked examples folder but all examples has single service. So how can I organize folder multiple services.

Can I define multiple services in main.go file? if I can, what about service's config.json file ?

Sorry my bad english.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.