Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: rename function and add logger #60

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 38 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ 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/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
)
Expand All @@ -15,25 +21,50 @@ 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/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
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/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.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
Expand All @@ -45,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
)
264 changes: 83 additions & 181 deletions go.sum

Large diffs are not rendered by default.

43 changes: 34 additions & 9 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,57 @@ 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/nakamasato/cloud-run-slack-bot/pkg/tracing"
"github.com/slack-go/slack"
"go.uber.org/zap"
)

func main() {
var err error
ctx := context.Background()

logger, err := logging.New(ctx)
if err != nil {
log.Fatalf("Failed to create logging client: %v", err)
}
defer func() {
if err := logger.Sync(); err != nil {
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 == "" {
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)
mClient, err := monitoring.NewMonitoringClient(project, monitoring.WithLogger(logger))
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)
rClient, err := cloudrun.NewClient(ctx, cloudrun.WithLogger(logger), cloudrun.WithProject(project), cloudrun.WithRegion(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{}
Expand All @@ -42,7 +67,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, slackinternal.WithLogger(logger), slackinternal.WithTmpDir(os.Getenv("TMP_DIR")))
svc := cloudrunslackbot.NewCloudRunSlackBotService(
sClient,
os.Getenv("SLACK_CHANNEL"),
Expand Down
64 changes: 46 additions & 18 deletions pkg/cloudrun/cloudrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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/<urlPath>?project=<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()
Expand All @@ -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 {
Expand All @@ -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,
Expand Down
8 changes: 4 additions & 4 deletions pkg/cloudrun/cloudrun_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
4 changes: 2 additions & 2 deletions pkg/cloudrunslackbot/cloudrunslackbot.go
Original file line number Diff line number Diff line change
Expand Up @@ -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...)
}
Loading