Added external logging package

master
Ice3man543 2020-02-26 16:12:19 +05:30
parent dbc2793946
commit 6924e9578a
9 changed files with 33 additions and 242 deletions

View File

@ -1,7 +1,7 @@
package main package main
import ( import (
"github.com/projectdiscovery/subfinder/pkg/log" "github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/subfinder/pkg/runner" "github.com/projectdiscovery/subfinder/pkg/runner"
) )
@ -11,11 +11,11 @@ func main() {
runner, err := runner.NewRunner(options) runner, err := runner.NewRunner(options)
if err != nil { if err != nil {
log.Fatalf("Could not create runner: %s\n", err) gologger.Fatalf("Could not create runner: %s\n", err)
} }
err = runner.RunEnumeration() err = runner.RunEnumeration()
if err != nil { if err != nil {
log.Fatalf("Could not run enumeration: %s\n", err) gologger.Fatalf("Could not run enumeration: %s\n", err)
} }
} }

View File

@ -1,2 +0,0 @@
// Package log provides a simple layer for leveled logging in go.
package log

View File

@ -1,173 +0,0 @@
package log
import (
"fmt"
"os"
"strings"
"sync"
"github.com/logrusorgru/aurora"
)
// Level defines all the available levels we can log at
type Level int
// Available logging levels
const (
Null Level = iota
Fatal
Silent
Label
Misc
Error
Info
Warning
Verbose
)
var (
// UseColors can be used to control coloring of the output
UseColors = true
// MaxLevel is the maximum level to log at. By default, logging
// is done at Info level. Using verbose will display all the errors too,
// Using silent will display only the most relevant information.
MaxLevel = Info
labels = map[Level]string{
Warning: "WRN",
Error: "ERR",
Label: "WRN",
Fatal: "FTL",
Info: "INF",
}
// mutex protects the current logger
mutex = &sync.Mutex{}
)
var stringBuilderPool = &sync.Pool{New: func() interface{} {
return new(strings.Builder)
}}
// wrap wraps a given label for a message to a logg-able representation.
// It checks if colors are specified and what level we are logging at.
func wrap(label string, level Level) string {
// Check if we are not using colors, if not, return
if !UseColors {
return label
}
switch level {
case Silent:
return label
case Info, Verbose:
return aurora.Blue(label).String()
case Fatal:
return aurora.Bold(aurora.Red(label)).String()
case Error:
return aurora.Red(label).String()
case Warning, Label:
return aurora.Yellow(label).String()
default:
return label
}
}
// getLabel generates a label for a given message, depending on the level
// and the label passed.
func getLabel(level Level, label string, sb *strings.Builder) {
switch level {
case Silent, Misc:
return
case Error, Fatal, Info, Warning, Label:
sb.WriteString("[")
sb.WriteString(wrap(labels[level], level))
sb.WriteString("]")
sb.WriteString(" ")
return
case Verbose:
sb.WriteString("[")
sb.WriteString(wrap(label, level))
sb.WriteString("]")
sb.WriteString(" ")
return
default:
return
}
}
// log logs the actual message to the screen
func log(level Level, label string, format string, args ...interface{}) {
// Don't log if the level is null
if level == Null {
return
}
if level <= MaxLevel {
// Build the log message using the string builder pool
sb := stringBuilderPool.Get().(*strings.Builder)
// Get the label and append it to string builder
getLabel(level, label, sb)
message := fmt.Sprintf(format, args...)
sb.WriteString(message)
if strings.HasSuffix(message, "\n") == false {
sb.WriteString("\n")
}
mutex.Lock()
switch level {
case Silent:
fmt.Fprintf(os.Stdout, sb.String())
default:
fmt.Fprintf(os.Stderr, sb.String())
}
mutex.Unlock()
sb.Reset()
stringBuilderPool.Put(sb)
}
}
// Infof writes a info message on the screen with the default label
func Infof(format string, args ...interface{}) {
log(Info, "", format, args...)
}
// Warningf writes a warning message on the screen with the default label
func Warningf(format string, args ...interface{}) {
log(Warning, "", format, args...)
}
// Errorf writes an error message on the screen with the default label
func Errorf(format string, args ...interface{}) {
log(Error, "", format, args...)
}
// Verbosef writes a verbose message on the screen with a tabel
func Verbosef(format string, label string, args ...interface{}) {
log(Verbose, label, format, args...)
}
// Silentf writes a message on the stdout with no label
func Silentf(format string, args ...interface{}) {
log(Silent, "", format, args...)
}
// Fatalf exits the program if we encounter a fatal error
func Fatalf(format string, args ...interface{}) {
log(Fatal, "", format, args...)
os.Exit(1)
}
// Printf prints a string on screen without any extra stuff
func Printf(format string, args ...interface{}) {
log(Misc, "", format, args...)
}
// Labelf prints a string on screen with a label interface
func Labelf(format string, args ...interface{}) {
log(Label, "", format, args...)
}

