├── Dockerfile ├── README.md ├── main.go ├── go.mod ├── pkg └── sink.go └── config.yaml /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.17 2 | 3 | WORKDIR /app 4 | COPY go.mod ./ 5 | COPY go.sum ./ 6 | RUN go mod download 7 | 8 | COPY . ./ 9 | 10 | RUN go build -o /envoy-als 11 | EXPOSE 5000 12 | CMD [ "/envoy-als"] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Envoy ALS example 2 | 3 | This example is used as part of the [Envoy Fundamentals course](https://academy.tetrate.io/courses/envoy-fundamentals). The example is a minimal is a minimal implementation of a gRPC access log service (ALS). -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | sink "envoy-als/pkg" 5 | "fmt" 6 | "log" 7 | "net" 8 | "os" 9 | 10 | v3 "github.com/envoyproxy/go-control-plane/envoy/service/accesslog/v3" 11 | "google.golang.org/grpc" 12 | ) 13 | 14 | var defaultPort = "5000" 15 | 16 | func main() { 17 | 18 | port, ok := os.LookupEnv("PORT") 19 | if !ok { 20 | port = defaultPort 21 | } 22 | grpcServer := grpc.NewServer() 23 | v3.RegisterAccessLogServiceServer(grpcServer, sink.New()) 24 | 25 | l, err := net.Listen("tcp", fmt.Sprintf(":%s", port)) 26 | if err != nil { 27 | log.Fatalf("failed to listen: %v", err) 28 | } 29 | 30 | log.Printf("Listening on :%s", port) 31 | grpcServer.Serve(l) 32 | } 33 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module envoy-als 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/envoyproxy/go-control-plane v0.10.0 7 | github.com/gogo/protobuf v1.3.2 8 | google.golang.org/grpc v1.42.0 9 | ) 10 | 11 | require ( 12 | github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 // indirect 13 | github.com/envoyproxy/protoc-gen-validate v0.1.0 // indirect 14 | github.com/golang/protobuf v1.5.2 // indirect 15 | golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect 16 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect 17 | golang.org/x/text v0.3.3 // indirect 18 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 19 | google.golang.org/protobuf v1.27.1 // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /pkg/sink.go: -------------------------------------------------------------------------------- 1 | package sink 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "log" 7 | 8 | v3 "github.com/envoyproxy/go-control-plane/envoy/service/accesslog/v3" 9 | "github.com/gogo/protobuf/jsonpb" 10 | ) 11 | 12 | type server struct { 13 | marshaler jsonpb.Marshaler 14 | } 15 | 16 | var _ v3.AccessLogServiceServer = &server{} 17 | 18 | func New() v3.AccessLogServiceServer { 19 | fmt.Println("Creating new ALS server") 20 | return &server{} 21 | } 22 | 23 | func (s *server) StreamAccessLogs(stream v3.AccessLogService_StreamAccessLogsServer) error { 24 | for { 25 | in, err := stream.Recv() 26 | log.Println("Received value") 27 | if err == io.EOF { 28 | return nil 29 | } 30 | if err != nil { 31 | return err 32 | } 33 | str, _ := s.marshaler.MarshalToString(in) 34 | log.Println(str) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /config.yaml: -------------------------------------------------------------------------------- 1 | static_resources: 2 | listeners: 3 | - name: listener_0 4 | address: 5 | socket_address: 6 | address: 0.0.0.0 7 | port_value: 10000 8 | filter_chains: 9 | - filters: 10 | - name: envoy.filters.network.http_connection_manager 11 | typed_config: 12 | "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager 13 | stat_prefix: ingress_http 14 | access_log: 15 | - name: envoy.access_loggers.http_grpc 16 | typed_config: 17 | "@type": type.googleapis.com/envoy.extensions.access_loggers.grpc.v3.HttpGrpcAccessLogConfig 18 | common_config: 19 | log_name: "mygrpclog" 20 | transport_api_version: V3 21 | grpc_service: 22 | envoy_grpc: 23 | cluster_name: grpc_als_cluster 24 | http_filters: 25 | - name: envoy.filters.http.router 26 | route_config: 27 | name: my_first_route 28 | virtual_hosts: 29 | - name: direct_response_service 30 | domains: ["*"] 31 | routes: 32 | - match: 33 | prefix: "/404" 34 | direct_response: 35 | status: 404 36 | body: 37 | inline_string: "404" 38 | - match: 39 | prefix: "/" 40 | direct_response: 41 | status: 200 42 | body: 43 | inline_string: "200" 44 | clusters: 45 | - name: grpc_als_cluster 46 | connect_timeout: 5s 47 | type: STRICT_DNS 48 | http2_protocol_options: {} 49 | load_assignment: 50 | cluster_name: grpc_als_cluster 51 | endpoints: 52 | - lb_endpoints: 53 | - endpoint: 54 | address: 55 | socket_address: 56 | address: 127.0.0.1 57 | port_value: 5000 --------------------------------------------------------------------------------