-
Notifications
You must be signed in to change notification settings - Fork 437
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into duxing/WithCustomTag
- Loading branch information
Showing
107 changed files
with
4,682 additions
and
946 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
Component,Origin,License,Copyright | ||
import,io.opentracing,Apache-2.0,Copyright 2016-2017 The OpenTracing Authors | ||
appsec,https://github.com/DataDog/libddwaf,Apache-2.0 OR BSD-3-Clause,Copyright (c) 2021 Datadog <info@datadoghq.com> | ||
golang,https://go.googlesource.com/go,BSD-3-Clause,Copyright (c) 2009 The Go Authors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Unless explicitly stated otherwise all files in this repository are licensed | ||
// under the Apache License Version 2.0. | ||
// This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
// Copyright 2022 Datadog, Inc. | ||
|
||
// Package gqlgen provides functions to trace the 99designs/gqlgen package (https://github.com/99designs/gqlgen). | ||
package gqlgen_test | ||
|
||
import ( | ||
"log" | ||
"net/http" | ||
|
||
"github.com/99designs/gqlgen/example/todo" | ||
"github.com/99designs/gqlgen/graphql/handler" | ||
|
||
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" | ||
|
||
gqlgentrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/99designs/gqlgen" | ||
) | ||
|
||
func Example() { | ||
tracer.Start() | ||
defer tracer.Stop() | ||
|
||
t := gqlgentrace.NewTracer( | ||
gqlgentrace.WithAnalytics(true), | ||
gqlgentrace.WithServiceName("todo.server"), | ||
) | ||
h := handler.NewDefaultServer(todo.NewExecutableSchema(todo.New())) | ||
h.Use(t) | ||
http.Handle("/query", h) | ||
log.Fatal(http.ListenAndServe(":8080", nil)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Unless explicitly stated otherwise all files in this repository are licensed | ||
// under the Apache License Version 2.0. | ||
// This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
// Copyright 2022 Datadog, Inc. | ||
|
||
package gqlgen | ||
|
||
import ( | ||
"math" | ||
|
||
"gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" | ||
) | ||
|
||
const defaultServiceName = "graphql" | ||
|
||
type config struct { | ||
serviceName string | ||
analyticsRate float64 | ||
} | ||
|
||
// An Option configures the gqlgen integration. | ||
type Option func(t *config) | ||
|
||
func defaults(t *config) { | ||
t.serviceName = defaultServiceName | ||
t.analyticsRate = globalconfig.AnalyticsRate() | ||
} | ||
|
||
// WithAnalytics enables or disables Trace Analytics for all started spans. | ||
func WithAnalytics(on bool) Option { | ||
if on { | ||
return WithAnalyticsRate(1.0) | ||
} | ||
return WithAnalyticsRate(math.NaN()) | ||
} | ||
|
||
// WithAnalyticsRate sets the sampling rate for Trace Analytics events correlated to started spans. | ||
func WithAnalyticsRate(rate float64) Option { | ||
return func(t *config) { | ||
t.analyticsRate = rate | ||
} | ||
} | ||
|
||
// WithServiceName sets the given service name for the gqlgen server. | ||
func WithServiceName(name string) Option { | ||
return func(t *config) { | ||
t.serviceName = name | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
// Unless explicitly stated otherwise all files in this repository are licensed | ||
// under the Apache License Version 2.0. | ||
// This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
// Copyright 2022 Datadog, Inc. | ||
|
||
// Package gqlgen contains an implementation of a gqlgen tracer, and functions | ||
// to construct and configure the tracer. The tracer can be passed to the gqlgen | ||
// handler (see package github.com/99designs/gqlgen/handler) | ||
// | ||
// Warning: Data obfuscation hasn't been implemented for graphql queries yet, | ||
// any sensitive data in the query will be sent to Datadog as the resource name | ||
// of the span. To ensure no sensitive data is included in your spans, always | ||
// use parameterized graphql queries with sensitive data in variables. | ||
package gqlgen | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"math" | ||
"strings" | ||
"time" | ||
|
||
"github.com/99designs/gqlgen/graphql" | ||
"github.com/vektah/gqlparser/v2/ast" | ||
|
||
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace" | ||
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext" | ||
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" | ||
) | ||
|
||
const ( | ||
defaultGraphqlOperation = "graphql.request" | ||
|
||
readOp = "graphql.read" | ||
parsingOp = "graphql.parse" | ||
validationOp = "graphql.validate" | ||
) | ||
|
||
type gqlTracer struct { | ||
cfg *config | ||
} | ||
|
||
// NewTracer creates a graphql.HandlerExtension instance that can be used with | ||
// a graphql.handler.Server. | ||
// Options can be passed in for further configuration. | ||
func NewTracer(opts ...Option) graphql.HandlerExtension { | ||
cfg := new(config) | ||
defaults(cfg) | ||
for _, fn := range opts { | ||
fn(cfg) | ||
} | ||
return &gqlTracer{cfg: cfg} | ||
} | ||
|
||
func (t *gqlTracer) ExtensionName() string { | ||
return "DatadogTracing" | ||
} | ||
|
||
func (t *gqlTracer) Validate(schema graphql.ExecutableSchema) error { | ||
return nil // unimplemented | ||
} | ||
|
||
func (t *gqlTracer) InterceptResponse(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { | ||
opts := []ddtrace.StartSpanOption{ | ||
tracer.SpanType(ext.SpanTypeGraphQL), | ||
tracer.ServiceName(t.cfg.serviceName), | ||
} | ||
if !math.IsNaN(t.cfg.analyticsRate) { | ||
opts = append(opts, tracer.Tag(ext.EventSampleRate, t.cfg.analyticsRate)) | ||
} | ||
var ( | ||
octx *graphql.OperationContext | ||
) | ||
name := defaultGraphqlOperation | ||
if graphql.HasOperationContext(ctx) { | ||
// Variables in the operation will be left out of the tags | ||
// until obfuscation is implemented in the agent. | ||
octx = graphql.GetOperationContext(ctx) | ||
if octx.Operation != nil { | ||
if octx.Operation.Operation == ast.Subscription { | ||
// These are long running queries for a subscription, | ||
// remaining open indefinitely until a subscription ends. | ||
// Return early and do not create these spans. | ||
return next(ctx) | ||
} | ||
name = fmt.Sprintf("%s.%s", ext.SpanTypeGraphQL, octx.Operation.Operation) | ||
} | ||
if octx.RawQuery != "" { | ||
opts = append(opts, tracer.ResourceName(octx.RawQuery)) | ||
} | ||
opts = append(opts, tracer.StartTime(octx.Stats.OperationStart)) | ||
} | ||
var span ddtrace.Span | ||
span, ctx = tracer.StartSpanFromContext(ctx, name, opts...) | ||
defer func() { | ||
var errs []string | ||
for _, err := range graphql.GetErrors(ctx) { | ||
errs = append(errs, err.Message) | ||
} | ||
var err error | ||
if len(errs) > 0 { | ||
err = fmt.Errorf(strings.Join(errs, ", ")) | ||
} | ||
span.Finish(tracer.WithError(err)) | ||
}() | ||
|
||
if octx != nil { | ||
// Create child spans based on the stats in the operation context. | ||
createChildSpan := func(name string, start, finish time.Time) { | ||
var childOpts []ddtrace.StartSpanOption | ||
childOpts = append(childOpts, tracer.StartTime(start)) | ||
childOpts = append(childOpts, tracer.ResourceName(name)) | ||
var childSpan ddtrace.Span | ||
childSpan, _ = tracer.StartSpanFromContext(ctx, name, childOpts...) | ||
childSpan.Finish(tracer.FinishTime(finish)) | ||
} | ||
createChildSpan(readOp, octx.Stats.Read.Start, octx.Stats.Read.End) | ||
createChildSpan(parsingOp, octx.Stats.Parsing.Start, octx.Stats.Parsing.End) | ||
createChildSpan(validationOp, octx.Stats.Validation.Start, octx.Stats.Validation.End) | ||
} | ||
return next(ctx) | ||
} | ||
|
||
// Ensure all of these interfaces are implemented. | ||
var _ interface { | ||
graphql.HandlerExtension | ||
graphql.ResponseInterceptor | ||
} = &gqlTracer{} |
Oops, something went wrong.