mirror of
https://github.com/pomerium/pomerium.git
synced 2025-07-07 03:48:17 +02:00
Bumps the go group with 24 updates: | Package | From | To | | --- | --- | --- | | [cloud.google.com/go/storage](https://github.com/googleapis/google-cloud-go) | `1.53.0` | `1.55.0` | | [github.com/VictoriaMetrics/fastcache](https://github.com/VictoriaMetrics/fastcache) | `1.12.2` | `1.12.4` | | [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) | `1.79.3` | `1.80.0` | | [github.com/docker/docker](https://github.com/docker/docker) | `28.1.1+incompatible` | `28.2.2+incompatible` | | [github.com/exaring/otelpgx](https://github.com/exaring/otelpgx) | `0.9.1` | `0.9.3` | | [github.com/google/go-jsonnet](https://github.com/google/go-jsonnet) | `0.20.0` | `0.21.0` | | [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) | `5.7.4` | `5.7.5` | | [github.com/miekg/dns](https://github.com/miekg/dns) | `1.1.65` | `1.1.66` | | [github.com/minio/minio-go/v7](https://github.com/minio/minio-go) | `7.0.91` | `7.0.92` | | [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) | `1.4.2` | `1.5.0` | | [github.com/pires/go-proxyproto](https://github.com/pires/go-proxyproto) | `0.8.0` | `0.8.1` | | [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) | `0.51.0` | `0.52.0` | | [go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc](https://github.com/open-telemetry/opentelemetry-go-contrib) | `0.60.0` | `0.61.0` | | [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) | `0.60.0` | `0.61.0` | | [go.opentelemetry.io/contrib/propagators/autoprop](https://github.com/open-telemetry/opentelemetry-go-contrib) | `0.60.0` | `0.61.0` | | [go.opentelemetry.io/otel/bridge/opencensus](https://github.com/open-telemetry/opentelemetry-go) | `1.35.0` | `1.36.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc](https://github.com/open-telemetry/opentelemetry-go) | `1.35.0` | `1.36.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlptrace](https://github.com/open-telemetry/opentelemetry-go) | `1.35.0` | `1.36.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc](https://github.com/open-telemetry/opentelemetry-go) | `1.35.0` | `1.36.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp](https://github.com/open-telemetry/opentelemetry-go) | `1.35.0` | `1.36.0` | | [go.opentelemetry.io/proto/otlp](https://github.com/open-telemetry/opentelemetry-proto-go) | `1.6.0` | `1.7.0` | | [google.golang.org/api](https://github.com/googleapis/google-api-go-client) | `0.230.0` | `0.235.0` | | [google.golang.org/genproto/googleapis/rpc](https://github.com/googleapis/go-genproto) | `0.0.0-20250428153025-10db94c68c34` | `0.0.0-20250528174236-200df99c418a` | | [google.golang.org/grpc](https://github.com/grpc/grpc-go) | `1.72.0` | `1.72.2` | Updates `cloud.google.com/go/storage` from 1.53.0 to 1.55.0 - [Release notes](https://github.com/googleapis/google-cloud-go/releases) - [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md) - [Commits](googleapis/google-cloud-go@spanner/v1.53.0...spanner/v1.55.0) Updates `github.com/VictoriaMetrics/fastcache` from 1.12.2 to 1.12.4 - [Release notes](https://github.com/VictoriaMetrics/fastcache/releases) - [Commits](VictoriaMetrics/fastcache@v1.12.2...v1.12.4) Updates `github.com/aws/aws-sdk-go-v2/service/s3` from 1.79.3 to 1.80.0 - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json) - [Commits](aws/aws-sdk-go-v2@service/s3/v1.79.3...service/s3/v1.80.0) Updates `github.com/docker/docker` from 28.1.1+incompatible to 28.2.2+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](moby/moby@v28.1.1...v28.2.2) Updates `github.com/exaring/otelpgx` from 0.9.1 to 0.9.3 - [Release notes](https://github.com/exaring/otelpgx/releases) - [Commits](exaring/otelpgx@v0.9.1...v0.9.3) Updates `github.com/google/go-jsonnet` from 0.20.0 to 0.21.0 - [Release notes](https://github.com/google/go-jsonnet/releases) - [Changelog](https://github.com/google/go-jsonnet/blob/master/.goreleaser.yml) - [Commits](google/go-jsonnet@v0.20.0...v0.21.0) Updates `github.com/jackc/pgx/v5` from 5.7.4 to 5.7.5 - [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md) - [Commits](jackc/pgx@v5.7.4...v5.7.5) Updates `github.com/miekg/dns` from 1.1.65 to 1.1.66 - [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release) - [Commits](miekg/dns@v1.1.65...v1.1.66) Updates `github.com/minio/minio-go/v7` from 7.0.91 to 7.0.92 - [Release notes](https://github.com/minio/minio-go/releases) - [Commits](minio/minio-go@v7.0.91...v7.0.92) Updates `github.com/open-policy-agent/opa` from 1.4.2 to 1.5.0 - [Release notes](https://github.com/open-policy-agent/opa/releases) - [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md) - [Commits](open-policy-agent/opa@v1.4.2...v1.5.0) Updates `github.com/pires/go-proxyproto` from 0.8.0 to 0.8.1 - [Release notes](https://github.com/pires/go-proxyproto/releases) - [Commits](pires/go-proxyproto@v0.8.0...v0.8.1) Updates `github.com/quic-go/quic-go` from 0.51.0 to 0.52.0 - [Release notes](https://github.com/quic-go/quic-go/releases) - [Commits](quic-go/quic-go@v0.51.0...v0.52.0) Updates `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc` from 0.60.0 to 0.61.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go-contrib@zpages/v0.60.0...zpages/v0.61.0) Updates `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp` from 0.60.0 to 0.61.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go-contrib@zpages/v0.60.0...zpages/v0.61.0) Updates `go.opentelemetry.io/contrib/propagators/autoprop` from 0.60.0 to 0.61.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go-contrib@zpages/v0.60.0...zpages/v0.61.0) Updates `go.opentelemetry.io/otel/bridge/opencensus` from 1.35.0 to 1.36.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.35.0...v1.36.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` from 1.35.0 to 1.36.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.35.0...v1.36.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlptrace` from 1.35.0 to 1.36.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.35.0...v1.36.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` from 1.35.0 to 1.36.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.35.0...v1.36.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp` from 1.35.0 to 1.36.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.35.0...v1.36.0) Updates `go.opentelemetry.io/proto/otlp` from 1.6.0 to 1.7.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-proto-go/releases) - [Commits](open-telemetry/opentelemetry-proto-go@v1.6.0...v1.7.0) Updates `google.golang.org/api` from 0.230.0 to 0.235.0 - [Release notes](https://github.com/googleapis/google-api-go-client/releases) - [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md) - [Commits](googleapis/google-api-go-client@v0.230.0...v0.235.0) Updates `google.golang.org/genproto/googleapis/rpc` from 0.0.0-20250428153025-10db94c68c34 to 0.0.0-20250528174236-200df99c418a - [Commits](https://github.com/googleapis/go-genproto/commits) Updates `google.golang.org/grpc` from 1.72.0 to 1.72.2 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](grpc/grpc-go@v1.72.0...v1.72.2) --- updated-dependencies: - dependency-name: cloud.google.com/go/storage dependency-version: 1.55.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/VictoriaMetrics/fastcache dependency-version: 1.12.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: github.com/aws/aws-sdk-go-v2/service/s3 dependency-version: 1.80.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/docker/docker dependency-version: 28.2.2+incompatible dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/exaring/otelpgx dependency-version: 0.9.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: github.com/google/go-jsonnet dependency-version: 0.21.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/jackc/pgx/v5 dependency-version: 5.7.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: github.com/miekg/dns dependency-version: 1.1.66 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: github.com/minio/minio-go/v7 dependency-version: 7.0.92 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: github.com/open-policy-agent/opa dependency-version: 1.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/pires/go-proxyproto dependency-version: 0.8.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: github.com/quic-go/quic-go dependency-version: 0.52.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc dependency-version: 0.61.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp dependency-version: 0.61.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/contrib/propagators/autoprop dependency-version: 0.61.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/otel/bridge/opencensus dependency-version: 1.36.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc dependency-version: 1.36.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace dependency-version: 1.36.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc dependency-version: 1.36.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp dependency-version: 1.36.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/proto/otlp dependency-version: 1.7.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: google.golang.org/api dependency-version: 0.235.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: google.golang.org/genproto/googleapis/rpc dependency-version: 0.0.0-20250528174236-200df99c418a dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: google.golang.org/grpc dependency-version: 1.72.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go ... Signed-off-by: dependabot[bot] <support@github.com>
375 lines
12 KiB
Go
375 lines
12 KiB
Go
package selftests_test
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"maps"
|
|
"net/http"
|
|
"slices"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/stretchr/testify/suite"
|
|
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
|
"go.opentelemetry.io/otel/sdk/resource"
|
|
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
|
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
|
oteltrace "go.opentelemetry.io/otel/trace"
|
|
|
|
"github.com/pomerium/pomerium/config"
|
|
"github.com/pomerium/pomerium/internal/testenv"
|
|
"github.com/pomerium/pomerium/internal/testenv/scenarios"
|
|
"github.com/pomerium/pomerium/internal/testenv/snippets"
|
|
"github.com/pomerium/pomerium/internal/testenv/upstreams"
|
|
. "github.com/pomerium/pomerium/internal/testutil/tracetest" //nolint:revive
|
|
"github.com/pomerium/pomerium/pkg/telemetry/trace"
|
|
)
|
|
|
|
var allServices = []string{
|
|
"Test Environment",
|
|
"Authorize",
|
|
"Authenticate",
|
|
"Control Plane",
|
|
"Data Broker",
|
|
"Proxy",
|
|
"Upstream",
|
|
"IDP",
|
|
"HTTP Client",
|
|
"Envoy",
|
|
}
|
|
|
|
func TestOTLPTracing(t *testing.T) {
|
|
srv := scenarios.NewOTLPTraceReceiver()
|
|
env := testenv.New(t, testenv.WithTraceDebugFlags(testenv.StandardTraceDebugFlags), testenv.WithTraceClient(srv.NewGRPCClient()))
|
|
env.Add(srv)
|
|
|
|
up := upstreams.HTTP(nil, upstreams.WithDisplayName("Upstream"))
|
|
up.Handle("/foo", func(w http.ResponseWriter, _ *http.Request) {
|
|
w.Write([]byte("OK"))
|
|
})
|
|
env.Add(scenarios.NewIDP([]*scenarios.User{
|
|
{
|
|
Email: "foo@example.com",
|
|
FirstName: "Firstname",
|
|
LastName: "Lastname",
|
|
},
|
|
}))
|
|
|
|
route := up.Route().
|
|
From(env.SubdomainURL("foo")).
|
|
PPL(`{"allow":{"and":["email":{"is":"foo@example.com"}]}}`)
|
|
|
|
env.AddUpstream(up)
|
|
env.Start()
|
|
snippets.WaitStartupComplete(env)
|
|
|
|
ctx, span := env.Tracer().Start(env.Context(), "Authenticate", oteltrace.WithNewRoot())
|
|
resp, err := up.Get(route, upstreams.AuthenticateAs("foo@example.com"), upstreams.Path("/foo"), upstreams.Context(ctx))
|
|
span.End()
|
|
require.NoError(t, err)
|
|
body, err := io.ReadAll(resp.Body)
|
|
assert.NoError(t, err)
|
|
assert.NoError(t, resp.Body.Close())
|
|
assert.Equal(t, resp.StatusCode, 200)
|
|
assert.Equal(t, "OK", string(body))
|
|
|
|
env.Stop()
|
|
|
|
results := NewTraceResults(srv.FlushResourceSpans())
|
|
var (
|
|
testEnvironmentLocalTest = fmt.Sprintf("Test Environment: %s", t.Name())
|
|
testEnvironmentAuthenticate = "Test Environment: Authenticate"
|
|
authenticateOAuth2Client = "Authenticate: OAuth2 Client: GET /.well-known/jwks.json"
|
|
authorizeDatabrokerSync = "Authorize: databroker.DataBrokerService/Sync"
|
|
authorizeDatabrokerSyncLatest = "Authorize: databroker.DataBrokerService/SyncLatest"
|
|
idpServerGetUserinfo = "IDP: Server: GET /oidc/userinfo"
|
|
idpServerPostToken = "IDP: Server: POST /oidc/token"
|
|
controlPlaneEnvoyAccessLogs = "Control Plane: envoy.service.accesslog.v3.AccessLogService/StreamAccessLogs"
|
|
controlPlaneEnvoyDiscovery = "Control Plane: envoy.service.discovery.v3.AggregatedDiscoveryService/DeltaAggregatedResources"
|
|
controlPlaneExport = "Control Plane: opentelemetry.proto.collector.trace.v1.TraceService/Export"
|
|
)
|
|
|
|
results.MatchTraces(t,
|
|
MatchOptions{
|
|
Exact: true,
|
|
CheckDetachedSpans: true,
|
|
},
|
|
Match{Name: testEnvironmentLocalTest, TraceCount: 1, Services: []string{"Test Environment", "Control Plane", "Data Broker"}},
|
|
Match{Name: testEnvironmentAuthenticate, TraceCount: 1, Services: allServices},
|
|
Match{Name: authenticateOAuth2Client, TraceCount: Greater(0)},
|
|
Match{Name: idpServerGetUserinfo, TraceCount: EqualToMatch(authenticateOAuth2Client)},
|
|
Match{Name: idpServerPostToken, TraceCount: EqualToMatch(authenticateOAuth2Client)},
|
|
Match{Name: authorizeDatabrokerSync, TraceCount: Greater(0)},
|
|
Match{Name: authorizeDatabrokerSyncLatest, TraceCount: Greater(0)},
|
|
Match{Name: controlPlaneEnvoyDiscovery, TraceCount: 1},
|
|
Match{Name: controlPlaneExport, TraceCount: Greater(0)},
|
|
Match{Name: controlPlaneEnvoyAccessLogs, TraceCount: Any{}},
|
|
)
|
|
}
|
|
|
|
func TestOTLPTracing_TraceCorrelation(t *testing.T) {
|
|
srv := scenarios.NewOTLPTraceReceiver()
|
|
env := testenv.New(t, testenv.WithTraceDebugFlags(testenv.StandardTraceDebugFlags), testenv.WithTraceClient(srv.NewGRPCClient()))
|
|
env.Add(srv)
|
|
|
|
up := upstreams.HTTP(nil, upstreams.WithDisplayName("Upstream"), upstreams.WithNoClientTracing())
|
|
up.Handle("/foo", func(w http.ResponseWriter, _ *http.Request) {
|
|
w.Write([]byte("OK"))
|
|
})
|
|
env.Add(scenarios.NewIDP([]*scenarios.User{
|
|
{
|
|
Email: "foo@example.com",
|
|
FirstName: "Firstname",
|
|
LastName: "Lastname",
|
|
},
|
|
}))
|
|
|
|
route := up.Route().
|
|
From(env.SubdomainURL("foo")).
|
|
PPL(`{"allow":{"and":["email":{"is":"foo@example.com"}]}}`)
|
|
|
|
env.AddUpstream(up)
|
|
env.Start()
|
|
snippets.WaitStartupComplete(env)
|
|
|
|
resp, err := up.Get(route, upstreams.AuthenticateAs("foo@example.com"), upstreams.Path("/foo"), upstreams.Context(t.Context()))
|
|
require.NoError(t, err)
|
|
body, err := io.ReadAll(resp.Body)
|
|
assert.NoError(t, err)
|
|
assert.NoError(t, resp.Body.Close())
|
|
assert.Equal(t, resp.StatusCode, 200)
|
|
assert.Equal(t, "OK", string(body))
|
|
|
|
env.Stop()
|
|
results := NewTraceResults(srv.FlushResourceSpans())
|
|
traces := results.GetTraces()
|
|
// one unauthenticated (ends in /.pomerium/callback redirect), one authenticated
|
|
assert.Len(t, traces.ByName[fmt.Sprintf("Envoy: ingress: GET foo.localhost.pomerium.io:%d/foo", env.Ports().ProxyHTTP.Value())].WithoutErrors(), 2)
|
|
}
|
|
|
|
type SamplingTestSuite struct {
|
|
suite.Suite
|
|
env testenv.Environment
|
|
receiver *scenarios.OTLPTraceReceiver
|
|
route testenv.Route
|
|
upstream upstreams.HTTPUpstream
|
|
|
|
sampled atomic.Int32
|
|
notSampled atomic.Int32
|
|
}
|
|
|
|
func (s *SamplingTestSuite) SetupTest() {
|
|
s.receiver = scenarios.NewOTLPTraceReceiver()
|
|
s.env = testenv.New(s.T(),
|
|
testenv.WithTraceDebugFlags(testenv.StandardTraceDebugFlags|trace.EnvoyFlushEverySpan),
|
|
testenv.WithTraceClient(s.receiver.NewGRPCClient()),
|
|
)
|
|
s.env.Add(s.receiver)
|
|
|
|
s.sampled.Store(0)
|
|
s.notSampled.Store(0)
|
|
|
|
s.env.Add(testenv.ModifierFunc(func(_ context.Context, cfg *config.Config) {
|
|
half := 0.5
|
|
cfg.Options.Tracing.OtelTracesSamplerArg = &half
|
|
}))
|
|
s.env.Add(scenarios.NewIDP([]*scenarios.User{
|
|
{
|
|
Email: "foo@example.com",
|
|
FirstName: "Firstname",
|
|
LastName: "Lastname",
|
|
},
|
|
}))
|
|
|
|
s.upstream = upstreams.HTTP(nil, upstreams.WithNoClientTracing(), upstreams.WithDisplayName("Upstream"))
|
|
s.upstream.Handle("/", s.handleRequest)
|
|
|
|
s.route = s.upstream.Route().
|
|
From(s.env.SubdomainURL("sampling-50pct")).
|
|
PPL(`{"allow":{"and":["email":{"is":"foo@example.com"}]}}`)
|
|
|
|
s.env.AddUpstream(s.upstream)
|
|
s.env.Start()
|
|
snippets.WaitStartupComplete(s.env)
|
|
}
|
|
|
|
func (s *SamplingTestSuite) TearDownTest() {
|
|
s.env.Stop()
|
|
}
|
|
|
|
func (s *SamplingTestSuite) handleRequest(w http.ResponseWriter, req *http.Request) {
|
|
span := oteltrace.SpanFromContext(req.Context())
|
|
flags := span.SpanContext().TraceFlags()
|
|
if flags.IsSampled() {
|
|
s.sampled.Add(1)
|
|
} else {
|
|
s.notSampled.Add(1)
|
|
}
|
|
w.Write([]byte("OK"))
|
|
}
|
|
|
|
func (s *SamplingTestSuite) doRequest(ctx context.Context) {
|
|
resp, err := s.upstream.Get(s.route, upstreams.AuthenticateAs("foo@example.com"), upstreams.Path("/"), upstreams.Context(ctx))
|
|
s.Require().NoError(err)
|
|
body, err := io.ReadAll(resp.Body)
|
|
s.Assert().NoError(err)
|
|
s.Assert().NoError(resp.Body.Close())
|
|
s.Assert().Equal(resp.StatusCode, 200)
|
|
s.Assert().Equal("OK", string(body))
|
|
}
|
|
|
|
func (s *SamplingTestSuite) TestNoExternalTraceparent() {
|
|
for {
|
|
s.doRequest(context.Background())
|
|
if s.sampled.Load() == 20 {
|
|
break
|
|
}
|
|
}
|
|
|
|
s.Assert().NoError(trace.ForceFlush(s.env.Context()))
|
|
trace.WaitForSpans(s.env.Context(), 10*time.Second)
|
|
|
|
s.Assert().Equal(int32(20), s.sampled.Load()) // 10 sampled
|
|
// Ideally we get ~50% sample rate, but CI will always be unlucky.
|
|
s.Assert().Greater(s.notSampled.Load(), int32(0))
|
|
|
|
results := NewTraceResults(s.receiver.FlushResourceSpans())
|
|
traces := results.GetTraces()
|
|
s.Assert().Len(traces.ByParticipant["Upstream"], 20)
|
|
}
|
|
|
|
func (s *SamplingTestSuite) TestExternalTraceparentAlwaysSample() {
|
|
tracer := trace.NewTracerProvider(s.env.Context(), "Always Sample",
|
|
sdktrace.WithSampler(sdktrace.AlwaysSample())).Tracer(trace.PomeriumCoreTracer)
|
|
for range 100 {
|
|
ctx, span := tracer.Start(context.Background(), "should sample")
|
|
s.doRequest(ctx)
|
|
span.End()
|
|
}
|
|
|
|
s.Assert().NoError(trace.ForceFlush(s.env.Context()))
|
|
trace.WaitForSpans(s.env.Context(), 10*time.Second)
|
|
|
|
// if the request already has a traceparent header, they will always be sampled
|
|
// regardless of the random sample rate we configured
|
|
s.Assert().Equal(int32(100), s.sampled.Load())
|
|
s.Assert().Equal(int32(0), s.notSampled.Load())
|
|
|
|
results := NewTraceResults(s.receiver.FlushResourceSpans())
|
|
traces := results.GetTraces()
|
|
s.Assert().Len(traces.ByParticipant["Envoy"], 100)
|
|
}
|
|
|
|
func (s *SamplingTestSuite) TestExternalTraceparentNeverSample() {
|
|
tracer := trace.NewTracerProvider(s.env.Context(), "Never Sample", sdktrace.WithSampler(sdktrace.NeverSample())).Tracer(trace.PomeriumCoreTracer)
|
|
for range 100 {
|
|
ctx, span := tracer.Start(context.Background(), "should not sample")
|
|
s.doRequest(ctx)
|
|
span.End()
|
|
}
|
|
|
|
s.Assert().NoError(trace.ForceFlush(s.env.Context()))
|
|
trace.WaitForSpans(s.env.Context(), 10*time.Second)
|
|
|
|
s.Assert().Equal(int32(0), s.sampled.Load())
|
|
s.Assert().Equal(int32(100), s.notSampled.Load())
|
|
|
|
results := NewTraceResults(s.receiver.FlushResourceSpans())
|
|
traces := results.GetTraces()
|
|
if (len(traces.ByParticipant)) != 0 {
|
|
// whether or not these show up is timing dependent, but not important
|
|
possibleTraces := map[string]struct{}{
|
|
"Test Environment: Start": {},
|
|
"IDP: Server: POST /oidc/token": {},
|
|
"IDP: Server: GET /oidc/userinfo": {},
|
|
"Authenticate: OAuth2 Client: GET /.well-known/jwks.json": {},
|
|
"Authorize: databroker.DataBrokerService/SyncLatest": {},
|
|
}
|
|
actual := slices.Collect(maps.Keys(traces.ByName))
|
|
for _, name := range actual {
|
|
if _, ok := possibleTraces[name]; !ok {
|
|
s.Fail("unexpected trace: " + name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSampling(t *testing.T) {
|
|
suite.Run(t, &SamplingTestSuite{})
|
|
}
|
|
|
|
func TestExternalSpans(t *testing.T) {
|
|
srv := scenarios.NewOTLPTraceReceiver()
|
|
|
|
// set up external tracer
|
|
external := otlptrace.NewUnstarted(srv.NewGRPCClient())
|
|
r, err := resource.Merge(
|
|
resource.Empty(),
|
|
resource.NewWithAttributes(
|
|
semconv.SchemaURL,
|
|
semconv.ServiceName("External"),
|
|
),
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
externalTracerProvider := sdktrace.NewTracerProvider(sdktrace.WithBatcher(external), sdktrace.WithResource(r))
|
|
|
|
env := testenv.New(t, testenv.WithTraceDebugFlags(testenv.StandardTraceDebugFlags|trace.EnvoyFlushEverySpan), testenv.WithTraceClient(srv.NewGRPCClient()))
|
|
env.Add(srv)
|
|
|
|
up := upstreams.HTTP(nil, upstreams.WithNoClientTracing())
|
|
up.Handle("/foo", func(w http.ResponseWriter, _ *http.Request) {
|
|
w.Write([]byte("OK"))
|
|
})
|
|
env.Add(scenarios.NewIDP([]*scenarios.User{
|
|
{
|
|
Email: "foo@example.com",
|
|
FirstName: "Firstname",
|
|
LastName: "Lastname",
|
|
},
|
|
}))
|
|
|
|
route := up.Route().
|
|
From(env.SubdomainURL("foo")).
|
|
PPL(`{"allow":{"and":["email":{"is":"foo@example.com"}]}}`)
|
|
|
|
env.AddUpstream(up)
|
|
env.Start()
|
|
require.NoError(t, external.Start(env.Context()))
|
|
snippets.WaitStartupComplete(env)
|
|
|
|
ctx, span := externalTracerProvider.Tracer("external").Start(t.Context(), "External Root", oteltrace.WithNewRoot())
|
|
t.Logf("external span id: %s", span.SpanContext().SpanID().String())
|
|
resp, err := up.Get(route, upstreams.AuthenticateAs("foo@example.com"), upstreams.Path("/foo"), upstreams.Context(ctx))
|
|
span.End()
|
|
require.NoError(t, err)
|
|
body, err := io.ReadAll(resp.Body)
|
|
assert.NoError(t, err)
|
|
assert.NoError(t, resp.Body.Close())
|
|
assert.Equal(t, resp.StatusCode, 200)
|
|
assert.Equal(t, "OK", string(body))
|
|
|
|
assert.NoError(t, externalTracerProvider.ForceFlush(t.Context()))
|
|
assert.NoError(t, externalTracerProvider.Shutdown(t.Context()))
|
|
assert.NoError(t, external.Shutdown(ctx))
|
|
env.Stop()
|
|
|
|
results := NewTraceResults(srv.FlushResourceSpans())
|
|
results.MatchTraces(t, MatchOptions{CheckDetachedSpans: true},
|
|
Match{Name: "External: External Root", TraceCount: 1, Services: []string{
|
|
"Authorize",
|
|
"Authenticate",
|
|
"Control Plane",
|
|
"Data Broker",
|
|
"Proxy",
|
|
"IDP",
|
|
"Envoy",
|
|
"External",
|
|
"HTTP Upstream",
|
|
}},
|
|
)
|
|
}
|