-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add dice example * Add manual instrumentation * Update changelog * Add comments * Use naked return consistently * Move handleFunc to main * refactor: Extract newHTTPHandler * Fix comment * Improve comments * Update example/dice/otel.go Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com> * Simplify BaseContext * Update doc.go * Update example/dice/main.go Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Rename span and metric names --------- Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com> Co-authored-by: Phillip Carter <pcarter@fastmail.com>
- Loading branch information
1 parent
612208d
commit 0425c09
Showing
10 changed files
with
358 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ go.work.sum | |
|
||
gen/ | ||
|
||
/example/dice/dice | ||
/example/fib/fib | ||
/example/fib/traces.txt | ||
/example/jaeger/jaeger | ||
|
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,16 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
// Dice is the "Roll the dice" getting started example application. | ||
package main |
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,35 @@ | ||
module go.opentelemetry.io/otel/example/dice | ||
|
||
go 1.20 | ||
|
||
require ( | ||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 | ||
go.opentelemetry.io/otel v1.19.0-rc.1 | ||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 | ||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 | ||
go.opentelemetry.io/otel/metric v1.19.0-rc.1 | ||
go.opentelemetry.io/otel/sdk v1.19.0-rc.1 | ||
go.opentelemetry.io/otel/sdk/metric v1.19.0-rc.1 | ||
) | ||
|
||
require ( | ||
github.com/felixge/httpsnoop v1.0.3 // indirect | ||
github.com/go-logr/logr v1.2.4 // indirect | ||
github.com/go-logr/stdr v1.2.2 // indirect | ||
go.opentelemetry.io/otel/trace v1.19.0-rc.1 // indirect | ||
golang.org/x/sys v0.12.0 // indirect | ||
) | ||
|
||
replace go.opentelemetry.io/otel/exporters/stdout/stdouttrace => ../../exporters/stdout/stdouttrace | ||
|
||
replace go.opentelemetry.io/otel/exporters/stdout/stdoutmetric => ../../exporters/stdout/stdoutmetric | ||
|
||
replace go.opentelemetry.io/otel => ../.. | ||
|
||
replace go.opentelemetry.io/otel/trace => ../../trace | ||
|
||
replace go.opentelemetry.io/otel/metric => ../../metric | ||
|
||
replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric | ||
|
||
replace go.opentelemetry.io/otel/sdk => ../../sdk |
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,16 @@ | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= | ||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= | ||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= | ||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= | ||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= | ||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= | ||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= | ||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= | ||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI= | ||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48= | ||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= | ||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= |
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,99 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package main | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"log" | ||
"net" | ||
"net/http" | ||
"os" | ||
"os/signal" | ||
"time" | ||
|
||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" | ||
) | ||
|
||
func main() { | ||
if err := run(); err != nil { | ||
log.Fatalln(err) | ||
} | ||
} | ||
|
||
func run() (err error) { | ||
// Handle SIGINT (CTRL+C) gracefully. | ||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) | ||
defer stop() | ||
|
||
// Set up OpenTelemetry. | ||
serviceName := "dice" | ||
serviceVersion := "0.1.0" | ||
otelShutdown, err := setupOTelSDK(ctx, serviceName, serviceVersion) | ||
if err != nil { | ||
return | ||
} | ||
// Handle shutdown properly so nothing leaks. | ||
defer func() { | ||
err = errors.Join(err, otelShutdown(context.Background())) | ||
}() | ||
|
||
// Start HTTP server. | ||
srv := &http.Server{ | ||
Addr: ":8080", | ||
BaseContext: func(_ net.Listener) context.Context { return ctx }, | ||
ReadTimeout: time.Second, | ||
WriteTimeout: 10 * time.Second, | ||
Handler: newHTTPHandler(), | ||
} | ||
srvErr := make(chan error, 1) | ||
go func() { | ||
srvErr <- srv.ListenAndServe() | ||
}() | ||
|
||
// Wait for interruption. | ||
select { | ||
case err = <-srvErr: | ||
// Error when starting HTTP server. | ||
return | ||
case <-ctx.Done(): | ||
// Wait for first CTRL+C. | ||
// Stop receiving signal notifications as soon as possible. | ||
stop() | ||
} | ||
|
||
// When Shutdown is called, ListenAndServe immediately returns ErrServerClosed. | ||
err = srv.Shutdown(context.Background()) | ||
return | ||
} | ||
|
||
func newHTTPHandler() http.Handler { | ||
mux := http.NewServeMux() | ||
|
||
// handleFunc is a replacement for mux.HandleFunc | ||
// which enriches the handler's HTTP instrumentation with the pattern as the http.route. | ||
handleFunc := func(pattern string, handlerFunc func(http.ResponseWriter, *http.Request)) { | ||
// Configure the "http.route" for the HTTP instrumentation. | ||
handler := otelhttp.WithRouteTag(pattern, http.HandlerFunc(handlerFunc)) | ||
mux.Handle(pattern, handler) | ||
} | ||
|
||
// Register handlers. | ||
handleFunc("/rolldice", rolldice) | ||
|
||
// Add HTTP instrumentation for the whole server. | ||
handler := otelhttp.NewHandler(mux, "/") | ||
return handler | ||
} |
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,118 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package main | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"time" | ||
|
||
"go.opentelemetry.io/otel" | ||
"go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" | ||
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace" | ||
"go.opentelemetry.io/otel/sdk/metric" | ||
"go.opentelemetry.io/otel/sdk/resource" | ||
"go.opentelemetry.io/otel/sdk/trace" | ||
semconv "go.opentelemetry.io/otel/semconv/v1.21.0" | ||
) | ||
|
||
// setupOTelSDK bootstraps the OpenTelemetry pipeline. | ||
// If it does not return an error, make sure to call shutdown for proper cleanup. | ||
func setupOTelSDK(ctx context.Context, serviceName, serviceVersion string) (shutdown func(context.Context) error, err error) { | ||
var shutdownFuncs []func(context.Context) error | ||
|
||
// shutdown calls cleanup functions registered via shutdownFuncs. | ||
// The errors from the calls are joined. | ||
// Each registered cleanup will be invoked once. | ||
shutdown = func(ctx context.Context) error { | ||
var err error | ||
for _, fn := range shutdownFuncs { | ||
err = errors.Join(err, fn(ctx)) | ||
} | ||
shutdownFuncs = nil | ||
return err | ||
} | ||
|
||
// handleErr calls shutdown for cleanup and makes sure that all errors are returned. | ||
handleErr := func(inErr error) { | ||
err = errors.Join(inErr, shutdown(ctx)) | ||
} | ||
|
||
// Setup resource. | ||
res, err := newResource(serviceName, serviceVersion) | ||
if err != nil { | ||
handleErr(err) | ||
return | ||
} | ||
|
||
// Setup trace provider. | ||
tracerProvider, err := newTraceProvider(res) | ||
if err != nil { | ||
handleErr(err) | ||
return | ||
} | ||
shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) | ||
otel.SetTracerProvider(tracerProvider) | ||
|
||
// Setup meter provider. | ||
meterProvider, err := newMeterProvider(res) | ||
if err != nil { | ||
handleErr(err) | ||
return | ||
} | ||
shutdownFuncs = append(shutdownFuncs, meterProvider.Shutdown) | ||
otel.SetMeterProvider(meterProvider) | ||
|
||
return | ||
} | ||
|
||
func newResource(serviceName, serviceVersion string) (*resource.Resource, error) { | ||
return resource.Merge(resource.Default(), | ||
resource.NewWithAttributes(semconv.SchemaURL, | ||
semconv.ServiceName(serviceName), | ||
semconv.ServiceVersion(serviceVersion), | ||
)) | ||
} | ||
|
||
func newTraceProvider(res *resource.Resource) (*trace.TracerProvider, error) { | ||
traceExporter, err := stdouttrace.New( | ||
stdouttrace.WithPrettyPrint()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
traceProvider := trace.NewTracerProvider( | ||
trace.WithBatcher(traceExporter, | ||
// Default is 5s. Set to 1s for demonstrative purposes. | ||
trace.WithBatchTimeout(time.Second)), | ||
trace.WithResource(res), | ||
) | ||
return traceProvider, nil | ||
} | ||
|
||
func newMeterProvider(res *resource.Resource) (*metric.MeterProvider, error) { | ||
metricExporter, err := stdoutmetric.New() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
meterProvider := metric.NewMeterProvider( | ||
metric.WithResource(res), | ||
metric.WithReader(metric.NewPeriodicReader(metricExporter, | ||
// Default is 1m. Set to 3s for demonstrative purposes. | ||
metric.WithInterval(3*time.Second))), | ||
) | ||
return meterProvider, 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,59 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package main | ||
|
||
import ( | ||
"io" | ||
"log" | ||
"math/rand" | ||
"net/http" | ||
"strconv" | ||
|
||
"go.opentelemetry.io/otel" | ||
"go.opentelemetry.io/otel/attribute" | ||
"go.opentelemetry.io/otel/metric" | ||
) | ||
|
||
var ( | ||
tracer = otel.Tracer("rolldice") | ||
meter = otel.Meter("rolldice") | ||
rollCnt metric.Int64Counter | ||
) | ||
|
||
func init() { | ||
var err error | ||
rollCnt, err = meter.Int64Counter("dice.rolls", | ||
metric.WithDescription("The number of rolls by roll value"), | ||
metric.WithUnit("{roll}")) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func rolldice(w http.ResponseWriter, r *http.Request) { | ||
ctx, span := tracer.Start(r.Context(), "roll") | ||
defer span.End() | ||
|
||
roll := 1 + rand.Intn(6) | ||
|
||
rollValueAttr := attribute.Int("roll.value", roll) | ||
span.SetAttributes(rollValueAttr) | ||
rollCnt.Add(ctx, 1, metric.WithAttributes(rollValueAttr)) | ||
|
||
resp := strconv.Itoa(roll) + "\n" | ||
if _, err := io.WriteString(w, resp); err != nil { | ||
log.Printf("Write failed: %v\n", err) | ||
} | ||
} |
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