Skip to content

Commit

Permalink
feat(metrics): Add stats.wasm to proxy config
Browse files Browse the repository at this point in the history
This change propagates the stats.wasm module to each sidecar proxy's
config. stats.wasm is built and embedded in the osm-controller binary
and configured inline via LDS.

Signed-off-by: Jon Huhn <johuhn@microsoft.com>
  • Loading branch information
nojnhuh committed Feb 17, 2021
1 parent 2434267 commit 1e44994
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ _dist/
creds.json
screenlog.*
demo/bin/
*.wasm

## Ignore test coverage files
coverage.json
Expand Down
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ clean-osm-injector:
build: build-osm-controller build-osm-injector

.PHONY: build-osm-controller
build-osm-controller: clean-osm-controller
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -o ./bin/osm-controller/osm-controller -ldflags "-X $(BUILD_DATE_VAR)=$(BUILD_DATE) -X $(BUILD_VERSION_VAR)=$(VERSION) -X $(BUILD_GITCOMMIT_VAR)=$(GIT_SHA) -s -w" ./cmd/osm-controller
build-osm-controller: clean-osm-controller wasm/stats.wasm
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -o ./bin/osm-controller/osm-controller -ldflags "-X $(BUILD_DATE_VAR)=$(BUILD_DATE) -X $(BUILD_VERSION_VAR)=$(VERSION) -X $(BUILD_GITCOMMIT_VAR)=$(GIT_SHA) -X github.com/openservicemesh/osm/pkg/envoy/lds.statsWASMBytes=$$(base64 < wasm/stats.wasm | tr -d \\n) -s -w" ./cmd/osm-controller

.PHONY: build-osm-injector
build-osm-injector: clean-osm-injector
Expand Down Expand Up @@ -147,6 +147,9 @@ docker-build-osm-controller: build-osm-controller
docker-build-osm-injector: build-osm-injector
docker build -t $(CTR_REGISTRY)/osm-injector:$(CTR_TAG) -f dockerfiles/Dockerfile.osm-injector bin/osm-injector

wasm/stats.wasm: wasm/stats.cc wasm/Makefile
docker run --rm -v $(PWD)/wasm:/work -w /work openservicemesh/proxy-wasm-cpp-sdk:956f0d500c380cc1656a2d861b7ee12c2515a664 /build_wasm.sh

.PHONY: docker-build
docker-build: $(DOCKER_DEMO_TARGETS) docker-build-init docker-build-osm-controller docker-build-osm-injector

Expand Down
16 changes: 16 additions & 0 deletions pkg/envoy/lds/connection_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/openservicemesh/osm/pkg/configurator"
"github.com/openservicemesh/osm/pkg/constants"
"github.com/openservicemesh/osm/pkg/envoy"
"github.com/openservicemesh/osm/pkg/featureflags"
)

const (
Expand Down Expand Up @@ -54,6 +55,21 @@ func getHTTPConnectionManager(routeName string, cfg configurator.Configurator) *
connManager.Tracing = tracing
}

if featureflags.IsWASMStatsEnabled() {
statsFilter, err := getStatsWASMFilter()
if err != nil {
log.Error().Err(err).Msg("failed to get stats WASM filter")
return connManager
}

// wellknown.Router filter must be last
var filters []*xds_hcm.HttpFilter
if statsFilter != nil {
filters = append(filters, statsFilter)
}
connManager.HttpFilters = append(filters, connManager.HttpFilters...)
}

return connManager
}

Expand Down
41 changes: 41 additions & 0 deletions pkg/envoy/lds/listener_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/openservicemesh/osm/pkg/constants"
"github.com/openservicemesh/osm/pkg/envoy"
"github.com/openservicemesh/osm/pkg/envoy/route"
"github.com/openservicemesh/osm/pkg/featureflags"
)

