Skip to content

Commit

Permalink
add Dockerfile (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
ktong authored Apr 30, 2024
1 parent c5e2983 commit f399418
Show file tree
Hide file tree
Showing 14 changed files with 126 additions and 64 deletions.
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.*
*.md
LICENSE
22 changes: 22 additions & 0 deletions examples/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# It builds a minimal multi-platform Docker image for a Go application using multi-stage builds.
#
# See https://docs.docker.com/engine/reference/builder.
# See https://docs.docker.com/develop/develop-images/multistage-build/.
# See https://docs.docker.com/build/building/multi-platform/

ARG GO_VERSION=1.22
FROM golang:$GO_VERSION-alpine as build

ARG TARGETARCH
ARG TARGETOS
ARG APP

WORKDIR /app
COPY . .
RUN GOARCH=$TARGETARCH GOOS=$TARGETOS CGO_ENABLED=0 go build -C examples/$APP -ldflags="-s -w" -a -trimpath -o /app/app ./cmd


FROM gcr.io/distroless/static:nonroot

COPY --from=build /app/app /app
ENTRYPOINT ["/app"]
7 changes: 6 additions & 1 deletion examples/grpc/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"embed"

"cloud.google.com/go/compute/metadata"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
"google.golang.org/grpc"

"github.com/nil-go/nilgo"
"github.com/nil-go/nilgo/config"
Expand Down Expand Up @@ -35,7 +37,10 @@ func main() {
}
args = append(args,
config.WithFS(configFS),
ngrpc.Run(ngrpc.NewServer()),
ngrpc.Run(
ngrpc.NewServer(grpc.StatsHandler(otelgrpc.NewServerHandler())),
ngrpc.WithConfigService(),
),
)

if err := nilgo.Run(args...); err != nil {
Expand Down
4 changes: 2 additions & 2 deletions examples/grpc/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ require (
github.com/nil-go/nilgo v0.0.0
github.com/nil-go/nilgo/gcp v0.0.0
github.com/nil-go/nilgo/grpc v0.0.0
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0
google.golang.org/grpc v1.63.2
)

replace (
Expand Down Expand Up @@ -34,7 +36,6 @@ require (
github.com/nil-go/sloth v0.3.0 // indirect
github.com/nil-go/sloth/otel v0.3.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 // indirect
go.opentelemetry.io/otel v1.26.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect
Expand All @@ -55,7 +56,6 @@ require (
google.golang.org/genproto v0.0.0-20240415180920-8c6c420018be // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240415180920-8c6c420018be // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect
google.golang.org/grpc v1.63.2 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
19 changes: 18 additions & 1 deletion examples/http/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ package main

import (
"embed"
"log/slog"
"net/http"
"time"

"cloud.google.com/go/compute/metadata"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"

"github.com/nil-go/nilgo"
"github.com/nil-go/nilgo/config"
Expand All @@ -35,9 +37,24 @@ func main() {
default:
args = append(args, nilgo.PProf)
}

mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
slog.InfoContext(r.Context(), "hello world")
if _, err := w.Write([]byte("Hello, World!")); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
server := &http.Server{
Handler: otelhttp.NewHandler(mux, "nilgo example"),
ReadTimeout: time.Second,
}
args = append(args,
config.WithFS(configFS),
nhttp.Run(&http.Server{ReadTimeout: time.Second}),
nhttp.Run(
server,
nhttp.WithConfigService(),
),
)

if err := nilgo.Run(args...); err != nil {
Expand Down
2 changes: 2 additions & 0 deletions examples/http/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/nil-go/nilgo v0.0.0
github.com/nil-go/nilgo/gcp v0.0.0
github.com/nil-go/nilgo/http v0.0.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0
)

replace (
Expand All @@ -23,6 +24,7 @@ require (
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
cloud.google.com/go/profiler v0.4.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
Expand Down
46 changes: 46 additions & 0 deletions examples/otel-collector.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
receivers:
otlp:
protocols:
grpc:

processors:
batch:
send_batch_max_size: 200
send_batch_size: 200
timeout: 5s

memory_limiter:
check_interval: 1s
limit_percentage: 65
spike_limit_percentage: 20

resourcedetection:
detectors: [env, gcp]
timeout: 2s
override: false

resource:
attributes:
- key: service.instance.id
from_attribute: faas.id
action: upsert
- key: service.name
from_attribute: faas.name
action: upsert
- key: service.version
from_attribute: faas.version
action: upsert

exporters:
googlecloud:

service:
pipelines:
traces:
receivers: [otlp]
processors: [batch, memory_limiter, resourcedetection, resource]
exporters: [googlecloud]
metrics:
receivers: [otlp]
processors: [batch, memory_limiter, resourcedetection, resource]
exporters: [googlecloud]
20 changes: 6 additions & 14 deletions gcp/gcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"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.24.0"
)

// Options provides the [nilgo.Run] options for application runs on GCP.
Expand All @@ -49,7 +48,10 @@ func Options(opts ...Option) ([]any, error) { //nolint:cyclop,funlen
}

appOpts := []any{
gcp.New(append(option.logOpts, gcp.WithErrorReporting(option.service, option.version))...),
gcp.New(append(option.logOpts,
gcp.WithTrace(option.project),
gcp.WithErrorReporting(option.service, option.version),
)...),
}
if option.project == "" {
return appOpts, nil
Expand All @@ -62,18 +64,7 @@ func Options(opts ...Option) ([]any, error) { //nolint:cyclop,funlen
return appOpts, nil
}

res, err := resource.Merge(
resource.Default(),
resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName(option.service),
semconv.ServiceVersion(option.version),
),
)
if err != nil {
return nil, fmt.Errorf("mergee otel resource: %w", err)
}

res := resource.Default()
ctx := context.Background()
if option.traceOpts != nil {
exporter, err := otlptracegrpc.New(ctx, option.traceOpts...)
Expand All @@ -84,6 +75,7 @@ func Options(opts ...Option) ([]any, error) { //nolint:cyclop,funlen
trace.NewTracerProvider(
trace.WithBatcher(exporter),
trace.WithResource(res),
trace.WithSampler(trace.ParentBased(trace.NeverSample())),
),
)
}
Expand Down
2 changes: 1 addition & 1 deletion gcp/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ require (
cloud.google.com/go/profiler v0.4.0
github.com/nil-go/sloth v0.3.0
github.com/stretchr/testify v1.9.0
go.opentelemetry.io/otel v1.26.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0
go.opentelemetry.io/otel/sdk v1.26.0
Expand All @@ -33,6 +32,7 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 // indirect
go.opentelemetry.io/otel v1.26.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect
go.opentelemetry.io/otel/metric v1.26.0 // indirect
go.opentelemetry.io/otel/trace v1.26.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions gcp/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func WithLogOptions(opts gcp.Option) Option {
func WithTrace(opts ...otlptracegrpc.Option) Option {
return func(options *options) {
if options.traceOpts == nil {
options.traceOpts = []otlptracegrpc.Option{}
options.traceOpts = []otlptracegrpc.Option{otlptracegrpc.WithInsecure()}
}
options.traceOpts = append(options.traceOpts, opts...)
}
Expand All @@ -57,7 +57,7 @@ func WithTrace(opts ...otlptracegrpc.Option) Option {
func WithMetric(opts ...otlpmetricgrpc.Option) Option {
return func(options *options) {
if options.metricOpts == nil {
options.metricOpts = []otlpmetricgrpc.Option{}
options.metricOpts = []otlpmetricgrpc.Option{otlpmetricgrpc.WithInsecure()}
}
options.metricOpts = append(options.metricOpts, opts...)
}
Expand Down
14 changes: 2 additions & 12 deletions log/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,11 @@ func WithSampler(sampler func(context.Context) bool) Option {
}
}

// WithLogAsTraceEvent enables logging as trace event.
//
// It could significantly reduce the log volume then cost as trace is priced by number of span.
func WithLogAsTraceEvent() Option {
return func(options *options) {
options.asTraceEvent = true
}
}

type (
// Option configures the logger with specific options.
Option func(*options)
options struct {
handler slog.Handler
sampler func(context.Context) bool
asTraceEvent bool
handler slog.Handler
sampler func(context.Context) bool
}
)
16 changes: 1 addition & 15 deletions log/slog.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,11 @@
package log

import (
"context"
"log/slog"

"github.com/nil-go/sloth/otel"
"github.com/nil-go/sloth/rate"
"github.com/nil-go/sloth/sampling"
"go.opentelemetry.io/otel/trace"
)

// New creates a new slog.Logger with the given Option(s).
Expand All @@ -47,22 +45,10 @@ func New(opts ...Option) *slog.Logger {
}

var handler slog.Handler = rate.New(option.handler)

if option.asTraceEvent {
// If the logger is configured to log as trace event, it disables sampling.
// However, sampling handler still can buffer and logs if there is a error log,
// or there is no valid trace context.
handler = sampling.New(handler, func(ctx context.Context) bool {
return !trace.SpanContextFromContext(ctx).IsValid()
})
handler = otel.New(handler, otel.WithRecordEvent(true))

return slog.New(handler)
}

if option.sampler != nil {
handler = sampling.New(handler, option.sampler)
}
handler = otel.New(handler)

return slog.New(handler)
}
15 changes: 0 additions & 15 deletions log/slog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"testing"

"github.com/nil-go/sloth/sampling"
"go.opentelemetry.io/otel/trace"

"github.com/nil-go/nilgo/internal/assert"
"github.com/nil-go/nilgo/log"
Expand Down Expand Up @@ -57,20 +56,6 @@ func TestNew(t *testing.T) {
{"level":"ERROR","msg":"error log"}
`,
},
{
description: "with log as trace event",
opts: []log.Option{
log.WithLogAsTraceEvent(),
},
fn: func(ctx context.Context, logger *slog.Logger) {
ctx = trace.ContextWithSpanContext(ctx, trace.NewSpanContext(trace.SpanContextConfig{
TraceID: [16]byte{75, 249, 47, 53, 119, 179, 77, 166, 163, 206, 146, 157, 14, 14, 71, 54},
SpanID: [8]byte{0, 240, 103, 170, 11, 169, 2, 183},
TraceFlags: trace.TraceFlags(1),
}))
logger.InfoContext(ctx, "info log")
},
},
}

for _, testcase := range testcases {
Expand Down
16 changes: 15 additions & 1 deletion run.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/nil-go/konf"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"

"github.com/nil-go/nilgo/config"
Expand All @@ -31,7 +32,7 @@ import (
// - log.Option
// - run.Option
// - func(context.Context) error
func Run(args ...any) error { //nolint:cyclop
func Run(args ...any) error { //nolint:cyclop,funlen
var (
configOpts []config.Option
logOpts []log.Option
Expand All @@ -48,11 +49,24 @@ func Run(args ...any) error { //nolint:cyclop
logOpts = append(logOpts, opt)
case trace.TracerProvider:
otel.SetTracerProvider(opt)
otel.SetTextMapPropagator(
propagation.NewCompositeTextMapPropagator(
propagation.TraceContext{},
propagation.Baggage{},
),
)
if provider, ok := opt.(interface {
Shutdown(ctx context.Context) error
}); ok {
runOpts = append(runOpts, run.WithPostRun(provider.Shutdown))
}
logOpts = append([]log.Option{
log.WithSampler(func(ctx context.Context) bool {
sc := trace.SpanContextFromContext(ctx)

return !sc.IsValid() || sc.IsSampled()
}),
}, logOpts...)
case metric.MeterProvider:
otel.SetMeterProvider(opt)
if provider, ok := opt.(interface {
Expand Down

0 comments on commit f399418

Please sign in to comment.