Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions Cookiecutter.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
---
layout: default
title: "Cookiecutter Setup"
nav_order: 3
description: "Detailed cookiecutter template setup for ColdBrew"
permalink: /getting-started
title: "Cookiecutter Reference"
nav_order: 10
description: "Detailed reference for the ColdBrew cookiecutter project template"
permalink: /cookiecutter-reference
---
# Cookiecutter Setup
# Cookiecutter Reference
{: .no_toc }

{: .note }
Looking to create your first ColdBrew service? See the **[Getting Started](/getting-started)** guide instead. This page is a detailed reference for the cookiecutter template.

## Table of contents
{: .no_toc .text-delta }

Expand Down
73 changes: 72 additions & 1 deletion FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
layout: default
title: "FAQ"
nav_order: 8
description: "Frequently asked questions about ColdBrew"
description: "Frequently asked questions about ColdBrew: gRPC framework configuration, interceptors, tracing, and troubleshooting"
permalink: /faq
---
# Frequently Asked Questions
Expand Down Expand Up @@ -64,6 +64,17 @@ func init() {
}
```

## How does trace ID propagation work?

ColdBrew generates a unique trace ID for every request automatically. It can also read a trace ID from two sources:

1. **HTTP header** — `x-trace-id` (configurable via `TRACE_HEADER_NAME`) is forwarded from the HTTP gateway to gRPC
2. **Proto field** — if your request message has a `trace_id` string field, ColdBrew reads it via the generated `GetTraceId()` method

The trace ID is then propagated to structured logs (`"trace": "abc123"`) and Sentry/Rollbar error reports — so you can search for one ID and find the complete request flow across your logs and error tracking.

See the [Tracing How-To](/howto/Tracing/#trace-id-propagation) for details.

## How do I migrate from OpenTracing to OpenTelemetry?

The `tracing` package supports both. To switch:
Expand All @@ -72,6 +83,37 @@ The `tracing` package supports both. To switch:
2. The `tracing.NewInternalSpan()`, `tracing.NewDatastoreSpan()`, and `tracing.NewExternalSpan()` functions work with both backends
3. See the [Tracing How-To](/howto/Tracing/) and [Integrations](/integrations) guides for setup details

## What is vtprotobuf and why does ColdBrew use it?

[vtprotobuf](https://github.com/planetscale/vtprotobuf) (by PlanetScale) generates optimized `MarshalVT()`/`UnmarshalVT()` methods for protobuf messages that are typically **2–3x faster** than standard `proto.Marshal()` with fewer allocations.

ColdBrew registers a custom gRPC codec that uses vtprotobuf automatically. You don't need to change any application code — if your proto messages have VT methods generated (the default with the cookiecutter template), the fast path is used. Messages without VT methods fall back to standard protobuf transparently.

**Key differences from standard protobuf:**

| | Standard protobuf | vtprotobuf |
|---|---|---|
| Marshal/Unmarshal | Reflection-based | Generated code, no reflection |
| Performance | Baseline | ~2–3x faster, fewer allocations |
| Extra features | None | `CloneVT()`, `EqualVT()`, object pooling |
| Compatibility | Universal | Falls back to standard if VT methods missing |

vtprotobuf only affects the **gRPC wire protocol**. The HTTP/JSON gateway uses grpc-gateway's own marshallers independently.

To disable: `DISABLE_VT_PROTOBUF=true`. See the [vtprotobuf How-To](/howto/vtproto) for full details including code generation setup.

## How does ColdBrew ensure API consistency?

Through **compile-time enforcement**. Your `.proto` file is the single source of truth. Running `buf generate` produces:

1. **Typed Go interfaces** — the compiler refuses to build until every RPC method is implemented
2. **HTTP gateway handlers** — REST endpoints that can't drift from the gRPC definition
3. **OpenAPI spec** — Swagger documentation generated from the same proto, always in sync

This strongly prevents a documented endpoint that doesn't exist, an undocumented endpoint that does exist, or an HTTP route that doesn't match the gRPC method signature. The proto file is the contract — the compiler, the gateway, and the docs all enforce it.

See [Self-Documenting APIs](/architecture#self-documenting-apis) for the full pipeline.

## Is hystrixprometheus still maintained?

**No.** The `hystrixprometheus` package depends on `afex/hystrix-go`, which is unmaintained. Do not invest in this package for new projects.
Expand Down Expand Up @@ -112,6 +154,23 @@ func init() {

See the [Metrics How-To](/howto/Metrics/) for more details.

## How do I use grpcurl or Postman with my ColdBrew service?

ColdBrew enables [gRPC server reflection](https://github.com/grpc/grpc/blob/master/doc/server-reflection.md) by default, so tools like [grpcurl](https://github.com/fullstorydev/grpcurl), [grpcui](https://github.com/fullstorydev/grpcui), and Postman can discover your services and methods without needing proto files.

```bash
# List all services
grpcurl -plaintext localhost:9090 list

