Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iter20 #23

Merged
merged 43 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
d1eb11a
добавил TODO
StasMerzlyakov Mar 20, 2024
9786d78
актуализировал вопросы
StasMerzlyakov Mar 20, 2024
a1b5354
переделал metric_operation_handler - убрал все что относится к бизнес…
StasMerzlyakov Mar 22, 2024
7e4c3a8
восстанавливаю тесты;
StasMerzlyakov Mar 22, 2024
c068828
убрал лишний код, поправил мидлу с логированием статуса ответа
StasMerzlyakov Mar 23, 2024
30cc8b6
актуализировал вопросы
StasMerzlyakov Mar 23, 2024
531f64a
реализовал agent
StasMerzlyakov Mar 23, 2024
0a35610
отладил проверку запроса
StasMerzlyakov Mar 23, 2024
1492c7f
мидла на ответ
StasMerzlyakov Mar 23, 2024
e5dacd7
поправпил статику
StasMerzlyakov Mar 23, 2024
c787c18
актуализировал вопросы
StasMerzlyakov Mar 23, 2024
98be88a
iter15
StasMerzlyakov Mar 27, 2024
bd3cb60
переименовал sender, отвечаюищий за пул
StasMerzlyakov Mar 27, 2024
0bd408e
поправил время в time.Sleep
StasMerzlyakov Mar 27, 2024
861d389
добавил вопрос по горутины
StasMerzlyakov Mar 27, 2024
fa5d552
iter16
StasMerzlyakov May 15, 2024
1548689
передалал на общий логгер
StasMerzlyakov May 19, 2024
3cb3b6d
добавил профилирование
StasMerzlyakov May 19, 2024
40ce5bf
Наработки
StasMerzlyakov May 19, 2024
6b7fe19
Merge branch 'main' into iter16
StasMerzlyakov May 19, 2024
2e60e3a
поправил импорт
StasMerzlyakov May 19, 2024
7c0a33b
добавил вопрос
StasMerzlyakov May 19, 2024
cbac13c
ещё правка
StasMerzlyakov May 19, 2024
bb38b0a
добавил скрипт для локального прогона тестов
StasMerzlyakov May 19, 2024
8dcbe54
добавил скрипт форматирования
StasMerzlyakov May 20, 2024
88b00c0
отформатировал goimports
StasMerzlyakov May 20, 2024
5af9320
убрал мусор
StasMerzlyakov May 20, 2024
43ebf89
добавил скрипт для сравнения результатов
StasMerzlyakov May 21, 2024
4f6f001
инкремент 18
StasMerzlyakov May 22, 2024
d813ad4
поправил ReadAll, добавил Questions
StasMerzlyakov May 23, 2024
961c096
Актуализировал TODO, Questions по итогам созвона
StasMerzlyakov May 26, 2024
00bd9d8
добавил requestID мидлу; убрал лишие выводы в лог
StasMerzlyakov May 29, 2024
12db9c3
добавил тестов с testcontainers
StasMerzlyakov May 29, 2024
56696da
добавил retriable мидлу, убрал retriable-wrapper перед хранилищем
StasMerzlyakov May 29, 2024
b3ee753
поправил проект для работы staticcheck
StasMerzlyakov Jun 3, 2024
998d257
перенес retryable в agent - применяется только там; server переведен …
StasMerzlyakov Jun 3, 2024
e52a0fe
наработки
StasMerzlyakov Jun 3, 2024
c726b66
добавил config.json
StasMerzlyakov Jun 4, 2024
3f2d8ce
отключил проверку генерируемых go test файлов
StasMerzlyakov Jun 4, 2024
2f2896f
Merge branch 'main' into iter19
StasMerzlyakov Jun 4, 2024
15865d6
добавил глобальные переменные
StasMerzlyakov Jun 9, 2024
ba815ad
поправил вызов shell-команд через Makefile
StasMerzlyakov Jun 9, 2024
b9dfa0c
убрал бинарник из исходников
StasMerzlyakov Jun 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ cmd/agent/main
cmd/agent/agent
cmd/server/main
cmd/server/server

cmd/staticlint/staticlint
# Dependency directories (remove the comment below to include it)
vendor/

Expand Down
13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.PHONY: build test clean

build:
go clean -testcache
GOOS=linux GOARCH=amd64 go build -buildvcs=false -o=cmd/server ./cmd/server/...
GOOS=linux GOARCH=amd64 go build -buildvcs=false -ldflags "-X main.buildVersion=v1.0.1 -X main.buildDate=$(shell date +'%Y-%m-%d') -X main.buildCommit=$(shell git rev-parse HEAD)" -o=cmd/agent ./cmd/agent/...

test: build
GOOS=linux GOARCH=amd64 go build -buildvcs=false -o=cmd/staticlint ./cmd/staticlint/...
cmd/staticlint/staticlint ./...
go mod tidy
go mod vendor
go test ./...
49 changes: 31 additions & 18 deletions Questions.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,28 @@ go tool pprof -http=":9090" -seconds=30 heap.out
3. godoc

* Не могу добиться чтоб заработали ссылкы на структуры в другом файле например [domain.Metrics]. Хотя в документации например ioutil.ReadDir() ссылки работают.
* -play

4. staticlint

Не работает чтение файла конфигурации при вызове через
```go
go vet -vettool=cmd/staticlint/staticlint ./...
```

есть ли идеи?


5. go vet - Можно ли отключить конкретный чекер на конкретной строке?

Прим. internal/exitcheck/testdata/pkg2/pkg2.go


6. (__ответ получен__ - Да) Цикл в b.Run
* play


4. Цикл в b.Run (__ответ получен__ - Да)
7. Цикл в b.Run (__ответ получен__ - Да)

Цикл в bench-тесте: до b.N или до фиксированного testN?

Expand All @@ -40,21 +58,16 @@ go tool pprof -http=":9090" -seconds=30 heap.out

*Если нужно делать профилирование(cpu/memory) - то нужно ставить функции в одинаковые условия запускать цикл фиксированное число раз; затем смотреть на результаты профилирования*

5. Статический анализатор для выявления не проверенных ошибок типа (отложить до следующего спринат? (там про go vet было?))
```go
_, _ = io.ReadAll(req.Body)
```
и необрабываемого проброса ошибок
```go
if _, err ;= io.ReadAll(req.Body); err!=nil {
return err
}
```

6. Не понял комментарий на строку
```go
logger.Infow("GetAllMetrics", "status", "start")

7. (__ответ получен__) Статический анализатор для выявления не проверенных ошибок типа (отложить до следующего спринат? (там про go vet было?))

[golangci](https://golangci-lint.run/)

[errcheck](https://github.com/kisielk/errcheck)

```bash
golangci-lint run ./...

