diff --git a/README.md b/README.md index 338dc6f..19af268 100644 --- a/README.md +++ b/README.md @@ -43,9 +43,9 @@ func main() { MemThreshold: 0.8, // Default: 0.75. Reporter: report.NewSlackReporter( &report.SlackReporterOption{ - App: "YOUR_APP_NAME", - Token: "YOUR_TOKEN_HERE", - Channel: "#REPORT_CHANNEL", + App: "YOUR_APP_NAME", + Token: "YOUR_TOKEN_HERE", + ChannelID: "REPORT_CHANNEL_ID", }, ), }) diff --git a/autopprof.go b/autopprof.go index 9210d8b..02f20e9 100644 --- a/autopprof.go +++ b/autopprof.go @@ -7,10 +7,10 @@ import ( "bytes" "context" "fmt" - "github.com/daangn/autopprof/queryer" "log" "time" + "github.com/daangn/autopprof/queryer" "github.com/daangn/autopprof/report" ) @@ -245,7 +245,8 @@ func (ap *autoPprof) reportCPUProfile(cpuUsage float64) error { UsagePercentage: cpuUsage * 100, } bReader := bytes.NewReader(b) - if err := ap.reporter.ReportCPUProfile(ctx, bReader, ci); err != nil { + bSize := len(b) + if err := ap.reporter.ReportCPUProfile(ctx, bReader, bSize, ci); err != nil { return err } return nil @@ -331,7 +332,8 @@ func (ap *autoPprof) reportHeapProfile(memUsage float64) error { UsagePercentage: memUsage * 100, } bReader := bytes.NewReader(b) - if err := ap.reporter.ReportHeapProfile(ctx, bReader, mi); err != nil { + bSize := len(b) + if err := ap.reporter.ReportHeapProfile(ctx, bReader, bSize, mi); err != nil { return err } return nil @@ -419,7 +421,8 @@ func (ap *autoPprof) reportGoroutineProfile(goroutineCount int) error { Count: goroutineCount, } bReader := bytes.NewReader(b) - if err := ap.reporter.ReportGoroutineProfile(ctx, bReader, gi); err != nil { + bSize := len(b) + if err := ap.reporter.ReportGoroutineProfile(ctx, bReader, bSize, gi); err != nil { return err } return nil diff --git a/autopprof_test.go b/autopprof_test.go index 5d4dc90..1f85dd9 100644 --- a/autopprof_test.go +++ b/autopprof_test.go @@ -79,9 +79,9 @@ func TestStart(t *testing.T) { opt: Option{ Reporter: report.NewSlackReporter( &report.SlackReporterOption{ - App: "appname", - Token: "token", - Channel: "channel", + App: "appname", + Token: "token", + ChannelID: "channel_id", }, ), }, @@ -93,9 +93,9 @@ func TestStart(t *testing.T) { MemThreshold: 0.5, Reporter: report.NewSlackReporter( &report.SlackReporterOption{ - App: "appname", - Token: "token", - Channel: "channel", + App: "appname", + Token: "token", + ChannelID: "channel_id", }, ), }, @@ -144,9 +144,9 @@ func TestStop(t *testing.T) { MemThreshold: 0.5, Reporter: report.NewSlackReporter( &report.SlackReporterOption{ - App: "appname", - Token: "token", - Channel: "channel", + App: "appname", + Token: "token", + ChannelID: "channel_id", }, ), }) @@ -266,10 +266,10 @@ func TestAutoPprof_watchCPUUsage(t *testing.T) { mockReporter := report.NewMockReporter(ctrl) mockReporter.EXPECT(). - ReportCPUProfile(gomock.Any(), gomock.Any(), gomock.Any()). + ReportCPUProfile(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). AnyTimes(). DoAndReturn( - func(_ context.Context, _ io.Reader, _ report.CPUInfo) error { + func(_ context.Context, _ io.Reader, _ int, _ report.CPUInfo) error { reported = true return nil }, @@ -329,10 +329,10 @@ func TestAutoPprof_watchCPUUsage_consecutive(t *testing.T) { mockReporter := report.NewMockReporter(ctrl) mockReporter.EXPECT(). - ReportCPUProfile(gomock.Any(), gomock.Any(), gomock.Any()). + ReportCPUProfile(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). AnyTimes(). DoAndReturn( - func(_ context.Context, _ io.Reader, _ report.CPUInfo) error { + func(_ context.Context, _ io.Reader, _ int, _ report.CPUInfo) error { reportedCnt++ return nil }, @@ -426,7 +426,7 @@ func TestAutoPprof_watchCPUUsage_reportAll(t *testing.T) { Return([]byte("cpu_prof"), nil), mockReporter.EXPECT(). - ReportCPUProfile(gomock.Any(), gomock.Any(), report.CPUInfo{ + ReportCPUProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.CPUInfo{ ThresholdPercentage: 0.5 * 100, UsagePercentage: 0.6 * 100, }). @@ -444,7 +444,7 @@ func TestAutoPprof_watchCPUUsage_reportAll(t *testing.T) { Return([]byte("mem_prof"), nil), mockReporter.EXPECT(). - ReportHeapProfile(gomock.Any(), gomock.Any(), report.MemInfo{ + ReportHeapProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.MemInfo{ ThresholdPercentage: 0.5 * 100, UsagePercentage: 0.2 * 100, }). @@ -462,7 +462,7 @@ func TestAutoPprof_watchCPUUsage_reportAll(t *testing.T) { Return([]byte("goroutine_prof"), nil), mockReporter.EXPECT(). - ReportGoroutineProfile(gomock.Any(), gomock.Any(), report.GoroutineInfo{ + ReportGoroutineProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.GoroutineInfo{ ThresholdCount: 500, Count: 200, }). @@ -494,7 +494,7 @@ func TestAutoPprof_watchCPUUsage_reportAll(t *testing.T) { Return([]byte("cpu_prof"), nil), mockReporter.EXPECT(). - ReportCPUProfile(gomock.Any(), gomock.Any(), report.CPUInfo{ + ReportCPUProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.CPUInfo{ ThresholdPercentage: 0.5 * 100, UsagePercentage: 0.6 * 100, }). @@ -512,7 +512,7 @@ func TestAutoPprof_watchCPUUsage_reportAll(t *testing.T) { Return([]byte("goroutine_prof"), nil), mockReporter.EXPECT(). - ReportGoroutineProfile(gomock.Any(), gomock.Any(), report.GoroutineInfo{ + ReportGoroutineProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.GoroutineInfo{ ThresholdCount: 500, Count: 200, }). @@ -543,7 +543,7 @@ func TestAutoPprof_watchCPUUsage_reportAll(t *testing.T) { Return([]byte("cpu_prof"), nil), mockReporter.EXPECT(). - ReportCPUProfile(gomock.Any(), gomock.Any(), report.CPUInfo{ + ReportCPUProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.CPUInfo{ ThresholdPercentage: 0.5 * 100, UsagePercentage: 0.6 * 100, }). @@ -617,9 +617,9 @@ func TestAutoPprof_watchMemUsage(t *testing.T) { mockReporter := report.NewMockReporter(ctrl) mockReporter.EXPECT(). - ReportHeapProfile(gomock.Any(), gomock.Any(), gomock.Any()). + ReportHeapProfile(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). DoAndReturn( - func(_ context.Context, _ io.Reader, _ report.MemInfo) error { + func(_ context.Context, _ io.Reader, _ int, _ report.MemInfo) error { reported = true return nil }, @@ -679,10 +679,10 @@ func TestAutoPprof_watchMemUsage_consecutive(t *testing.T) { mockReporter := report.NewMockReporter(ctrl) mockReporter.EXPECT(). - ReportHeapProfile(gomock.Any(), gomock.Any(), gomock.Any()). + ReportHeapProfile(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). AnyTimes(). DoAndReturn( - func(_ context.Context, _ io.Reader, _ report.MemInfo) error { + func(_ context.Context, _ io.Reader, _ int, _ report.MemInfo) error { reportedCnt++ return nil }, @@ -776,7 +776,7 @@ func TestAutoPprof_watchMemUsage_reportAll(t *testing.T) { Return([]byte("mem_prof"), nil), mockReporter.EXPECT(). - ReportHeapProfile(gomock.Any(), gomock.Any(), report.MemInfo{ + ReportHeapProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.MemInfo{ ThresholdPercentage: 0.5 * 100, UsagePercentage: 0.6 * 100, }). @@ -794,7 +794,7 @@ func TestAutoPprof_watchMemUsage_reportAll(t *testing.T) { Return([]byte("cpu_prof"), nil), mockReporter.EXPECT(). - ReportCPUProfile(gomock.Any(), gomock.Any(), report.CPUInfo{ + ReportCPUProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.CPUInfo{ ThresholdPercentage: 0.5 * 100, UsagePercentage: 0.2 * 100, }). @@ -812,7 +812,7 @@ func TestAutoPprof_watchMemUsage_reportAll(t *testing.T) { Return([]byte("goroutine_prof"), nil), mockReporter.EXPECT(). - ReportGoroutineProfile(gomock.Any(), gomock.Any(), report.GoroutineInfo{ + ReportGoroutineProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.GoroutineInfo{ ThresholdCount: 500, Count: 200, }). @@ -844,7 +844,7 @@ func TestAutoPprof_watchMemUsage_reportAll(t *testing.T) { Return([]byte("mem_prof"), nil), mockReporter.EXPECT(). - ReportHeapProfile(gomock.Any(), gomock.Any(), report.MemInfo{ + ReportHeapProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.MemInfo{ ThresholdPercentage: 0.5 * 100, UsagePercentage: 0.6 * 100, }). @@ -862,7 +862,7 @@ func TestAutoPprof_watchMemUsage_reportAll(t *testing.T) { Return([]byte("goroutine_prof"), nil), mockReporter.EXPECT(). - ReportGoroutineProfile(gomock.Any(), gomock.Any(), report.GoroutineInfo{ + ReportGoroutineProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.GoroutineInfo{ ThresholdCount: 500, Count: 200, }). @@ -894,7 +894,7 @@ func TestAutoPprof_watchMemUsage_reportAll(t *testing.T) { Return([]byte("mem_prof"), nil), mockReporter.EXPECT(). - ReportHeapProfile(gomock.Any(), gomock.Any(), report.MemInfo{ + ReportHeapProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.MemInfo{ ThresholdPercentage: 0.5 * 100, UsagePercentage: 0.6 * 100, }). @@ -968,9 +968,9 @@ func TestAutoPprof_watchGoroutineCount(t *testing.T) { mockReporter := report.NewMockReporter(ctrl) mockReporter.EXPECT(). - ReportGoroutineProfile(gomock.Any(), gomock.Any(), gomock.Any()). + ReportGoroutineProfile(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). DoAndReturn( - func(_ context.Context, _ io.Reader, _ report.GoroutineInfo) error { + func(_ context.Context, _ io.Reader, _ int, _ report.GoroutineInfo) error { reported = true return nil }, @@ -1031,10 +1031,10 @@ func TestAutoPprof_watchGoroutineCount_consecutive(t *testing.T) { mockReporter := report.NewMockReporter(ctrl) mockReporter.EXPECT(). - ReportGoroutineProfile(gomock.Any(), gomock.Any(), gomock.Any()). + ReportGoroutineProfile(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). AnyTimes(). DoAndReturn( - func(_ context.Context, _ io.Reader, _ report.GoroutineInfo) error { + func(_ context.Context, _ io.Reader, _ int, _ report.GoroutineInfo) error { reportedCnt++ return nil }, @@ -1129,7 +1129,7 @@ func TestAutoPprof_watchGoroutineCount_reportAll(t *testing.T) { Return([]byte("goroutine_prof"), nil), mockReporter.EXPECT(). - ReportGoroutineProfile(gomock.Any(), gomock.Any(), report.GoroutineInfo{ + ReportGoroutineProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.GoroutineInfo{ ThresholdCount: 100, Count: 200, }). @@ -1147,7 +1147,7 @@ func TestAutoPprof_watchGoroutineCount_reportAll(t *testing.T) { Return([]byte("cpu_prof"), nil), mockReporter.EXPECT(). - ReportCPUProfile(gomock.Any(), gomock.Any(), report.CPUInfo{ + ReportCPUProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.CPUInfo{ ThresholdPercentage: 0.5 * 100, UsagePercentage: 0.2 * 100, }). @@ -1165,7 +1165,7 @@ func TestAutoPprof_watchGoroutineCount_reportAll(t *testing.T) { Return([]byte("mem_prof"), nil), mockReporter.EXPECT(). - ReportHeapProfile(gomock.Any(), gomock.Any(), report.MemInfo{ + ReportHeapProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.MemInfo{ ThresholdPercentage: 0.5 * 100, UsagePercentage: 0.2 * 100, }). @@ -1197,7 +1197,7 @@ func TestAutoPprof_watchGoroutineCount_reportAll(t *testing.T) { Return([]byte("goroutine_prof"), nil), mockReporter.EXPECT(). - ReportGoroutineProfile(gomock.Any(), gomock.Any(), report.GoroutineInfo{ + ReportGoroutineProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.GoroutineInfo{ ThresholdCount: 100, Count: 200, }). @@ -1215,7 +1215,7 @@ func TestAutoPprof_watchGoroutineCount_reportAll(t *testing.T) { Return([]byte("mem_prof"), nil), mockReporter.EXPECT(). - ReportHeapProfile(gomock.Any(), gomock.Any(), report.MemInfo{ + ReportHeapProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.MemInfo{ ThresholdPercentage: 0.5 * 100, UsagePercentage: 0.2 * 100, }). @@ -1247,7 +1247,7 @@ func TestAutoPprof_watchGoroutineCount_reportAll(t *testing.T) { Return([]byte("goroutine_prof"), nil), mockReporter.EXPECT(). - ReportGoroutineProfile(gomock.Any(), gomock.Any(), report.GoroutineInfo{ + ReportGoroutineProfile(gomock.Any(), gomock.Any(), gomock.Any(), report.GoroutineInfo{ ThresholdCount: 100, Count: 200, }). diff --git a/examples/example.go b/examples/example.go index 8c20a74..6963822 100644 --- a/examples/example.go +++ b/examples/example.go @@ -18,11 +18,13 @@ type mm struct { func main() { err := autopprof.Start(autopprof.Option{ + CPUThreshold: 0.8, // Default: 0.75. + MemThreshold: 0.8, // Default: 0.75. Reporter: report.NewSlackReporter( &report.SlackReporterOption{ - App: "YOUR_APP_NAME", - Token: "YOUR_TOKEN_HERE", - Channel: "#REPORT_CHANNEL", + App: "YOUR_APP_NAME", + Token: "YOUR_TOKEN_HERE", + ChannelID: "REPORT_CHANNEL_ID", }, ), }) diff --git a/go.mod b/go.mod index 4935b5c..843ebea 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( github.com/containerd/cgroups v1.0.4 github.com/golang/mock v1.6.0 - github.com/slack-go/slack v0.11.3 + github.com/slack-go/slack v0.14.0 ) require ( @@ -14,7 +14,7 @@ require ( github.com/docker/go-units v0.4.0 // indirect github.com/godbus/dbus/v5 v5.0.4 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/gorilla/websocket v1.4.2 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/opencontainers/runtime-spec v1.0.2 // indirect github.com/sirupsen/logrus v1.8.1 // indirect golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect diff --git a/go.sum b/go.sum index df937ab..efe628a 100644 --- a/go.sum +++ b/go.sum @@ -22,8 +22,9 @@ github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+Licev github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -38,12 +39,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/slack-go/slack v0.11.3 h1:GN7revxEMax4amCc3El9a+9SGnjmBvSUobs0QnO6ZO8= -github.com/slack-go/slack v0.11.3/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/slack-go/slack v0.14.0 h1:6c0UTfbRnvRssZUsZ2qe0Iu07VAMPjRqOa6oX8ewF4k= +github.com/slack-go/slack v0.14.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= diff --git a/report/report.go b/report/report.go index ee7513e..bec08c1 100644 --- a/report/report.go +++ b/report/report.go @@ -24,13 +24,13 @@ const ( // Reporter is responsible for reporting the profiling report to the destination. type Reporter interface { // ReportCPUProfile sends the CPU profiling data to the specific destination. - ReportCPUProfile(ctx context.Context, r io.Reader, ci CPUInfo) error + ReportCPUProfile(ctx context.Context, r io.Reader, size int, ci CPUInfo) error // ReportHeapProfile sends the heap profiling data to the specific destination. - ReportHeapProfile(ctx context.Context, r io.Reader, mi MemInfo) error + ReportHeapProfile(ctx context.Context, r io.Reader, size int, mi MemInfo) error // ReportGoroutineProfile sends the goroutine profiling data to the specific destination. - ReportGoroutineProfile(ctx context.Context, r io.Reader, gi GoroutineInfo) error + ReportGoroutineProfile(ctx context.Context, r io.Reader, size int, gi GoroutineInfo) error } // CPUInfo is the CPU usage information. diff --git a/report/report_mock.go b/report/report_mock.go index 56a4c62..7706cfc 100644 --- a/report/report_mock.go +++ b/report/report_mock.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: report/report.go +// Source: report.go // Package report is a generated GoMock package. package report @@ -36,43 +36,43 @@ func (m *MockReporter) EXPECT() *MockReporterMockRecorder { } // ReportCPUProfile mocks base method. -func (m *MockReporter) ReportCPUProfile(ctx context.Context, r io.Reader, ci CPUInfo) error { +func (m *MockReporter) ReportCPUProfile(ctx context.Context, r io.Reader, size int, ci CPUInfo) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReportCPUProfile", ctx, r, ci) + ret := m.ctrl.Call(m, "ReportCPUProfile", ctx, r, size, ci) ret0, _ := ret[0].(error) return ret0 } // ReportCPUProfile indicates an expected call of ReportCPUProfile. -func (mr *MockReporterMockRecorder) ReportCPUProfile(ctx, r, ci interface{}) *gomock.Call { +func (mr *MockReporterMockRecorder) ReportCPUProfile(ctx, r, size, ci interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReportCPUProfile", reflect.TypeOf((*MockReporter)(nil).ReportCPUProfile), ctx, r, ci) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReportCPUProfile", reflect.TypeOf((*MockReporter)(nil).ReportCPUProfile), ctx, r, size, ci) } // ReportGoroutineProfile mocks base method. -func (m *MockReporter) ReportGoroutineProfile(ctx context.Context, r io.Reader, gi GoroutineInfo) error { +func (m *MockReporter) ReportGoroutineProfile(ctx context.Context, r io.Reader, size int, gi GoroutineInfo) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReportGoroutineProfile", ctx, r, gi) + ret := m.ctrl.Call(m, "ReportGoroutineProfile", ctx, r, size, gi) ret0, _ := ret[0].(error) return ret0 } // ReportGoroutineProfile indicates an expected call of ReportGoroutineProfile. -func (mr *MockReporterMockRecorder) ReportGoroutineProfile(ctx, r, gi interface{}) *gomock.Call { +func (mr *MockReporterMockRecorder) ReportGoroutineProfile(ctx, r, size, gi interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReportGoroutineProfile", reflect.TypeOf((*MockReporter)(nil).ReportGoroutineProfile), ctx, r, gi) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReportGoroutineProfile", reflect.TypeOf((*MockReporter)(nil).ReportGoroutineProfile), ctx, r, size, gi) } // ReportHeapProfile mocks base method. -func (m *MockReporter) ReportHeapProfile(ctx context.Context, r io.Reader, mi MemInfo) error { +func (m *MockReporter) ReportHeapProfile(ctx context.Context, r io.Reader, size int, mi MemInfo) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReportHeapProfile", ctx, r, mi) + ret := m.ctrl.Call(m, "ReportHeapProfile", ctx, r, size, mi) ret0, _ := ret[0].(error) return ret0 } // ReportHeapProfile indicates an expected call of ReportHeapProfile. -func (mr *MockReporterMockRecorder) ReportHeapProfile(ctx, r, mi interface{}) *gomock.Call { +func (mr *MockReporterMockRecorder) ReportHeapProfile(ctx, r, size, mi interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReportHeapProfile", reflect.TypeOf((*MockReporter)(nil).ReportHeapProfile), ctx, r, mi) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReportHeapProfile", reflect.TypeOf((*MockReporter)(nil).ReportHeapProfile), ctx, r, size, mi) } diff --git a/report/slack.go b/report/slack.go index 27ab319..d9c87f0 100644 --- a/report/slack.go +++ b/report/slack.go @@ -24,28 +24,36 @@ type SlackReporter struct { app string channel string + channelID string + client *slack.Client } // SlackReporterOption is the option for the Slack reporter. type SlackReporterOption struct { - App string - Token string - Channel string + App string + Token string + // Deprecated: Use ChannelID instead. Reporting with a channel name is no longer supported because the latest Slack API for file uploads requires a channel ID instead of a channel name. + // For more details about the Slack API, refer to: https://api.slack.com/methods/files.completeUploadExternal + // + // For details about the file upload process: https://api.slack.com/messaging/files#uploading_files + Channel string + ChannelID string } // NewSlackReporter returns the new SlackReporter. func NewSlackReporter(opt *SlackReporterOption) *SlackReporter { return &SlackReporter{ - app: opt.App, - channel: opt.Channel, - client: slack.New(opt.Token), + app: opt.App, + channel: opt.Channel, + channelID: opt.ChannelID, + client: slack.New(opt.Token), } } // ReportCPUProfile sends the CPU profiling data to the Slack. func (s *SlackReporter) ReportCPUProfile( - ctx context.Context, r io.Reader, ci CPUInfo, + ctx context.Context, r io.Reader, size int, ci CPUInfo, ) error { hostname, _ := os.Hostname() // Don't care about this error. var ( @@ -53,13 +61,7 @@ func (s *SlackReporter) ReportCPUProfile( filename = fmt.Sprintf(CPUProfileFilenameFmt, s.app, hostname, now) comment = fmt.Sprintf(cpuCommentFmt, ci.UsagePercentage, ci.ThresholdPercentage) ) - if _, err := s.client.UploadFileContext(ctx, slack.FileUploadParameters{ - Reader: r, - Filename: filename, - Title: filename, - InitialComment: comment, - Channels: []string{s.channel}, - }); err != nil { + if err := s.reportProfile(ctx, r, size, filename, comment); err != nil { return fmt.Errorf("autopprof: failed to upload a file to Slack channel: %w", err) } return nil @@ -67,7 +69,7 @@ func (s *SlackReporter) ReportCPUProfile( // ReportHeapProfile sends the heap profiling data to the Slack. func (s *SlackReporter) ReportHeapProfile( - ctx context.Context, r io.Reader, mi MemInfo, + ctx context.Context, r io.Reader, size int, mi MemInfo, ) error { hostname, _ := os.Hostname() // Don't care about this error. var ( @@ -75,13 +77,7 @@ func (s *SlackReporter) ReportHeapProfile( filename = fmt.Sprintf(HeapProfileFilenameFmt, s.app, hostname, now) comment = fmt.Sprintf(memCommentFmt, mi.UsagePercentage, mi.ThresholdPercentage) ) - if _, err := s.client.UploadFileContext(ctx, slack.FileUploadParameters{ - Reader: r, - Filename: filename, - Title: filename, - InitialComment: comment, - Channels: []string{s.channel}, - }); err != nil { + if err := s.reportProfile(ctx, r, size, filename, comment); err != nil { return fmt.Errorf("autopprof: failed to upload a file to Slack channel: %w", err) } return nil @@ -89,7 +85,7 @@ func (s *SlackReporter) ReportHeapProfile( // ReportGoroutineProfile sends the goroutine profiling data to the Slack. func (s *SlackReporter) ReportGoroutineProfile( - ctx context.Context, r io.Reader, gi GoroutineInfo, + ctx context.Context, r io.Reader, size int, gi GoroutineInfo, ) error { hostname, _ := os.Hostname() // Don't care about this error. var ( @@ -97,14 +93,30 @@ func (s *SlackReporter) ReportGoroutineProfile( filename = fmt.Sprintf(GoroutineProfileFilenameFmt, s.app, hostname, now) comment = fmt.Sprintf(goroutineCommentFmt, gi.Count, gi.ThresholdCount) ) - if _, err := s.client.UploadFileContext(ctx, slack.FileUploadParameters{ + if err := s.reportProfile(ctx, r, size, filename, comment); err != nil { + return fmt.Errorf("autopprof: failed to upload a file to Slack channel: %w", err) + } + return nil +} + +func (s *SlackReporter) reportProfile(ctx context.Context, r io.Reader, size int, filename, comment string) error { + if s.channelID != "" { + _, err := s.client.UploadFileV2Context(ctx, slack.UploadFileV2Parameters{ + Reader: r, + Filename: filename, + FileSize: size, + Title: filename, + InitialComment: comment, + Channel: s.channelID, + }) + return err + } + _, err := s.client.UploadFileContext(ctx, slack.FileUploadParameters{ Reader: r, Filename: filename, Title: filename, InitialComment: comment, Channels: []string{s.channel}, - }); err != nil { - return fmt.Errorf("autopprof: failed to upload a file to Slack channel: %w", err) - } - return nil + }) + return err }