caddy/modules/caddyhttp/tracing/module_test.go
Andrii Kushch d0b608af31
tracing: New OpenTelemetry module (#4361)
* opentelemetry: create a new module

* fix imports

* fix test

* Update modules/caddyhttp/opentelemetry/README.md

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* Update modules/caddyhttp/opentelemetry/README.md

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* Update modules/caddyhttp/opentelemetry/README.md

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* Update modules/caddyhttp/opentelemetry/tracer.go

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* rename error ErrUnsupportedTracesProtocol

* replace spaces with tabs in the test data

* Update modules/caddyhttp/opentelemetry/README.md

Co-authored-by: Francis Lavoie <lavofr@gmail.com>

* Update modules/caddyhttp/opentelemetry/README.md

Co-authored-by: Francis Lavoie <lavofr@gmail.com>

* replace spaces with tabs in the README.md

* use default values for a propagation and exporter protocol

* set http attributes with helper

* simplify code

* Cleanup modules/caddyhttp/opentelemetry/README.md

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* Update link in README.md

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* Update documentation in README.md

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* Update link to naming spec in README.md

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* Rename module from opentelemetry to tracing

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* Rename span_name to span

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* Rename span_name to span

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* Simplify otel resource creation

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* handle extra attributes

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* update go.opentelemetry.io/otel/semconv to 1.7.0

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* update go.opentelemetry.io/otel version

* remove environment variable handling

* always use tracecontext,baggage as propagators

* extract tracer name into variable

* rename OpenTelemetry to Tracing

* simplify resource creation

* update go.mod

* rename package from opentelemetry to tracing

* cleanup tests

* update Caddyfile example in README.md

* update README.md

* fix test

* fix module name in README.md

* fix module name in README.md

* change names in README.md and tests

* order imports

* remove redundant tests

* Update documentation README.md

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* Fix grammar

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* Update comments

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* Update comments

Co-authored-by: Dave Henderson <dhenderson@gmail.com>

* update go.sum

* update go.sum

* Add otelhttp instrumentation, update OpenTelemetry libraries.

* Use otelhttp instrumentation for instrumenting HTTP requests.

This change uses context.WithValue to inject the next handler into the
request context via a "nextCall" carrier struct, and pass it on to a
standard Go HTTP handler returned by otelhttp.NewHandler. The
underlying handler will extract the next handler from the context,
call it and pass the returned error to the carrier struct.

* use zap.Error() for the error log

* remove README.md

* update dependencies

* clean up the code

* change comment

* move serveHTTP method from separate file

* add syntax to the UnmarshalCaddyfile comment

* go import the file

* admin: Write proper status on invalid requests (#4569) (fix #4561)

* update dependencies

Co-authored-by: Dave Henderson <dhenderson@gmail.com>
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
Co-authored-by: Vibhav Pant <vibhavp@gmail.com>
Co-authored-by: Alok Naushad <alokme123@gmail.com>
Co-authored-by: Cedric Ziel <cedric@cedric-ziel.com>
2022-03-08 12:18:32 -07:00

183 lines
4.2 KiB
Go

package tracing
import (
"context"
"errors"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
)
func TestTracing_UnmarshalCaddyfile(t *testing.T) {
tests := []struct {
name string
spanName string
d *caddyfile.Dispenser
wantErr bool
}{
{
name: "Full config",
spanName: "my-span",
d: caddyfile.NewTestDispenser(`
tracing {
span my-span
}`),
wantErr: false,
},
{
name: "Only span name in the config",
spanName: "my-span",
d: caddyfile.NewTestDispenser(`
tracing {
span my-span
}`),
wantErr: false,
},
{
name: "Empty config",
d: caddyfile.NewTestDispenser(`
tracing {
}`),
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ot := &Tracing{}
if err := ot.UnmarshalCaddyfile(tt.d); (err != nil) != tt.wantErr {
t.Errorf("UnmarshalCaddyfile() error = %v, wantErrType %v", err, tt.wantErr)
}
if ot.SpanName != tt.spanName {
t.Errorf("UnmarshalCaddyfile() SpanName = %v, want SpanName %v", ot.SpanName, tt.spanName)
}
})
}
}
func TestTracing_UnmarshalCaddyfile_Error(t *testing.T) {
tests := []struct {
name string
d *caddyfile.Dispenser
wantErr bool
}{
{
name: "Unknown parameter",
d: caddyfile.NewTestDispenser(`
tracing {
foo bar
}`),
wantErr: true,
},
{
name: "Missed argument",
d: caddyfile.NewTestDispenser(`
tracing {
span
}`),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ot := &Tracing{}
if err := ot.UnmarshalCaddyfile(tt.d); (err != nil) != tt.wantErr {
t.Errorf("UnmarshalCaddyfile() error = %v, wantErrType %v", err, tt.wantErr)
}
})
}
}
func TestTracing_ServeHTTP_Propagation_Without_Initial_Headers(t *testing.T) {
ot := &Tracing{
SpanName: "mySpan",
}
req := httptest.NewRequest("GET", "https://example.com/foo", nil)
w := httptest.NewRecorder()
var handler caddyhttp.HandlerFunc = func(writer http.ResponseWriter, request *http.Request) error {
traceparent := request.Header.Get("Traceparent")
if traceparent == "" || strings.HasPrefix(traceparent, "00-00000000000000000000000000000000-0000000000000000") {
t.Errorf("Invalid traceparent: %v", traceparent)
}
return nil
}
ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()})
defer cancel()
if err := ot.Provision(ctx); err != nil {
t.Errorf("Provision error: %v", err)
t.FailNow()
}
if err := ot.ServeHTTP(w, req, handler); err != nil {
t.Errorf("ServeHTTP error: %v", err)
}
}
func TestTracing_ServeHTTP_Propagation_With_Initial_Headers(t *testing.T) {
ot := &Tracing{
SpanName: "mySpan",
}
req := httptest.NewRequest("GET", "https://example.com/foo", nil)
req.Header.Set("traceparent", "00-11111111111111111111111111111111-1111111111111111-01")
w := httptest.NewRecorder()
var handler caddyhttp.HandlerFunc = func(writer http.ResponseWriter, request *http.Request) error {
traceparent := request.Header.Get("Traceparent")
if !strings.HasPrefix(traceparent, "00-11111111111111111111111111111111") {
t.Errorf("Invalid traceparent: %v", traceparent)
}
return nil
}
ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()})
defer cancel()
if err := ot.Provision(ctx); err != nil {
t.Errorf("Provision error: %v", err)
t.FailNow()
}
if err := ot.ServeHTTP(w, req, handler); err != nil {
t.Errorf("ServeHTTP error: %v", err)
}
}
func TestTracing_ServeHTTP_Next_Error(t *testing.T) {
ot := &Tracing{
SpanName: "mySpan",
}
req := httptest.NewRequest("GET", "https://example.com/foo", nil)
w := httptest.NewRecorder()
expectErr := errors.New("test error")
var handler caddyhttp.HandlerFunc = func(writer http.ResponseWriter, request *http.Request) error {
return expectErr
}
ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()})
defer cancel()
if err := ot.Provision(ctx); err != nil {
t.Errorf("Provision error: %v", err)
t.FailNow()
}
if err := ot.ServeHTTP(w, req, handler); err == nil || !errors.Is(err, expectErr) {
t.Errorf("expected error, got: %v", err)
}
}