From 18d9dc9630a2cc4c03e388988e4c148761480523 Mon Sep 17 00:00:00 2001 From: Daniel Grau Date: Wed, 23 Oct 2024 21:58:05 +0000 Subject: [PATCH 1/2] Add native cloud logging support --- dataplane/standalone/lucius/BUILD | 14 ++-- dataplane/standalone/lucius/lucius.go | 12 ++- go.mod | 17 ++-- go.sum | 28 ++++--- internal/cloudlog/BUILD | 13 +++ internal/cloudlog/cloudlog.go | 115 ++++++++++++++++++++++++++ repositories.bzl | 36 +++++--- 7 files changed, 195 insertions(+), 40 deletions(-) create mode 100644 internal/cloudlog/BUILD create mode 100644 internal/cloudlog/cloudlog.go diff --git a/dataplane/standalone/lucius/BUILD b/dataplane/standalone/lucius/BUILD index ba3a73a4..7a56ed0f 100644 --- a/dataplane/standalone/lucius/BUILD +++ b/dataplane/standalone/lucius/BUILD @@ -12,9 +12,11 @@ go_library( "//dataplane/dplaneopts", "//dataplane/saiserver", "//dataplane/saiserver/attrmgr", + "//internal/cloudlog", "//proto/forwarding", "@com_github_googlecloudplatform_opentelemetry_operations_go_exporter_trace//:trace", "@com_github_grpc_ecosystem_go_grpc_middleware_v2//interceptors/logging", + "@io_opentelemetry_go_contrib_detectors_gcp//:gcp", "@io_opentelemetry_go_contrib_instrumentation_google_golang_org_grpc_otelgrpc//:otelgrpc", "@io_opentelemetry_go_otel//:otel", "@io_opentelemetry_go_otel//propagation", @@ -31,12 +33,6 @@ go_library( ], ) -go_binary( - name = "lucius", - embed = [":lucius_lib"], - visibility = ["//visibility:public"], -) - pkg_tar( name = "bin-tar", srcs = [":lucius"], @@ -67,3 +63,9 @@ oci_tarball( image = ":image", repo_tags = ["us-west1-docker.pkg.dev/openconfig-lemming/release/lucius:ga"], ) + +go_binary( + name = "lucius", + embed = [":lucius_lib"], + visibility = ["//visibility:public"], +) diff --git a/dataplane/standalone/lucius/lucius.go b/dataplane/standalone/lucius/lucius.go index 7701411a..67c13d05 100644 --- a/dataplane/standalone/lucius/lucius.go +++ b/dataplane/standalone/lucius/lucius.go @@ -25,6 +25,7 @@ import ( texporter "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging" + "go.opentelemetry.io/contrib/detectors/gcp" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/stdout/stdoutlog" @@ -42,6 +43,7 @@ import ( "github.com/openconfig/lemming/dataplane/dplaneopts" "github.com/openconfig/lemming/dataplane/saiserver" "github.com/openconfig/lemming/dataplane/saiserver/attrmgr" + "github.com/openconfig/lemming/internal/cloudlog" fwdpb "github.com/openconfig/lemming/proto/forwarding" ) @@ -53,7 +55,7 @@ var ( _ = flag.String("port_map", "", "Map of modeled port names to Linux interface to as comma seperated list (eg Ethernet8:eth1,Ethernet10,eth2) (deprecated, no-op will be removed in future release)") _ = flag.Bool("eth_dev_as_lane", true, "If true, when creating ports, use ethX and hardware lane X (deprecated, no-op will always to true in future release)") _ = flag.Bool("remote_cpu_port", true, "If true, send all packets from/to the CPU port over gRPC (deprecated, no-op will always to true in future release)") - gcpTelemExport = flag.Bool("gcp_telem_export", false, "If true, export OTEL telemetry to GCP") + gcpTelemExport = flag.Bool("gcp_telem_export", false, "If true, export OTEL telemetry and logs to GCP") gcpProject = flag.String("gcp_project", "", "GCP project to export to, by default it will use project where the GCE instance is running") hwProfile = flag.String("hw_profile", "", "Path to hardware profile config file.") ) @@ -126,10 +128,11 @@ func setupOTelSDK(ctx context.Context) (func(context.Context) error, error) { var err error if *gcpTelemExport { - exporter, err = texporter.New(texporter.WithProjectID(*gcpProject)) + exporter, err = texporter.New(texporter.WithProjectID(*gcpProject), texporter.WithDestinationProjectQuota()) if err != nil { return nil, err } + cloudlog.SetGlobalLogger(ctx, *gcpProject, "lucius") } shutdown := func(ctx context.Context) error { @@ -141,7 +144,10 @@ func setupOTelSDK(ctx context.Context) (func(context.Context) error, error) { return err } - res := resource.Default() + res, err := resource.New(ctx, resource.WithDetectors(gcp.NewDetector()), resource.WithHost(), resource.WithTelemetrySDK()) + if err != nil { + return nil, err + } // Set up propagator. prop := newPropagator() diff --git a/go.mod b/go.mod index e8bf2b81..05e04c58 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ toolchain go1.22.3 require ( cloud.google.com/go/cloudbuild v1.16.3 + cloud.google.com/go/logging v1.10.0 github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.24.1 github.com/fatih/color v1.15.0 github.com/go-logr/logr v1.4.2 @@ -38,17 +39,17 @@ require ( github.com/spf13/viper v1.19.0 github.com/stoewer/go-strcase v1.3.0 github.com/vishvananda/netlink v1.2.1-beta.2 + go.opentelemetry.io/contrib/detectors/gcp v1.31.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 - go.opentelemetry.io/otel v1.30.0 + go.opentelemetry.io/otel v1.31.0 go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.6.0 go.opentelemetry.io/otel/log v0.6.0 - go.opentelemetry.io/otel/sdk v1.30.0 + go.opentelemetry.io/otel/sdk v1.31.0 go.opentelemetry.io/otel/sdk/log v0.6.0 go.opentelemetry.io/otel/sdk/metric v1.27.0 - go.opentelemetry.io/otel/trace v1.30.0 + go.opentelemetry.io/otel/trace v1.31.0 go.uber.org/mock v0.2.0 - golang.org/x/oauth2 v0.21.0 - golang.org/x/sys v0.25.0 + golang.org/x/sys v0.26.0 google.golang.org/api v0.188.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5 google.golang.org/grpc v1.64.1 @@ -66,11 +67,12 @@ require ( cloud.google.com/go v0.115.0 // indirect cloud.google.com/go/auth v0.7.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.3 // indirect - cloud.google.com/go/compute/metadata v0.5.0 // indirect + cloud.google.com/go/compute/metadata v0.5.2 // indirect cloud.google.com/go/iam v1.1.10 // indirect cloud.google.com/go/longrunning v0.5.9 // indirect cloud.google.com/go/pubsub v1.40.0 // indirect cloud.google.com/go/trace v1.10.10 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.2 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/aristanetworks/arista-ceoslab-operator/v2 v2.1.2 // indirect @@ -148,12 +150,13 @@ require ( github.com/vishvananda/netns v0.0.4 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect - go.opentelemetry.io/otel/metric v1.30.0 // indirect + go.opentelemetry.io/otel/metric v1.31.0 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.25.0 // indirect golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 // indirect golang.org/x/net v0.27.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/term v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect diff --git a/go.sum b/go.sum index 6d54e933..40e91138 100644 --- a/go.sum +++ b/go.sum @@ -360,8 +360,8 @@ cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZ cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= -cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= +cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= +cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= @@ -1342,6 +1342,8 @@ gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zum git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.2 h1:cZpsGsWTIFKymTA0je7IIvi1O7Es7apb9CF3EQlOcfE= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.2/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.24.1 h1:01bHLeqkrxYSkjvyTBEZ8rxBxDhWm1snWGEW73Te4lU= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.24.1/go.mod h1:UFO9jC3njhKdD/ymLnaKi7Or5miVWq06LvRWQNFfnTU= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1 h1:oTX4vsorBZo/Zdum6OKPA4o7544hm6smoRv1QjpTwGo= @@ -1953,6 +1955,8 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/detectors/gcp v1.31.0 h1:G1JQOreVrfhRkner+l4mrGxmfqYCAuy76asTDAo0xsA= +go.opentelemetry.io/contrib/detectors/gcp v1.31.0/go.mod h1:tzQL6E1l+iV44YFTkcAeNQqzXUiekSYP9jjJjXwEd00= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= @@ -1970,8 +1974,8 @@ go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znn go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0= go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= -go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= +go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= +go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.6.0 h1:bZHOb8k/CwwSt0DgvgaoOhBXWNdWqFWaIsGTtg1H3KE= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.6.0/go.mod h1:XlV163j81kDdIt5b5BXCjdqVfqJFy/LJrHA697SorvQ= go.opentelemetry.io/otel/log v0.6.0 h1:nH66tr+dmEgW5y+F9LanGJUBYPrRgP4g2EkmPE3LeK8= @@ -1981,13 +1985,13 @@ go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzu go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= -go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= +go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= +go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= -go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE= -go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg= +go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= +go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= go.opentelemetry.io/otel/sdk/log v0.6.0 h1:4J8BwXY4EeDE9Mowg+CyhWVBhTSLXVXodiXxS/+PGqI= go.opentelemetry.io/otel/sdk/log v0.6.0/go.mod h1:L1DN8RMAduKkrwRAFDEX3E3TLOq46+XMGSbUfHU/+vE= go.opentelemetry.io/otel/sdk/metric v1.27.0 h1:5uGNOlpXi+Hbo/DRoI31BSb1v+OGcpv2NemcCrOL8gI= @@ -1997,8 +2001,8 @@ go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+ go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= -go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= +go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= +go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= @@ -2342,8 +2346,8 @@ golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= diff --git a/internal/cloudlog/BUILD b/internal/cloudlog/BUILD new file mode 100644 index 00000000..50aec053 --- /dev/null +++ b/internal/cloudlog/BUILD @@ -0,0 +1,13 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "cloudlog", + srcs = ["cloudlog.go"], + importpath = "github.com/openconfig/lemming/internal/cloudlog", + visibility = ["//:__subpackages__"], + deps = [ + "@com_google_cloud_go_logging//:logging", + "@com_google_cloud_go_logging//apiv2/loggingpb", + "@io_opentelemetry_go_otel_trace//:trace", + ], +) diff --git a/internal/cloudlog/cloudlog.go b/internal/cloudlog/cloudlog.go new file mode 100644 index 00000000..cf5bd097 --- /dev/null +++ b/internal/cloudlog/cloudlog.go @@ -0,0 +1,115 @@ +// Copyright 2024 Google LLC +// +// 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 cloudlog + +import ( + "context" + "fmt" + "log/slog" + "os" + "os/signal" + "runtime" + "syscall" + "time" + + "cloud.google.com/go/logging" + "cloud.google.com/go/logging/apiv2/loggingpb" + "go.opentelemetry.io/otel/trace" +) + +// SetGlobal sets the global slog to use output a GCP cloud logging and stderr +func SetGlobalLogger(ctx context.Context, project, logName string) error { + cl, err := logging.NewClient(ctx, fmt.Sprintf("projects/%s", project)) + if err != nil { + return err + } + + h := &cloudLogHandle{ + Handler: slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{}), + l: cl.Logger(logName), + project: project, + } + + t := time.NewTicker(time.Second) + + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + + go func() { + for { + select { + case <-sigs: + h.l.Flush() + case <-t.C: + if err := h.l.Flush(); err != nil { + fmt.Println(err) + } + } + } + }() + + slog.SetDefault(slog.New(h)) + return nil +} + +type cloudLogHandle struct { + slog.Handler + l *logging.Logger + project string +} + +func (t *cloudLogHandle) Handle(ctx context.Context, record slog.Record) error { + payload := map[string]string{ + "message": record.Message, + } + + entry := logging.Entry{ + Timestamp: record.Time, + } + switch record.Level { + case slog.LevelError: + entry.Severity = logging.Error + case slog.LevelWarn: + entry.Severity = logging.Warning + case slog.LevelInfo: + entry.Severity = logging.Info + case slog.LevelDebug: + entry.Severity = logging.Debug + } + record.Attrs(func(a slog.Attr) bool { + payload[a.Key] = a.Value.String() + return true + }) + + entry.Payload = payload + + if s := trace.SpanContextFromContext(ctx); s.IsValid() { + entry.Trace = fmt.Sprintf("projects/%s/traces/%s", t.project, s.TraceID().String()) + entry.SpanID = s.SpanID().String() + entry.TraceSampled = s.IsSampled() + } + + fs := runtime.CallersFrames([]uintptr{record.PC}) + f, _ := fs.Next() + entry.SourceLocation = &loggingpb.LogEntrySourceLocation{ + File: f.File, + Line: int64(f.Line), + Function: f.Function, + } + + t.l.Log(entry) + + return t.Handler.Handle(ctx, record) +} diff --git a/repositories.bzl b/repositories.bzl index a09049f1..21c53c58 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -820,6 +820,12 @@ def go_repositories(): sum = "h1:zC34cGQu69FG7qzJ3WiKW244WfhDC3xxYMeNOX2gtUQ=", version = "v0.0.0-20210719221736-1c9a4c676720", ) + go_repository( + name = "com_github_googlecloudplatform_opentelemetry_operations_go_detectors_gcp", + importpath = "github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp", + sum = "h1:cZpsGsWTIFKymTA0je7IIvi1O7Es7apb9CF3EQlOcfE=", + version = "v1.24.2", + ) go_repository( name = "com_github_googlecloudplatform_opentelemetry_operations_go_exporter_trace", importpath = "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace", @@ -2117,8 +2123,8 @@ def go_repositories(): go_repository( name = "com_google_cloud_go_compute_metadata", importpath = "cloud.google.com/go/compute/metadata", - sum = "h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=", - version = "v0.5.0", + sum = "h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo=", + version = "v0.5.2", ) go_repository( name = "com_google_cloud_go_contactcenterinsights", @@ -2970,6 +2976,12 @@ def go_repositories(): sum = "h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=", version = "v0.24.0", ) + go_repository( + name = "io_opentelemetry_go_contrib_detectors_gcp", + importpath = "go.opentelemetry.io/contrib/detectors/gcp", + sum = "h1:G1JQOreVrfhRkner+l4mrGxmfqYCAuy76asTDAo0xsA=", + version = "v1.31.0", + ) go_repository( name = "io_opentelemetry_go_contrib_instrumentation_google_golang_org_grpc_otelgrpc", importpath = "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc", @@ -2985,8 +2997,8 @@ def go_repositories(): go_repository( name = "io_opentelemetry_go_otel", importpath = "go.opentelemetry.io/otel", - sum = "h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=", - version = "v1.30.0", + sum = "h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY=", + version = "v1.31.0", ) go_repository( name = "io_opentelemetry_go_otel_exporters_otlp_otlptrace", @@ -3015,14 +3027,14 @@ def go_repositories(): go_repository( name = "io_opentelemetry_go_otel_metric", importpath = "go.opentelemetry.io/otel/metric", - sum = "h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=", - version = "v1.30.0", + sum = "h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE=", + version = "v1.31.0", ) go_repository( name = "io_opentelemetry_go_otel_sdk", importpath = "go.opentelemetry.io/otel/sdk", - sum = "h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE=", - version = "v1.30.0", + sum = "h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk=", + version = "v1.31.0", ) go_repository( name = "io_opentelemetry_go_otel_sdk_log", @@ -3039,8 +3051,8 @@ def go_repositories(): go_repository( name = "io_opentelemetry_go_otel_trace", importpath = "go.opentelemetry.io/otel/trace", - sum = "h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=", - version = "v1.30.0", + sum = "h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys=", + version = "v1.31.0", ) go_repository( name = "io_opentelemetry_go_proto_otlp", @@ -3203,8 +3215,8 @@ def go_repositories(): go_repository( name = "org_golang_x_sys", importpath = "golang.org/x/sys", - sum = "h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=", - version = "v0.25.0", + sum = "h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=", + version = "v0.26.0", ) go_repository( name = "org_golang_x_term", From cd19b5b7b61c1c13821f93ea7231ff4831473bb5 Mon Sep 17 00:00:00 2001 From: Daniel Grau Date: Thu, 24 Oct 2024 17:21:58 +0000 Subject: [PATCH 2/2] feedback --- internal/cloudlog/cloudlog.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cloudlog/cloudlog.go b/internal/cloudlog/cloudlog.go index cf5bd097..b9a237b5 100644 --- a/internal/cloudlog/cloudlog.go +++ b/internal/cloudlog/cloudlog.go @@ -54,7 +54,7 @@ func SetGlobalLogger(ctx context.Context, project, logName string) error { h.l.Flush() case <-t.C: if err := h.l.Flush(); err != nil { - fmt.Println(err) + fmt.Fprintf(os.Stderr, "log flush err: %v", err) } } }