View File

@ -1,34 +0,0 @@
package log
import (
"fmt"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/logrusorgru/aurora"
)
func TestGetLabel(t *testing.T) {
tests := []struct {
level Level
label string
expected string
}{
{Fatal, "", fmt.Sprintf("[%s] ", aurora.Bold(aurora.Red(labels[Fatal])).String())},
{Silent, "hello", ""},
{Error, "error", fmt.Sprintf("[%s] ", aurora.Red(labels[Error]).String())},
{Info, "", fmt.Sprintf("[%s] ", aurora.Blue(labels[Info]).String())},
{Warning, "", fmt.Sprintf("[%s] ", aurora.Yellow(labels[Warning]).String())},
{Verbose, "dns", fmt.Sprintf("[%s] ", aurora.Blue("dns").String())},
}
sb := &strings.Builder{}
for _, test := range tests {
sb.Reset()
getLabel(test.level, test.label, sb)
data := sb.String()
assert.Equal(t, data, test.expected, "Expected message and generate message don't match")
}
}

View File

@ -6,7 +6,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/projectdiscovery/subfinder/pkg/log" "github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/subfinder/pkg/subscraping" "github.com/projectdiscovery/subfinder/pkg/subscraping"
) )
@ -47,7 +47,7 @@ func (a *Agent) EnumerateSubdomains(domain string, keys subscraping.Keys, timeou
wg.Wait() wg.Wait()
for source, data := range timeTaken { for source, data := range timeTaken {
log.Verbosef(data, source) gologger.Verbosef(data, source)
} }
close(results) close(results)

View File

@ -1,7 +1,7 @@
package runner package runner
import ( import (
"github.com/projectdiscovery/subfinder/pkg/log" "github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/subfinder/pkg/passive" "github.com/projectdiscovery/subfinder/pkg/passive"
"github.com/projectdiscovery/subfinder/pkg/resolve" "github.com/projectdiscovery/subfinder/pkg/resolve"
) )
@ -18,19 +18,19 @@ const Version = `2.3.2`
// showBanner is used to show the banner to the user // showBanner is used to show the banner to the user
func showBanner() { func showBanner() {
log.Printf("%s\n", banner) gologger.Printf("%s\n", banner)
log.Printf("\t\tprojectdiscovery.io\n\n") gologger.Printf("\t\tprojectdiscovery.io\n\n")
log.Labelf("Use with caution. You are responsible for your actions\n") gologger.Labelf("Use with caution. You are responsible for your actions\n")
log.Labelf("Developers assume no liability and are not responsible for any misuse or damage.\n") gologger.Labelf("Developers assume no liability and are not responsible for any misuse or damage.\n")
log.Labelf("By using subfinder, you also agree to the terms of the APIs used.\n\n") gologger.Labelf("By using subfinder, you also agree to the terms of the APIs used.\n\n")
} }
// normalRunTasks runs the normal startup tasks // normalRunTasks runs the normal startup tasks
func (options *Options) normalRunTasks() { func (options *Options) normalRunTasks() {
configFile, err := UnmarshalRead(options.ConfigFile) configFile, err := UnmarshalRead(options.ConfigFile)
if err != nil { if err != nil {
log.Fatalf("Could not read configuration file %s: %s\n", options.ConfigFile, err) gologger.Fatalf("Could not read configuration file %s: %s\n", options.ConfigFile, err)
} }
options.YAMLConfig = configFile options.YAMLConfig = configFile
} }
@ -49,9 +49,9 @@ func (options *Options) firstRunTasks() {
err := config.MarshalWrite(options.ConfigFile) err := config.MarshalWrite(options.ConfigFile)
if err != nil { if err != nil {
log.Fatalf("Could not write configuration file to %s: %s\n", options.ConfigFile, err) gologger.Fatalf("Could not write configuration file to %s: %s\n", options.ConfigFile, err)
} }
options.YAMLConfig = config options.YAMLConfig = config
log.Infof("Configuration file saved to %s\n", options.ConfigFile) gologger.Infof("Configuration file saved to %s\n", options.ConfigFile)
} }