# Describe a specific service
grpcurl -plaintext localhost:9090 describe mypackage.MyService

# Call a method
grpcurl -plaintext -d '{"msg": "hello"}' localhost:9090 mypackage.MyService/Echo
```

To disable reflection (e.g., in production for security), set `DISABLE_GRPC_REFLECTION=true`. See the [Configuration Reference](/config-reference) for details.

## How do I configure graceful shutdown?

ColdBrew handles SIGTERM and SIGINT automatically. When a signal is received:
Expand Down Expand Up @@ -140,6 +199,18 @@ notifier.Notify(err, ctx)

See the [Errors How-To](/howto/errors) and [Integrations](/integrations) for full setup instructions.

## Is ColdBrew designed for Kubernetes?

Yes — ColdBrew is Kubernetes-native by design. Out of the box you get:

- **Liveness probe** at `/healthcheck` and **readiness probe** at `/readycheck`
- **Graceful shutdown** on SIGTERM with configurable drain periods (`SHUTDOWN_DURATION_IN_SECONDS`, `GRPC_GRACEFUL_DURATION_IN_SECONDS`)
- **Prometheus metrics** at `/metrics` for scraping
- **Structured JSON logging** to stdout (ready for Fluentd, Loki, or any log aggregator)
- **Environment variable configuration** via [envconfig](https://github.com/kelseyhightower/envconfig) — works natively with ConfigMaps and Secrets

ColdBrew also follows [12-factor app](https://12factor.net/) principles: no config files, stateless processes, port binding, and log streams. See the [Production Deployment guide](/howto/production) for K8s manifests, ServiceMonitor setup, and graceful shutdown tuning, and the [Architecture](/architecture) page for the full design principles table.

## Where can I get help?

- **[GitHub Discussions](https://github.com/go-coldbrew/core/discussions)** — Ask questions, share ideas
Expand Down
70 changes: 31 additions & 39 deletions Index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ permalink: /
# ColdBrew
{: .fs-9 }

A Go microservice framework for building production-grade gRPC services with built-in observability, resilience, and HTTP gateway support.
A Kubernetes-native Go microservice framework for building production-grade gRPC services with built-in observability, resilience, and HTTP gateway support. Follows [12-factor](https://12factor.net/) principles out of the box.
{: .fs-6 .fw-300 }

**Production-proven:** Powers 100+ microservices, handling peaks of ~70k QPS per service at [Gojek](https://www.gojek.com/en-id/).
Expand All @@ -25,12 +25,19 @@ A Go microservice framework for building production-grade gRPC services with bui

| Feature | Description |
|---------|-------------|
| **gRPC + REST Gateway** | Define your API once in protobuf, get both gRPC and REST endpoints automatically via [grpc-gateway] |
| **gRPC + REST Gateway** | Define your API once in protobufget gRPC, REST, and [Swagger docs](/architecture#self-documenting-apis) automatically via [grpc-gateway] |
| **Structured Logging** | Pluggable backends (go-kit, zap, logrus) with per-request context fields and trace ID propagation |
| **Distributed Tracing** | [OpenTelemetry], [Jaeger], and [New Relic] support with automatic span creation in interceptors |
| **Prometheus Metrics** | Built-in request latency, error rate, and circuit breaker metrics at `/metrics` |
| **Error Tracking** | Stack traces, gRPC status codes, and async notification to [Sentry], Rollbar, or Airbrake |
| **Resilience** | Client-side circuit breaking and retries via interceptors |
| **Fast Serialization** | [vtprotobuf] codec enabled by default — faster gRPC marshalling with automatic fallback to standard protobuf |
| **Kubernetes-native** | Health/ready probes, graceful SIGTERM shutdown, structured JSON logs, Prometheus metrics — all wired automatically |
| **Swagger / OpenAPI** | Interactive API docs auto-served at `/swagger/` from your protobuf definitions |
| **Profiling** | Go [pprof] endpoints at `/debug/pprof/` for CPU, memory, goroutine, and trace profiling |
| **gRPC Reflection** | Server reflection enabled by default — works with [grpcurl], [grpcui], and Postman |
| **HTTP Compression** | Automatic gzip compression for all HTTP gateway responses |
| **Container-aware Runtime** | Auto-tunes GOMAXPROCS to match container CPU limits via [automaxprocs] |

## Quick Start

Expand Down Expand Up @@ -60,44 +67,27 @@ Your service starts with all of these endpoints ready:
| `localhost:9091/swagger/` | Swagger UI |
| `localhost:9091/debug/pprof/` | Go pprof profiling |

## Minimal Service Example
## Define Once, Get Everything

A ColdBrew service implements the `CBService` interface:
Your API is defined once in protobuf — ColdBrew generates everything else:

```go
package main

