A gRPC service that accepts any gRPC requests and logs them in JSON format without decoding the request body.
- ✅ Accepts any gRPC unary-unary requests without requiring proto definitions
- ✅ Logs requests with timestamp, metadata, and raw binary body
- ✅ Configurable port via
PORTenvironment variable - ✅ Hexagonal architecture for clean separation of concerns
- ✅ JSON logging to stdout
- ✅ Comprehensive test coverage (unit + integration tests)
The project follows hexagonal architecture:
├── cmd/server/ # Application entry point
├── internal/
│ ├── ports/ # Abstract interfaces (Logger, Config)
│ ├── adapters/ # Concrete implementations (JSONLogger, EnvConfig)
│ └── services/ # Business logic (GRPCHandler)
├── tests/ # Integration tests
└── test_client/ # Example test client
# Build everything
make all
# Or build individually
make build # Server
make client # Simple test client
make client-proto # Protobuf test client
make decoder # Decoder tool# Use default port 50051
./grpc-raw-dumper
# Use custom port
PORT=9090 ./grpc-raw-dumper# Run all tests (unit + integration)
go test ./...
# Run with verbose output
go test -v ./...
# Run only unit tests
go test ./internal/...
# Run only integration tests
go test ./tests/...# Run full demo with server, client, and decoder
make demoThe service logs each request as a JSON object:
{
"timestamp": "2025-11-13T08:25:34.019+02:00",
"method": "/test.Service/TestMethod",
"metadata": {
":authority": "localhost:50051",
"content-type": "application/grpc+raw",
"user-agent": "grpc-go/1.59.0",
"custom-header": "custom-value"
},
"body": "SGVsbG8gd29ybGQh"
}- timestamp: ISO 8601 formatted timestamp
- method: Full gRPC method name (format:
/package.Service/Method) - metadata: All gRPC metadata headers as key-value pairs
- body: Base64-encoded binary request body
Build and run the simple test client (sends raw messages):
# Build and run
make client
./test_client/test_client
# Connect to custom port
PORT=9090 ./test_client/test_clientThe advanced test client sends real protobuf-encoded messages:
# Build and run
make client-proto
./test_client_proto/test_client_protoThis client sends realistic requests:
- Creates users with email, roles, etc.
- Gets users by ID
- Updates user information
- Creates products with prices and tags
- Lists products with pagination
Use the decoder tool to decode base64-encoded protobuf messages from logs:
# Build decoder
make decoder
# Decode a CreateUser request
./tools/decoder/decoder "/example.UserService/CreateUser" "Cghqb2huX2RvZRIU..."
# Output:
# Method: /example.UserService/CreateUser
# Decoded message:
# {
# "username": "john_doe",
# "email": "john.doe@example.com",
# ...
# }Python decoder also available: tools/decoder.py (requires pip install grpcio-tools protobuf)
Run a complete demo with server, client, and decoder:
make demo$ PORT=50051 ./grpc-raw-dumper
2025/11/13 08:25:12 gRPC server listening on 0.0.0.0:50051
{"timestamp":"2025-11-13T08:25:34.019+02:00","method":"/test.Service/TestMethod","metadata":{":authority":"localhost:50051","client-version":"1.0.0","content-type":"application/grpc+raw","request-id":"12345","user-agent":"grpc-go/1.59.0","user-id":"user-abc"},"body":"SGVsbG8gZnJvbSB0ZXN0IGNsaWVudCEgVGhpcyBpcyBhIHRlc3QgbWVzc2FnZS4="}
{"timestamp":"2025-11-13T08:25:34.121+02:00","method":"/another.Service/AnotherMethod","metadata":{":authority":"localhost:50051","content-type":"application/grpc+raw","request-id":"67890","user-agent":"grpc-go/1.59.0"},"body":"U2Vjb25kIHJlcXVlc3Qgd2l0aCBkaWZmZXJlbnQgZGF0YQ=="}- Go 1.21+
- google.golang.org/grpc v1.59.0+
- google.golang.org/protobuf v1.31.0+
go mod downloadPorts (interfaces):
Logger- Interface for logging requestsConfig- Interface for configuration
Adapters (implementations):
JSONLogger- Logs to stdout in JSON formatEnvConfig- Reads configuration from environment variables
Services (business logic):
GRPCHandler- Handles incoming gRPC requests using UnknownServiceHandler- Uses custom
rawCodecto work with raw binary data without proto definitions
- The server uses
grpc.UnknownServiceHandlerto accept any gRPC method call - A custom codec (
rawCodec) passes through binary data without decoding - Metadata is extracted from the gRPC context
- Request details are logged as JSON to stdout
- Server responds with an empty message
# All tests
go test -v ./...
# With coverage
go test -cover ./...
# Integration test only
go test -v ./tests/
# Specific package
go test -v ./internal/services/- Adapters: Tests for JSON logger and environment config
- Services: Tests for gRPC handler with mock logger
- Integration: End-to-end test with real server and client
See ADVANCED_USAGE.md for:
- Working with custom protobuf files
- Decoding messages (Go and Python)
- Real-world use cases
- Performance tips
- Troubleshooting
grpc-raw-dumper/
├── cmd/server/ # Server entry point
├── internal/ # Core implementation
│ ├── adapters/ # Concrete implementations
│ ├── ports/ # Interface definitions
│ └── services/ # Business logic
├── proto/ # Protobuf definitions
│ ├── example.proto # Example service definitions
│ ├── example.pb.go # Generated protobuf code
│ └── example_grpc.pb.go # Generated gRPC code
├── test_client/ # Simple test client
├── test_client_proto/ # Advanced protobuf client
├── tests/ # Integration tests
├── tools/
│ ├── decoder/ # Go decoder tool
│ └── decoder.py # Python decoder tool
└── Makefile # Build commands
MIT