```
"Не совсем понимаю зачем ты пишешь это через запятые".
Обсудить - практику формирования записей в лог (кроме requestID - так как requestID я уже научился добавлять )
Возможно - запись о начале работы метода, запись о завершении, времени выполнения?


18 changes: 17 additions & 1 deletion cmd/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,38 @@ package main

import (
"context"
"fmt"
"log"
"os"
"os/signal"
"syscall"

"github.com/StasMerzlyakov/go-metrics/internal/agent"
"github.com/StasMerzlyakov/go-metrics/internal/common/wrapper/retriable"
"github.com/StasMerzlyakov/go-metrics/internal/agent/retriable"
"github.com/StasMerzlyakov/go-metrics/internal/config"
)

var (
buildVersion string = "N/A"
buildDate string = "N/A"
buildCommit string = "N/A"
)

func printVersion() {
fmt.Printf("Build version: %s\n", buildVersion)
fmt.Printf("Build date: %s\n", buildDate)
fmt.Printf("Build commit: %s\n", buildCommit)
}

type Agent interface {
Start(ctx context.Context)
Wait()
}

func main() {

printVersion()

agentCfg, err := config.LoadAgentConfig()
if err != nil {
log.Fatal(err)
Expand Down
54 changes: 26 additions & 28 deletions cmd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,16 @@ import (
"syscall"
"time"

"github.com/StasMerzlyakov/go-metrics/internal/common/wrapper/retriable"
"github.com/StasMerzlyakov/go-metrics/internal/config"
"github.com/StasMerzlyakov/go-metrics/internal/server/adapter/fs/backup"
"github.com/StasMerzlyakov/go-metrics/internal/server/adapter/http/handler"
"github.com/StasMerzlyakov/go-metrics/internal/server/adapter/http/middleware"
"github.com/StasMerzlyakov/go-metrics/internal/server/adapter/http/middleware/compress"
"github.com/StasMerzlyakov/go-metrics/internal/server/adapter/http/middleware/digest"
"github.com/StasMerzlyakov/go-metrics/internal/server/adapter/http/middleware/logging"
"github.com/StasMerzlyakov/go-metrics/internal/server/adapter/http/middleware/retry"
"github.com/StasMerzlyakov/go-metrics/internal/server/adapter/storage/memory"
"github.com/StasMerzlyakov/go-metrics/internal/server/adapter/storage/postgres"
"github.com/StasMerzlyakov/go-metrics/internal/server/adapter/storage/wrapper"
"github.com/StasMerzlyakov/go-metrics/internal/server/app"
"github.com/StasMerzlyakov/go-metrics/internal/server/domain"
"github.com/go-chi/chi/v5"
Expand All @@ -36,6 +35,7 @@ type Server interface {

func createMiddleWareList(srvConf *config.ServerConfiguration) []func(http.Handler) http.Handler {
var mwList []func(http.Handler) http.Handler
mwList = append(mwList, logging.EncrichWithRequestIDMW())
mwList = append(mwList, logging.NewLoggingResponseMW())
if srvConf.Key != "" {
mwList = append(mwList, digest.NewWriteHashDigestResponseHeaderMW(srvConf.Key))
Expand All @@ -45,6 +45,30 @@ func createMiddleWareList(srvConf *config.ServerConfiguration) []func(http.Handl

mwList = append(mwList, logging.NewLoggingRequestMW())

// при работе с Postgres добавляем retriable-обертку
// функция, обрабатывающая ошибки; в нужных случаях выкидывает нужную ошибку(domain.ErrDBConnection)
// на которую реагирует retriableWrapper
pgErrPreProcFn := func(err error) error {
if err == nil {
return nil
}
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
if pgerrcode.IsConnectionException(pgErr.Code) {
return domain.ErrDBConnection
}
}

var conErr *pgconn.ConnectError
if errors.As(err, &conErr) {
return domain.ErrDBConnection
}
return err
}
mwList = append(mwList, retry.NewRetriableRequestMWConf(
time.Duration(time.Second), time.Duration(2*time.Second), 4, pgErrPreProcFn,
StasMerzlyakov marked this conversation as resolved.
Show resolved Hide resolved
))

return mwList
}

Expand Down Expand Up @@ -83,32 +107,6 @@ func main() {

if srvConf.DatabaseDSN != "" {
storage = postgres.NewStorage(srvConf.DatabaseDSN)

// при работе с Postgres добавляем retriable-обертку

// функция, обрабатывающая ошибки; в нужных случаях выкидывает нужную ошибку(domain.ErrDBConnection)
// на которую реагирует retriableWrapper
pgErrPreProcFn := func(err error) error {
if err == nil {
return nil
}
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
if pgerrcode.IsConnectionException(pgErr.Code) {
return domain.ErrDBConnection
}
}

var conErr *pgconn.ConnectError
if errors.As(err, &conErr) {
return domain.ErrDBConnection
}
return err
}

retriableConf := retriable.DefaultConfFn(domain.ErrDBConnection, pgErrPreProcFn)
storage = wrapper.NewRetriable(retriableConf, sugarLog, storage)

} else {
storage = memory.NewStorage()
}
Expand Down
172 changes: 172 additions & 0 deletions cmd/staticlint/staticlint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// Package main contains project multicheck linter:
// - standart golang.org/x/tools/go/analysis
// - SAXXX + QF1004 staticcheck.io
// - github.com/jingyugao/rowserrcheck/passes/rowserr
// - github.com/kisielk/errcheck/errcheck
//
// If `config.json` exists in the current project directory it will be used for reading excludedchecks.
//
// content: {
//
// "excludedcheck": ["appends", "QF1004"]
// }
package main

import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/StasMerzlyakov/go-metrics/internal/osexit"
"github.com/jingyugao/rowserrcheck/passes/rowserr"
"github.com/kisielk/errcheck/errcheck"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/multichecker"
"golang.org/x/tools/go/analysis/passes/appends"
"golang.org/x/tools/go/analysis/passes/asmdecl"
"golang.org/x/tools/go/analysis/passes/assign"
"golang.org/x/tools/go/analysis/passes/atomic"
"golang.org/x/tools/go/analysis/passes/bools"
"golang.org/x/tools/go/analysis/passes/buildtag"
"golang.org/x/tools/go/analysis/passes/cgocall"
"golang.org/x/tools/go/analysis/passes/composite"
"golang.org/x/tools/go/analysis/passes/copylock"
"golang.org/x/tools/go/analysis/passes/defers"
"golang.org/x/tools/go/analysis/passes/directive"
"golang.org/x/tools/go/analysis/passes/errorsas"
"golang.org/x/tools/go/analysis/passes/framepointer"
"golang.org/x/tools/go/analysis/passes/httpresponse"
"golang.org/x/tools/go/analysis/passes/ifaceassert"
"golang.org/x/tools/go/analysis/passes/loopclosure"
"golang.org/x/tools/go/analysis/passes/lostcancel"
"golang.org/x/tools/go/analysis/passes/nilfunc"
"golang.org/x/tools/go/analysis/passes/printf"
"golang.org/x/tools/go/analysis/passes/shift"
"golang.org/x/tools/go/analysis/passes/sigchanyzer"
"golang.org/x/tools/go/analysis/passes/slog"
"golang.org/x/tools/go/analysis/passes/stdmethods"
"golang.org/x/tools/go/analysis/passes/stringintconv"
"golang.org/x/tools/go/analysis/passes/structtag"
"golang.org/x/tools/go/analysis/passes/testinggoroutine"
"golang.org/x/tools/go/analysis/passes/tests"
"golang.org/x/tools/go/analysis/passes/timeformat"
"golang.org/x/tools/go/analysis/passes/unmarshal"
"golang.org/x/tools/go/analysis/passes/unreachable"
"golang.org/x/tools/go/analysis/passes/unsafeptr"
"golang.org/x/tools/go/analysis/passes/unusedresult"
"honnef.co/go/tools/staticcheck"
)

type ConfigData struct {
ExcludedChecks []string `json:"excludedChecks"`
}

const ConfigX = "config.json"

func main() {

var analyzers []*analysis.Analyzer
var cfg ConfigData

ex, err := os.Executable()
if err != nil {
panic(err)
}

exPath := filepath.Dir(ex)
confFilePath := filepath.Join(exPath, ConfigX)
fmt.Println(confFilePath)

data, err := os.ReadFile(ConfigX)
if err != nil {
fmt.Printf("can't find conf file: %s; used default conifguration\n", ConfigX)
} else {
if err = json.Unmarshal(data, &cfg); err != nil {
panic(err)
}
}

excludedChecks := make(map[string]bool)
for _, v := range cfg.ExcludedChecks {
excludedChecks[v] = true
}

standardAnalyzers := []*analysis.Analyzer{
appends.Analyzer, // check for missing values after append
asmdecl.Analyzer, // report mismatches between assembly files and Go declarations
assign.Analyzer, // check for useless assignments
atomic.Analyzer, // check for common mistakes using the sync/atomic package
bools.Analyzer, // check for common mistakes involving boolean operators
buildtag.Analyzer, // check //go:build and // +build directives
cgocall.Analyzer, // detect some violations of the cgo pointer passing rules
composite.Analyzer, // check for unkeyed composite literals
copylock.Analyzer, // check for locks erroneously passed by value
defers.Analyzer, // report common mistakes in defer statements
directive.Analyzer, // check Go toolchain directives such as //go:debug
errorsas.Analyzer, // report passing non-pointer or non-error values to errors.As
framepointer.Analyzer, // report assembly that clobbers the frame pointer before saving it
httpresponse.Analyzer, // check for mistakes using HTTP responses
ifaceassert.Analyzer, // detect impossible interface-to-interface type assertions
loopclosure.Analyzer, // check references to loop variables from within nested functions
lostcancel.Analyzer, // check cancel func returned by context.WithCancel is called
nilfunc.Analyzer, // check for useless comparisons between functions and nil
printf.Analyzer, // check consistency of Printf format strings and arguments
shift.Analyzer, // check for shifts that equal or exceed the width of the integer
sigchanyzer.Analyzer, // check for unbuffered channel of os.Signal
slog.Analyzer, // check for invalid structured logging calls
stdmethods.Analyzer, // check signature of methods of well-known interfaces
stringintconv.Analyzer, // check for string(int) conversions
structtag.Analyzer, // check that struct field tags conform to reflect.StructTag.Get
testinggoroutine.Analyzer, // report calls to (*testing.T).Fatal from goroutines started by a test
tests.Analyzer, // check for common mistaken usages of tests and examples
timeformat.Analyzer, // check for calls of (time.Time).Format or time.Parse with 2006-02-01
unmarshal.Analyzer, // report passing non-pointer or non-interface values to unmarshal
unreachable.Analyzer, // check for unreachable code
unsafeptr.Analyzer, // check for invalid conversions of uintptr to unsafe.Pointer
unusedresult.Analyzer, // check for unused results of calls to some functions
}

// golang.org/x/tools/go/analysis/passes analazers
for _, v := range standardAnalyzers {
if !excludedChecks[v.Name] {
analyzers = append(analyzers, v)
}
}

// SA + QF1004 staticcheck.io
for _, v := range staticcheck.Analyzers {
if !excludedChecks[v.Analyzer.Name] {
if strings.HasPrefix(v.Analyzer.Name, "SA") ||
v.Analyzer.Name == "QF1004" { // use strings.ReplaceAll instead of strings.Replace with n == -1
analyzers = append(analyzers, v.Analyzer)
}
}
}

// errcheck
errCheck := errcheck.Analyzer
if !excludedChecks[errCheck.Name] {
analyzers = append(analyzers, errCheck) // check for unchecked errors in Go code.
}

// rowserrcheck
rser := rowserr.NewAnalyzer(
"github.com/StasMerzlyakov/go-metrics/internal/server/adapter/storage/postgres",
)

if !excludedChecks[rser.Name] {
analyzers = append(analyzers, rser) // rowserrcheck is a static analysis tool which checks whether sql.Rows.Err is correctly checked
}

// osexit
ocheck := osexit.Analyzer
if !excludedChecks[ocheck.Name] {
analyzers = append(analyzers, ocheck) // prohibits the use of a direct os.Exit call in the main function of the main package.
}

multichecker.Main(
analyzers...,
)
}
3 changes: 3 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"excludedChecks": ["errcheck"]
}
Empty file modified cover.sh
100644 → 100755
Empty file.
Loading
Loading