// Tests TestGetFilterForService checks that a proper filter type is properly returned
Expand Down Expand Up @@ -112,5 +113,45 @@ var _ = Describe("Test getHTTPConnectionManager", func() {

Expect(connManager.Tracing).To(Equal(nilHcmTrace))
})

It("Returns no stats config when WASM is disabled", func() {
mockConfigurator.EXPECT().IsTracingEnabled().AnyTimes()
oldWASMflag := featureflags.Features.WASMStats
featureflags.Features.WASMStats = false

oldStatsWASMBytes := statsWASMBytes
statsWASMBytes = "some bytes"

connManager := getHTTPConnectionManager(route.InboundRouteConfigName, mockConfigurator)

Expect(connManager.HttpFilters).To(HaveLen(2))
Expect(connManager.HttpFilters[0].GetName()).To(Equal(wellknown.HTTPRoleBasedAccessControl))
Expect(connManager.HttpFilters[1].GetName()).To(Equal(wellknown.Router))
Expect(connManager.LocalReplyConfig).To(BeNil())

// reset global state
statsWASMBytes = oldStatsWASMBytes
featureflags.Features.WASMStats = oldWASMflag
})

It("Returns proper stats config when WASM is enabled", func() {
mockConfigurator.EXPECT().IsTracingEnabled().AnyTimes()
oldWASMflag := featureflags.Features.WASMStats
featureflags.Features.WASMStats = true

oldStatsWASMBytes := statsWASMBytes
statsWASMBytes = "some bytes"

connManager := getHTTPConnectionManager(route.InboundRouteConfigName, mockConfigurator)

Expect(connManager.GetHttpFilters()).To(HaveLen(3))
Expect(connManager.GetHttpFilters()[0].GetName()).To(Equal("envoy.filters.http.wasm"))
Expect(connManager.GetHttpFilters()[1].GetName()).To(Equal(wellknown.HTTPRoleBasedAccessControl))
Expect(connManager.GetHttpFilters()[2].GetName()).To(Equal(wellknown.Router))

// reset global state
statsWASMBytes = oldStatsWASMBytes
featureflags.Features.WASMStats = oldWASMflag
})
})
})
61 changes: 61 additions & 0 deletions pkg/envoy/lds/wasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package lds

import (
"encoding/base64"
"io/ioutil"
"strings"

envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
xds_wasm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/wasm/v3"
xds_hcm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
xds_wasm_ext "github.com/envoyproxy/go-control-plane/envoy/extensions/wasm/v3"

"github.com/golang/protobuf/ptypes"
)

var statsWASMBytes string

func init() {
b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(statsWASMBytes))
b, _ := ioutil.ReadAll(b64)
statsWASMBytes = string(b)
}

func getStatsWASMFilter() (*xds_hcm.HttpFilter, error) {
if len(statsWASMBytes) == 0 {
return nil, nil
}
wasmPlug := &xds_wasm.Wasm{
Config: &xds_wasm_ext.PluginConfig{
Name: "stats",
Vm: &xds_wasm_ext.PluginConfig_VmConfig{
VmConfig: &xds_wasm_ext.VmConfig{
Runtime: "envoy.wasm.runtime.v8",
Code: &envoy_config_core_v3.AsyncDataSource{
Specifier: &envoy_config_core_v3.AsyncDataSource_Local{
Local: &envoy_config_core_v3.DataSource{
Specifier: &envoy_config_core_v3.DataSource_InlineBytes{
InlineBytes: []byte(statsWASMBytes),
},
},
},
},
AllowPrecompiled: true,
},
},
},
}

wasmAny, err := ptypes.MarshalAny(wasmPlug)
if err != nil {
log.Error().Err(err).Msg("Error marshalling WasmService object")
return nil, err
}

return &xds_hcm.HttpFilter{
Name: "envoy.filters.http.wasm",
ConfigType: &xds_hcm.HttpFilter_TypedConfig{
TypedConfig: wasmAny,
},
}, nil
}

0 comments on commit 1e44994

Please sign in to comment.