Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

go-grpc-middleware.v2: Action Plan. #275

Closed
4 of 18 tasks
bwplotka opened this issue Feb 29, 2020 · 46 comments
Closed
4 of 18 tasks

go-grpc-middleware.v2: Action Plan. #275

bwplotka opened this issue Feb 29, 2020 · 46 comments

Comments

@bwplotka
Copy link
Collaborator

bwplotka commented Feb 29, 2020

Hi 👋

We have tons of stuff to improve in this library and there wasn't really time for this. Let's do it finally! Let's maintain this issue as a single place to track our work. 💪 cc @domgreen @johanbrandhorst @mwitkow

The plan is to start from scratch in the v2 branch. We will work in the background until it's done.

Work Done

  • Started v2 branch, implemented all while leaving same API. Assignee: @bwplotka

  • Never again use those weird module_names 🙃 Done Assignee: @bwplotka

  • Multi-module architecture, allowing us to avoid dependency hell, but also retaining mono repo. Module structure: Done Assignee: @bwplotka
    The key part is to make sure the core is never importing the provider's code. There has to be indirection. This way the lib has minimum dependencies possible, with core literally having core only.

    If maintaining multi modules will be problematic, we can look into modularise cc @Helcaraxan

TODO (help wanted!) for 2.0:

Blockers:

Can be done in 2.x

Any other ideas?

@bwplotka bwplotka self-assigned this Feb 29, 2020
bwplotka added a commit that referenced this issue Feb 29, 2020
As per: #275

## Change:

* Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* Moved all specific implementations to separate modules.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
bwplotka added a commit that referenced this issue Feb 29, 2020
As per: #275

## Change:

* Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* Moved all specific implementations to separate modules.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
bwplotka added a commit that referenced this issue Feb 29, 2020
As per: #275

## Change:

* Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* Moved all specific implementations to separate modules. Exception is opentracing, as opentracing itself
is just amazing interface, so.. perfect (:
* Added generic internal interceptor code that both monitoring, logging and tracing will use.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
@bwplotka bwplotka mentioned this issue Feb 29, 2020
10 tasks
@brancz
Copy link

brancz commented Mar 2, 2020

I have no strong opinion about essentially having a monorepo, but I do wonder what the benefit is. I think they were separate because they had nothing in common not even shared unit test framework or anything. So I wonder if it’s worth it considering that given that things become harder with modules...

More generally though I do think these things need a pretty major overhaul and would love to see that happen! :)

@bwplotka
Copy link
Collaborator Author

bwplotka commented Mar 2, 2020

Thanks for the feedback!

I have no strong opinion about essentially having a monorepo, but I do wonder what the benefit is. I think they were separate because they had nothing in common not even shared unit test framework or anything.

