1
0
mirror of https://github.com/google/gops.git synced 2024-11-24 08:22:25 +02:00
gops/agent/agent.go
2016-11-03 21:30:12 -07:00

80 lines
1.6 KiB
Go

// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package agent provides hooks programs can register to retrieve
// diagnostics data by using gops.
package agent
import (
"fmt"
"log"
"net"
"os"
"runtime"
"runtime/debug"
"time"
)
const (
// Stack represents a command to print stack trace.
Stack = byte(0x1)
// GC runs the garbage collector.
GC = byte(0x2)
// GCStats prints GC stats.
GCStats = byte(0x3)
)
func init() {
sock := fmt.Sprintf("/tmp/gops%d.sock", os.Getpid())
l, err := net.Listen("unix", sock)
if err != nil {
log.Fatal(err)
}
// TODO(jbd): cleanup the socket on shutdown.
go func() {
buf := make([]byte, 1)
for {
fd, err := l.Accept()
if err != nil {
log.Println(err)
continue
}
if _, err := fd.Read(buf); err != nil {
log.Println(err)
continue
}
if err := handle(fd, buf); err != nil {
log.Println(err)
continue
}
fd.Close()
}
}()
}
func handle(conn net.Conn, msg []byte) error {
switch msg[0] {
case Stack:
buf := make([]byte, 1<<16)
n := runtime.Stack(buf, true)
_, err := conn.Write(buf[:n])
return err
case GC:
runtime.GC()
_, err := conn.Write([]byte("ok"))
return err
case GCStats:
var stats debug.GCStats
debug.ReadGCStats(&stats)
fmt.Fprintf(conn, "Num GC: %v\n", stats.NumGC)
if stats.NumGC > 0 {
fmt.Fprintf(conn, "Last GC: %v ago\n", time.Now().Sub(stats.LastGC))
fmt.Fprintf(conn, "Total pause: %v\n", stats.PauseTotal)
}
}
return nil
}