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

feat:#96 #98

Merged
merged 5 commits into from
May 19, 2022
Merged
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
49 changes: 22 additions & 27 deletions holmes.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ type Holmes struct {
}

type ProfileReporter interface {
Report(pType string, buf []byte, reason string, eventID string) error
Report(pType string, filename string, reason string, eventID string) error
}

// New creates a holmes dumper.
Expand Down Expand Up @@ -374,9 +374,8 @@ func (h *Holmes) goroutineProfile(gNum int, c grOptions) bool {

var buf bytes.Buffer
_ = pprof.Lookup("goroutine").WriteTo(&buf, int(h.opts.DumpProfileType)) // nolint: errcheck
h.writeProfileDataToFile(buf, goroutine, "")

h.ReportProfile(type2name[goroutine], buf.Bytes(), reason, "")
h.ReportProfile(type2name[goroutine], h.writeProfileDataToFile(buf, goroutine, ""), reason, "")
return true
}

Expand Down Expand Up @@ -417,9 +416,7 @@ func (h *Holmes) memProfile(rss int, c typeOption) bool {
var buf bytes.Buffer
_ = pprof.Lookup("heap").WriteTo(&buf, int(h.opts.DumpProfileType)) // nolint: errcheck

h.writeProfileDataToFile(buf, mem, "")

h.ReportProfile(type2name[mem], buf.Bytes(), reason, "")
h.ReportProfile(type2name[mem], h.writeProfileDataToFile(buf, mem, ""), reason, "")
return true
}

Expand Down Expand Up @@ -522,15 +519,13 @@ func (h *Holmes) threadProfile(curThreadNum int, c typeOption) bool {
var buf bytes.Buffer

_ = pprof.Lookup("threadcreate").WriteTo(&buf, int(h.opts.DumpProfileType)) // nolint: errcheck
h.writeProfileDataToFile(buf, thread, eventID)

h.ReportProfile(type2name[thread], buf.Bytes(), reason, eventID)
h.ReportProfile(type2name[thread], h.writeProfileDataToFile(buf, thread, eventID), reason, eventID)

buf.Reset()
_ = pprof.Lookup("goroutine").WriteTo(&buf, int(h.opts.DumpProfileType)) // nolint: errcheck
h.writeProfileDataToFile(buf, goroutine, eventID)

h.ReportProfile(type2name[goroutine], buf.Bytes(), reason, eventID)
h.ReportProfile(type2name[goroutine], h.writeProfileDataToFile(buf, goroutine, eventID), reason, eventID)

return true
}
Expand Down Expand Up @@ -592,16 +587,11 @@ func (h *Holmes) cpuProfile(curCPUUsage int, c typeOption) bool {
h.Errorf("encounter error when dumping profile to logger, failed to read cpu profile file: %v", err)
return true
}
h.Infof("[Holmes] CPU profile:: \n" + string(bfCpy))
h.Infof("[Holmes] CPU profile name : " + "::" + binFileName + " \n" + string(bfCpy))
}

if opts := h.opts.GetReporterOpts(); opts.active == 1 {
bfCpy, err := ioutil.ReadFile(binFileName)
if err != nil {
h.Errorf("[holmes reporter] failed to read cpu profile file: %v", err)
return true
}
h.ReportProfile(type2name[cpu], bfCpy, reason, "")
h.ReportProfile(type2name[cpu], binFileName, reason, "")
}

return true
Expand Down Expand Up @@ -716,24 +706,24 @@ func (h *Holmes) gcHeapProfile(gc int, force bool, c typeOption) bool {

var buf bytes.Buffer
_ = pprof.Lookup("heap").WriteTo(&buf, int(h.opts.DumpProfileType)) // nolint: errcheck
h.writeProfileDataToFile(buf, gcHeap, eventID)

h.ReportProfile(type2name[gcHeap], buf.Bytes(), reason, eventID)
h.ReportProfile(type2name[gcHeap], h.writeProfileDataToFile(buf, gcHeap, eventID), reason, eventID)
return true
}