Now (as you will see in #276) all middlewares with reuse the majority of its code. Same for test frameworks (: It will be then easier for all maintainers (including Dom, Johan) to understand Prometheus one.

So I wonder if it’s worth it considering that given that things become harder with modules...

Yes, but in the same time we have to solve it for logrus, zap, go-kit and potentially other implementations (: So far it's quite easy to work with multiple modules, but let's see the pain points (:

@brancz
Copy link

brancz commented Mar 2, 2020

Yeah loggers would all be in the same repo, I'm more thinking things that are more distinct like logging and metrics middleware. But as I said, I'm not against trying this at all.

@bwplotka
Copy link
Collaborator Author

bwplotka commented Mar 2, 2020 via email

bwplotka added a commit that referenced this issue Mar 2, 2020
As per: #275

The main goals is to have separate modules per each implementation and all reusing same code.
This way we can ensure consistency, and we reduce LOC to minimum, including tests.

## Change:

* Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* Moved all specific implementations to separate modules. Exception is opentracing, as opentracing itself
is just amazing interface, so.. perfect (:
* Added generic internal interceptor code that both monitoring, logging and tracing will use.
* Added scripts for proto generation.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
bwplotka added a commit that referenced this issue Mar 2, 2020
As per: #275

The main goals is to have separate modules per each implementation and all reusing same code.
This way we can ensure consistency, and we reduce LOC to minimum, including tests.

## Change:

* Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* Moved all specific implementations to separate modules. Exception is opentracing, as opentracing itself
is just amazing interface, so.. perfect (:
* Added generic internal interceptor code that both monitoring, logging and tracing will use.
* Added scripts for proto generation.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
@bwplotka
Copy link
Collaborator Author

bwplotka commented Mar 2, 2020

Essentially this is only what all implementations (including Prometheus) will need to implement and test (!):

type ClientReportable interface {
	ClientReporter(ctx context.Context, typ GRPCType, serviceName string, methodName string) (Reporter, context.Context)
}

type ServerReportable interface {
	ServerReporter(ctx context.Context, typ GRPCType, serviceName string, methodName string) (Reporter, context.Context)
}

type Reporter interface {
	PostCall(error, time.Duration)

	PostMsgSend(error, time.Duration)
	PostMsgReceive(error, time.Duration)
}

@brancz
Copy link

brancz commented Mar 2, 2020

Not against you mean (:

whops, what a great typo.. :D fixed my comment

bwplotka added a commit that referenced this issue Mar 2, 2020
As per: #275

The main goals is to have separate modules per each implementation and all reusing same code.
This way we can ensure consistency, and we reduce LOC to minimum, including tests.

## Change:

* Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* Moved all specific implementations to separate modules. Exception is opentracing, as opentracing itself
is just amazing interface, so.. perfect (:
* Added generic internal interceptor code that both monitoring, logging and tracing will use.
* Added scripts for proto generation.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
bwplotka added a commit that referenced this issue Mar 2, 2020
As per: #275

The main goals are to have separate modules per each implementation and all reusing same code.
This way we can ensure consistency, and we reduce LOC to minimum, including tests.

## Changes:

* [x] Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* [x] Moved all specific implementations to separate modules. Exception is opentracing, as opentracing itself
is just amazing interface, so.. perfect (:
* [x] Added generic interceptor code that both monitoring, logging and tracing will use under /interceptors
* [x] Reuse generic interceptors in interceptor/{logging,tracing,metrics,tags}. This allows huge simplificaiton of those.
* [x] Not context logger. Only ctxtags.Tags responsible for propagating tags in context and proto messages.
* [x] Tags are now map[string]string to discourage context value abuse.
* [x] Added scripts for proto generation.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
bwplotka added a commit that referenced this issue Mar 3, 2020
As per: #275

The main goals are to have separate modules per each implementation and all reusing same code.
This way we can ensure consistency, and we reduce LOC to minimum, including tests.

## Changes:

* [x] Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* [x] Moved all specific implementations to separate modules. Exception is opentracing, as opentracing itself
is just amazing interface, so.. perfect (:
* [x] Added generic interceptor code that both monitoring, logging and tracing will use under /interceptors
* [x] Reuse generic interceptors in interceptor/{logging,tracing,metrics,tags}. This allows huge simplificaiton of those.
* [x] No context logger. Only ctxtags.Tags responsible for propagating tags in context and proto messages.
* [x] Tags are now map[string]string to discourage context value abuse.
* [x] Changed tags to allow grpc client inside grpc server tags.
* [x] PayloadUnary works as a standalone interceptor as well.
* [x] Added scripts for proto generation.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
bwplotka added a commit that referenced this issue Mar 3, 2020
As per: #275

The main goals are to have separate modules per each implementation and all reusing same code.
This way we can ensure consistency, and we reduce LOC to minimum, including tests.

## Changes:

* [x] Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* [x] Moved all specific implementations to separate modules. Exception is opentracing, as opentracing itself
is just amazing interface, so.. perfect (:
* [x] Added generic interceptor code that both monitoring, logging and tracing will use under /interceptors
* [x] Reuse generic interceptors in interceptor/{logging,tracing,metrics,tags}. This allows huge simplificaiton of those.
* [x] No context logger. Only ctxtags.Tags responsible for propagating tags in context and proto messages.
* [x] Tags are now map[string]string to discourage context value abuse.
* [x] PayloadUnary works as a standalone interceptor as well.
* [x] Tags will actually will use map tag instead of noop if not created.
* [x] Added scripts for proto generation.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
bwplotka added a commit that referenced this issue Mar 3, 2020
As per: #275

The main goals are to have separate modules per each implementation and all reusing same code.
This way we can ensure consistency, and we reduce LOC to minimum, including tests.

## Changes:

* [x] Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* [x] Moved all specific implementations to separate modules. Exception is opentracing, as opentracing itself
is just amazing interface, so.. perfect (:
* [x] Added generic interceptor code that both monitoring, logging and tracing will use under /interceptors
* [x] Reuse generic interceptors in interceptor/{logging,tracing,metrics,tags}. This allows huge simplificaiton of those.
* [x] No context logger. Only ctxtags.Tags responsible for propagating tags in context and proto messages.
* [x] Tags are now map[string]string to discourage context value abuse.
* [x] PayloadUnary works as a standalone interceptor as well.
* [x] Tags will actually will use map tag instead of noop if not created.
* [x] Added scripts for proto generation.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
bwplotka added a commit that referenced this issue Mar 4, 2020
As per: #275

The main goals are to have separate modules per each implementation and all reusing same code.
This way we can ensure consistency, and we reduce LOC to minimum, including tests.

## Changes:

* [x] Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* [x] Moved all specific implementations to separate modules. Exception is opentracing, as opentracing itself
is just amazing interface, so.. perfect (:
* [x] Added generic interceptor code that both monitoring, logging and tracing will use under /interceptors
* [x] Reuse generic interceptors in interceptor/{logging,tracing,metrics,tags}. This allows huge simplificaiton of those.
* [x] No context logger. Only ctxtags.Tags responsible for propagating tags in context and proto messages.
* [x] Tags are now map[string]string to discourage context value abuse.
* [x] PayloadUnary works as a standalone interceptor as well.
* [x] Tags will actually will use map tag instead of noop if not created.
* [x] Added scripts for proto generation.
* [x] Let tag.Interceptor to extract request data for all types of requests.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
bwplotka added a commit that referenced this issue Mar 4, 2020
As per: #275

The main goals are to have separate modules per each implementation and all reusing same code.
This way we can ensure consistency, and we reduce LOC to minimum, including tests.

## Changes:

* [x] Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* [x] Moved all specific implementations to separate modules. Exception is opentracing, as opentracing itself
is just amazing interface, so.. perfect (:
* [x] Added generic interceptor code that both monitoring, logging and tracing will use under /interceptors
* [x] Reuse generic interceptors in interceptor/{logging,tracing,metrics,tags}. This allows huge simplificaiton of those.
* [x] No context logger. Only ctxtags.Tags responsible for propagating tags in context and proto messages.
* [x] Tags are now map[string]string to discourage context value abuse.
* [x] PayloadUnary works as a standalone interceptor as well.
* [x] Tags will actually will use map tag instead of noop if not created.
* [x] Added scripts for proto generation.
* [x] Let tag.Interceptor to extract request data for all types of requests.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
bwplotka added a commit that referenced this issue Mar 4, 2020
As per: #275

The main goals are to have separate modules per each implementation and all reusing same code.
This way we can ensure consistency, and we reduce LOC to minimum, including tests.

## Changes:

* [x] Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* [x] Moved all specific implementations to separate modules. Exception is opentracing, as opentracing itself
is just amazing interface, so.. perfect (:
* [x] Added generic interceptor code that both monitoring, logging and tracing will use under /interceptors
* [x] Reuse generic interceptors in interceptor/{logging,tracing,metrics,tags}. This allows huge simplificaiton of those.
* [x] No context logger. Only ctxtags.Tags responsible for propagating tags in context and proto messages.
* [x] Tags are now map[string]string to discourage context value abuse.
* [x] PayloadUnary works as a standalone interceptor as well.
* [x] Tags will actually will use map tag instead of noop if not created.
* [x] Added scripts for proto generation.
* [x] Let tag.Interceptor to extract request data for all types of requests.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
bwplotka added a commit that referenced this issue Mar 4, 2020
As per: #275

The main goals are to have separate modules per each implementation and all reusing same code.
This way we can ensure consistency, and we reduce LOC to minimum, including tests.

## Changes:

* [x] Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* [x] Moved all specific implementations to separate modules. Exception is opentracing, as opentracing itself
is just amazing interface, so.. perfect (:
* [x] Added generic interceptor code that both monitoring, logging and tracing will use under /interceptors
* [x] Reuse generic interceptors in interceptor/{logging,tracing,metrics,tags}. This allows huge simplificaiton of those.
* [x] No context logger. Only ctxtags.Tags responsible for propagating tags in context and proto messages.
* [x] Tags are now map[string]string to discourage context value abuse.
* [x] PayloadUnary works as a standalone interceptor as well.
* [x] Tags will actually will use map tag instead of noop if not created.
* [x] Added scripts for proto generation.
* [x] Let tag.Interceptor to extract request data for all types of requests.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
bwplotka added a commit that referenced this issue Mar 4, 2020
As per: #275

The main goals are to have separate modules per each implementation and all reusing same code.
This way we can ensure consistency, and we reduce LOC to minimum, including tests.

## Changes:

* [x] Removed grpc_ prefix from all packages like `grpc_middleware`. User can add them on their own.
* [x] Moved all specific implementations to separate modules. Exception is opentracing, as opentracing itself
is just amazing interface, so.. perfect (:
* [x] Added generic interceptor code that both monitoring, logging and tracing will use under /interceptors
* [x] Reuse generic interceptors in interceptor/{logging,tracing,metrics,tags}. This allows huge simplificaiton of those.
* [x] No context logger. Only ctxtags.Tags responsible for propagating tags in context and proto messages.
* [x] Tags are now map[string]string to discourage context value abuse.
* [x] PayloadUnary works as a standalone interceptor as well.
* [x] Tags will actually will use map tag instead of noop if not created.
* [x] Added scripts for proto generation.
* [x] Let tag.Interceptor to extract request data for all types of requests.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
@bwplotka
Copy link
Collaborator Author

bwplotka commented Mar 5, 2020

First to points are done thanks to this: #276

Added few more todos as well. Please propose PRs to v2 if you want to help 🤗

@pgbytes
Copy link
Contributor

pgbytes commented Mar 9, 2020

TODO suggestion:

grpc_logrus.Decider currently takes fullMethodName string and err error as parameters, that restricts us in filtering by only two arguments. Would be nice to get the context in this method, so that we can filter by more things, such as the IP address of requester.

@bwplotka
Copy link
Collaborator Author

bwplotka commented Mar 9, 2020 via email

@mattbailey
Copy link

I'd like to see an interceptor that uses grpclog

It might be effective to, instead of writing an interceptor for each log library, write one for grpclog and then write interface shims for log libraries to satisfy the grpclog.LoggerV2 interface.

@bwplotka
Copy link
Collaborator Author

bwplotka commented Mar 18, 2020 via email

@irridia
Copy link
Contributor

irridia commented Jun 4, 2020

FWIW, I've had luck with multiple modules in a repo, but non-nested and without the v2+ go module "feature". I did suspect that the /v2/ needs to be at the end of the nested modules, but I wasn't 100% sure it wasn't part of Go's Very Well Documented Module Magick. :-|

I tried playing around with this in my fork, but it got very complicated. I can also poke at it later today after I get some sleep.

@bwplotka
Copy link
Collaborator Author

bwplotka commented Jun 4, 2020

Fixing modules in this Pr: #296

@XSAM
Copy link
Contributor

XSAM commented Jun 23, 2020

I'd like to help this part.

Add tracing interface and move opentracing to provides. Add opentelemetry providers.

@bwplotka
Copy link
Collaborator Author

Please help @XSAM (:

Also @johanbrandhorst we were having an interesting discussion with @yashrsharma44

For example, all our intercepters are using a solid reporter interface. Such a reporter is not really tied to gRPC which gives us a quick way to implement tripperware and middleware for pure HTTP code as well that ensure the same metric, logging, tracing and tags behavior among HTTP and gRPC. This, however, would mean that:

  • interceptors/logging would need to be more agnostic to gRPC (e.g Code to Level might be int code, not codes.Code etc)
  • we might want to even host HTTP version of interceptors. This sounds quite crazy and is far from scope of this library, but some sibling projects would make sense - as long as we allow reusing our "reporters" for both gRPC interceptors and HTTP middleware.

What do you think? (:

@johanbrandhorst
Copy link
Collaborator

I think there's a real danger of going to deep on abstractions. Lets keep it simple if we can.

@bwplotka
Copy link
Collaborator Author

bwplotka commented Jun 25, 2020 via email

@irridia
Copy link
Contributor

irridia commented Jul 31, 2020

Just FYI, I've been using the logging interceptors (zerolog specifically) in prod with zero issues.

@bwplotka
Copy link
Collaborator Author

bwplotka commented Aug 1, 2020

Amazing, looking for more time to finish things up (: protobuf and grpc nearly updated to latest

@bwplotka
Copy link
Collaborator Author

bwplotka commented Oct 2, 2020

I pulled all the tasks to separate issues, so the idea is for @yashrsharma44 to create GH project for first v2 release and track outstanding items there. (:

@bwplotka bwplotka closed this as completed Oct 2, 2020
@ash2k
Copy link
Contributor

ash2k commented Oct 6, 2020

@bwplotka I'm glad to see v2 happening!

For metrics, have you considered using gRPC's stats.Handler (via grpc.StatsHandler() for server and grpc.WithStatsHandler() for dials) instead of interceptors?

https://github.com/piotrkowalczuk/promgrpc uses stats.Handler API.

p.s. I'm glad that v2 does not have any global state and does not register with the global prometheus registry!

@drewwells
Copy link
Contributor

Amazing, looking for more time to finish things up (: protobuf and grpc nearly updated to latest

Where is outstanding working being tracked? I was looking at the list in this issue and noticed some where already done like github-actions.

@codefromthecrypt
Copy link

Is it time for another release candidate? last was 9 months ago

@yashrsharma44
Copy link
Collaborator

For metrics, have you considered using gRPC's stats.Handler (via grpc.StatsHandler() for server and grpc.WithStatsHandler() for dials) instead of interceptors?

@ash2k Is there any difference on using StatsHandler instead of the interceptors for gRPC Middlewares? Just curious to know more about them.

@ash2k
Copy link
Contributor

ash2k commented Mar 12, 2021

@yashrsharma44 I'm not the best person to ask as I'm not a gRPC expert, but off the top of my head:

  • I suppose if gRPC team introduced a special way to collect stats, the approach must have some clear benefits.
  • Interceptors are invoked in some order. If an interceptor that sits before the stats interceptor aborts the request, then the stats interceptor does not get a chance to measure the call.
  • It feels cleaner to use a separate API for stats if it's there than mixing it with interceptors.
  • Less chance of incorrect interceptor ordering.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.