1// Copyright 2015 Keybase, Inc. All rights reserved. Use of
2// this source code is governed by the included BSD license.
3
4package libkb
5
6import (
7	"fmt"
8	"strings"
9	"sync"
10
11	"github.com/keybase/client/go/logger"
12	"golang.org/x/net/context"
13)
14
15// VDebugLog is a "Verbose" debug logger; enable it if you really
16// want spam and/or minutiae
17type VDebugLog struct {
18	log              logger.Logger
19	dumpSiteLoadUser bool
20	dumpPayload      bool
21
22	lock sync.RWMutex
23	lev  VDebugLevel
24}
25
26type VDebugLevel int
27
28func NewVDebugLog(l logger.Logger) *VDebugLog {
29	return &VDebugLog{log: l}
30}
31
32const (
33	VLogNone VDebugLevel = iota - 1
34	VLog0
35	VLog1
36	VLog2
37	VLog3
38
39	VLogNoneString       = "mobile"
40	VLog0String          = "vlog0"
41	VLog1String          = "vlog1"
42	VLog2String          = "vlog2"
43	VLog3String          = "vlog3"
44	VLogDumpSiteLoadUser = "dump-site-load-user"
45	VLogDumpPayload      = "dump-payload"
46)
47
48func (v VDebugLevel) String() string {
49	switch v {
50	case VLogNone:
51		return VLogNoneString
52	case VLog0:
53		return VLog0String
54	case VLog1:
55		return VLog1String
56	case VLog2:
57		return VLog2String
58	case VLog3:
59		return VLog3String
60	default:
61		return "unknown"
62	}
63}
64
65func (v *VDebugLog) getLev() VDebugLevel {
66	v.lock.RLock()
67	defer v.lock.RUnlock()
68	return v.lev
69}
70
71func (v *VDebugLog) Log(lev VDebugLevel, fs string, args ...interface{}) {
72	if lev <= v.getLev() {
73		prfx := fmt.Sprintf("{VDL:%d} ", int(lev))
74		fs = prfx + fs
75		v.log.CloneWithAddedDepth(1).Debug(fs, args...)
76	}
77}
78
79func (v *VDebugLog) CLogf(ctx context.Context, lev VDebugLevel, fs string, args ...interface{}) {
80	if lev <= v.getLev() {
81		prfx := fmt.Sprintf("{VDL:%d} ", int(lev))
82		fs = prfx + fs
83		v.log.CloneWithAddedDepth(1).CDebugf(ctx, fs, args...)
84	}
85}
86
87func (v *VDebugLog) CLogfWithAddedDepth(ctx context.Context, lev VDebugLevel, d int, fs string, args ...interface{}) {
88	if lev <= v.getLev() {
89		prfx := fmt.Sprintf("{VDL:%d} ", int(lev))
90		fs = prfx + fs
91		v.log.CloneWithAddedDepth(1+d).CDebugf(ctx, fs, args...)
92	}
93}
94
95func (v *VDebugLog) DumpSiteLoadUser() bool {
96	return v.dumpSiteLoadUser
97}
98
99func (v *VDebugLog) DumpPayload() bool {
100	return v.dumpPayload
101}
102
103func (v *VDebugLog) Configure(s string) {
104	v.lock.Lock()
105	defer v.lock.Unlock()
106
107	v.lev = VLog0
108	if len(s) == 0 {
109		return
110	}
111	v.log.Debug("Setting Vdebug to %q", s)
112	parts := strings.Split(s, ",")
113	for _, s := range parts {
114		switch s {
115		case VLogNoneString:
116			v.lev = VLogNone
117		case VLog0String:
118			v.lev = VLog0
119		case VLog1String:
120			v.lev = VLog1
121		case VLog2String:
122			v.lev = VLog2
123		case VLog3String:
124			v.lev = VLog3
125		case VLogDumpSiteLoadUser:
126			v.dumpSiteLoadUser = true
127		case VLogDumpPayload:
128			v.dumpPayload = true
129		default:
130			v.log.Warning("Ignoring Vdebug log directive: %q", s)
131		}
132	}
133}
134