File: log_windows.go

package info (click to toggle)
golang-github-op-go-logging 1%2Bgit20160315.970db52-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 208 kB
  • sloc: makefile: 4
file content (107 lines) | stat: -rw-r--r-- 2,978 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// +build windows
// Copyright 2013, Örjan Persson. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package logging

import (
	"bytes"
	"io"
	"log"
	"syscall"
)

var (
	kernel32DLL                 = syscall.NewLazyDLL("kernel32.dll")
	setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute")
)

// Character attributes
// Note:
// -- The attributes are combined to produce various colors (e.g., Blue + Green will create Cyan).
//    Clearing all foreground or background colors results in black; setting all creates white.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682088(v=vs.85).aspx#_win32_character_attributes.
const (
	fgBlack     = 0x0000
	fgBlue      = 0x0001
	fgGreen     = 0x0002
	fgCyan      = 0x0003
	fgRed       = 0x0004
	fgMagenta   = 0x0005
	fgYellow    = 0x0006
	fgWhite     = 0x0007
	fgIntensity = 0x0008
	fgMask      = 0x000F
)

var (
	colors = []uint16{
		INFO:     fgWhite,
		CRITICAL: fgMagenta,
		ERROR:    fgRed,
		WARNING:  fgYellow,
		NOTICE:   fgGreen,
		DEBUG:    fgCyan,
	}
	boldcolors = []uint16{
		INFO:     fgWhite | fgIntensity,
		CRITICAL: fgMagenta | fgIntensity,
		ERROR:    fgRed | fgIntensity,
		WARNING:  fgYellow | fgIntensity,
		NOTICE:   fgGreen | fgIntensity,
		DEBUG:    fgCyan | fgIntensity,
	}
)

type file interface {
	Fd() uintptr
}

// LogBackend utilizes the standard log module.
type LogBackend struct {
	Logger *log.Logger
	Color  bool

	// f is set to a non-nil value if the underlying writer which logs writes to
	// implements the file interface. This makes us able to colorise the output.
	f file
}

// NewLogBackend creates a new LogBackend.
func NewLogBackend(out io.Writer, prefix string, flag int) *LogBackend {
	b := &LogBackend{Logger: log.New(out, prefix, flag)}

	// Unfortunately, the API used only takes an io.Writer where the Windows API
	// need the actual fd to change colors.
	if f, ok := out.(file); ok {
		b.f = f
	}

	return b
}

func (b *LogBackend) Log(level Level, calldepth int, rec *Record) error {
	if b.Color && b.f != nil {
		buf := &bytes.Buffer{}
		setConsoleTextAttribute(b.f, colors[level])
		buf.Write([]byte(rec.Formatted(calldepth + 1)))
		err := b.Logger.Output(calldepth+2, buf.String())
		setConsoleTextAttribute(b.f, fgWhite)
		return err
	}
	return b.Logger.Output(calldepth+2, rec.Formatted(calldepth+1))
}

// setConsoleTextAttribute sets the attributes of characters written to the
// console screen buffer by the WriteFile or WriteConsole function.
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx.
func setConsoleTextAttribute(f file, attribute uint16) bool {
	ok, _, _ := setConsoleTextAttributeProc.Call(f.Fd(), uintptr(attribute), 0)
	return ok != 0
}

func doFmtVerbLevelColor(layout string, level Level, output io.Writer) {
	// TODO not supported on Windows since the io.Writer here is actually a
	// bytes.Buffer.
}