Skip to content

Commit

Permalink
README translated to english
Browse files Browse the repository at this point in the history
  • Loading branch information
iimos committed Jan 28, 2024
1 parent f272e4c commit 687c205
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 37 deletions.
101 changes: 101 additions & 0 deletions README-ru.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# go-check-err-chains

Линтер проверяет что текст ошибок содержит префикс указывающий на пакет/функцию/метод в котором произошла ошибка.

Проверка проводится только для экспортируемых функций.

Пример:
```go
package pkg

func Get(key string) error {
id, err := strconv.Atoi(key)
if err != nil {
return errors.New("pkg.Get: %w; key=%s", err, key) // good
}
if empty {
return sql.ErrNoRows // bad
}
return nil
}
```


## Зачем

Этот линтер – попытка навести порядок влогах.

По логам часто не понятно где произошла проблема.

У этой проблемы уже есть есть пара решений, но все имеют существенные недостатки:

1. Использовать логер снабжающий записи указанием на файл и строку где лог был написан.

Файл и номер строки логер указать может, но это будет место где вызвали log.Error,
а не место в котором произошла ошибка.

Это значит что ошибки нужно логировать прямо там где они произошли.
В итоге логи начинают писать повсюду и с большой избыточностью.

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

2. Использовать для ошибок сторонние библиотеки типа [pkg/errors](https://github.com/pkg/errors)

Есть множество библиотек которые сохраянют стек вызовов при создания ошибки.

Это не плохой подход, но есть ряд минусов:
- повсюду нужно использовать одну определенную библиотеку для ошибок
- плохо сочетается с нативным [врапингом через %w](https://go.dev/blog/go1.13-errors)


На данный момент оптимальным компромисом кажется идти идиоматическим путем принятым
в стандартной библиотеке:

Примеры ошибок из стандартной библиотеки:
- strconv.Atoi: parsing "x": invalid syntax
- plugin.Open("file.so"): realpath failed
- bytes.Buffer: too large
- open file.go: no such file or directory
- strings.Builder.Grow: negative count

Видно что строгой схемы нет, но паттерн прослеживается: вначале имя пакета/метода/функции, затем двоеточие и далее подробности.

```go
package pkg

func Get(key string) error {
id, err := strconv.Atoi(key)
if err != nil {
return errors.New("pkg.Get: %w; key=%s", err, key)
}
// ...
}
```

`pkg.Get("abc")` дает ошибку:
```
pkg.Get: strconv.Atoi: parsing "abc": invalid syntax; key=abc
```

У такого подхода ряд плюсов:

- Хорошо стыкуется с ошибками стандартной библиотеки

- Дружит с врапингом

- Писать текст ошибки проще:

`failed to get package cause key abc is not valid ...` vs `pkg.Get: strconv.Atoi: parsing "abc": invalid syntax`.

Второй вариант инженеру проще и читать и писать.

- Логи удобно грепать


А главный минус подхода в том что нужно следить за согласованностью имени пакета/функции
и текста ошибок/логов, ведь при переименовании функции нужно не забыть поменять
все ошибки/логи.

Именнно эту проблему и решает этот линтер.
73 changes: 36 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# go-check-err-chains

Линтер проверяет что текст ошибок содержит префикс указывающий на пакет/функцию/метод в котором произошла ошибка.
The linter checks that the error text contains a prefix indicating the package/function/method where the error occurred.

Проверка проводится только для экспортируемых функций.
The check is only performed for exported functions.

Example:

Пример:
```go
package pkg

Expand All @@ -20,47 +21,46 @@ func Get(key string) error {
}
```

## Why

This linter is an attempt to bring order to the logs.

## Зачем
It is often unclear from the logs where the problem occurred.

Этот линтер – попытка навести порядок влогах.
There are already a couple of solutions to this problem, but all have significant drawbacks:

По логам часто не понятно где произошла проблема.
1. Use a logger that annotates entries with the file and line where the log was written.

У этой проблемы уже есть есть пара решений, но все имеют существенные недостатки:
The file and line number can be indicated by the logger, but this will be the place where log.Error was called,
not the place where the error occurred.

1. Использовать логер снабжающий записи указанием на файл и строку где лог был написан.
This means that errors need to be logged right where they occurred.
As a result, logs start to be written everywhere and with great redundancy.

Файл и номер строки логер указать может, но это будет место где вызвали log.Error,
а не место в котором произошла ошибка.

Это значит что ошибки нужно логировать прямо там где они произошли.
В итоге логи начинают писать повсюду и с большой избыточностью.
One error generates several similar messages about the same error
and each message has a slightly different context and to see the full context,
all these entries need to be collected.

Одна ошибка генерирует несколько похожих сообщений про одну и ту же ошибку
и в каждом сообщении немного свой контекст и чтобы увидеть полный контекст
необходимо собрать все эти записи.
2. Use third-party libraries like [pkg/errors](https://github.com/pkg/errors) for errors.

2. Использовать для ошибок сторонние библиотеки типа [pkg/errors](https://github.com/pkg/errors)
There are many libraries that save the call stack when creating an error.

Есть множество библиотек которые сохраянют стек вызовов при создания ошибки.
This is not a bad approach, but there are a number of downsides:
- everywhere you need to use one specific library for errors
- poorly combined with native [wrapping through %w](https://go.dev/blog/go1.13-errors)

Это не плохой подход, но есть ряд минусов:
- повсюду нужно использовать одну определенную библиотеку для ошибок
- плохо сочетается с нативным [врапингом через %w](https://go.dev/blog/go1.13-errors)

At the moment, the optimal compromise seems to be to go the idiomatic way accepted in the standard library:

На данный момент оптимальным компромисом кажется идти идиоматическим путем принятым
в стандартной библиотеке:
Examples of errors from the standard library:

Примеры ошибок из стандартной библиотеки:
- strconv.Atoi: parsing "x": invalid syntax
- plugin.Open("file.so"): realpath failed
- bytes.Buffer: too large
- open file.go: no such file or directory
- strings.Builder.Grow: negative count

Видно что строгой схемы нет, но паттерн прослеживается: вначале имя пакета/метода/функции, затем двоеточие и далее подробности.
It can be seen that there is no strict scheme, but a pattern can be traced: first the name of the package/method/function, then a colon and further details.

```go
package pkg
Expand All @@ -74,28 +74,27 @@ func Get(key string) error {
}
```

`pkg.Get("abc")` дает ошибку:
`pkg.Get("abc")` gives an error:
```
pkg.Get: strconv.Atoi: parsing "abc": invalid syntax; key=abc
```

У такого подхода ряд плюсов:
This approach has several advantages:

- Хорошо стыкуется с ошибками стандартной библиотеки
- Well aligned with standard library errors

- Дружит с врапингом
- Compatible with wrapping

- Писать текст ошибки проще:
- Writing error text is easier:

`failed to get package cause key abc is not valid ...` vs `pkg.Get: strconv.Atoi: parsing "abc": invalid syntax`.

Второй вариант инженеру проще и читать и писать.

- Логи удобно грепать
The second option is easier for an engineer to read and write.

- Logs are easy to grep


А главный минус подхода в том что нужно следить за согласованностью имени пакета/функции
и текста ошибок/логов, ведь при переименовании функции нужно не забыть поменять
все ошибки/логи.
The main disadvantage of the approach is that you need to monitor the consistency of the package/function name
and error/log text, because when renaming a function, you need to remember to change all errors/logs.

Именнно эту проблему и решает этот линтер.
This is the problem that this linter solves.

0 comments on commit 687c205

Please sign in to comment.