View File

@ -6,14 +6,14 @@ import (
"sync" "sync"
"time" "time"
"github.com/projectdiscovery/subfinder/pkg/log" "github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/subfinder/pkg/resolve" "github.com/projectdiscovery/subfinder/pkg/resolve"
"github.com/projectdiscovery/subfinder/pkg/subscraping" "github.com/projectdiscovery/subfinder/pkg/subscraping"
) )
// EnumerateSingleDomain performs subdomain enumeration against a single domain // EnumerateSingleDomain performs subdomain enumeration against a single domain
func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error { func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error {
log.Infof("Enumerating subdomains for %s\n", domain) gologger.Infof("Enumerating subdomains for %s\n", domain)
// Get the API keys for sources from the configuration // Get the API keys for sources from the configuration
// and also create the active resolving engine for the domain. // and also create the active resolving engine for the domain.
@ -27,7 +27,7 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
err := resolutionPool.InitWildcards(domain) err := resolutionPool.InitWildcards(domain)
if err != nil { if err != nil {
// Log the error but don't quit. // Log the error but don't quit.
log.Warningf("Could not get wildcards for domain %s: %s\n", domain, err) gologger.Warningf("Could not get wildcards for domain %s: %s\n", domain, err)
} }
} }
@ -43,7 +43,7 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
for result := range passiveResults { for result := range passiveResults {
switch result.Type { switch result.Type {
case subscraping.Error: case subscraping.Error:
log.Warningf("Could not run source %s: %s\n", result.Source, result.Error) gologger.Warningf("Could not run source %s: %s\n", result.Source, result.Error)
case subscraping.Subdomain: case subscraping.Subdomain:
// Validate the subdomain found and remove wildcards from // Validate the subdomain found and remove wildcards from
if !strings.HasSuffix(result.Value, "."+domain) { if !strings.HasSuffix(result.Value, "."+domain) {
@ -60,7 +60,7 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
// Log the verbose message about the found subdomain and send the // Log the verbose message about the found subdomain and send the
// host for resolution to the resolution pool // host for resolution to the resolution pool
log.Verbosef("%s\n", result.Source, subdomain) gologger.Verbosef("%s\n", result.Source, subdomain)
// If the user asked to remove wildcard then send on the resolve // If the user asked to remove wildcard then send on the resolve
// queue. Otherwise, if mode is not verbose print the results on // queue. Otherwise, if mode is not verbose print the results on
@ -70,7 +70,7 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
} }
if !r.options.Verbose { if !r.options.Verbose {
log.Silentf("%s\n", subdomain) gologger.Silentf("%s\n", subdomain)
} }
} }
} }
@ -89,7 +89,7 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
for result := range resolutionPool.Results { for result := range resolutionPool.Results {
switch result.Type { switch result.Type {
case resolve.Error: case resolve.Error:
log.Warningf("Could not resolve host: %s\n", result.Error) gologger.Warningf("Could not resolve host: %s\n", result.Error)
case resolve.Subdomain: case resolve.Subdomain:
// Add the found subdomain to a map. // Add the found subdomain to a map.
if _, ok := foundResults[result.Host]; !ok { if _, ok := foundResults[result.Host]; !ok {
@ -105,11 +105,11 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
if r.options.Verbose { if r.options.Verbose {
if r.options.RemoveWildcard { if r.options.RemoveWildcard {
for result := range foundResults { for result := range foundResults {
log.Silentf("%s\n", result) gologger.Silentf("%s\n", result)
} }
} else { } else {
for result := range uniqueMap { for result := range uniqueMap {
log.Silentf("%s\n", result) gologger.Silentf("%s\n", result)
} }
} }
} }
@ -135,7 +135,7 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
file, err = os.Create(output) file, err = os.Create(output)
} }
if err != nil { if err != nil {
log.Errorf("Could not create file %s for %s: %s\n", output, domain, err) gologger.Errorf("Could not create file %s for %s: %s\n", output, domain, err)
return err return err
} }
@ -152,7 +152,7 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
} }
} }
if err != nil { if err != nil {
log.Errorf("Could not write results to file %s for %s: %s\n", output, domain, err) gologger.Errorf("Could not write results to file %s for %s: %s\n", output, domain, err)
} }
file.Close() file.Close()
return err return err

