From 4e1a25190a59bd827bb9d1b354fd2ef1b3683c6d Mon Sep 17 00:00:00 2001 From: Masato Naka Date: Mon, 12 Aug 2024 15:26:03 +0900 Subject: [PATCH 1/8] chore: rename function --- pkg/monitoring/client.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/pkg/monitoring/client.go b/pkg/monitoring/client.go index 2459e54..0289b2d 100644 --- a/pkg/monitoring/client.go +++ b/pkg/monitoring/client.go @@ -108,11 +108,11 @@ func (mc *Client) GetCloudRunServiceRequestCount(ctx context.Context, service st }, // PageSize: int32(10000), 100,000 if empty } - return mc.GetRequestCountByLabel(ctx, "response_code_class", "metric", req) + return mc.aggregateRequestCount(ctx, "response_code_class", "metric", req) } // labelType: metric or resource -func (mc *Client) GetRequestCountByLabel(ctx context.Context, label, labelType string, req *monitoringpb.ListTimeSeriesRequest) (*TimeSeriesMap, error) { +func (mc *Client) aggregateRequestCount(ctx context.Context, label, labelType string, req *monitoringpb.ListTimeSeriesRequest) (*TimeSeriesMap, error) { it := mc.client.ListTimeSeries(ctx, req) var requestCount int64 var loopCnt int @@ -131,7 +131,6 @@ func (mc *Client) GetRequestCountByLabel(ctx context.Context, label, labelType s return nil, err } if resp == nil { - log.Println("nil") continue } log.Printf("resp %v\n", resp.String()) @@ -168,13 +167,12 @@ func (mc *Client) GetRequestCountByLabel(ctx context.Context, label, labelType s return &seriesMap, nil } -func (mc *Client) AggregateLatencies(ctx context.Context, req *monitoringpb.ListTimeSeriesRequest) (*TimeSeries, error) { +func (mc *Client) aggregateRequestLatency(ctx context.Context, req *monitoringpb.ListTimeSeriesRequest) (*TimeSeries, error) { it := mc.client.ListTimeSeries(ctx, req) var requestCount int64 var loopCnt int cnt := Counter{} series := TimeSeries{} - labelValue := "p99" for { resp, err := it.Next() if err == iterator.Done { @@ -195,7 +193,7 @@ func (mc *Client) AggregateLatencies(ctx context.Context, req *monitoringpb.List for i, p := range resp.GetPoints() { // Point per min log.Println(p.Value.String()) - log.Printf("Latency Point:%d\t%s:%s\tstart:%s\tend:%s\tvalue:%d\n", i, "revision_name", labelValue, p.Interval.StartTime.AsTime(), p.Interval.EndTime.AsTime(), p.Value.GetInt64Value()) + log.Printf("Latency Point:%d\tstart:%s\tend:%s\tvalue:%d\n", i, p.Interval.StartTime.AsTime(), p.Interval.EndTime.AsTime(), p.Value.GetInt64Value()) val := p.GetValue().GetDoubleValue() series = append(series, Point{Time: p.Interval.StartTime.AsTime(), Val: float64(val)}) } @@ -236,7 +234,7 @@ func (mc *Client) GetCloudRunServiceRequestLatencies(ctx context.Context, servic }, // PageSize: int32(10000), 100,000 if empty } - series, err := mc.AggregateLatencies(ctx, req) + series, err := mc.aggregateRequestLatency(ctx, req) if err != nil { return nil, err } From 7da9ad145ae9fbe2c641a0097621413ea41bac28 Mon Sep 17 00:00:00 2001 From: Masato Naka Date: Mon, 12 Aug 2024 16:19:10 +0900 Subject: [PATCH 2/8] chore use zap logger --- go.mod | 6 +- go.sum | 179 ++----------------------------------- main.go | 25 ++++-- pkg/slack/event_handler.go | 16 ++-- 4 files changed, 36 insertions(+), 190 deletions(-) diff --git a/go.mod b/go.mod index e61173f..bb4408a 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,10 @@ module github.com/nakamasato/cloud-run-slack-bot go 1.21.4 require ( - cloud.google.com/go/logging v1.11.0 cloud.google.com/go/monitoring v1.20.4 github.com/slack-go/slack v0.13.1 github.com/wcharczuk/go-chart/v2 v2.1.1 + go.uber.org/zap v1.27.0 google.golang.org/api v0.191.0 google.golang.org/protobuf v1.34.2 ) @@ -15,25 +15,25 @@ require ( cloud.google.com/go/auth v0.8.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/longrunning v0.5.11 // indirect github.com/blend/go-sdk v1.20220411.3 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.4 // indirect github.com/google/s2a-go v0.1.8 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.13.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect + github.com/stretchr/testify v1.9.0 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.uber.org/multierr v1.10.0 // indirect golang.org/x/crypto v0.25.0 // indirect golang.org/x/image v0.14.0 // indirect golang.org/x/net v0.27.0 // indirect diff --git a/go.sum b/go.sum index 845ed0f..da23ce4 100644 --- a/go.sum +++ b/go.sum @@ -1,53 +1,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/auth v0.3.0 h1:PRyzEpGfx/Z9e8+lHsbkoUVXD0gnu4MNmm7Gp8TQNIs= -cloud.google.com/go/auth v0.3.0/go.mod h1:lBv6NKTWp8E3LPzmO1TbiiRKc4drLOfHsgmlH9ogv5w= -cloud.google.com/go/auth v0.4.1 h1:Z7YNIhlWRtrnKlZke7z3GMqzvuYzdc2z98F9D1NV5Hg= -cloud.google.com/go/auth v0.4.1/go.mod h1:QVBuVEKpCn4Zp58hzRGvL0tjRGU0YqdRTdCHM1IHnro= -cloud.google.com/go/auth v0.4.2 h1:sb0eyLkhRtpq5jA+a8KWw0W70YcdVca7KJ8TM0AFYDg= -cloud.google.com/go/auth v0.4.2/go.mod h1:Kqvlz1cf1sNA0D+sYJnkPQOP+JMHkuHeIgVmCRtZOLc= -cloud.google.com/go/auth v0.5.1 h1:0QNO7VThG54LUzKiQxv8C6x1YX7lUrzlAa1nVLF8CIw= -cloud.google.com/go/auth v0.5.1/go.mod h1:vbZT8GjzDf3AVqCcQmqeeM32U9HBFc32vVVAbwDsa6s= -cloud.google.com/go/auth v0.6.0 h1:5x+d6b5zdezZ7gmLWD1m/xNjnaQ2YDhmIz/HH3doy1g= -cloud.google.com/go/auth v0.6.0/go.mod h1:b4acV+jLQDyjwm4OXHYjNvRi4jvGBzHWJRtJcy+2P4g= -cloud.google.com/go/auth v0.6.1 h1:T0Zw1XM5c1GlpN2HYr2s+m3vr1p2wy+8VN+Z1FKxW38= -cloud.google.com/go/auth v0.6.1/go.mod h1:eFHG7zDzbXHKmjJddFG/rBlcGp6t25SwRUiEQSlO4x4= -cloud.google.com/go/auth v0.7.0 h1:kf/x9B3WTbBUHkC+1VS8wwwli9TzhSt0vSTVBmMR8Ts= -cloud.google.com/go/auth v0.7.0/go.mod h1:D+WqdrpcjmiCgWrXmLLxOVq1GACoE36chW6KXoEvuIw= -cloud.google.com/go/auth v0.7.2 h1:uiha352VrCDMXg+yoBtaD0tUF4Kv9vrtrWPYXwutnDE= -cloud.google.com/go/auth v0.7.2/go.mod h1:VEc4p5NNxycWQTMQEDQF0bd6aTMb6VgYDXEwiJJQAbs= -cloud.google.com/go/auth v0.7.3 h1:98Vr+5jMaCZ5NZk6e/uBgf60phTk/XN84r8QEWB9yjY= -cloud.google.com/go/auth v0.7.3/go.mod h1:HJtWUx1P5eqjy/f6Iq5KeytNpbAcGolPhOgyop2LlzA= cloud.google.com/go/auth v0.8.0 h1:y8jUJLl/Fg+qNBWxP/Hox2ezJvjkrPb952PC1p0G6A4= cloud.google.com/go/auth v0.8.0/go.mod h1:qGVp/Y3kDRSDZ5gFD/XPUfYQ9xW1iI7q8RIRoCyBbJc= -cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= -cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= cloud.google.com/go/auth/oauth2adapt v0.2.3 h1:MlxF+Pd3OmSudg/b1yZ5lJwoXCEaeedAguodky1PcKI= cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.4.0 h1:vHzJCWaM4g8XIcm8kopr3XmDA4Gy/lblD3EhhSux05c= -cloud.google.com/go/compute/metadata v0.4.0/go.mod h1:SIQh1Kkb4ZJ8zJ874fqVkslA29PRXuleyj6vOzlbK7M= 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/logging v1.9.0 h1:iEIOXFO9EmSiTjDmfpbRjOxECO7R8C7b8IXUGOj7xZw= -cloud.google.com/go/logging v1.9.0/go.mod h1:1Io0vnZv4onoUnsVUQY3HZ3Igb1nBchky0A0y7BBBhE= -cloud.google.com/go/logging v1.10.0/go.mod h1:EHOwcxlltJrYGqMGfghSet736KR3hX1MAj614mrMk9I= -cloud.google.com/go/logging v1.11.0/go.mod h1:5LDiJC/RxTt+fHc1LAt20R9TKiUTReDg6RuuFOZ67+A= -cloud.google.com/go/longrunning v0.5.6 h1:xAe8+0YaWoCKr9t1+aWe+OeQgN/iJK1fEgZSXmjuEaE= -cloud.google.com/go/longrunning v0.5.6/go.mod h1:vUaDrWYOMKRuhiv6JBnn49YxCPz2Ayn9GqyjaBT8/mA= -cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng= -cloud.google.com/go/longrunning v0.5.9/go.mod h1:HD+0l9/OOW0za6UWdKJtXoFAX/BGg/3Wj8p10NeWF7c= -cloud.google.com/go/longrunning v0.5.11/go.mod h1:rDn7//lmlfWV1Dx6IB4RatCPenTwwmqXuiP0/RgoEO4= -cloud.google.com/go/monitoring v1.19.0 h1:NCXf8hfQi+Kmr56QJezXRZ6GPb80ZI7El1XztyUuLQI= -cloud.google.com/go/monitoring v1.19.0/go.mod h1:25IeMR5cQ5BoZ8j1eogHE5VPJLlReQ7zFp5OiLgiGZw= -cloud.google.com/go/monitoring v1.20.0 h1:GsIGYe6Q42EHONJtrUenZFpPIF60qLpeMhxVHIBcaPA= -cloud.google.com/go/monitoring v1.20.0/go.mod h1:5oUy5KllE4yxpztDJuzq/VVck0Q0cn/ykC98C9MXux0= -cloud.google.com/go/monitoring v1.20.1 h1:XmM6uk4+mI2ZhWdI2n/2GNhJdpeQN+1VdG2UWEDhX48= -cloud.google.com/go/monitoring v1.20.1/go.mod h1:FYSe/brgfuaXiEzOQFhTjsEsJv+WePyK71X7Y8qo6uQ= -cloud.google.com/go/monitoring v1.20.2 h1:B/L+xrw9PYO7ywh37sgnjI/6dzEE+yQTAwfytDcpPto= -cloud.google.com/go/monitoring v1.20.2/go.mod h1:36rpg/7fdQ7NX5pG5x1FA7cXTVXusOp6Zg9r9e1+oek= -cloud.google.com/go/monitoring v1.20.3 h1:v/7MXFxYrhXLEZ9sSfwXdlTLLB/xrU7xTyYjY5acynQ= -cloud.google.com/go/monitoring v1.20.3/go.mod h1:GPIVIdNznIdGqEjtRKQWTLcUeRnPjZW85szouimiczU= cloud.google.com/go/monitoring v1.20.4 h1:zwcViK7mT9SV0kzKqLOI3spRadvsmvw/R9z1MHNeC0E= cloud.google.com/go/monitoring v1.20.4/go.mod h1:v7F/UcLRw15EX7xq565N7Ae5tnYEE28+Cl717aTXG4c= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -66,8 +23,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -101,8 +56,6 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -110,12 +63,6 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA= -github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= -github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg= -github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= -github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= -github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= @@ -123,10 +70,6 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/slack-go/slack v0.12.5 h1:ddZ6uz6XVaB+3MTDhoW04gG+Vc/M/X1ctC+wssy2cqs= -github.com/slack-go/slack v0.12.5/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/slack-go/slack v0.13.0 h1:7my/pR2ubZJ9912p9FtvALYpbt0cQPAqkRy2jaSI1PQ= -github.com/slack-go/slack v0.13.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/slack-go/slack v0.13.1 h1:6UkM3U1OnbhPsYeb1IMkQ6HSNOSikWluwOncJt4Tz/o= github.com/slack-go/slack v0.13.1/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -153,15 +96,15 @@ go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGX go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -183,21 +126,9 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg= -golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= -golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= -golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -205,8 +136,6 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -218,12 +147,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -234,14 +157,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -254,34 +171,6 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.177.0 h1:8a0p/BbPa65GlqGWtUKxot4p0TV8OGOfyTjtmkXNXmk= -google.golang.org/api v0.177.0/go.mod h1:srbhue4MLjkjbkux5p3dw/ocYOSZTaIEvf7bCOnFQDw= -google.golang.org/api v0.178.0 h1:yoW/QMI4bRVCHF+NWOTa4cL8MoWL3Jnuc7FlcFF91Ok= -google.golang.org/api v0.178.0/go.mod h1:84/k2v8DFpDRebpGcooklv/lais3MEfqpaBLA12gl2U= -google.golang.org/api v0.179.0 h1:QyHDLm/HqM7ysaHgGO0wu7P4NbwbimnOoKxu5Cfdx8s= -google.golang.org/api v0.179.0/go.mod h1:51AiyoEg1MJPSZ9zvklA8VnRILPXxn1iVen9v25XHAE= -google.golang.org/api v0.180.0 h1:M2D87Yo0rGBPWpo1orwfCLehUUL6E7/TYe5gvMQWDh4= -google.golang.org/api v0.180.0/go.mod h1:51AiyoEg1MJPSZ9zvklA8VnRILPXxn1iVen9v25XHAE= -google.golang.org/api v0.181.0 h1:rPdjwnWgiPPOJx3IcSAQ2III5aX5tCer6wMpa/xmZi4= -google.golang.org/api v0.181.0/go.mod h1:MnQ+M0CFsfUwA5beZ+g/vCBCPXvtmZwRz2qzZk8ih1k= -google.golang.org/api v0.182.0 h1:if5fPvudRQ78GeRx3RayIoiuV7modtErPIZC/T2bIvE= -google.golang.org/api v0.182.0/go.mod h1:cGhjy4caqA5yXRzEhkHI8Y9mfyC2VLTlER2l08xaqtM= -google.golang.org/api v0.183.0 h1:PNMeRDwo1pJdgNcFQ9GstuLe/noWKIc89pRWRLMvLwE= -google.golang.org/api v0.183.0/go.mod h1:q43adC5/pHoSZTx5h2mSmdF7NcyfW9JuDyIOJAgS9ZQ= -google.golang.org/api v0.184.0 h1:dmEdk6ZkJNXy1JcDhn/ou0ZUq7n9zropG2/tR4z+RDg= -google.golang.org/api v0.184.0/go.mod h1:CeDTtUEiYENAf8PPG5VZW2yNp2VM3VWbCeTioAZBTBA= -google.golang.org/api v0.185.0 h1:ENEKk1k4jW8SmmaT6RE+ZasxmxezCrD5Vw4npvr+pAU= -google.golang.org/api v0.185.0/go.mod h1:HNfvIkJGlgrIlrbYkAm9W9IdkmKZjOTVh33YltygGbg= -google.golang.org/api v0.186.0 h1:n2OPp+PPXX0Axh4GuSsL5QL8xQCTb2oDwyzPnQvqUug= -google.golang.org/api v0.186.0/go.mod h1:hvRbBmgoje49RV3xqVXrmP6w93n6ehGgIVPYrGtBFFc= -google.golang.org/api v0.187.0 h1:Mxs7VATVC2v7CY+7Xwm4ndkX71hpElcvx0D1Ji/p1eo= -google.golang.org/api v0.187.0/go.mod h1:KIHlTc4x7N7gKKuVsdmfBXN13yEEWXWFURWY6SBp2gk= -google.golang.org/api v0.188.0 h1:51y8fJ/b1AaaBRJr4yWm96fPcuxSo0JcegXE3DaHQHw= -google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag= -google.golang.org/api v0.189.0 h1:equMo30LypAkdkLMBqfeIqtyAnlyig1JSZArl4XPwdI= -google.golang.org/api v0.189.0/go.mod h1:FLWGJKb0hb+pU2j+rJqwbnsF+ym+fQs73rbJ+KAUgy8= -google.golang.org/api v0.190.0 h1:ASM+IhLY1zljNdLu19W1jTmU6A+gMk6M46Wlur61s+Q= -google.golang.org/api v0.190.0/go.mod h1:QIr6I9iedBLnfqoD6L6Vze1UvS5Hzj5r2aUBOaZnLHo= google.golang.org/api v0.191.0 h1:cJcF09Z+4HAB2t5qTQM1ZtfL/PemsLFkcFG67qq2afk= google.golang.org/api v0.191.0/go.mod h1:tD5dsFGxFza0hnQveGfVk9QQYKcfp+VzgRqyXFxE0+E= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -289,58 +178,10 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda h1:wu/KJm9KJwpfHWhkkZGohVC6KRrc1oJNr4jwtQMOQXw= -google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda/go.mod h1:g2LLCvCeCSir/JJSWosk19BR4NVxGqHUC6rxIRsd7Aw= -google.golang.org/genproto v0.0.0-20240528184218-531527333157 h1:u7WMYrIrVvs0TF5yaKwKNbcJyySYf+HAIFXxWltJOXE= -google.golang.org/genproto v0.0.0-20240528184218-531527333157/go.mod h1:ubQlAQnzejB8uZzszhrTCU2Fyp6Vi7ZE5nn0c3W8+qQ= -google.golang.org/genproto v0.0.0-20240604185151-ef581f913117 h1:HCZ6DlkKtCDAtD8ForECsY3tKuaR+p4R3grlK80uCCc= -google.golang.org/genproto v0.0.0-20240604185151-ef581f913117/go.mod h1:lesfX/+9iA+3OdqeCpoDddJaNxVB1AB6tD7EfqMmprc= -google.golang.org/genproto v0.0.0-20240617180043-68d350f18fd4 h1:CUiCqkPw1nNrNQzCCG4WA65m0nAmQiwXHpub3dNyruU= -google.golang.org/genproto v0.0.0-20240617180043-68d350f18fd4/go.mod h1:EvuUDCulqGgV80RvP1BHuom+smhX4qtlhnNatHuroGQ= -google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d h1:PksQg4dV6Sem3/HkBX+Ltq8T0ke0PKIRBNBatoDTVls= -google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:s7iA721uChleev562UJO2OYB0PPT9CMFjV+Ce7VJH5M= -google.golang.org/genproto v0.0.0-20240708141625-4ad9e859172b h1:dSTjko30weBaMj3eERKc0ZVXW4GudCswM3m+P++ukU0= -google.golang.org/genproto v0.0.0-20240708141625-4ad9e859172b/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= -google.golang.org/genproto v0.0.0-20240722135656-d784300faade h1:lKFsS7wpngDgSCeFn7MoLy+wBDQZ1UQIJD4UNM1Qvkg= -google.golang.org/genproto v0.0.0-20240722135656-d784300faade/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= google.golang.org/genproto v0.0.0-20240730163845-b1a4ccb954bf h1:OqdXDEakZCVtDiZTjcxfwbHPCT11ycCEsTKesBVKvyY= google.golang.org/genproto v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:mCr1K1c8kX+1iSBREvU3Juo11CB+QOEWxbRS01wWl5M= -google.golang.org/genproto/googleapis/api v0.0.0-20240429193739-8cf5692501f6 h1:DTJM0R8LECCgFeUwApvcEJHz85HLagW8uRENYxHh1ww= -google.golang.org/genproto/googleapis/api v0.0.0-20240429193739-8cf5692501f6/go.mod h1:10yRODfgim2/T8csjQsMPgZOMvtytXKTDRzH6HRGzRw= -google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 h1:W5Xj/70xIA4x60O/IFyXivR5MGqblAb8R3w26pnD6No= -google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas= -google.golang.org/genproto/googleapis/api v0.0.0-20240521202816-d264139d666e h1:SkdGTrROJl2jRGT/Fxv5QUf9jtdKCQh4KQJXbXVLAi0= -google.golang.org/genproto/googleapis/api v0.0.0-20240521202816-d264139d666e/go.mod h1:LweJcLbyVij6rCex8YunD8DYR5VDonap/jYl3ZRxcIU= -google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= -google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= -google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3 h1:QW9+G6Fir4VcRXVH8x3LilNAb6cxBGLa6+GM4hRwexE= -google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3/go.mod h1:kdrSS/OiLkPrNUpzD4aHgCq2rVuC/YRxok32HXZ4vRE= -google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4 h1:MuYw1wJzT+ZkybKfaOXKp5hJiZDn2iHaXRw0mRYdHSc= -google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4/go.mod h1:px9SlOOZBg1wM1zdnr8jEL4CNGUBZ+ZKYtNPApNQc4c= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= -google.golang.org/genproto/googleapis/api v0.0.0-20240722135656-d784300faade h1:WxZOF2yayUHpHSbUE6NMzumUzBxYc3YGwo0YHnbzsJY= -google.golang.org/genproto/googleapis/api v0.0.0-20240722135656-d784300faade/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f h1:b1Ln/PG8orm0SsBbHZWke8dDp2lrCD4jSmfglFpTZbk= google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:AHT0dDg3SoMOgZGnZk29b5xTbPHMoEC8qthmBLJCpys= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6 h1:DujSIu+2tC9Ht0aPNA7jgj23Iq8Ewi5sgkQ++wdvonE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e h1:Elxv5MwEkCI9f5SkoL6afed6NTdxaGoAo39eANBwHL8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240617180043-68d350f18fd4 h1:Di6ANFilr+S60a4S61ZM00vLdw0IrQOSMS2/6mrnOU0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240617180043-68d350f18fd4/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d h1:k3zyW3BYYR30e8v3x0bTDdE9vpYFjZHK+HcyqkrppWk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b h1:04+jVzTs2XBnOZcPsLnmrTGqltqJbZQ1Ey26hjYdQQ0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade h1:oCRSWfwGXQsqlVdErcyTt4A93Y8fo0/9D4b1gnI++qo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf h1:liao9UHurZLtiEwBgT9LMOnKYsHze6eA6w1KQCMVN2Q= google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -348,10 +189,6 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -363,10 +200,6 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= -google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/main.go b/main.go index 2c7278a..792f842 100644 --- a/main.go +++ b/main.go @@ -10,29 +10,40 @@ import ( "github.com/nakamasato/cloud-run-slack-bot/pkg/monitoring" slackinternal "github.com/nakamasato/cloud-run-slack-bot/pkg/slack" "github.com/slack-go/slack" + "go.uber.org/zap" ) func main() { - var err error + ctx := context.Background() + + logger, err := zap.NewProduction() + if err != nil { + log.Fatal(err) + } + defer func() { + if err := logger.Sync(); err != nil { + log.Printf("Error syncing logger: %v", err) + } + }() + project := os.Getenv("PROJECT") if project == "" { - log.Fatal("PROJECT env var is required") + logger.Fatal("PROJECT env var is required") } region := os.Getenv("REGION") if region == "" { - log.Fatal("REGION env var is required") + logger.Fatal("REGION env var is required") } mClient, err := monitoring.NewMonitoringClient(project) if err != nil { - log.Fatal(err) + logger.Fatal("failed to initialize monitoring client", zap.Error(err)) } defer mClient.Close() - ctx := context.Background() rClient, err := cloudrun.NewClient(ctx, project, region) if err != nil { - log.Fatalf("Failed to create run service: %v", err) + logger.Fatal("Failed to create run service", zap.Error(err)) } ops := []slack.Option{} @@ -42,7 +53,7 @@ func main() { } sClient := slack.New(os.Getenv("SLACK_BOT_TOKEN"), ops...) - handler := slackinternal.NewSlackEventHandler(sClient, rClient, mClient, os.Getenv("TMP_DIR")) + handler := slackinternal.NewSlackEventHandler(sClient, rClient, mClient, logger, os.Getenv("TMP_DIR")) svc := cloudrunslackbot.NewCloudRunSlackBotService( sClient, os.Getenv("SLACK_CHANNEL"), diff --git a/pkg/slack/event_handler.go b/pkg/slack/event_handler.go index 8576080..9473783 100644 --- a/pkg/slack/event_handler.go +++ b/pkg/slack/event_handler.go @@ -15,6 +15,7 @@ import ( "github.com/nakamasato/cloud-run-slack-bot/pkg/visualize" "github.com/slack-go/slack" "github.com/slack-go/slack/slackevents" + "go.uber.org/zap" ) const ( @@ -64,14 +65,16 @@ type SlackEventHandler struct { mClient *monitoring.Client // Cloud Run Client rClient *cloudrun.Client + // logger + logger *zap.Logger // Memory for storing target cloud run service memory *Memory // Temporary directory for storing images tmpDir string } -func NewSlackEventHandler(client *slack.Client, rClient *cloudrun.Client, mClient *monitoring.Client, tmpDir string) *SlackEventHandler { - return &SlackEventHandler{client: client, rClient: rClient, mClient: mClient, memory: NewMemory(), tmpDir: tmpDir} +func NewSlackEventHandler(client *slack.Client, rClient *cloudrun.Client, mClient *monitoring.Client, logger *zap.Logger, tmpDir string) *SlackEventHandler { + return &SlackEventHandler{client: client, rClient: rClient, mClient: mClient, memory: NewMemory(), logger: logger, tmpDir: tmpDir} } // NewSlackEventHandler handles AppMention events @@ -85,7 +88,7 @@ func (h *SlackEventHandler) HandleEvent(event *slackevents.EventsAPIEvent) error if len(message) > 1 { command = message[1] // e.Text is "<@bot_id> command" } - log.Printf("command: %s\n", command) + h.logger.Info("command", zap.String("command", command)) currentService, ok := h.memory.Get(e.User) switch command { case "describe", "d": @@ -142,8 +145,7 @@ func (h *SlackEventHandler) HandleInteraction(interaction *slack.InteractionCall } } - log.Printf("test: %d\n", len(interaction.ActionCallback.AttachmentActions)) - // metricsTypeVal := interaction.ActionCallback.AttachmentActions[1].SelectedOptions[0].Value + h.logger.Info("action metrics", zap.String("duration", durationVal), zap.String("metricsType", metricsTypeVal)) svc, ok := h.memory.Get(interaction.User.ID) if !ok { return h.list(ctx, interaction.Channel.ID, ActionIdMetricsService) @@ -262,9 +264,9 @@ func (h *SlackEventHandler) getServiceMetrics(ctx context.Context, channelId, sv return err } - log.Println("visualizing") + h.logger.Info("visualizing") imgName := path.Join(h.tmpDir, fmt.Sprintf("%s-metrics.png", svcName)) - log.Printf("imgName: %s\n", imgName) + h.logger.Info("image name", zap.String("imgName", imgName)) size, err := visualize.Visualize(title, imgName, startTime, endTime, aggregationPeriod, seriesMap) if err != nil { From 034ddd3187070a9db674bf22dc0d872a2f236ef1 Mon Sep 17 00:00:00 2001 From: Masato Naka Date: Mon, 12 Aug 2024 18:13:34 +0900 Subject: [PATCH 3/8] use logger --- main.go | 2 +- pkg/cloudrun/cloudrun.go | 64 +++++++++++++------ pkg/cloudrun/cloudrun_test.go | 8 +-- pkg/cloudrunslackbot/cloudrunslackbot.go | 4 +- pkg/cloudrunslackbot/cloudrunslackbot_http.go | 53 +++++++++++---- pkg/monitoring/client.go | 56 +++++++++------- pkg/slack/event_handler.go | 4 +- 7 files changed, 130 insertions(+), 61 deletions(-) diff --git a/main.go b/main.go index 792f842..1d7d252 100644 --- a/main.go +++ b/main.go @@ -41,7 +41,7 @@ func main() { } defer mClient.Close() - rClient, err := cloudrun.NewClient(ctx, project, region) + rClient, err := cloudrun.NewClient(ctx, cloudrun.WithLogger(logger), cloudrun.WithProject(project), cloudrun.WithRegion(region)) if err != nil { logger.Fatal("Failed to create run service", zap.Error(err)) } diff --git a/pkg/cloudrun/cloudrun.go b/pkg/cloudrun/cloudrun.go index 986f442..44eecb2 100644 --- a/pkg/cloudrun/cloudrun.go +++ b/pkg/cloudrun/cloudrun.go @@ -7,16 +7,18 @@ import ( "strings" "time" + "go.uber.org/zap" "google.golang.org/api/run/v2" ) -type Client struct { +type Service struct { project string region string projectLocationServiceClient *run.ProjectsLocationsServicesService + logger *zap.Logger } -type CloudRunService struct { +type CloudRunInfo struct { Name string Region string Project string @@ -27,49 +29,75 @@ type CloudRunService struct { ResourceLimits map[string]string } -func (c *CloudRunService) GetMetricsUrl() string { +type ServiceOption func(*Service) + +func WithLogger(l *zap.Logger) ServiceOption { + return func(s *Service) { + s.logger = l + } +} + +func WithProject(p string) ServiceOption { + return func(s *Service) { + s.project = p + } +} + +func WithRegion(r string) ServiceOption { + return func(s *Service) { + s.region = r + } +} + +func (c *CloudRunInfo) GetMetricsUrl() string { return c.getUrl("metrics") } -func (c *CloudRunService) GetYamlUrl() string { +func (c *CloudRunInfo) GetYamlUrl() string { return c.getUrl("yaml") } // https://console.cloud.google.com/run/detail/asia-northeast1/cloud-run-slack-bot/?project= // Supported urlPath: metrics, slos, logs, revisions, networking, triggers, integrations, yaml -func (c *CloudRunService) getUrl(urlPath string) string { +func (c *CloudRunInfo) getUrl(urlPath string) string { return fmt.Sprintf("https://console.cloud.google.com/run/detail/%s/%s/%s?project=%s", c.Region, c.Name, urlPath, c.Project) } -func (c *CloudRunService) String() string { +func (c *CloudRunInfo) String() string { return fmt.Sprintf( "Name: %s\n- LatestRevision: %s\n- Image: %s\n- LastModifier: %s\n- UpdateTime: %s\n- Resource Limit: (cpu:%s, memory:%s)\n", c.Name, c.LatestRevision, c.Image, c.LastModifier, c.UpdateTime, c.ResourceLimits["cpu"], c.ResourceLimits["memory"], ) } -func (c *Client) getProjectLocation() string { - return fmt.Sprintf("projects/%s/locations/%s", c.project, c.region) +func (s *Service) getProjectLocation() string { + return fmt.Sprintf("projects/%s/locations/%s", s.project, s.region) } -func (c *Client) GetServiceNameFromFullname(fullname string) string { - return strings.TrimPrefix(fullname, fmt.Sprintf("%s/services/", c.getProjectLocation())) +func (s *Service) GetServiceNameFromFullname(fullname string) string { + return strings.TrimPrefix(fullname, fmt.Sprintf("%s/services/", s.getProjectLocation())) } -func NewClient(ctx context.Context, project, region string) (*Client, error) { +func NewClient(ctx context.Context, opts ...ServiceOption) (*Service, error) { runService, err := run.NewService(ctx) if err != nil { return nil, err } plSvc := run.NewProjectsLocationsServicesService(runService) - return &Client{ - project: project, - region: region, + s := &Service{ projectLocationServiceClient: plSvc, - }, nil + } + for _, opt := range opts { + opt(s) + } + // デフォルトのロガー設定 + if s.logger == nil { + s.logger = zap.NewExample() + } + return s, nil } -func (c *Client) ListServices(ctx context.Context) ([]string, error) { +func (c *Service) ListServices(ctx context.Context) ([]string, error) { projLoc := c.getProjectLocation() log.Printf("Listing services in %s\n", projLoc) res, err := c.projectLocationServiceClient.List(projLoc).Context(ctx).Do() @@ -84,7 +112,7 @@ func (c *Client) ListServices(ctx context.Context) ([]string, error) { return services, nil } -func (c *Client) GetService(ctx context.Context, serviceName string) (*CloudRunService, error) { +func (c *Service) GetService(ctx context.Context, serviceName string) (*CloudRunInfo, error) { projLoc := c.getProjectLocation() res, err := c.projectLocationServiceClient.Get(fmt.Sprintf("%s/services/%s", projLoc, serviceName)).Context(ctx).Do() if err != nil { @@ -97,7 +125,7 @@ func (c *Client) GetService(ctx context.Context, serviceName string) (*CloudRunS return nil, err } - return &CloudRunService{ + return &CloudRunInfo{ Name: c.GetServiceNameFromFullname(res.Name), Region: c.region, Project: c.project, diff --git a/pkg/cloudrun/cloudrun_test.go b/pkg/cloudrun/cloudrun_test.go index ca0df17..45a3f65 100644 --- a/pkg/cloudrun/cloudrun_test.go +++ b/pkg/cloudrun/cloudrun_test.go @@ -7,12 +7,12 @@ import ( func TestCloudRunService_GetMetricsUrl(t *testing.T) { tests := []struct { name string - c *CloudRunService + c *CloudRunInfo want string }{ { name: "test", - c: &CloudRunService{ + c: &CloudRunInfo{ Name: "test", Region: "asia-northeast1", Project: "project", @@ -32,12 +32,12 @@ func TestCloudRunService_GetMetricsUrl(t *testing.T) { func TestCloudRunService_GetYamlUrl(t *testing.T) { tests := []struct { name string - c *CloudRunService + c *CloudRunInfo want string }{ { name: "test", - c: &CloudRunService{ + c: &CloudRunInfo{ Name: "test", Region: "asia-northeast1", Project: "project", diff --git a/pkg/cloudrunslackbot/cloudrunslackbot.go b/pkg/cloudrunslackbot/cloudrunslackbot.go index a8e82f3..52b9f76 100644 --- a/pkg/cloudrunslackbot/cloudrunslackbot.go +++ b/pkg/cloudrunslackbot/cloudrunslackbot.go @@ -9,9 +9,9 @@ type CloudRunSlackBotService interface { Run() } -func NewCloudRunSlackBotService(sClient *slack.Client, channel, slackMode string, handler *slackinternal.SlackEventHandler) CloudRunSlackBotService { +func NewCloudRunSlackBotService(sClient *slack.Client, channel, slackMode string, handler *slackinternal.SlackEventHandler, opts ...ServiceOption) CloudRunSlackBotService { if slackMode == "socket" { return NewCloudRunSlackBotSocket(channel, sClient, handler) } - return NewCloudRunSlackBotHttp(channel, sClient, handler) + return NewCloudRunSlackBotHttp(channel, sClient, handler, opts...) } diff --git a/pkg/cloudrunslackbot/cloudrunslackbot_http.go b/pkg/cloudrunslackbot/cloudrunslackbot_http.go index 9e72d41..45f4f16 100644 --- a/pkg/cloudrunslackbot/cloudrunslackbot_http.go +++ b/pkg/cloudrunslackbot/cloudrunslackbot_http.go @@ -3,27 +3,56 @@ package cloudrunslackbot import ( "encoding/json" "io" - "log" "net/http" "github.com/nakamasato/cloud-run-slack-bot/pkg/pubsub" slackinternal "github.com/nakamasato/cloud-run-slack-bot/pkg/slack" "github.com/slack-go/slack" "github.com/slack-go/slack/slackevents" + "go.uber.org/zap" ) +type ServiceOption func(*CloudRunSlackBotHttp) + type CloudRunSlackBotHttp struct { client *slack.Client slackHandler *slackinternal.SlackEventHandler auditHandler *pubsub.CloudRunAuditLogHandler + logger *zap.Logger +} + +func WithLogger(l *zap.Logger) ServiceOption { + return func(s *CloudRunSlackBotHttp) { + s.logger = l + } +} + +func WithClient(c *slack.Client) ServiceOption { + return func(s *CloudRunSlackBotHttp) { + s.client = c + } +} + +func WithSlackHandler(h *slackinternal.SlackEventHandler) ServiceOption { + return func(s *CloudRunSlackBotHttp) { + s.slackHandler = h + } } -func NewCloudRunSlackBotHttp(channel string, sClient *slack.Client, handler *slackinternal.SlackEventHandler) *CloudRunSlackBotHttp { - return &CloudRunSlackBotHttp{ +func NewCloudRunSlackBotHttp(channel string, sClient *slack.Client, handler *slackinternal.SlackEventHandler, opts ...ServiceOption) *CloudRunSlackBotHttp { + s := &CloudRunSlackBotHttp{ client: sClient, slackHandler: handler, auditHandler: pubsub.NewCloudRunAuditLogHandler(channel, sClient), } + for _, opt := range opts { + opt(s) + } + // default logger + if s.logger == nil { + s.logger = zap.NewExample() + } + return s } // SlackEventsHandler starts http server @@ -31,9 +60,9 @@ func (svc *CloudRunSlackBotHttp) Run() { http.HandleFunc("/slack/events", svc.SlackEventsHandler()) http.HandleFunc("/slack/interaction", svc.SlackInteractionHandler()) http.HandleFunc("/cloudrun/events", svc.auditHandler.HandleCloudRunAuditLogs) - log.Println("[INFO] Server listening") + svc.logger.Info("Server listening") if err := http.ListenAndServe(":8080", nil); err != nil { - log.Fatal(err) + svc.logger.Error("failed to start server", zap.Error(err)) } } @@ -42,14 +71,14 @@ func (svc *CloudRunSlackBotHttp) SlackEventsHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) if err != nil { - log.Println(err) + svc.logger.Error("failed to read request body", zap.Error(err)) w.WriteHeader(http.StatusInternalServerError) return } eventsAPIEvent, err := slackevents.ParseEvent(json.RawMessage(body), slackevents.OptionNoVerifyToken()) if err != nil { - log.Println(err) + svc.logger.Error("failed to parse event", zap.Error(err)) w.WriteHeader(http.StatusInternalServerError) return } @@ -58,20 +87,20 @@ func (svc *CloudRunSlackBotHttp) SlackEventsHandler() http.HandlerFunc { case slackevents.URLVerification: var res *slackevents.ChallengeResponse if err := json.Unmarshal(body, &res); err != nil { - log.Println(err) + svc.logger.Error("failed to unmarshal challenge response", zap.Error(err)) w.WriteHeader(http.StatusInternalServerError) return } w.Header().Set("Content-Type", "text/plain") if _, err := w.Write([]byte(res.Challenge)); err != nil { - log.Println(err) + svc.logger.Error("failed to write challenge response", zap.Error(err)) w.WriteHeader(http.StatusInternalServerError) return } case slackevents.CallbackEvent: err := svc.slackHandler.HandleEvent(&eventsAPIEvent) if err != nil { - log.Println(err) + svc.logger.Error("failed to handle event", zap.Error(err)) w.WriteHeader(http.StatusInternalServerError) return } @@ -83,14 +112,14 @@ func (svc *CloudRunSlackBotHttp) SlackInteractionHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var interaction slack.InteractionCallback if err := json.Unmarshal([]byte(r.FormValue("payload")), &interaction); err != nil { - log.Println(err) + svc.logger.Error("failed to unmarshal interaction", zap.Error(err)) w.WriteHeader(http.StatusInternalServerError) return } err := svc.slackHandler.HandleInteraction(&interaction) if err != nil { - log.Println(err) + svc.logger.Error("failed to handle interaction", zap.Error(err)) w.WriteHeader(http.StatusInternalServerError) return } diff --git a/pkg/monitoring/client.go b/pkg/monitoring/client.go index 0289b2d..590df0f 100644 --- a/pkg/monitoring/client.go +++ b/pkg/monitoring/client.go @@ -10,6 +10,7 @@ import ( monitoring "cloud.google.com/go/monitoring/apiv3/v2" "cloud.google.com/go/monitoring/apiv3/v2/monitoringpb" + "go.uber.org/zap" "google.golang.org/api/iterator" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/timestamppb" @@ -69,16 +70,28 @@ func (c *MonitorCondition) filter() string { type Client struct { project string client *monitoring.MetricClient + logger *zap.Logger } -func NewMonitoringClient(project string) (*Client, error) { +type ClientOption func(*Client) + +func NewMonitoringClient(project string, opts ...ClientOption) (*Client, error) { ctx := context.Background() client, err := monitoring.NewMetricClient(ctx) if err != nil { return nil, err } log.Printf("Monitoring client created for project %s\n", project) - return &Client{project: project, client: client}, nil + c := &Client{project: project, client: client} + + for _, opt := range opts { + opt(c) + } + // default logger + if c.logger == nil { + c.logger = zap.NewExample() + } + return c, nil } func (mc *Client) GetCloudRunServiceRequestCount(ctx context.Context, service string, aggregationPeriod time.Duration, startTime, endTime time.Time) (*TimeSeriesMap, error) { @@ -90,7 +103,7 @@ func (mc *Client) GetCloudRunServiceRequestCount(ctx context.Context, service st }, } // See https://pkg.go.dev/cloud.google.com/go/monitoring/apiv3/v2/monitoringpb#ListTimeSeriesRequest. - log.Printf("[%s] get metrics %s (%s -> %s)\n", mc.project, monCon.filter(), startTime, endTime) + mc.logger.Info("get metrics", zap.String("project", mc.project), zap.String("filter", monCon.filter()), zap.Time("start", startTime), zap.Time("end", endTime)) // monitoringpb.Aggregation_ALIGN_SUM // monitoringpb.Aggregation_ALIGN_RATE // monitoringpb.Aggregation_ALIGN_PERCENTILE_99 @@ -121,19 +134,19 @@ func (mc *Client) aggregateRequestCount(ctx context.Context, label, labelType st for { resp, err := it.Next() if err == iterator.Done { - log.Printf("iterator.Done %d\n", loopCnt) + mc.logger.Info("iterator.Done", zap.Int("loopCnt", loopCnt)) break } pageInfo := it.PageInfo() - log.Printf("[page info] token:%s\tMaxSize:%d\n", pageInfo.Token, pageInfo.MaxSize) + mc.logger.Info("page info", zap.String("token", pageInfo.Token), zap.Int("maxSize", pageInfo.MaxSize)) if err != nil { - log.Printf("err %v\n", err) + mc.logger.Error("error", zap.Error(err)) return nil, err } if resp == nil { continue } - log.Printf("resp %v\n", resp.String()) + mc.logger.Info("resp", zap.String("resp", resp.String())) var labelValue string var ok bool switch labelType { @@ -142,20 +155,19 @@ func (mc *Client) aggregateRequestCount(ctx context.Context, label, labelType st case "resource": labelValue, ok = resp.Resource.Labels[label] default: - log.Printf("Invalid label type %s\n", labelType) - return nil, fmt.Errorf("invalid label type %s", labelType) + mc.logger.Error("invalid label type", zap.String("labelType", labelType)) + return nil, err } if seriesMap[labelValue] == nil { seriesMap[labelValue] = TimeSeries{} } if !ok { - log.Printf("Metric label '%s' not found", label) + mc.logger.Error("Metric label not found", zap.String("label", label)) continue } for i, p := range resp.GetPoints() { // Point per min - log.Println(p.Value.String()) - log.Printf("Point:%d\t%s:%s\tstart:%s\tend:%s\tvalue:%d\n", i, label, labelValue, p.Interval.StartTime.AsTime(), p.Interval.EndTime.AsTime(), p.Value.GetInt64Value()) + mc.logger.Info("Point", zap.Int("i", i), zap.String("label", label), zap.String("labelValue", labelValue), zap.Time("start", p.Interval.StartTime.AsTime()), zap.Time("end", p.Interval.EndTime.AsTime()), zap.Int64("value", p.Value.GetInt64Value())) val := p.GetValue().GetInt64Value() requestCount += val cnt[labelValue] += val @@ -163,43 +175,42 @@ func (mc *Client) aggregateRequestCount(ctx context.Context, label, labelType st } loopCnt++ } - log.Printf("Request count:%d\nCounter:\n%s\nseriesMap:\n%s\n", requestCount, cnt, seriesMap) + mc.logger.Info("Request count", zap.Int64("requestCount", requestCount), zap.Any("counter", cnt), zap.Any("seriesMap", seriesMap)) return &seriesMap, nil } func (mc *Client) aggregateRequestLatency(ctx context.Context, req *monitoringpb.ListTimeSeriesRequest) (*TimeSeries, error) { it := mc.client.ListTimeSeries(ctx, req) - var requestCount int64 var loopCnt int cnt := Counter{} series := TimeSeries{} for { resp, err := it.Next() if err == iterator.Done { - log.Printf("iterator.Done %d\n", loopCnt) + mc.logger.Info("iterator.Done", zap.Int("loopCnt", loopCnt)) break } pageInfo := it.PageInfo() - log.Printf("[page info] token:%s\tMaxSize:%d\n", pageInfo.Token, pageInfo.MaxSize) + mc.logger.Info("page info", zap.String("token", pageInfo.Token), zap.Int("maxSize", pageInfo.MaxSize)) if err != nil { - log.Printf("err %v\n", err) + mc.logger.Error("failed to get page info", zap.Error(err)) return nil, err } if resp == nil { - log.Println("nil") + mc.logger.Info("page info resp is nil") continue } - log.Printf("resp %v\n", resp.String()) + mc.logger.Info("successfully got page info", zap.String("resp", resp.String())) for i, p := range resp.GetPoints() { // Point per min log.Println(p.Value.String()) - log.Printf("Latency Point:%d\tstart:%s\tend:%s\tvalue:%d\n", i, p.Interval.StartTime.AsTime(), p.Interval.EndTime.AsTime(), p.Value.GetInt64Value()) + mc.logger.Info("Latency Point", zap.Int("i", i), zap.Time("start", p.Interval.StartTime.AsTime()), zap.Time("end", p.Interval.EndTime.AsTime()), zap.Int64("value", p.Value.GetInt64Value())) val := p.GetValue().GetDoubleValue() series = append(series, Point{Time: p.Interval.StartTime.AsTime(), Val: float64(val)}) } loopCnt++ } - log.Printf("Request count:%d\nCounter:\n%s\nseries:\n%s\n", requestCount, cnt, series) + mc.logger.Info("Request Latency", zap.Any("counter", cnt), zap.Any("series", series), zap.Int("loopCnt", loopCnt)) return &series, nil } @@ -212,7 +223,7 @@ func (mc *Client) GetCloudRunServiceRequestLatencies(ctx context.Context, servic }, } // See https://pkg.go.dev/cloud.google.com/go/monitoring/apiv3/v2/monitoringpb#ListTimeSeriesRequest. - log.Printf("[%s] get metrics %s (%s -> %s)\n", mc.project, monCon.filter(), startTime, endTime) + mc.logger.Info("get metrics", zap.String("project", mc.project), zap.String("filter", monCon.filter()), zap.Time("start", startTime), zap.Time("end", endTime)) aligners := []monitoringpb.Aggregation_Aligner{ monitoringpb.Aggregation_ALIGN_PERCENTILE_50, monitoringpb.Aggregation_ALIGN_PERCENTILE_95, @@ -236,6 +247,7 @@ func (mc *Client) GetCloudRunServiceRequestLatencies(ctx context.Context, servic } series, err := mc.aggregateRequestLatency(ctx, req) if err != nil { + mc.logger.Error("failed to get request latency", zap.Error(err)) return nil, err } timeSeriesMap[aligner.String()] = *series diff --git a/pkg/slack/event_handler.go b/pkg/slack/event_handler.go index 9473783..81f3711 100644 --- a/pkg/slack/event_handler.go +++ b/pkg/slack/event_handler.go @@ -64,7 +64,7 @@ type SlackEventHandler struct { // Cloud Monitoring Client mClient *monitoring.Client // Cloud Run Client - rClient *cloudrun.Client + rClient *cloudrun.Service // logger logger *zap.Logger // Memory for storing target cloud run service @@ -73,7 +73,7 @@ type SlackEventHandler struct { tmpDir string } -func NewSlackEventHandler(client *slack.Client, rClient *cloudrun.Client, mClient *monitoring.Client, logger *zap.Logger, tmpDir string) *SlackEventHandler { +func NewSlackEventHandler(client *slack.Client, rClient *cloudrun.Service, mClient *monitoring.Client, logger *zap.Logger, tmpDir string) *SlackEventHandler { return &SlackEventHandler{client: client, rClient: rClient, mClient: mClient, memory: NewMemory(), logger: logger, tmpDir: tmpDir} } From d34dd4eab23620eed652e8730b3c2dd7a9c0c830 Mon Sep 17 00:00:00 2001 From: Masato Naka Date: Mon, 12 Aug 2024 18:15:49 +0900 Subject: [PATCH 4/8] add withlogger --- main.go | 2 +- pkg/monitoring/client.go | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index 1d7d252..15afec2 100644 --- a/main.go +++ b/main.go @@ -35,7 +35,7 @@ func main() { logger.Fatal("REGION env var is required") } - mClient, err := monitoring.NewMonitoringClient(project) + mClient, err := monitoring.NewMonitoringClient(project, monitoring.WithLogger(logger)) if err != nil { logger.Fatal("failed to initialize monitoring client", zap.Error(err)) } diff --git a/pkg/monitoring/client.go b/pkg/monitoring/client.go index 590df0f..be6f42d 100644 --- a/pkg/monitoring/client.go +++ b/pkg/monitoring/client.go @@ -75,6 +75,12 @@ type Client struct { type ClientOption func(*Client) +func WithLogger(l *zap.Logger) ClientOption { + return func(c *Client) { + c.logger = l + } +} + func NewMonitoringClient(project string, opts ...ClientOption) (*Client, error) { ctx := context.Background() client, err := monitoring.NewMetricClient(ctx) From 221a1d5978b527382edec8a9b5593d4d8515d6fd Mon Sep 17 00:00:00 2001 From: Masato Naka Date: Mon, 12 Aug 2024 19:54:22 +0900 Subject: [PATCH 5/8] fix --- pkg/monitoring/client.go | 3 +-- pkg/visualize/visualize.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg/monitoring/client.go b/pkg/monitoring/client.go index be6f42d..b808abc 100644 --- a/pkg/monitoring/client.go +++ b/pkg/monitoring/client.go @@ -209,8 +209,7 @@ func (mc *Client) aggregateRequestLatency(ctx context.Context, req *monitoringpb mc.logger.Info("successfully got page info", zap.String("resp", resp.String())) for i, p := range resp.GetPoints() { // Point per min - log.Println(p.Value.String()) - mc.logger.Info("Latency Point", zap.Int("i", i), zap.Time("start", p.Interval.StartTime.AsTime()), zap.Time("end", p.Interval.EndTime.AsTime()), zap.Int64("value", p.Value.GetInt64Value())) + mc.logger.Info("Latency Point", zap.Int("i", i), zap.Time("start", p.Interval.StartTime.AsTime()), zap.Time("end", p.Interval.EndTime.AsTime()), zap.Float64("value", p.GetValue().GetDoubleValue())) val := p.GetValue().GetDoubleValue() series = append(series, Point{Time: p.Interval.StartTime.AsTime(), Val: float64(val)}) } diff --git a/pkg/visualize/visualize.go b/pkg/visualize/visualize.go index b53a372..3d48a91 100644 --- a/pkg/visualize/visualize.go +++ b/pkg/visualize/visualize.go @@ -76,7 +76,7 @@ func makeChartTimeSeries(i int, name string, startTime, endTime time.Time, inter cTs.XValues = append(cTs.XValues, t) cTs.YValues = append(cTs.YValues, counter[t]) } - log.Printf("name: %s\nXValues:%d, YValues:%d", name, len(cTs.XValues), len(cTs.YValues)) + log.Printf("name: %s, XValues:%d, YValues:%d", name, len(cTs.XValues), len(cTs.YValues)) return &cTs } From 4adb037ece7919ce6f9bb6c6798627d109eef31e Mon Sep 17 00:00:00 2001 From: Masato Naka Date: Mon, 12 Aug 2024 20:21:06 +0900 Subject: [PATCH 6/8] set color --- pkg/visualize/visualize.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pkg/visualize/visualize.go b/pkg/visualize/visualize.go index 3d48a91..c0e3ce1 100644 --- a/pkg/visualize/visualize.go +++ b/pkg/visualize/visualize.go @@ -12,9 +12,12 @@ import ( ) var predefinedColorMap = map[string]drawing.Color{ - "2xx": chart.ColorAlternateGreen, - "4xx": chart.ColorAlternateYellow, - "5xx": chart.ColorRed, + "2xx": chart.ColorAlternateGreen, + "4xx": chart.ColorAlternateYellow, + "5xx": chart.ColorRed, + "ALIGN_PERCENTILE_99": chart.ColorBlue, + "ALIGN_PERCENTILE_90": chart.ColorCyan, + "ALIGN_PERCENTILE_50": chart.ColorOrange, } // Visualize draw a line chart and export to a file. From 51b08fb4bb8c0688c3ee3b8f6964cd0ca6a107fd Mon Sep 17 00:00:00 2001 From: Masato Naka Date: Mon, 12 Aug 2024 21:33:24 +0900 Subject: [PATCH 7/8] enable to connect trace --- go.mod | 1 + go.sum | 7 ++ main.go | 7 +- pkg/cloudrunslackbot/cloudrunslackbot_http.go | 5 +- pkg/logging/logging.go | 47 ++++++++++++++ pkg/logging/middleware.go | 65 +++++++++++++++++++ pkg/slack/event_handler.go | 38 ++++++++++- 7 files changed, 163 insertions(+), 7 deletions(-) create mode 100644 pkg/logging/logging.go create mode 100644 pkg/logging/middleware.go diff --git a/go.mod b/go.mod index bb4408a..bfbfe39 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.21.4 require ( cloud.google.com/go/monitoring v1.20.4 + github.com/blendle/zapdriver v1.3.1 github.com/slack-go/slack v0.13.1 github.com/wcharczuk/go-chart/v2 v2.1.1 go.uber.org/zap v1.27.0 diff --git a/go.sum b/go.sum index da23ce4..72b35d9 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ cloud.google.com/go/monitoring v1.20.4/go.mod h1:v7F/UcLRw15EX7xq565N7Ae5tnYEE28 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/blend/go-sdk v1.20220411.3 h1:GFV4/FQX5UzXLPwWV03gP811pj7B8J2sbuq+GJQofXc= github.com/blend/go-sdk v1.20220411.3/go.mod h1:7lnH8fTi6U4i1fArEXRyOIY2E1X4MALg09qsQqY1+ak= +github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= +github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -67,6 +69,7 @@ github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDP github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -76,6 +79,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= @@ -96,10 +100,13 @@ go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGX go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/main.go b/main.go index 15afec2..c0a401c 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "github.com/nakamasato/cloud-run-slack-bot/pkg/cloudrun" "github.com/nakamasato/cloud-run-slack-bot/pkg/cloudrunslackbot" + "github.com/nakamasato/cloud-run-slack-bot/pkg/logging" "github.com/nakamasato/cloud-run-slack-bot/pkg/monitoring" slackinternal "github.com/nakamasato/cloud-run-slack-bot/pkg/slack" "github.com/slack-go/slack" @@ -16,9 +17,9 @@ import ( func main() { ctx := context.Background() - logger, err := zap.NewProduction() + logger, err := logging.New(ctx) if err != nil { - log.Fatal(err) + log.Fatalf("Failed to create logging client: %v", err) } defer func() { if err := logger.Sync(); err != nil { @@ -53,7 +54,7 @@ func main() { } sClient := slack.New(os.Getenv("SLACK_BOT_TOKEN"), ops...) - handler := slackinternal.NewSlackEventHandler(sClient, rClient, mClient, logger, os.Getenv("TMP_DIR")) + handler := slackinternal.NewSlackEventHandler(sClient, rClient, mClient, slackinternal.WithLogger(logger), slackinternal.WithTmpDir(os.Getenv("TMP_DIR"))) svc := cloudrunslackbot.NewCloudRunSlackBotService( sClient, os.Getenv("SLACK_CHANNEL"), diff --git a/pkg/cloudrunslackbot/cloudrunslackbot_http.go b/pkg/cloudrunslackbot/cloudrunslackbot_http.go index 45f4f16..83159c4 100644 --- a/pkg/cloudrunslackbot/cloudrunslackbot_http.go +++ b/pkg/cloudrunslackbot/cloudrunslackbot_http.go @@ -5,6 +5,7 @@ import ( "io" "net/http" + "github.com/nakamasato/cloud-run-slack-bot/pkg/logging" "github.com/nakamasato/cloud-run-slack-bot/pkg/pubsub" slackinternal "github.com/nakamasato/cloud-run-slack-bot/pkg/slack" "github.com/slack-go/slack" @@ -57,8 +58,8 @@ func NewCloudRunSlackBotHttp(channel string, sClient *slack.Client, handler *sla // SlackEventsHandler starts http server func (svc *CloudRunSlackBotHttp) Run() { - http.HandleFunc("/slack/events", svc.SlackEventsHandler()) - http.HandleFunc("/slack/interaction", svc.SlackInteractionHandler()) + http.Handle("/slack/events", logging.Middleware(svc.SlackEventsHandler())) + http.Handle("/slack/interaction", logging.Middleware(svc.SlackInteractionHandler())) http.HandleFunc("/cloudrun/events", svc.auditHandler.HandleCloudRunAuditLogs) svc.logger.Info("Server listening") if err := http.ListenAndServe(":8080", nil); err != nil { diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go new file mode 100644 index 0000000..d202739 --- /dev/null +++ b/pkg/logging/logging.go @@ -0,0 +1,47 @@ +package logging + +import ( + "context" + "os" + + "github.com/blendle/zapdriver" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +func newProductionEncoderConfig() zapcore.EncoderConfig { + cfg := zap.NewProductionEncoderConfig() + + cfg.TimeKey = "time" + cfg.LevelKey = "severity" + cfg.MessageKey = "message" + cfg.EncodeTime = zapcore.RFC3339NanoTimeEncoder + + return cfg +} + +func newGCPConfig() zap.Config { + cfg := zap.NewProductionConfig() + cfg.Level.SetLevel(zap.ErrorLevel) + cfg.EncoderConfig = newProductionEncoderConfig() + + return cfg +} + +func New(ctx context.Context) (*zap.Logger, error) { + // https://cloud.google.com/run/docs/container-contract#services-env-vars + if os.Getenv("K_SERVICE") == "" { + return zap.NewDevelopment() + } + cfg := newGCPConfig() + trace := ForContext(ctx) + logger, err := cfg.Build() + if err != nil { + return nil, err + } + if trace != nil { + fields := zapdriver.TraceContext(trace.TraceID, trace.SpanID, trace.Sampled, os.Getenv("PROJECT")) + logger = logger.With(fields...) + } + return logger, nil +} diff --git a/pkg/logging/middleware.go b/pkg/logging/middleware.go new file mode 100644 index 0000000..3d3641a --- /dev/null +++ b/pkg/logging/middleware.go @@ -0,0 +1,65 @@ +package logging + +import ( + "context" + "net/http" + "regexp" +) + +var TraceCtxKey = &contextKey{"trace"} + +type contextKey struct { + name string +} + +type Trace struct { + TraceID string + SpanID string + Sampled bool +} + +// Extracts the trace information from the incoming request (Cloud Run) and stores it in the context. +func Middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + header := r.Header.Get("X-Cloud-Trace-Context") + if len(header) > 0 { + traceID, spanID, sampled := deconstructXCloudTraceContext(header) + + t := &Trace{ + TraceID: traceID, + SpanID: spanID, + Sampled: sampled, + } + + ctx := context.WithValue(r.Context(), TraceCtxKey, t) + r = r.WithContext(ctx) + } + + next.ServeHTTP(w, r) + }) +} + +var reCloudTraceContext = regexp.MustCompile( + // Matches on "TRACE_ID" + `([a-f\d]+)?` + + // Matches on "/SPAN_ID" + `(?:/([a-f\d]+))?` + + // Matches on ";0=TRACE_TRUE" + `(?:;o=(\d))?`) + +func deconstructXCloudTraceContext(s string) (traceID, spanID string, traceSampled bool) { + matches := reCloudTraceContext.FindStringSubmatch(s) + + traceID, spanID, traceSampled = matches[1], matches[2], matches[3] == "1" + + if spanID == "0" { + spanID = "" + } + + return +} + +func ForContext(ctx context.Context) *Trace { + raw, _ := ctx.Value(TraceCtxKey).(*Trace) + return raw +} diff --git a/pkg/slack/event_handler.go b/pkg/slack/event_handler.go index 81f3711..72f973e 100644 --- a/pkg/slack/event_handler.go +++ b/pkg/slack/event_handler.go @@ -73,8 +73,42 @@ type SlackEventHandler struct { tmpDir string } -func NewSlackEventHandler(client *slack.Client, rClient *cloudrun.Service, mClient *monitoring.Client, logger *zap.Logger, tmpDir string) *SlackEventHandler { - return &SlackEventHandler{client: client, rClient: rClient, mClient: mClient, memory: NewMemory(), logger: logger, tmpDir: tmpDir} +type ServiceOption func(*SlackEventHandler) + +func WithLogger(l *zap.Logger) ServiceOption { + return func(s *SlackEventHandler) { + s.logger = l + } +} + +func WithTmpDir(d string) ServiceOption { + return func(s *SlackEventHandler) { + s.tmpDir = d + } +} + +func WithMemory(m *Memory) ServiceOption { + return func(s *SlackEventHandler) { + s.memory = m + } +} + + +func NewSlackEventHandler(client *slack.Client, rClient *cloudrun.Service, mClient *monitoring.Client, opts ...ServiceOption) *SlackEventHandler { + s := &SlackEventHandler{client: client, rClient: rClient, mClient: mClient} + for _, opt := range opts { + opt(s) + } + if s.logger == nil { + s.logger = zap.NewExample() + } + if s.memory == nil { + s.memory = NewMemory() + } + if s.tmpDir == "" { + s.tmpDir = os.TempDir() + } + return s } // NewSlackEventHandler handles AppMention events From 7614c3fa05b2664eb59e9e34b6f8a522a8706361 Mon Sep 17 00:00:00 2001 From: Masato Naka Date: Mon, 12 Aug 2024 21:50:05 +0900 Subject: [PATCH 8/8] add trace --- go.mod | 42 ++++++++++++++++++---- go.sum | 82 ++++++++++++++++++++++++++++++++++++------ main.go | 15 +++++++- pkg/tracing/tracing.go | 54 ++++++++++++++++++++++++++++ 4 files changed, 176 insertions(+), 17 deletions(-) create mode 100644 pkg/tracing/tracing.go diff --git a/go.mod b/go.mod index bfbfe39..e7eac1a 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,11 @@ require ( github.com/blendle/zapdriver v1.3.1 github.com/slack-go/slack v0.13.1 github.com/wcharczuk/go-chart/v2 v2.1.1 + go.opentelemetry.io/contrib/exporters/autoexport v0.53.0 + go.opentelemetry.io/contrib/propagators/autoprop v0.53.0 + go.opentelemetry.io/otel v1.28.0 + go.opentelemetry.io/otel/sdk v1.28.0 + go.opentelemetry.io/otel/sdk/metric v1.28.0 go.uber.org/zap v1.27.0 google.golang.org/api v0.191.0 google.golang.org/protobuf v1.34.2 @@ -16,7 +21,10 @@ require ( cloud.google.com/go/auth v0.8.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.3 // indirect cloud.google.com/go/compute/metadata v0.5.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect github.com/blend/go-sdk v1.20220411.3 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -27,14 +35,36 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.13.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect - github.com/stretchr/testify v1.9.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/bridges/prometheus v0.53.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - go.opentelemetry.io/otel v1.24.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect - go.uber.org/multierr v1.10.0 // indirect + go.opentelemetry.io/contrib/propagators/aws v1.28.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.28.0 // indirect + go.opentelemetry.io/contrib/propagators/jaeger v1.28.0 // indirect + go.opentelemetry.io/contrib/propagators/ot v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.4.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.50.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 // indirect + go.opentelemetry.io/otel/log v0.4.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.4.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.25.0 // indirect golang.org/x/image v0.14.0 // indirect golang.org/x/net v0.27.0 // indirect @@ -46,5 +76,5 @@ require ( google.golang.org/genproto v0.0.0-20240730163845-b1a4ccb954bf // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf // indirect - google.golang.org/grpc v1.64.1 // indirect + google.golang.org/grpc v1.65.0 // indirect ) diff --git a/go.sum b/go.sum index 72b35d9..5140e22 100644 --- a/go.sum +++ b/go.sum @@ -8,11 +8,17 @@ cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykW cloud.google.com/go/monitoring v1.20.4 h1:zwcViK7mT9SV0kzKqLOI3spRadvsmvw/R9z1MHNeC0E= cloud.google.com/go/monitoring v1.20.4/go.mod h1:v7F/UcLRw15EX7xq565N7Ae5tnYEE28+Cl717aTXG4c= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blend/go-sdk v1.20220411.3 h1:GFV4/FQX5UzXLPwWV03gP811pj7B8J2sbuq+GJQofXc= github.com/blend/go-sdk v1.20220411.3/go.mod h1:7lnH8fTi6U4i1fArEXRyOIY2E1X4MALg09qsQqY1+ak= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -69,10 +75,22 @@ github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDP github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/slack-go/slack v0.13.1 h1:6UkM3U1OnbhPsYeb1IMkQ6HSNOSikWluwOncJt4Tz/o= github.com/slack-go/slack v0.13.1/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -90,22 +108,66 @@ github.com/wcharczuk/go-chart/v2 v2.1.1/go.mod h1:CyCAUt2oqvfhCl6Q5ZvAZwItgpQKZO github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 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/bridges/prometheus v0.53.0 h1:BdkKDtcrHThgjcEia1737OUuFdP6xzBKAMx2sNZCkvE= +go.opentelemetry.io/contrib/bridges/prometheus v0.53.0/go.mod h1:ZkhVxcJgeXlL/lVyT/vxNHVFiSG5qOaDwYaSgD8IfZo= +go.opentelemetry.io/contrib/exporters/autoexport v0.53.0 h1:13K+tY7E8GJInkrvRiPAhC0gi/7vKjzDNhtmCf+QXG8= +go.opentelemetry.io/contrib/exporters/autoexport v0.53.0/go.mod h1:lyQF6xQ4iDnMg4sccNdFs1zf62xd79YI8vZqKjOTwMs= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/contrib/propagators/autoprop v0.53.0 h1:4zaVLcJ5mvYw0vlk63TX62qS4qty/4jAY1BKZ1usu18= +go.opentelemetry.io/contrib/propagators/autoprop v0.53.0/go.mod h1:RPlvYtxp5D8PKnRzyPM+rwMQrvzdlfA49Sgworkg7aQ= +go.opentelemetry.io/contrib/propagators/aws v1.28.0 h1:acyTl4oyin/iLr5Nz3u7p/PKHUbLh42w/fqg9LblExk= +go.opentelemetry.io/contrib/propagators/aws v1.28.0/go.mod h1:5WgIv6yG9DvLlSY2uIHrYSeVVwCDCqp4jhwinNNyeT4= +go.opentelemetry.io/contrib/propagators/b3 v1.28.0 h1:XR6CFQrQ/ttAYmTBX2loUEFGdk1h17pxYI8828dk/1Y= +go.opentelemetry.io/contrib/propagators/b3 v1.28.0/go.mod h1:DWRkzJONLquRz7OJPh2rRbZ7MugQj62rk7g6HRnEqh0= +go.opentelemetry.io/contrib/propagators/jaeger v1.28.0 h1:xQ3ktSVS128JWIaN1DiPGIjcH+GsvkibIAVRWFjS9eM= +go.opentelemetry.io/contrib/propagators/jaeger v1.28.0/go.mod h1:O9HIyI2kVBrFoEwQZ0IN6PHXykGoit4mZV2aEjkTRH4= +go.opentelemetry.io/contrib/propagators/ot v1.28.0 h1:rmlG+2pc5k5M7Y7izDrxAHZUIwDERdGMTD9oMV7llMk= +go.opentelemetry.io/contrib/propagators/ot v1.28.0/go.mod h1:MNgXIn+UrMbNGpd7xyckyo2LCHIgCdmdjEE7YNZGG+w= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.4.0 h1:zBPZAISA9NOc5cE8zydqDiS0itvg/P/0Hn9m72a5gvM= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.4.0/go.mod h1:gcj2fFjEsqpV3fXuzAA+0Ze1p2/4MJ4T7d77AmkvueQ= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 h1:U2guen0GhqH8o/G2un8f/aG/y++OuW6MyCo6hT9prXk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0/go.mod h1:yeGZANgEcpdx/WK0IvvRFC+2oLiMS2u4L/0Rj2M2Qr0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0 h1:aLmmtjRke7LPDQ3lvpFz+kNEH43faFhzW7v8BFIEydg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0/go.mod h1:TC1pyCt6G9Sjb4bQpShH+P5R53pO6ZuGnHuuln9xMeE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk= +go.opentelemetry.io/otel/exporters/prometheus v0.50.0 h1:2Ewsda6hejmbhGFyUvWZjUThC98Cf8Zy6g0zkIimOng= +go.opentelemetry.io/otel/exporters/prometheus v0.50.0/go.mod h1:pMm5PkUo5YwbLiuEf7t2xg4wbP0/eSJrMxIMxKosynY= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0 h1:0MH3f8lZrflbUWXVxyBg/zviDFdGE062uKh5+fu8Vv0= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0/go.mod h1:Vh68vYiHY5mPdekTr0ox0sALsqjoVy0w3Os278yX5SQ= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 h1:BJee2iLkfRfl9lc7aFmBwkWxY/RI1RDdXepSF6y8TPE= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0/go.mod h1:DIzlHs3DRscCIBU3Y9YSzPfScwnYnzfnCd4g8zA7bZc= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 h1:EVSnY9JbEEW92bEkIYOVMw4q1WJxIAGoFTrtYOzWuRQ= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0/go.mod h1:Ea1N1QQryNXpCD0I1fdLibBAIpQuBkznMmkdKrapk1Y= +go.opentelemetry.io/otel/log v0.4.0 h1:/vZ+3Utqh18e8TPjuc3ecg284078KWrR8BRz+PQAj3o= +go.opentelemetry.io/otel/log v0.4.0/go.mod h1:DhGnQvky7pHy82MIRV43iXh3FlKN8UUKftn0KbLOq6I= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/sdk/log v0.4.0 h1:1mMI22L82zLqf6KtkjrRy5BbagOTWdJsqMY/HSqILAA= +go.opentelemetry.io/otel/sdk/log v0.4.0/go.mod h1:AYJ9FVF0hNOgAVzUG/ybg/QttnXhUePWAupmCqtdESo= +go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= +go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= -go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= @@ -196,8 +258,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= -google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/main.go b/main.go index c0a401c..2812613 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ import ( "github.com/nakamasato/cloud-run-slack-bot/pkg/logging" "github.com/nakamasato/cloud-run-slack-bot/pkg/monitoring" slackinternal "github.com/nakamasato/cloud-run-slack-bot/pkg/slack" + "github.com/nakamasato/cloud-run-slack-bot/pkg/tracing" "github.com/slack-go/slack" "go.uber.org/zap" ) @@ -23,10 +24,22 @@ func main() { } defer func() { if err := logger.Sync(); err != nil { - log.Printf("Error syncing logger: %v", err) + log.Fatalf("Error syncing logger: %v", err) } }() + // Setup metrics, tracing, and context propagation + shutdown, err := tracing.SetupOpenTelemetry(ctx) + if err != nil { + logger.Fatal("error setting up OpenTelemetry", zap.Error(err)) + os.Exit(1) + } + defer func(ctx context.Context) { + if err := shutdown(ctx); err != nil { + logger.Fatal("error shutting down OpenTelemetry", zap.Error(err)) + } + }(ctx) + project := os.Getenv("PROJECT") if project == "" { logger.Fatal("PROJECT env var is required") diff --git a/pkg/tracing/tracing.go b/pkg/tracing/tracing.go new file mode 100644 index 0000000..f68e497 --- /dev/null +++ b/pkg/tracing/tracing.go @@ -0,0 +1,54 @@ +package tracing + +import ( + "context" + "errors" + + "go.opentelemetry.io/contrib/propagators/autoprop" + "go.opentelemetry.io/contrib/exporters/autoexport" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/trace" +) + +func SetupOpenTelemetry(ctx context.Context) (shutdown func(context.Context) error, err error) { + var shutdownFuncs []func(context.Context) error + + // shutdown combines shutdown functions from multiple OpenTelemetry + // components into a single function. + shutdown = func(ctx context.Context) error { + var err error + for _, fn := range shutdownFuncs { + err = errors.Join(err, fn(ctx)) + } + shutdownFuncs = nil + return err + } + + // Configure Context Propagation to use the default W3C traceparent format + otel.SetTextMapPropagator(autoprop.NewTextMapPropagator()) + + // Configure Trace Export to send spans as OTLP + texporter, err := autoexport.NewSpanExporter(ctx) + if err != nil { + err = errors.Join(err, shutdown(ctx)) + return + } + tp := trace.NewTracerProvider(trace.WithBatcher(texporter)) + shutdownFuncs = append(shutdownFuncs, tp.Shutdown) + otel.SetTracerProvider(tp) + + // Configure Metric Export to send metrics as OTLP + mreader, err := autoexport.NewMetricReader(ctx) + if err != nil { + err = errors.Join(err, shutdown(ctx)) + return + } + mp := metric.NewMeterProvider( + metric.WithReader(mreader), + ) + shutdownFuncs = append(shutdownFuncs, mp.Shutdown) + otel.SetMeterProvider(mp) + + return shutdown, nil +}