浏览代码

nicer tracing interface and bugfixing...

Christoph Hack 12 年之前
父节点
当前提交
041e8ecacd
共有 3 个文件被更改,包括 55 次插入48 次删除
  1. 3 31
      conn.go
  2. 8 10
      marshal.go
  3. 44 7
      session.go

+ 3 - 31
conn.go

@@ -419,11 +419,9 @@ func (c *Conn) decodeFrame(f frame, trace Tracer) (rval interface{}, err error)
 		if len(f) < 16 {
 			return nil, ErrProtocol
 		}
-		var traceId []byte
-		traceId, f = f[:16], f[16:]
-		if err := c.gatherTrace(traceId, trace); err != nil {
-			return nil, err
-		}
+		traceId := []byte(f[:16])
+		f = f[16:]
+		trace.Trace(c, traceId)
 	}
 
 	switch op {
@@ -466,32 +464,6 @@ func (c *Conn) decodeFrame(f frame, trace Tracer) (rval interface{}, err error)
 	}
 }
 
-func (c *Conn) gatherTrace(traceId []byte, trace Tracer) error {
-	if trace == nil {
-		return nil
-	}
-	iter := c.executeQuery(&Query{
-		Stmt: `SELECT event_id, activity, source, source_elapsed
-			FROM system_traces.events
-			WHERE session_id = ?`,
-		Args: []interface{}{traceId},
-		Cons: One,
-	}, nil)
-	var (
-		time     time.Time
-		activity string
-		source   string
-		elapsed  int
-	)
-	for iter.Scan(&time, &activity, &source, &elapsed) {
-		trace.Trace(time, activity, source, elapsed)
-	}
-	if err := iter.Close(); err != nil {
-		return err
-	}
-	return nil
-}
-
 type queryInfo struct {
 	id   []byte
 	args []ColumnInfo

+ 8 - 10
marshal.go

@@ -918,16 +918,14 @@ func unmarshalTimeUUID(info *TypeInfo, data []byte, value interface{}) error {
 		if version := int(data[6] & 0xF0 >> 4); version != 1 {
 			return unmarshalErrorf("invalid timeuuid")
 		}
-		timestamp := uint64(data[0])<<24 + uint64(data[1])<<16 +
-			uint64(data[2])<<8 + uint64(data[3]) + uint64(data[4])<<40 +
-			uint64(data[5])<<32 + uint64(data[7])<<48 + uint64(data[6]&0x0F)<<56
-		if timestamp == 0 {
-			*v = time.Time{}
-			return nil
-		}
-		sec := timestamp / 10000000
+		timestamp := int64(uint64(data[0])<<24|uint64(data[1])<<16|
+			uint64(data[2])<<8|uint64(data[3])) +
+			int64(uint64(data[4])<<40|uint64(data[5])<<32) +
+			int64(uint64(data[6]&0x0F)<<56|uint64(data[7])<<48)
+		timestamp = timestamp - timeEpoch
+		sec := timestamp / 1e7
 		nsec := timestamp - sec
-		*v = time.Unix(int64(sec)+timeBase, int64(nsec))
+		*v = time.Unix(int64(sec), int64(nsec)).UTC()
 		return nil
 	}
 	return unmarshalErrorf("can not unmarshal %s into %T", info, value)
@@ -1062,4 +1060,4 @@ func unmarshalErrorf(format string, args ...interface{}) UnmarshalError {
 	return UnmarshalError(fmt.Sprintf(format, args...))
 }
 
-var timeBase = time.Date(1582, time.October, 15, 0, 0, 0, 0, time.UTC).Unix()
+var timeEpoch int64 = 0x01B21DD213814000

+ 44 - 7
session.go

@@ -8,6 +8,7 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"sync"
 	"time"
 )
 
@@ -247,19 +248,55 @@ type ColumnInfo struct {
 }
 
 type Tracer interface {
-	Trace(time time.Time, activity string, source string, elapsed int)
+	Trace(conn *Conn, traceId []byte)
 }
 
 type traceWriter struct {
-	w io.Writer
+	w  io.Writer
+	mu sync.Mutex
 }
 
 func NewTraceWriter(w io.Writer) Tracer {
-	return traceWriter{w}
-}
-
-func (t traceWriter) Trace(time time.Time, activity string, source string, elapsed int) {
-	fmt.Fprintf(t.w, "%s: %s (source: %s, elapsed: %d)\n", time, activity, source, elapsed)
+	return traceWriter{w: w}
+}
+
+func (t traceWriter) Trace(conn *Conn, traceId []byte) {
+	var (
+		coordinator string
+		duration    int
+	)
+	conn.executeQuery(&Query{
+		Stmt: `SELECT coordinator, duration
+			FROM system_traces.sessions
+			WHERE session_id = ?`,
+		Args: []interface{}{traceId},
+		Cons: One,
+	}, nil).Scan(&coordinator, &duration)
+
+	iter := conn.executeQuery(&Query{
+		Stmt: `SELECT event_id, activity, source, source_elapsed
+			FROM system_traces.events
+			WHERE session_id = ?`,
+		Args: []interface{}{traceId},
+		Cons: One,
+	}, nil)
+	var (
+		timestamp time.Time
+		activity  string
+		source    string
+		elapsed   int
+	)
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	fmt.Fprintf(t.w, "Tracing session %016x (coordinator: %s, duration: %v):\n",
+		traceId, coordinator, time.Duration(duration)*time.Microsecond)
+	for iter.Scan(&timestamp, &activity, &source, &elapsed) {
+		fmt.Fprintf(t.w, "%s: %s (source: %s, elapsed: %d)\n",
+			timestamp.Format("2006/01/02 15:04:05.999999"), activity, source, elapsed)
+	}
+	if err := iter.Close(); err != nil {
+		fmt.Fprintln(t.w, "Error:", err)
+	}
 }
 
 type Error struct {