import (
"context"

"github.com/go-coldbrew/core"
"github.com/go-coldbrew/core/config"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"google.golang.org/grpc"

pb "github.com/yourorg/myservice/proto" // your generated protobuf package
)

type myService struct{}

func (s *myService) InitGRPC(ctx context.Context, server *grpc.Server) error {
pb.RegisterMyServiceServer(server, s)
return nil
}

func (s *myService) InitHTTP(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) error {
return pb.RegisterMyServiceHandlerFromEndpoint(ctx, mux, endpoint, opts)
}

func main() {
cfg := config.GetColdBrewConfig()
cb := core.New(cfg)
cb.SetService(&myService{})
cb.Run()
```protobuf
rpc Echo(EchoRequest) returns (EchoResponse) {
option (google.api.http) = {
post: "/api/v1/echo"
body: "*"
};
}
```

All logging, tracing, metrics, health checks, and graceful shutdown are wired automatically.
This single definition gives you:
- **gRPC endpoint** on `:9090` — with reflection for [grpcurl] and Postman
- **REST endpoint** at `POST /api/v1/echo` on `:9091` — via [grpc-gateway]
- **Swagger UI** at `/swagger/` — interactive API docs from your proto
- **Prometheus metrics** — per-method latency, error rate, and request count
- **Distributed tracing** — automatic span creation through the interceptor chain

Run `buf generate` — it creates typed Go interfaces from your proto definitions. The compiler ensures every RPC method is implemented, so API changes are caught at build time, not runtime. Just fill in your business logic and `make run`. Logging, tracing, metrics, health checks, and graceful shutdown are wired automatically. See the [full pipeline](/architecture#self-documenting-apis) for details.

## How It Works

Expand Down Expand Up @@ -125,10 +115,6 @@ All logging, tracing, metrics, health checks, and graceful shutdown are wired au

ColdBrew is modular — use the full framework or pick individual packages:

```
options → errors → log → tracing → grpcpool → interceptors → data-builder → core
```

| Package | What It Does |
|---------|-------------|
| [**core**](https://github.com/go-coldbrew/core) | gRPC server + HTTP gateway, health checks, graceful shutdown |
Expand All @@ -152,6 +138,7 @@ ColdBrew integrates with the tools you already use:
- [new relic] — Application performance monitoring
- [sentry] — Error tracking and alerting
- [go-grpc-middleware] — Middleware utilities
- [vtprotobuf] — Fast protobuf serialization

## Next Steps

Expand All @@ -170,3 +157,8 @@ ColdBrew integrates with the tools you already use:
[new relic]: https://newrelic.com/
[sentry]: https://sentry.io/
[go-grpc-middleware]: https://pkg.go.dev/github.com/grpc-ecosystem/go-grpc-middleware
[vtprotobuf]: https://github.com/planetscale/vtprotobuf
[pprof]: https://pkg.go.dev/net/http/pprof
[grpcurl]: https://github.com/fullstorydev/grpcurl
[grpcui]: https://github.com/fullstorydev/grpcui
[automaxprocs]: https://github.com/uber-go/automaxprocs
2 changes: 1 addition & 1 deletion Packages.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
layout: default
title: Packages
description: "ColdBrew packages documentation"
description: "ColdBrew Go packages: core, interceptors, errors, log, tracing, options, grpcpool, and data-builder API reference"
permalink: /packages
nav_order: 9
---
Expand Down
12 changes: 7 additions & 5 deletions USING.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,13 @@ ColdBrew uses environment variables for configuration. Common settings:
| `HTTP_PORT` | `9091` | HTTP gateway port |
| `LOG_LEVEL` | `info` | Log level (debug, info, warn, error) |
| `JSON_LOGS` | `true` | JSON formatted logs |
| `ENVIRONMENT` | `development` | Environment name |
| `TRACE_HEADER_NAME` | `X-Trace-Id` | Header name for trace propagation |
| `NEW_RELIC_APP_NAME` | | New Relic application name |
| `NEW_RELIC_LICENSE_KEY` | | New Relic license key |
| `SENTRY_DSN` | | Sentry DSN for error tracking |
| `ENVIRONMENT` | `""` | Environment name |
| `TRACE_HEADER_NAME` | `x-trace-id` | Header name for trace propagation |
| `NEW_RELIC_APPNAME` | `""` | New Relic application name |
| `NEW_RELIC_LICENSE_KEY` | `""` | New Relic license key |
| `SENTRY_DSN` | `""` | Sentry DSN for error tracking |

See the **[Configuration Reference](/config-reference)** for the complete list of 40+ environment variables including gRPC keepalive, TLS, OpenTelemetry OTLP, Prometheus histogram buckets, and graceful shutdown tuning.

## Adding Interceptors

Expand Down
77 changes: 76 additions & 1 deletion architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,81 @@ permalink: /architecture

---

## Design Principles

ColdBrew follows [12-factor app](https://12factor.net/) methodology and is designed to run on Kubernetes from day one:

| 12-Factor Principle | How ColdBrew Implements It |
|--------------------|-----------------------------|
| **Config** | All configuration via environment variables ([envconfig](https://github.com/kelseyhightower/envconfig)) — no config files, no YAML. See [Configuration Reference](/config-reference) |
| **Port binding** | Self-contained HTTP (`:9091`) and gRPC (`:9090`) servers, no external app server needed |
| **Logs** | Structured JSON to stdout by default — ready for any log aggregator (Fluentd, Loki, CloudWatch) |
| **Disposability** | Graceful SIGTERM handling with configurable drain periods. See [Signals](/howto/signals) |
| **Dev/prod parity** | Same binary, same config mechanism, same observability in every environment |
| **Concurrency** | Stateless processes — scale horizontally by adding replicas |
| **Backing services** | External dependencies (databases, caches, queues) attached via environment variables |

ColdBrew is **Kubernetes-native**: health/ready probe endpoints, Prometheus metrics scraping, graceful pod termination, and structured logging work without any additional setup. See the [Production Deployment guide](/howto/production) for K8s manifests and configuration.

## Self-Documenting APIs

ColdBrew follows a **define once, get everything** approach. Your `.proto` file is the single source of truth — one `buf generate` produces everything your service needs:

```
┌─── Go protobuf types (*.pb.go)
├─── gRPC service stubs (*_grpc.pb.go)
myservice.proto ──buf──►├─── HTTP/REST gateway handlers (*.gw.go)
├─── OpenAPI/Swagger spec (*.swagger.json)
└─── vtprotobuf fast codec (*_vtproto.pb.go)
```

Each output maps to a self-documenting endpoint:

| Output | Serves | How Clients Discover It |
|--------|--------|------------------------|
| gRPC stubs | `:9090` | gRPC reflection — `grpcurl -plaintext localhost:9090 list` |
| HTTP gateway | `:9091/api/...` | Swagger UI at `/swagger/` |
| OpenAPI spec | `:9091/swagger/*.swagger.json` | Import into Postman, code generators, or API gateways |
| Health/version | `:9091/healthcheck` | Returns git commit, version, build date, Go version as JSON |
| Metrics | `:9091/metrics` | Prometheus self-describing exposition format with HELP lines |
| Profiling | `:9091/debug/pprof/` | Standard Go pprof index page |

**Every client gets documentation for free:**
- **gRPC clients** use server reflection to discover services and methods without proto files
- **REST clients** use the interactive Swagger UI or import the OpenAPI spec
- **Operations** use health checks (build metadata), Prometheus metrics, and pprof

The HTTP annotations in your proto file define both the REST routes and their Swagger documentation simultaneously:

```protobuf
rpc Echo(EchoRequest) returns (EchoResponse) {
option (google.api.http) = {
post: "/api/v1/example/echo"
body: "*"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Echo endpoint"
description: "Returns the input message unchanged."
tags: "example"
};
}
```

This creates: a gRPC method, a `POST /api/v1/example/echo` REST endpoint, and a documented Swagger UI entry — all from one definition.

### Type-Safe by Design

`buf generate` produces typed Go interfaces from your proto service definitions. When you add a new RPC method to your `.proto` file and regenerate, the Go compiler will refuse to build until you implement it — there's no way to forget an endpoint or deploy a half-implemented API.

```
myservice.proto buf generate Go compiler
─────────────── ──────────────────────► ─────────────────
rpc Echo(...) EchoServer interface ✓ Implemented
rpc Greet(...) GreetServer interface ✗ Build error until implemented
```

This means your proto file is the **contract** — the compiler enforces it, grpc-gateway serves it as REST, and the OpenAPI spec documents it. They can never drift from each other.

## Overview

ColdBrew is a layered framework where each layer is an independent Go module. The `core` package orchestrates everything, but you can use any package standalone.
Expand Down Expand Up @@ -125,7 +200,7 @@ Interceptors are gRPC middleware that run on every request. ColdBrew chains them
| Order | Interceptor | Package | What It Does |
|-------|------------|---------|--------------|
| 1 | Response Time Logging | `interceptors` | Logs method name, duration, and status code |
| 2 | Trace ID | `interceptors` | Extracts or generates a trace ID and adds it to the context |
| 2 | Trace ID | `interceptors` | Generates a trace ID (or reads it from the `x-trace-id` HTTP header or a `trace_id` proto field) and propagates it to structured logs and Sentry/Rollbar error reports |
| 3 | Context Tags | `grpc_ctxtags` | Extracts gRPC metadata into context tags for logging |
| 4 | OpenTracing | `grpc_opentracing` | Creates a tracing span for the request |
| 5 | Prometheus | `grpc_prometheus` | Records request count, latency histogram, and status codes |
Expand Down
Loading
Loading