Integrations
ColdBrew provides thin wrappers over other services and tools. This page lists the services and tools that ColdBrew integrates with.
These integrations are optional and you can choose to use them or not. You can also choose to use other services and tools instead of the ones listed here. ColdBrew is designed to be flexible and easy to integrate with other services and tools.
If you want to integrate ColdBrew with a service or tool that is not listed here, please open an issue.
Table of contents
- GRPC Gateway
- New Relic
- Prometheus
- OpenTelemetry Metrics
- Sentry
- Opentelemetry
- Buf
- Logger
- Generic OpenTelemetry
- Jaeger / OTLP-compatible backends
- Circuit Breaker / Resilience
- Environment Configuration
- vtprotobuf
- ColdBrew packages
GRPC Gateway
ColdBrew relies on GRPC Gateway to expose the gRPC API as a REST API. The gateway is a proxy that translates a RESTful HTTP API into gRPC. It’s a great tool to expose gRPC services to the web and mobile clients.
To see how it works in ColdBrew, check out the gRPC Gateway example.
New Relic
New Relic is a SaaS-based monitoring tool that helps to monitor the performance of the services. It collects data about the services and displays it in a dashboard. It also provides alerts when the service is not performing well.
Configuring
To configure New Relic, set the following environment variables as defined in Config
-
NEW_RELIC_APPNAME: New Relic app name (e.g.my-app) -
NEW_RELIC_LICENSE_KEY: New Relic license key -
NEW_RELIC_OPENTELEMETRY: Set totrueto use New Relic Opentelemetry interface -
NEW_RELIC_DISTRIBUTED_TRACING: Set totrueto enable distributed tracing -
NEW_RELIC_OPENTELEMETRY_SAMPLE: Set to float value between0and1to set the sampling rate for distributed tracing
Initialising
If your app is using ColdBrew cookiecutter template, initialisation is done automatically.
If you are using ColdBrew packages in your app, you need to initialise New Relic manually. To initialise New Relic use the SetupNewRelic function and to initialise New Relic Opentelemetry use the SetupNROpenTelemetry function from the go-coldbrew/core package.
Using
To use New Relic tracing in your app, use the ColdBrew tracing and interceptors packages. They will setup the New Relic tracing provider and add the tracing middleware to the gRPC and HTTP servers.
You can also add more tracing to your app by adding tracing to your functions.
Prometheus
ColdBrew uses Prometheus to collect metrics from the services. Prometheus is an open-source systems monitoring and alerting toolkit originally built at SoundCloud. It includes a time series database, a query language, and a visualization UI.
Configuring
To configure Prometheus, set the following environment variables as defined in Config
-
DISABLE_PROMETHEUS: Set totrueto disable Prometheus/metricsendpoint -
ENABLE_PROMETHEUS_GRPC_HISTOGRAM: Set totrueto enable Prometheus gRPC histograms
Initialising
If your app is using ColdBrew cookiecutter template, initialisation is done automatically.
If you are using ColdBrew packages in your app, you need to initialise Prometheus manually. Make sure you expose Prometheus /metrics endpoint in your app and add the interceptors to your gRPC and HTTP servers.
Using
ColdBrew uses the prometheus/client_golang package to collect metrics. To see how to use it check out the metrics documentation.
OpenTelemetry Metrics
ColdBrew can export gRPC metrics via OTLP alongside Prometheus. This uses the native grpc/stats/opentelemetry package and shares the same OTLP endpoint as tracing.
Configuring
Set the following environment variables as defined in Config:
-
ENABLE_OTEL_METRICS: Set totrueto enable OTLP metrics export -
OTEL_METRICS_INTERVAL: Export interval in seconds (default:60) -
OTLP_ENDPOINT: OTLP gRPC endpoint (shared with tracing)
Using
OTEL metrics are exported automatically when enabled — no code changes required. Standard gRPC server/client metrics (grpc.server.call.duration, grpc.client.call.duration, etc.) are exported via OTLP.
Custom application metrics registered with promauto are not exported via OTLP — they remain Prometheus-only. To export custom metrics via OTLP, use the OpenTelemetry Go SDK directly with the global MeterProvider (available via otel.GetMeterProvider() or core.OTELMeterProvider()).
See the Metrics How-To for details on which metrics are exported and how OTEL metrics relate to Prometheus.
Sentry
Sentry is an error tracking tool that helps to monitor and fix crashes in real time. It collects data about the errors and displays it in a dashboard. It also provides alerts when the service is not performing well.
Configuring
To configure Sentry, set the following environment variables as defined in Config
-
SENTRY_DSN: Sentry DSN -
ENVIRONMENT: Environment (e.g.production) -
RELEASE_NAME: App release (e.g.v1.0.0)
Initialising
If your app is using ColdBrew cookiecutter template, initialisation is done automatically.
If you are using ColdBrew packages in your app, you need to initialise Sentry manually. To initialise Sentry use the SetupSentry function from the go-coldbrew/core package.
Using
To use Sentry in your app, have a look at the errors documentation.
Opentelemetry
Opentelemetry is a collection of tools that help to collect and analyze telemetry data. It includes a time series database, a query language, and a visualization UI.
Initialising
If your app is using ColdBrew cookiecutter template, initialisation is done automatically.
If you are using ColdBrew packages in your app, you need to initialise Opentelemetry manually. To initialise Opentelemetry follow the Opentelemetry documentation and configure the otel exporter to send the data.
To initialise New Relic Opentelemetry use the SetupNROpenTelemetry function from the go-coldbrew/core package.
Using
To use Opentelemetry tracing in your app, use the ColdBrew tracing and interceptors packages.
You can also add more tracing to your app by adding tracing to your functions.
Buf
Buf is a tool for managing protocol buffers. It can be used to generate code, lint proto files, and more. Buf simplifies the process of managing proto files and helps to keep them consistent across the team. It also helps to avoid common mistakes and helps to keep the proto files up to date.
ColdBrew cookiecutter template includes a buf.yaml file that configures Buf to generate code for the gRPC service. The code generation config is stored in the buf.gen.yaml file.
Logger
ColdBrew provides a unified logging setup through the core package.
Configuring
To configure the logger, set the following environment variables as defined in Config:
-
LOG_LEVEL: Log level (e.g.debug,info,warn,error) -
JSON_LOGS: Set totrueto enable JSON output,falsefor logfmt
Initialising
If your app is using ColdBrew cookiecutter template, initialisation is done automatically.
If you are using ColdBrew packages in your app, you need to initialise the logger manually:
import "github.com/go-coldbrew/core"
func main() {
// SetupLogger configures the logger with the specified log level and format
// logLevel: "debug", "info", "warn", "error"
// jsonlogs: true for JSON output, false for logfmt
err := core.SetupLogger("info", true)
if err != nil {
panic(err)
}
}
Generic OpenTelemetry
ColdBrew supports any OTLP-compatible backend (Jaeger, Honeycomb, etc.) through a generic OpenTelemetry setup.
Configuring
To configure generic OpenTelemetry, you can use the OTLPConfig struct:
type OTLPConfig struct {
Endpoint string // OTLP gRPC endpoint (e.g., "localhost:4317")
Headers map[string]string // Custom headers (e.g., API keys)
ServiceName string // Name of your service
ServiceVersion string // Version of your service
SamplingRatio float64 // Sampling ratio (0.0 to 1.0)
Compression string // "gzip" or "none"
Insecure bool // Disable TLS (for local development)
}
Initialising
import "github.com/go-coldbrew/core"
func main() {
config := core.OTLPConfig{
Endpoint: "localhost:4317",
ServiceName: "my-service",
ServiceVersion: "v1.0.0",
SamplingRatio: 0.1,
Insecure: true, // for local development
}
err := core.SetupOpenTelemetry(config)
if err != nil {
panic(err)
}
}
Jaeger / OTLP-compatible backends
Jaeger is an open-source distributed tracing system. ColdBrew supports Jaeger (and any OTLP-compatible backend like Grafana Tempo, Honeycomb, etc.) through the OpenTelemetry OTLP exporter.
Configuring
To send traces to Jaeger, configure the OTLP endpoint to point to your Jaeger collector:
import "github.com/go-coldbrew/core"
func main() {
config := core.OTLPConfig{
Endpoint: "localhost:4317", // Jaeger OTLP endpoint
ServiceName: "my-service",
ServiceVersion: "v1.0.0",
SamplingRatio: 0.1,
Insecure: true,
}
err := core.SetupOpenTelemetry(config)
if err != nil {
panic(err)
}
}
Circuit Breaker / Resilience
ColdBrew provides a pluggable executor hook for client-side resilience (circuit breaking, retries, bulkheading, etc.). You bring your own resilience library — failsafe-go is recommended.
How it works
Call interceptors.SetDefaultExecutor during init to register your resilience logic. The executor receives the gRPC method name, so you can choose which methods get circuit breaking:
import (
"github.com/failsafe-go/failsafe-go"
"github.com/failsafe-go/failsafe-go/circuitbreaker"
"github.com/go-coldbrew/interceptors"
)
func init() {
cb := circuitbreaker.NewBuilder[any]().
WithFailureThreshold(5).
WithDelay(5 * time.Second).
WithSuccessThreshold(2).
Build()
// Only apply circuit breaking to specific methods
protected := map[string]bool{
"/payment.Service/Charge": true,
"/payment.Service/Refund": true,
}
interceptors.SetDefaultExecutor(func(ctx context.Context, method string, fn func(ctx context.Context) error) error {
if !protected[method] {
return fn(ctx) // passthrough for non-protected methods
}
return failsafe.With[any](cb).WithContext(ctx).Run(func() error {
return fn(ctx)
})
})
}
Per-method circuit breakers
Each method can have its own circuit breaker with different limits — sensitive methods trip fast, tolerant methods allow more failures:
func init() {
type cbConfig struct {
failureThreshold uint
delay time.Duration
}
configs := map[string]cbConfig{
"/payment.Service/Charge": {failureThreshold: 3, delay: 10 * time.Second},
"/payment.Service/Refund": {failureThreshold: 3, delay: 10 * time.Second},
"/user.Service/GetUser": {failureThreshold: 10, delay: 5 * time.Second},
"/feed.Service/GetFeed": {failureThreshold: 10, delay: 5 * time.Second},
}
var (
mu sync.Mutex
breakers = make(map[string]circuitbreaker.CircuitBreaker[any])
)
interceptors.SetDefaultExecutor(func(ctx context.Context, method string, fn func(ctx context.Context) error) error {
cfg, ok := configs[method]
if !ok {
return fn(ctx) // no circuit breaker for unconfigured methods
}
mu.Lock()
cb, exists := breakers[method]
if !exists {
cb = circuitbreaker.NewBuilder[any]().
WithFailureThreshold(cfg.failureThreshold).
WithDelay(cfg.delay).
Build()
breakers[method] = cb
}
mu.Unlock()
return failsafe.With[any](cb).WithContext(ctx).Run(func() error {
return fn(ctx)
})
})
}
Disabling for specific connections
Use WithoutExecutor() to skip resilience for internal or loopback connections:
interceptors.DefaultClientInterceptor(
interceptors.WithoutExecutor(),
)
Per-call executor
WithExecutor can be passed directly to any gRPC call to use a specific executor for that call. This works even without calling SetDefaultExecutor — you don’t need a global executor to use per-call executors. This is useful for per-service circuit breaker tuning.
Per-call WithExecutor requires ExecutorClientInterceptor in the interceptor chain. This is included automatically when using DefaultClientInterceptors. If you build your own interceptor chain, make sure to include it.
// Create a sensitive circuit breaker for the payment service
paymentCB := circuitbreaker.NewBuilder[any]().
WithFailureThreshold(3).
WithDelay(10 * time.Second).
Build()
paymentExec := func(ctx context.Context, method string, fn func(ctx context.Context) error) error {
return failsafe.With[any](paymentCB).WithContext(ctx).Run(func() error {
return fn(ctx)
})
}
// Pass it directly to the gRPC call
resp, err := paymentClient.Charge(ctx, req,
interceptors.WithExecutor(paymentExec),
)
Excluded errors
Use WithExcludedErrors or WithExcludedCodes to prevent expected errors from tripping the circuit breaker. These can also be passed directly to gRPC calls:
resp, err := client.GetUser(ctx, req,
interceptors.WithExcludedCodes(codes.NotFound, codes.InvalidArgument),
)
See the interceptors examples for more patterns including circuit breaker + bulkhead composition.
Legacy: The previous HystrixClientInterceptor (wrapping afex/hystrix-go) is deprecated and will be removed in v1. Migrate to SetDefaultExecutor with failsafe-go.
Environment Configuration
ColdBrew provides functions to configure the environment and release information used by monitoring tools.
Initialising
import "github.com/go-coldbrew/core"
func main() {
// SetupEnvironment identifies the environment in Sentry and New Relic
core.SetupEnvironment("production")
// SetupReleaseName identifies the release in Sentry
core.SetupReleaseName("v1.0.0")
}
vtprotobuf
vtprotobuf is a Protocol Buffers compiler that generates optimized marshalling code, created by PlanetScale. ColdBrew uses it as the default gRPC serialization codec for faster message encoding/decoding.
How ColdBrew uses it
ColdBrew registers a custom gRPC codec at startup that prioritizes vtprotobuf’s MarshalVT()/UnmarshalVT() methods, falling back to standard protobuf for messages that don’t have VT methods generated. This is transparent — you get the speed benefit without changing any application code.
Setup
The ColdBrew cookiecutter template includes vtprotobuf code generation in buf.gen.yaml:
- remote: buf.build/community/planetscale-vtprotobuf:v0.6.0
out: proto
opt: paths=source_relative,features=marshal+unmarshal+size+clone+pool+equal
After make generate, your proto messages will have additional *_vtproto.pb.go files with fast MarshalVT(), UnmarshalVT(), CloneVT(), EqualVT(), and pool methods.
Configuration
vtprotobuf is enabled by default. To disable it (e.g., for debugging serialization issues):
export DISABLE_VT_PROTOBUF=true
For more details, see the vtprotobuf how-to guide.
ColdBrew packages
All ColdBrew packages are designed to be used as standalone packages. They can be used in any Go project. They are not tied to ColdBrew and can be used in any Go project.
When you build your service using ColdBrew cookiecutter template, it includes the Core package which initialises all the packages and sets up the service. You can use the Core package in any Go project to set up the service.
To see all the ColdBrew packages, check out the ColdBrew packages page.