Skip to content
Draft
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
15 changes: 12 additions & 3 deletions apps/rpc/golang/Dockerfile.calendar.go.dd
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
# Unless explicitly stated otherwise all files in this repository are licensed
# under the Apache 2.0 License.
#
FROM golang:1.22

# Multi-stage build for the calendar-dd gRPC server.
# Stage 1: Build the Go binary.
FROM golang:1.22 AS builder

WORKDIR /app
COPY calendar-dd calendar/
COPY protos protos/

WORKDIR /app/calendar
RUN go mod download
RUN CGO_ENABLED=0 go build -o /calendar

# Stage 2: Create a minimal runtime image.
FROM gcr.io/distroless/static-debian12:nonroot

COPY --from=builder /calendar /calendar

RUN go build -o /calendar
# Expose the gRPC port.
EXPOSE 9090

# Run as non-root user (provided by distroless:nonroot).
CMD [ "/calendar" ]
15 changes: 12 additions & 3 deletions apps/rpc/golang/Dockerfile.calendar.go.otel
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
# Unless explicitly stated otherwise all files in this repository are licensed
# under the Apache 2.0 License.
#
FROM golang:1.22

# Multi-stage build for the calendar-otel gRPC server.
# Stage 1: Build the Go binary.
FROM golang:1.22 AS builder

WORKDIR /app
COPY calendar-otel calendar/
COPY protos protos/

WORKDIR /app/calendar
RUN go mod download
RUN CGO_ENABLED=0 go build -o /calendar

# Stage 2: Create a minimal runtime image.
FROM gcr.io/distroless/static-debian12:nonroot

COPY --from=builder /calendar /calendar

RUN go build -o /calendar
# Expose the gRPC port.
EXPOSE 9090

# Run as non-root user (provided by distroless:nonroot).
CMD [ "/calendar" ]
60 changes: 50 additions & 10 deletions apps/rpc/golang/README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,46 @@
# Calendar GRPC server
# Calendar gRPC Server

Generate proto files using script `generate.sh`

`calendar-dd` is instrumented with DD tracer.
`calendar-otel` is instrumented with Otel tracer.
`calendar-dd` is instrumented with the DD tracer (`dd-trace-go` OTel provider).
`calendar-otel` is instrumented with the OTel SDK tracer (OTLP exporter to DD Agent).

Both the servers have implemented [health grpc](https://github.com/grpc-ecosystem/grpc-health-probe)
Both servers implement [gRPC health checking](https://github.com/grpc-ecosystem/grpc-health-probe).

## kubernetes
## gRPC Instrumentation

***Build***
Both variants use `otelgrpc.NewServerHandler()` (stats handler) for gRPC tracing,
which is the recommended approach as of otelgrpc v0.49.0+. The deprecated
`UnaryServerInterceptor`/`StreamServerInterceptor` pattern has been replaced.

The stats handler automatically creates spans with semantic convention attributes:
- `rpc.system` = "grpc"
- `rpc.service` = the gRPC service name
- `rpc.method` = the gRPC method name
- `rpc.grpc.status_code` = the gRPC status code

These attributes map to Datadog APM resource names when ingested via OTLP.

## OpenCensus Bridge (Deprecated)

The `calendar-client` and `calendar-otel` variants use the OpenCensus gRPC plugin
(`go.opencensus.io/plugin/ocgrpc`) for collecting gRPC metrics (e.g.,
`grpc.io/client/roundtrip_latency`, `grpc.io/server/server_latency`). These metrics
are bridged to OTel via `go.opentelemetry.io/otel/bridge/opencensus` and exported
through the OTLP pipeline to the Datadog Agent.

**OpenCensus is archived (deprecated since 2023).** The recommended migration path is:

1. Replace `ocgrpc.ServerHandler` / `ocgrpc.ClientHandler` with
`otelgrpc.NewServerHandler()` / `otelgrpc.NewClientHandler()`, which provide
built-in metrics collection starting with otelgrpc v0.49.0+.
2. Remove the `go.opencensus.io` and `go.opentelemetry.io/otel/bridge/opencensus`
dependencies.
3. See: https://opentelemetry.io/docs/migration/opencensus/

## Kubernetes

**Build**

calendar-dd

Expand All @@ -23,7 +54,7 @@ calendar-otel
docker build --file Dockerfile.calendar.go.otel --tag otel-demo:calendar-go-otel .
```

***Deploy***
**Deploy**

Install calendar-dd

Expand All @@ -39,13 +70,22 @@ helm install -n otel-ingest calendar-go-otel-ingest ./calendar-otel/k8s/ --set n
```


# Calendar client
# Calendar Client

When you have the calendar server running locally, you can use calendar-client to send gRPC requests to the server.

```
cd calendar-client
cd calendar-client
go run main.go
```

The client is instrumented with [OpenCensus gRPC plug-in](https://pkg.go.dev/go.opencensus.io/plugin/ocgrpc) which automatically collects gRPC metrics. It then uses the [OpenCensus Bridge from OpenTelemetry](https://github.com/open-telemetry/opentelemetry-go/tree/main/bridge/opencensus) and [OTLP exporter](https://github.com/open-telemetry/opentelemetry-go/tree/main/exporters/otlp/otlpmetric) to export the metrics in OTLP format.
The client is instrumented with [OpenCensus gRPC plug-in](https://pkg.go.dev/go.opencensus.io/plugin/ocgrpc) which automatically collects gRPC metrics. It then uses the [OpenCensus Bridge from OpenTelemetry](https://github.com/open-telemetry/opentelemetry-go/tree/main/bridge/opencensus) and [OTLP exporter](https://github.com/open-telemetry/opentelemetry-go/tree/main/exporters/otlp/otlpmetric) to export the metrics in OTLP format.

## TLS Configuration

Both servers currently use insecure connections for simplicity. For production deployments:

1. Generate TLS certificates (e.g., via cert-manager in Kubernetes).
2. Use `grpc.Creds(credentials.NewTLS(tlsConfig))` server option.
3. Use `grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))` client option.
4. See: https://grpc.io/docs/guides/auth/#with-server-authentication-ssltls
48 changes: 23 additions & 25 deletions apps/rpc/golang/calendar-client/go.mod
Original file line number Diff line number Diff line change
@@ -1,38 +1,36 @@
module github.com/DataDog/opentelemetry-examples/apps/rpc/calendar-client

go 1.20
go 1.22.0

replace github.com/DataDog/opentelemetry-examples/apps/rpc/protos => ../protos/

require (
github.com/DataDog/opentelemetry-examples/apps/rpc/protos v0.0.0-00010101000000-000000000000
go.opencensus.io v0.24.0
go.opentelemetry.io/otel v1.16.0
go.opentelemetry.io/otel/bridge/opencensus v0.39.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.39.0
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.39.0
go.opentelemetry.io/otel/sdk/metric v0.39.0
google.golang.org/grpc v1.57.1
go.opentelemetry.io/otel v1.34.0
go.opentelemetry.io/otel/bridge/opencensus v1.34.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0
go.opentelemetry.io/otel/sdk/metric v1.34.0
google.golang.org/grpc v1.69.4
)

require (
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.39.0 // indirect
go.opentelemetry.io/otel/metric v1.16.0 // indirect
go.opentelemetry.io/otel/sdk v1.16.0 // indirect
go.opentelemetry.io/otel/trace v1.16.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/protobuf v1.31.0 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
golang.org/x/net v0.34.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/text v0.21.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/protobuf v1.36.3 // indirect
)
Loading