Example #1
0
//SetUpLogging configures logging based on configuration
func SetUpLogging(config *util.Config) error {
	var backends = []logging.Backend{}

	if prefix := "logging/file/"; config.GetBool(prefix+"enabled", false) {
		logFile, err := os.OpenFile(config.GetString(prefix+"filename", "gohan.log"),
			os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660)
		if err != nil {
			return err
		}
		fileBackendLeveled := getLeveledBackend(logFile, mustGohanJSONFormatter("gohan"))
		addLevelsToBackend(config, prefix, fileBackendLeveled)
		backends = append(backends, fileBackendLeveled)
	}

	if prefix := "logging/stderr/"; config.GetBool(prefix+"enabled", true) {
		stringFormatter := logging.MustStringFormatter(
			"%{color}%{time:15:04:05.000} %{module} %{level} %{color:reset} %{message}",
		)
		stderrBackendLeveled := getLeveledBackend(os.Stderr, stringFormatter)
		addLevelsToBackend(config, prefix, stderrBackendLeveled)
		backends = append(backends, stderrBackendLeveled)
	}

	logging.SetBackend(backends...)
	return nil
}
Example #2
0
func init() {
	Logger = gologging.MustGetLogger("netspel")
	format := gologging.MustStringFormatter("%{time:2006-01-02T15:04:05.000000Z} %{level} %{message}")
	backend := gologging.NewLogBackend(os.Stdout, "", 0)
	backendFormatter := gologging.NewBackendFormatter(backend, format)
	LogLevel = gologging.AddModuleLevel(backendFormatter)
	gologging.SetBackend(LogLevel)
}
Example #3
0
func init() {
	backend := logging.NewLogBackend(os.Stderr, "", 0)
	logging.SetBackend(backend)
	formatter := logging.MustStringFormatter("[%{time:15:04:05.000}] %{shortfile:18s}: %{color}[%{level:-5s}]%{color:reset} %{message}")
	logging.SetFormatter(formatter)
	logger = logging.MustGetLogger("orderer/kafka")
	logging.SetLevel(logging.INFO, "") // Silence debug-level outputs when testing
}
Example #4
0
func CreateLogger() *go_logging.Logger {
	var logger = go_logging.MustGetLogger("vamp-gateway-agent")
	var backend = go_logging.NewLogBackend(io.Writer(os.Stdout), "", 0)
	backendFormatter := go_logging.NewBackendFormatter(backend, go_logging.MustStringFormatter(
		"%{color}%{time:15:04:05.000} %{shortpkg:.4s} %{level:.4s} ==> %{message} %{color:reset}",
	))
	go_logging.SetBackend(backendFormatter)
	return logger
}
Example #5
0
func init() {
	syncRoot = &sync.RWMutex{}
	format := gologging.MustStringFormatter("%{color}%{time:15:04:05:000} %{shortfunc} > %{level:.4s} %{id:03x}%{color:reset} %{message}")
	backend := gologging.NewLogBackend(os.Stdout, "", 0)
	backendFormatter := gologging.NewBackendFormatter(backend, format)
	backendLeveled = gologging.AddModuleLevel(backendFormatter)
	backendLeveled.SetLevel(gologging.INFO, "")
	gologging.SetBackend(backendLeveled)
}
Example #6
0
func init() {
	var format = "%{color}%{time:15:04:05.000000} ▶ %{level:.4s} %{color:reset} %{message}"
	logBackend := logging.NewLogBackend(os.Stderr, "", 0)
	logging.SetFormatter(logging.MustStringFormatter(format))
	logging.SetBackend(logBackend)

	exp.Exp(metrics.DefaultRegistry)

}
Example #7
0
func setUpLogging() {
	backend := logging.NewLogBackend(os.Stderr, "", 0)
	format := logging.MustStringFormatter(
		"%{color}%{time:15:04:05.000}: %{module} %{level} %{color:reset} %{message}")
	backendFormatter := logging.NewBackendFormatter(backend, format)
	leveledBackendFormatter := logging.AddModuleLevel(backendFormatter)
	leveledBackendFormatter.SetLevel(logging.CRITICAL, "")
	leveledBackendFormatter.SetLevel(logging.DEBUG, "extest")
	logging.SetBackend(leveledBackendFormatter)
}
Example #8
0
func initLogging(level logging.Level, color bool) {
	format := logging.MustStringFormatter(logFormat)
	logging.SetFormatter(format)
	for _, s := range logModules {
		logging.SetLevel(level, s)
	}
	stdout := logging.NewLogBackend(os.Stdout, "", 0)
	stdout.Color = color
	logging.SetBackend(stdout)
}
Example #9
0
// SetUpLogging sets up logging to output for the test framework
func SetUpLogging(output io.Writer) {
	backend := logging.NewLogBackend(output, "", 0)
	format := logging.MustStringFormatter(
		"%{color}%{time:15:04:05.000}: %{module} %{level} %{color:reset} %{message}")
	backendFormatter := logging.NewBackendFormatter(backend, format)
	leveledBackendFormatter := logging.AddModuleLevel(backendFormatter)
	leveledBackendFormatter.SetLevel(logging.INFO, "")
	leveledBackendFormatter.SetLevel(logging.DEBUG, "extest")
	logging.SetBackend(leveledBackendFormatter)
}
Example #10
0
func TestParmsLog(t *testing.T) {
	Convey("Testing log()", t, func() {
		tests := []struct {
			dbug bool
			name string
			str  string
			verb bool
		}{
			{name: "Info", str: "This is a log.Info test", dbug: false, verb: true},
			{name: "Debug", str: "This is a log.Debug test", dbug: true, verb: false},
			{name: "Debug & Info", str: "This is both a log.Debug and log.Info test ", dbug: true, verb: true},
			{name: "Both Debug or Info", str: "This is both a log.Debug and log.Info test and there should be output", dbug: true, verb: true},
			{name: "Neither Debug or Info", str: "This is both a log.Debug and log.Info test and there shouldn't be any output", dbug: false, verb: false},
		}

		var (
			scrFmt = logging.MustStringFormatter(`%{level:.4s}[%{id:03x}] ▶ %{message}`)

			act      = &bytes.Buffer{}
			p        = &Parms{Logger: logging.MustGetLogger("TestParmsLog"), Verb: true}
			scr      = logging.NewLogBackend(act, "", 0)
			scrFmttr = logging.NewBackendFormatter(scr, scrFmt)
		)

		logging.SetBackend(scrFmttr)

		for i, tt := range tests {
			Convey("Testing "+tt.name, func() {
				p.Dbug = tt.dbug
				p.Verb = tt.verb

				switch {
				case tt.dbug:
					p.debug(tt.str)
					So(act.String(), ShouldEqual, fmt.Sprintf("DEBU[00%d] ▶ %v\n", i+1, tt.str))
				case tt.verb:
					p.log(tt.str)
					So(act.String(), ShouldEqual, fmt.Sprintf("INFO[00%d] ▶ %v\n", i+1, tt.str))
				case tt.dbug && tt.verb:
					exp := fmt.Sprintf("DEBU[00%d] ▶ %v\n", i+1, tt.str)
					exp += fmt.Sprintf("INFO[00%d] ▶ %v\n", i+1, tt.str)
					p.debug(tt.str)
					p.log(tt.str)
					So(act.String(), ShouldEqual, exp)
				default:
					p.debug(tt.str)
					p.log(tt.str)
					So(act.String(), ShouldEqual, "")
				}
				act.Reset()
			})
		}
	})
}
Example #11
0
func newLog() (*logging.Logger, error) {
	fdFmt := logging.MustStringFormatter(
		`%{level:.4s}[%{id:03x}]%{time:2006-01-02 15:04:05.000} ▶ %{message}`,
	)

	scrFmt := logging.MustStringFormatter(
		`%{color:bold}%{level:.4s}%{color:reset}[%{id:03x}]%{time:15:04:05.000} ▶ %{message}`,
	)

	fd, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	fdlog := logging.NewLogBackend(fd, "", 0)
	fdFmttr := logging.NewBackendFormatter(fdlog, fdFmt)

	scr := logging.NewLogBackend(os.Stderr, "", 0)
	scrFmttr := logging.NewBackendFormatter(scr, scrFmt)

	logging.SetBackend(fdFmttr, scrFmttr)

	return logging.MustGetLogger(basename(os.Args[0])), err
}
Example #12
0
func (lc *LoggerConfig) newGoLogger() *gol.Logger {
	// Leveled formatted file backend.
	backend := gol.AddModuleLevel(
		gol.NewBackendFormatter(
			gol.NewLogBackend(lc.Out, "", 0),
			gol.MustStringFormatter(lc.Format)))
	backend.SetLevel(lc.Level, "")
	logger := gol.MustGetLogger("")
	logger.SetBackend(backend)
	return logger
}
Example #13
0
func configureLogging(verbose bool) {
	backend := log.NewLogBackend(os.Stdout, "", 0)
	f := "%{time:15:04:05.000} %{module} ▶ %{level:.5s} %{id:03x} %{message}"
	//	f = "%{time:15:04:05.000} %{module} ▶ %{level:.5s} %{id:03x} %{message}"
	format := log.MustStringFormatter(f)
	formatter := log.NewBackendFormatter(backend, format)
	log.SetBackend(formatter)
	log.SetLevel(log.ERROR, "lidc")
	if verbose {
		log.SetLevel(log.DEBUG, "lidc")
	}
}
Example #14
0
func init() {
	Log = Logger{
		log: gologging.MustGetLogger("default"),
	}

	format := gologging.MustStringFormatter(`%{shortfile} %{color} %{time:2006-01-02T15:04:05.000000Z} %{level:.4s} %{color:reset} %{message}`)
	backend := gologging.NewLogBackend(os.Stdout, "", 0)
	backendFormatter := gologging.NewBackendFormatter(backend, format)
	leveledBackend = gologging.AddModuleLevel(backendFormatter)
	gologging.SetBackend(leveledBackend)
	SetLogLevel(SILENT)
}
Example #15
0
// initialize logging using this LogConfig;
// it panics if l.Format is invalid or l.Level is invalid
func (l *LogConfig) InitLogger() {
	l.initLevel()

	format := logging.MustStringFormatter(l.Format)
	logging.SetFormatter(format)
	for _, s := range l.Modules {
		logging.SetLevel(l.level, s)
	}
	stdout := logging.NewLogBackend(os.Stdout, "", 0)
	stdout.Color = l.Colors
	logging.SetBackend(stdout)
}
Example #16
0
func initLogging(level logging.Level, color bool) {
	format := logging.MustStringFormatter(logFormat)
	logging.SetFormatter(format)
	bk := logging.NewLogBackend(os.Stdout, "", 0)
	bk.Color = true
	bkLvd := logging.AddModuleLevel(bk)
	for _, s := range logModules {
		bkLvd.SetLevel(level, s)
	}

	logging.SetBackend(bkLvd)
}
Example #17
0
func setLogger() *logging.Logger {
	var log = logging.MustGetLogger("beano")
	var format = logging.MustStringFormatter(
		"%{color}%{time:15:04:05.000000} %{level:.5s} %{id:04d}%{color:reset} %{message}",
	)
	var logBackend = logging.NewLogBackend(os.Stdout, "", 0)
	//	bel := logging.AddModuleLevel(logBackend)
	//	bel.SetLevel(logging.ERROR, "")
	var bf = logging.NewBackendFormatter(logBackend, format)
	logging.SetBackend(bf)
	return log
}
func init() {
	var format = "%{color}%{time:15:04:05.000000} ▶ %{level:.4s} %{color:reset} %{message}"
	logBackend := logging.NewLogBackend(os.Stderr, "", 0)
	logging.SetFormatter(logging.MustStringFormatter(format))
	logging.SetBackend(logBackend)

	input.SetLogger(log)
	tbl.SetLogger(log)
	route.SetLogger(log)
	destination.SetLogger(log)
	telnet.SetLogger(log)
	web.SetLogger(log)
}
Example #19
0
func init() {

	Log = Logger{
		log: gologging.MustGetLogger(defaultModule),
	}
	Log.log.ExtraCalldepth = 1
	format = gologging.MustStringFormatter("%{time:2006-01-02T15:04:05.000000Z} %{shortfunc:.6s} %{level}: %{message}")
	backend := gologging.NewLogBackend(os.Stdout, "", 0)
	backendFormatter := gologging.NewBackendFormatter(backend, format)
	leveledBackend := gologging.AddModuleLevel(backendFormatter)
	backends = append(backends, leveledBackend)
	gologging.SetBackend(backends...)
	SetLevel(SILENT)
}
Example #20
0
// GetLog gets log handler
func GetLog(level logging.Level) (l *logging.Logger) {
	l = logging.MustGetLogger("ghostbox")
	var customLogFormat = logging.MustStringFormatter(
		"%{color}%{time:2006-01-02 15:04:05.000} %{level:.4s} %{shortfunc:16s} ▶ %{id:03x}%{color:reset} %{message}",
	)
	backend1 := logging.NewLogBackend(os.Stderr, "", 0)
	backend2 := logging.NewLogBackend(os.Stdout, "", 0)
	backend2Formatter := logging.NewBackendFormatter(backend2, customLogFormat)
	backend1Leveled := logging.AddModuleLevel(backend1)
	backend1Leveled.SetLevel(logging.ERROR, "")
	backend2Leveled := logging.AddModuleLevel(backend2Formatter)
	backend2Leveled.SetLevel(level, "") // 0=crit 1=err 2=warn 3=notice 4=info 5=debug
	logging.SetBackend(backend1Leveled, backend2Leveled)
	return
}
Example #21
0
func configureLogging(colorLogs bool) {
	golog.SetFormatter(golog.MustStringFormatter("[0x%{id:x}] [%{level}] [%{module}] %{message}"))
	stdoutLogBackend := golog.NewLogBackend(os.Stdout, "", stdlog.LstdFlags|stdlog.Lshortfile)
	stdoutLogBackend.Color = colorLogs

	golog.SetBackend(stdoutLogBackend)
	golog.SetLevel(golog.DEBUG, "")

	// test logs
	jabberwocky, err := ioutil.ReadFile("the_jabberwocky.txt")
	if err != nil {
		log.Warning("Failed to read \"The Jabberwocky\", it looks like nonsense")
		return
	}
	log.Notice(fmt.Sprintf("\n\n%s", string(jabberwocky)))
}
Example #22
0
// SetupLOG sets up logger with the correct parameters for the whole cilium architecture.
func SetupLOG(logger *l.Logger, logLevel string) {
	hostname, _ := os.Hostname()
	fileFormat := l.MustStringFormatter(
		`%{time:` + RFC3339Milli + `} ` + hostname +
			` %{level:.4s} %{id:03x} %{shortfunc} > %{message}`,
	)

	level, err := l.LogLevel(logLevel)
	if err != nil {
		logger.Fatal(err)
	}

	backend := l.NewLogBackend(os.Stderr, "", 0)
	oBF := l.NewBackendFormatter(backend, fileFormat)

	backendLeveled := l.SetBackend(oBF)
	backendLeveled.SetLevel(level, "")
	logger.SetBackend(backendLeveled)
}
Example #23
0
func main() {
	var loglevel string

	client := &clientImpl{doneChan: make(chan struct{})}

	backend := logging.NewLogBackend(os.Stderr, "", 0)
	logging.SetBackend(backend)
	formatter := logging.MustStringFormatter("[%{time:15:04:05}] %{shortfile:18s}: %{color}[%{level:-5s}]%{color:reset} %{message}")
	logging.SetFormatter(formatter)
	logger = logging.MustGetLogger(pkgName)

	flag.StringVar(&loglevel, "loglevel", "info",
		"The logging level. (Suggested values: info, debug)")
	flag.StringVar(&client.config.server, "server",
		"127.0.0.1:7050", "The RPC server to connect to.")
	flag.StringVar(&client.config.cmd.cmd, "cmd", "new-chain",
		"The action that this client is requesting via the config transaction.")
	flag.StringVar(&client.config.cmd.args.creationPolicy, "creationPolicy", "AcceptAllPolicy",
		"In case of a new-chain command, the chain createion policy this request should be validated against.")
	flag.StringVar(&client.config.cmd.args.chainID, "chainID", "NewChainID",
		"In case of a new-chain command, the chain ID to create.")
	flag.Parse()

	client.config.logLevel, _ = logging.LogLevel(strings.ToUpper(loglevel))
	logging.SetLevel(client.config.logLevel, logger.Module)

	conn, err := grpc.Dial(client.config.server, grpc.WithInsecure())
	if err != nil {
		logger.Fatalf("Client did not connect to %s: %v", client.config.server, err)
	}
	defer conn.Close()
	client.rpc = ab.NewAtomicBroadcastClient(conn)

	switch client.config.cmd.cmd {
	case "new-chain":
		envelope := newChainRequest(client.config.cmd.args.creationPolicy, client.config.cmd.args.chainID)
		logger.Infof("Requesting the creation of chain \"%s\"", client.config.cmd.args.chainID)
		client.broadcast(envelope)
	default:
		panic("Invalid cmd given")
	}
}
Example #24
0
func BenchmarkGologgingTextPositive(b *testing.B) {
	stream := &blackholeStream{}
	logger := log.MustGetLogger("")
	subBackend := log.NewLogBackend(stream, "", 0)
	formatter := log.MustStringFormatter("%{time:2006-01-02T15:04:05Z07:00} %{level} %{message}")
	backend := log.NewBackendFormatter(subBackend, formatter)
	leveled := log.AddModuleLevel(backend)
	logger.SetBackend(leveled)
	b.ResetTimer()

	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info("The quick brown fox jumps over the lazy dog")
		}
	})

	if stream.WriteCount() != uint64(b.N) {
		b.Fatalf("Log write count")
	}
}
Example #25
0
func logSetupGlobal(logLevelStr string) {
	logLevel, err := logging.LogLevel(logLevelStr)
	if err != nil {
		log.Fatal("Invalid log level specified")
	}

	var formatStdout = logging.MustStringFormatter(
		"%{color}%{time:2006-01-02T15:04:05.000} %{shortfunc} ▶ %{level:.4s} %{color:reset} %{message}",
	)
	stdout := logging.NewLogBackend(os.Stdout, "", 0)
	formatter := logging.NewBackendFormatter(stdout, formatStdout)
	stdoutLeveled := logging.AddModuleLevel(formatter)
	stdoutLeveled.SetLevel(logLevel, "")
	syslogBackend, err := logging.NewSyslogBackendPriority("cluegetter", syslog.LOG_MAIL)
	if err != nil {
		Log.Fatal(err)
	}

	logging.SetBackend(syslogBackend, stdoutLeveled)
}
Example #26
0
func Configure() {
	golog.SetFormatter(golog.MustStringFormatter("[0x%{id:x}] [%{level}] [%{module}] %{message}"))
	stdoutLogBackend := golog.NewLogBackend(os.Stdout, "", stdlog.LstdFlags|stdlog.Lshortfile)
	stdoutLogBackend.Color = true
	golog.SetLevel(defaultLevel, "")

	// NOTE these file permissions are restricted by umask, so they probably won't work right.
	err := os.MkdirAll("./log", 0775)
	if err != nil {
		panic(err)
	}
	logFile, err := os.OpenFile("./log/zendesk-livestats.log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0664)
	if err != nil {
		panic(err)
	}

	fileLogBackend := golog.NewLogBackend(logFile, "", stdlog.LstdFlags|stdlog.Lshortfile)
	fileLogBackend.Color = false

	golog.SetBackend(stdoutLogBackend, fileLogBackend)
}
Example #27
0
func ConfigureLog(logPath string, headless bool) *gologging.Logger {

	var log = gologging.MustGetLogger("vamp-router")
	var backend *gologging.LogBackend
	var format = gologging.MustStringFormatter(
		"%{color}%{time:15:04:05.000} %{shortpkg:.4s} %{level:.4s} ==> %{color:reset} %{message}",
	)

	// mix in the Lumberjack logger so we can have rotation on log files
	if headless {

		if len(logPath) > 0 {
			backend = gologging.NewLogBackend(io.MultiWriter(&lumberjack.Logger{
				Filename:   logPath,
				MaxSize:    50, // megabytes
				MaxBackups: 2,  //days
				MaxAge:     14,
			}), "", 0)
		}

	} else {

		if len(logPath) > 0 {
			backend = gologging.NewLogBackend(io.MultiWriter(&lumberjack.Logger{
				Filename:   logPath,
				MaxSize:    50, // megabytes
				MaxBackups: 2,  //days
				MaxAge:     14,
			}, os.Stdout), "", 0)
		}
	}

	backendFormatter := gologging.NewBackendFormatter(backend, format)
	gologging.SetBackend(backendFormatter)

	return log

}
Example #28
0
func SetLogging(cfg Config) (err error) {
	var file *os.File
	file = os.Stdout

	if cfg.Logfile != "" {
		file, err = os.OpenFile(cfg.Logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
		if err != nil {
			log.Fatal(err)
		}
	}
	logBackend := logging.NewLogBackend(file, "",
		stdlog.LstdFlags|stdlog.Lmicroseconds|stdlog.Lshortfile)
	logging.SetBackend(logBackend)

	logging.SetFormatter(logging.MustStringFormatter("%{level}: %{message}"))

	lv, err := logging.LogLevel(cfg.Loglevel)
	if err != nil {
		panic(err.Error())
	}
	logging.SetLevel(lv, "")

	return
}
Example #29
0
func main() {
	var format = logging.MustStringFormatter("%{level} %{message}")
	logging.SetFormatter(format)
	logging.SetLevel(logging.INFO, "iloveck101")

	usr, _ := user.Current()
	baseDir = fmt.Sprintf("%v/Pictures/iloveck101", usr.HomeDir)

	var postUrl string
	var workerNum int

	rootCmd := &cobra.Command{
		Use:   "iloveck101",
		Short: "Download all the images in given post url",
		Run: func(cmd *cobra.Command, args []string) {
			crawler(postUrl, workerNum)
		},
	}
	rootCmd.Flags().StringVarP(&postUrl, "url", "u", "http://ck101.com/thread-2876990-1-1.html", "Url of post")
	rootCmd.Flags().IntVarP(&workerNum, "worker", "w", 25, "Number of workers")

	searchCmd := &cobra.Command{
		Use:   "search",
		Short: "Download all the images in given post url",
		Run: func(cmd *cobra.Command, args []string) {
			page := 0
			keyword := args[0]
			hrefs := printGoogleResult(keyword, page)

			scanner := bufio.NewScanner(os.Stdin)
			quit := false

			for !quit {
				fmt.Print("ck101> ")

				if !scanner.Scan() {
					break
				}

				line := scanner.Text()
				parts := strings.Split(line, " ")
				cmd := parts[0]
				args := parts[1:]

				switch cmd {
				case "quit":
					quit = true
				case "n":
					page = page + 1
					hrefs = printGoogleResult(keyword, page)
				case "p":
					if page > 0 {
						page = page - 1
					}
					hrefs = printGoogleResult(keyword, page)
				case "s":
					page = 0
					hrefs = printGoogleResult(args[0], page)
				case "o":
					open.Run(baseDir)
				case "d":
					index, err := strconv.ParseUint(args[0], 0, 0)
					if err != nil {
						fmt.Println(err)
						continue
					}
					if int(index) >= len(hrefs) {
						fmt.Println("Invalid index")
						continue
					}

					// Only support url with format ck101.com/thread-xxx
					if threadId.Match([]byte(hrefs[index])) {
						crawler(hrefs[index], 25)
						fmt.Println("Done!")
					} else {
						fmt.Println("Unsupport url:", hrefs[index])
					}
				default:
					fmt.Println("Unrecognized command:", cmd, args)
				}
			}
		},
	}

	rootCmd.AddCommand(searchCmd)
	rootCmd.Execute()
}
Example #30
0
import (
	"fmt"
	zmq "github.com/alecthomas/gozmq"
	logging "github.com/op/go-logging"
	"os"
	"syscall"
)

const (
	LOGFMT = "%{color}%{time:15:04:05.000000} %{shortfunc} ▶ %{level:.4s} %{id:03x}%{color:reset} %{message}"
)

//this is log file
var (
	logFile   *os.File
	logFormat               = logging.MustStringFormatter(LOGFMT)
	log                     = logging.MustGetLogger("logfile")
	Gloglevel logging.Level = logging.DEBUG
)

func main() {
	arg := "server"
	if len(os.Args) > 1 {
		arg = os.Args[1]
	}
	log.Info("=[%s\n]===================================================================", arg)

	path := os.Getenv("GOPATH")
	fmt.Println(path)

	path = os.Getenv("GOROOT")