Как найти, где в программе Golang происходит мошенническая запись в stderr?

Решения, вышеперечисленные с использованием классов с int-константами, не имеют безопасности типа. То есть вы могли бы изобретать новые значения, фактически не определенные в классе. Кроме того, не представляется возможным, например, написать метод, принимающий один из этих классов в качестве входных данных.

Вам нужно было бы написать

public void DoSomethingMeaningFull(int consumeValue) ...

. Однако существует решение класса на основе старые дни Java, когда не было доступных перечислений. Это обеспечивает почти перечислимое поведение. Единственное предостережение состоит в том, что эти константы не могут использоваться в инструкции switch.

public class MyBaseEnum
{
    public static readonly MyBaseEnum A = new MyBaseEnum( 1 );
    public static readonly MyBaseEnum B = new MyBaseEnum( 2 );
    public static readonly MyBaseEnum C = new MyBaseEnum( 3 );

    public int InternalValue { get; protected set; }

    protected MyBaseEnum( int internalValue )
    {
        this.InternalValue = internalValue;
    }
}

public class MyEnum : MyBaseEnum
{
    public static readonly MyEnum D = new MyEnum( 4 );
    public static readonly MyEnum E = new MyEnum( 5 );

    protected MyEnum( int internalValue ) : base( internalValue )
    {
        // Nothing
    }
}

[TestMethod]
public void EnumTest()
{
    this.DoSomethingMeaningful( MyEnum.A );
}

private void DoSomethingMeaningful( MyBaseEnum enumValue )
{
    // ...
    if( enumValue == MyEnum.A ) { /* ... */ }
    else if (enumValue == MyEnum.B) { /* ... */ }
    // ...
}
1
задан Jacob Davis-Hansson 1 March 2019 в 23:13
поделиться

1 ответ

Вы можете перехватить ведение журнала, предоставив io.Writer - log.SetOutput . Там вы можете просто проверить, является ли записываемая строка тем, что вам нужно отследить и записать трассировку стека делегированному завернутому модулю записи.

Вот пример игровой площадки: https://play.golang.org/p/2bClt2JBuFs

Обратите внимание, что получение текущей трассировки стека не является бесплатным, оно вызывает остановку и может резко замедлить ваше приложение. Если у вас есть приложение, которое создает большой объем журналов, я бы рекомендовал ограничить количество отслеживаемых данных (например, трассировать только первое совпадение или N раз в секунду / минуту)

package main

import (
    "fmt"
    "log"
    "os"
    "regexp"
    "runtime/debug"
)

func main() {
    log.SetOutput(NewLogInterceptor(LogInterceptionCheck{Pattern: ".*Some.*", Description: "with 'Some' substring"}))
    f1()
    log.Println("message that is not traced")
}

func f1() {
    log.Println("Some message")
}



type LogInterceptor struct {
    target *os.File
    checks []LogInterceptionCheck
}

type LogInterceptionCheck struct {
    regexp      *regexp.Regexp
    Pattern     string
    Description string
}

func NewLogInterceptor(checks ...LogInterceptionCheck) *LogInterceptor {
    for i := 0; i < len(checks); i++ {
        each := checks[i]
        compiled, e := regexp.Compile(each.Pattern)
        if e != nil {
            log.Fatalf("cannot compile regexpt [%s]: %s", each, e)
        }
        checks[i].regexp = compiled
    }
    return &LogInterceptor{os.Stderr, checks}
}

func (interceptor *LogInterceptor) Write(p []byte) (n int, err error) {
    i, err := interceptor.target.Write(p)
    // use loop because it is faster and generates less garbage compared to for-range loop
    for i := 0; i < len(interceptor.checks); i++ {
        check := interceptor.checks[i]
        if check.regexp.Match(p) {
            _, e := fmt.Fprintf(interceptor.target, ">>>> Printing stacktrace [%s]\n", check.Description)
            if e != nil {
                log.Fatalf("cannot write: %s", e)
            }
            _, e = interceptor.target.Write(debug.Stack())
            if e != nil {
                log.Fatalf("cannot write stacktrace: %s", e)
            }
            break
        }
    }
    return i, err
}
0
ответ дан Alexey Mukas 1 March 2019 в 23:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: