Conversation
| } | ||
|
|
||
| // Observer определяет интерфейс наблюдателя, получающего уведомления об аудит-событиях. | ||
| type Observer interface { |
There was a problem hiding this comment.
В Go интерфейсы принято объявлять рядом с местом их использования: в одном пакете и, чаще всего, рядом с функцией/методом, которые их используют. Существуют исключения, но это не тот случай
| return fmt.Errorf("could not marshal audit event to JSON: %w", err) | ||
| } | ||
|
|
||
| file, err := os.OpenFile(f.filePath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644) |
There was a problem hiding this comment.
Т.к. в файл пишет только эта программа, его можно держать открытым все время ее жизни, чтобы не тратить время на его открытие/закрытие. Необходимо только убедиться, что при завершении программы, файл будет корректно закрыт
|
|
||
| // Notify записывает событие в файл аудита. | ||
| func (f *FileObserver) Notify(event AuditEvent) error { | ||
| f.mu.Lock() |
There was a problem hiding this comment.
Критическую секцию (защищенный мьютексом участок кода) необходимо делать как можно более компактной: это позволит оптимизировать время блокирования на мьютексе другими горутинами
В данном случае в нее достаточно поместить только запись в файл
| notifier.Register(audit.NewFileObserver(cfg.AuditFile)) | ||
| } | ||
| if cfg.AuditURL != "" { | ||
| notifier.Register(audit.NewHTTPObserver(cfg.AuditURL, http.Client{})) |
There was a problem hiding this comment.
Для http-клиента практически всегда хорошей практикой будет добавление механизма ретраев.
Постарайся сделать логику ретраев прозрачной: код оптравки нотификации должен меняться минимально. Проще всего этого можно добиться, написав обертку над http-клиентом, которая будет автоматически делать ретраи. Или использовать уже существующую: например, https://github.com/hashicorp/go-retryablehttp
| } | ||
|
|
||
| // Register добавляет наблюдателя в список рассылки. | ||
| func (n *NotifierService) Register(observer Observer) { |
There was a problem hiding this comment.
Желательно сделать работу с этим компонентом потокобезопасной
| } | ||
|
|
||
| // NotifyAll рассылает событие всем наблюдателям и возвращает список ошибок. | ||
| func (n *NotifierService) NotifyAll(event AuditEvent) []error { |
There was a problem hiding this comment.
Не хотелось бы, чтобы медленные observer'ы блокировали отправку. С другой стороны, надо учесть, что количество горутин не должно расти неограниченно
| metric := &models.Metrics{ID: "requests", MType: models.Counter, Delta: &delta} | ||
|
|
||
| b.ResetTimer() | ||
| for i := 0; i < b.N; i++ { |
There was a problem hiding this comment.
Начиная с Go 1.24 бенчмарки принято запускать с использованием https://pkg.go.dev/testing#B.Loop
См. здесь почему: https://go.dev/blog/testing-b-loop
No description provided.