func (h *Holmes) writeProfileDataToFile(data bytes.Buffer, dumpType configureType, eventID string) {
func (h *Holmes) writeProfileDataToFile(data bytes.Buffer, dumpType configureType, eventID string) string {
fileName, err := writeFile(data, dumpType, h.opts.DumpOptions, eventID)
if err != nil {
h.Errorf("failed to write profile to file(%v), err: %s", fileName, err.Error())
return
return ""
}

if h.opts.DumpOptions.DumpToLogger {
h.Infof(fmt.Sprintf("[Holmes] %v profile: \n", check2name[dumpType]) + data.String())
}

h.Infof("[Holmes] pprof %v profile write to file %v successfully", check2name[dumpType], fileName)
return fileName
}

func (h *Holmes) initEnvironment() {
Expand Down Expand Up @@ -778,7 +768,12 @@ func (h *Holmes) EnableProfileReporter() {
atomic.StoreInt32(&h.opts.rptOpts.active, 1)
}

func (h *Holmes) ReportProfile(pType string, buf []byte, reason string, eventID string) {
func (h *Holmes) ReportProfile(pType string, filename string, reason string, eventID string) {
if filename == "" {
h.Errorf("dump name is empty, type:%s, reason:%s, eventID:%s", pType, reason, eventID)
return
}

defer func() {
if r := recover(); r != nil {
h.Errorf("Panic during report profile: %v", r)
Expand All @@ -795,10 +790,10 @@ func (h *Holmes) ReportProfile(pType string, buf []byte, reason string, eventID
}

msg := rptEvent{
PType: pType,
Buf: buf,
Reason: reason,
EventID: eventID,
PType: pType,
FileName: filename,
Reason: reason,
EventID: eventID,
}

// read channel should be atomic.
Expand Down Expand Up @@ -827,7 +822,7 @@ func (h *Holmes) startReporter(ch chan rptEvent) {
continue
}
// It's supposed to be sending judgment, isn't it?
err := opts.reporter.Report(evt.PType, evt.Buf, evt.Reason, evt.EventID) // nolint: errcheck
err := opts.reporter.Report(evt.PType, evt.FileName, evt.Reason, evt.EventID) // nolint: errcheck
if err != nil {
h.Infof("reporter err:", err)

Expand Down
8 changes: 4 additions & 4 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ type options struct {

// rptEvent stands of the args of report event
type rptEvent struct {
PType string
Buf []byte
Reason string
EventID string
PType string
FileName string
Reason string
EventID string
}

type ReporterOptions struct {
Expand Down
15 changes: 13 additions & 2 deletions reporters/http_reporter/http_reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,27 @@ func NewReporter(token string, url string) holmes.ProfileReporter {
}
}

func (r *HttpReporter) Report(ptype string, buf []byte, reason string, eventID string) error {
func (r *HttpReporter) Report(ptype string, filename string, reason string, eventID string) error {
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)

// read filename
if filename == "" {
return fmt.Errorf("file name is empty")
}
data, err := ioutil.ReadFile(filename)
if err != nil {
return fmt.Errorf("read form File: %s err: %v", filename, err)
}
part, err := writer.CreateFormFile("profile", "go-pprof-profile")
if err != nil {
return fmt.Errorf("create form File err: %v", err)
}
if _, err := part.Write(buf); err != nil {

if _, err := part.Write(data); err != nil {
return fmt.Errorf("write buf to file part err: %v", err)
}

writer.WriteField("token", r.token) // nolint: errcheck
writer.WriteField("profile_type", ptype) // nolint: errcheck
writer.WriteField("event_id", eventID) // nolint: errcheck
Expand Down
3 changes: 1 addition & 2 deletions reporters/http_reporter/http_reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ func TestHttpReporter_Report(t *testing.T) {

reporter := NewReporter("test", "http://127.0.0.1:8080/profile/upload")

buf := []byte("test-data")
if err := reporter.Report("goroutine", buf, "test", "test-id"); err != nil {
if err := reporter.Report("goroutine", "reporter_filename_test", "test", "test-id"); err != nil {
log.Fatalf("failed to report: %v", err)
}
}
Expand Down
Empty file.
7 changes: 4 additions & 3 deletions reporters/reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@ var cpuReportCount int
type mockReporter struct {
}

func (m *mockReporter) Report(pType string, buf []byte, reason string, eventID string) error {
log.Printf("call %s report \n", pType)
func (m *mockReporter) Report(pType string, filename string, reason string, eventID string) error {
log.Printf("call %s , filename %s report \n", pType, filename)

// read filename
switch pType {
case "goroutine":
grReportCount++
Expand All @@ -65,7 +66,7 @@ var grReopenReportCount int
type mockReopenReporter struct {
}

func (m *mockReopenReporter) Report(pType string, buf []byte, reason string, eventID string) error {
func (m *mockReopenReporter) Report(pType string, filename string, reason string, eventID string) error {
log.Printf("call %s report \n", pType)

switch pType {
Expand Down