View File

@ -5,7 +5,7 @@ import (
"os" "os"
"path" "path"
"github.com/projectdiscovery/subfinder/pkg/log" "github.com/projectdiscovery/gologger"
) )
// Options contains the configuration options for tuning // Options contains the configuration options for tuning
@ -42,7 +42,7 @@ func ParseOptions() *Options {
config, err := GetConfigDirectory() config, err := GetConfigDirectory()
if err != nil { if err != nil {
// This should never be reached // This should never be reached
log.Fatalf("Could not get user home: %s\n", err) gologger.Fatalf("Could not get user home: %s\n", err)
} }
flag.BoolVar(&options.Verbose, "v", false, "Show Verbose output") flag.BoolVar(&options.Verbose, "v", false, "Show Verbose output")
@ -76,7 +76,7 @@ func ParseOptions() *Options {
showBanner() showBanner()
if options.Version { if options.Version {
log.Infof("Current Version: %s\n", Version) gologger.Infof("Current Version: %s\n", Version)
os.Exit(0) os.Exit(0)
} }
@ -93,7 +93,7 @@ func ParseOptions() *Options {
// invalid options have been used, exit. // invalid options have been used, exit.
err = options.validateOptions() err = options.validateOptions()
if err != nil { if err != nil {
log.Fatalf("Program exiting: %s\n", err) gologger.Fatalf("Program exiting: %s\n", err)
} }
return options return options

View File

@ -3,7 +3,7 @@ package runner
import ( import (
"errors" "errors"
"github.com/projectdiscovery/subfinder/pkg/log" "github.com/projectdiscovery/gologger"
) )
// validateOptions validates the configuration options passed // validateOptions validates the configuration options passed
@ -47,12 +47,12 @@ func (options *Options) validateOptions() error {
func (options *Options) configureOutput() { func (options *Options) configureOutput() {
// If the user desires verbose output, show verbose output // If the user desires verbose output, show verbose output
if options.Verbose { if options.Verbose {
log.MaxLevel = log.Verbose gologger.MaxLevel = gologger.Verbose
} }
if options.NoColor { if options.NoColor {
log.UseColors = false gologger.UseColors = false
} }
if options.Silent { if options.Silent {
log.MaxLevel = log.Silent gologger.MaxLevel = gologger.Silent
} }
} }