| layout | default |
|---|---|
| title | Integrations |
| permalink | /integrations |
| description | ColdBrew integrations with Prometheus, New Relic, Sentry, OpenTelemetry, Buf, Jaeger, and vtprotobuf for observability and code generation |
| nav_order | 6 |
{: .no_toc } 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.
{: .no_toc .text-delta }
- TOC {:toc}
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 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.
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 keyNEW_RELIC_OPENTELEMETRY: Set totrueto use New Relic Opentelemetry interfaceNEW_RELIC_DISTRIBUTED_TRACING: Set totrueto enable distributed tracingNEW_RELIC_OPENTELEMETRY_SAMPLE: Set to float value between0and1to set the sampling rate for distributed tracing
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.
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.
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.
To configure Prometheus, set the following environment variables as defined in Config
DISABLE_PROMETHEUS: Set totrueto disable Prometheus/metricsendpointENABLE_PROMETHEUS_GRPC_HISTOGRAM: Set totrueto enable Prometheus gRPC histograms
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.
ColdBrew uses the prometheus/client_golang package to collect metrics. To see how to use it check out the metrics documentation.
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.
Set the following environment variables as defined in Config:
ENABLE_OTEL_METRICS: Set totrueto enable OTLP metrics exportOTEL_METRICS_INTERVAL: Export interval in seconds (default:60)OTLP_ENDPOINT: OTLP gRPC endpoint (shared with tracing)
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 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.
To configure Sentry, set the following environment variables as defined in Config
SENTRY_DSN: Sentry DSNENVIRONMENT: Environment (e.g.production)RELEASE_NAME: App release (e.g.v1.0.0)
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.
To use Sentry in your app, have a look at the errors documentation.
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.
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.
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 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.
ColdBrew provides a unified logging setup through the core package.
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
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)
}
}ColdBrew supports any OTLP-compatible backend (Jaeger, Honeycomb, etc.) through a generic OpenTelemetry setup.
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)
}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 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.
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)
}
}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.
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)
})
})
}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)
})
})
}Use WithoutExecutor() to skip resilience for internal or loopback connections:
interceptors.DefaultClientInterceptor(
interceptors.WithoutExecutor(),
)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.
{: .note .note-info }
DefaultClientInterceptor(...) includes ExecutorClientInterceptor, so per-call WithExecutor works out of the box. If you build your own interceptor chain, make sure to include ExecutorClientInterceptor.
// 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),
)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.
{: .warning }
Legacy: The previous HystrixClientInterceptor (wrapping afex/hystrix-go) is deprecated and will be removed in v1. Migrate to SetDefaultExecutor with failsafe-go.
ColdBrew provides functions to configure the environment and release information used by monitoring tools.
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 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.
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.
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+equalAfter make generate, your proto messages will have additional *_vtproto.pb.go files with fast MarshalVT(), UnmarshalVT(), CloneVT(), EqualVT(), and pool methods.
vtprotobuf is enabled by default. To disable it (e.g., for debugging serialization issues):
export DISABLE_VT_PROTOBUF=trueFor more details, see the vtprotobuf how-to guide.
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.