File: app.go

package info (click to toggle)
go-dlib 5.6.0.9%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 2,740 kB
  • sloc: ansic: 4,664; xml: 1,456; makefile: 20; sh: 15
file content (144 lines) | stat: -rw-r--r-- 4,454 bytes parent folder | download | duplicates (3)
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
 * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd.
 *
 * Author:     jouyouyun <jouyouwen717@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

// app provide a convenient application structure with commandline and profile features.
package app

import (
	"fmt"
	"gopkg.in/alecthomas/kingpin.v2"
	"pkg.deepin.io/lib/log"
	"pkg.deepin.io/lib/profile"
	"strings"
)

func toLogLevel(name string) (log.Priority, error) {
	name = strings.ToLower(name)
	logLevel := log.LevelInfo
	var err error
	switch name {
	case "":
	case "error":
		logLevel = log.LevelError
	case "warn":
		logLevel = log.LevelWarning
	case "info":
		logLevel = log.LevelInfo
	case "debug":
		logLevel = log.LevelDebug
	case "no":
		logLevel = log.LevelDisable
	default:
		err = fmt.Errorf("%s is not support", name)
	}

	return logLevel, err
}

// App is app structure with commandline and profile features.
type App struct {
	cmd      *kingpin.Application
	verbose  *bool
	logLevel *string
	memprof  *string
	cpuprof  *string
	profile  *profile.Config
}

// ParseCommandLine will parse command line which should not contains the executable name,
// and then return the sub-command. Exit if parse failed.
func (app *App) ParseCommandLine(args []string) string {
	subcmd := kingpin.MustParse(app.cmd.Parse(args))

	app.profile.CPUProfile = app.CpuProf()
	app.profile.MemProfile = app.MemProf()

	return subcmd
}

// Flag extends a new global flag. see kingpin for details.
func (app *App) Flag(longName string, desc string) *kingpin.FlagClause {
	return app.cmd.Flag(longName, desc)
}

// Command extends an sub-command. see kingpin for details.
func (app *App) Command(name string, desc string) *kingpin.CmdClause {
	return app.cmd.Command(name, desc)
}

// StartProfile starts all possible profiles.
func (app *App) StartProfile() error {
	return app.profile.Start()
}

// StopProfile stop profile, this should be called when shutdown hook is disabled,
// and this method does nothing when shutdown hook is enabled.
func (app *App) StopProfile() {
	app.profile.Stop()
}

// EnableNoHookShutdown enables or disable shutdown hook.
// If shutdown hook is disabled, StopProfile is needed to be called.
func (app *App) EnableNoShutdownHook(noShutdownHook bool) {
	app.profile.NoShutdownHook = noShutdownHook
}

// LogLevel returns the log level.
func (app *App) LogLevel() log.Priority {
	if *app.logLevel == "" && *app.verbose {
		return log.LevelDebug
	}
	lv, _ := toLogLevel(*app.logLevel)
	return lv
}

func (app *App) IsLogLevelNone() bool {
	return !(*app.verbose) && *app.logLevel == ""
}

// MemProf returns memory profile's path.
func (app *App) MemProf() string {
	return *app.memprof
}

// CpuProf returns cpu profile's path
func (app *App) CpuProf() string {
	return *app.cpuprof
}

// New creates a new application according to name, description and version.
// There are some default command line flag:
// 	verbose(v for short): show much more message, shorthand for --loglevel debug which will be ignored if loglevel is specificed.
// 	loglevel(l for short): set log level, possible value is error/warn/info/debug/no, info is default.
// 	memprof: the file to save memory profile.
// 	cpuprof: the file to save cpu profile.
func New(name string, desc string, version string) *App {
	cmd := kingpin.New(name, desc)
	cmd.Version(version)

	app := &App{
		cmd:      cmd,
		profile:  &profile.Config{},
		verbose:  cmd.Flag("verbose", "Show much more message, shorthand for --loglevel debug which will be ignored if loglevel is specificed.").Short('v').Bool(),
		logLevel: cmd.Flag("loglevel", "Set log level, possible value is error/warn/info/debug/no, info is default.").Short('l').String(),
		memprof:  cmd.Flag("memprof", "Write memory profile to specific file").String(),
		cpuprof:  cmd.Flag("cpuprof", "Write cpu profile to specific file").String(),
	}
	return app
}