Documentation
¶
Index ¶
- Constants
- Variables
- type App
- type BindFlags
- type Closer
- type CloserOsSignal
- type Component
- type Components
- type Config
- type Configurator
- type Container
- type Debuger
- type Errorer
- type Informer
- type Level
- type Logger
- type Option
- func WithCloser(closer Closer, cmp *Component) Option
- func WithComponents(components ...*Component) Option
- func WithConfigurator(configurator Configurator, cmp *Component) Option
- func WithContainer(container Container, cmp *Component) Option
- func WithLogger(logger Logger, cmp *Component) Option
- func WithOsSignalCloser() Option
- type Panicer
- type Printer
- type Step
- type StepFunc
- type WaitFunc
- type Warner
Constants ¶
const ( ClusterFieldName = "cluster" NamespaceFieldName = "namespace" ContainerIdFieldName = "container.id" ContainerNameFieldName = "container.name" HostnameFieldName = "hostname" ClusterDefault = "unknown-cluster" NamespaceDefault = "unknown-namespace" ContainerIdDefault = "unknown-container_id" ContainerNameDefault = "unknown-container_name" HostnameDefault = "unknown-hostname" )
const ( // MetricNamePrefix — префикс для всех метрик, собираемых Compogo. // Используется для идентификации метрик фреймворка в системах мониторинга. // // Пример: // compogo_app_start_time // compogo_component_execute_duration MetricNamePrefix = "compogo_" // MetricAppNameFieldName — имя поля в метриках, содержащее имя приложения. // Используется как label для фильтрации метрик по приложению. // // Пример использования в метрике: // compogo_app_info{app="myapp", version="1.0.0"} MetricAppNameFieldName = "app" )
Константы для метрик приложения Compogo.
Variables ¶
var ( // ContainerUndefinedError возникает, если DI-контейнер не был предоставлен через опцию WithContainer. // Приложение не может работать без контейнера. ContainerUndefinedError = errors.New("container is undefined") // ConfiguratorUndefinedError возникает, если конфигуратор не был предоставлен через опцию WithConfigurator. // Приложение не может загружать конфигурацию без конфигуратора. ConfiguratorUndefinedError = errors.New("configurator is undefined") // CloserUndefinedError возникает, если менеджер завершения (Closer) не был предоставлен через опцию WithCloser. // Приложение не может корректно завершиться без Closer. CloserUndefinedError = errors.New("closer is undefined") // LoggerUndefinedError возникает, если логгер не был предоставлен через опцию WithLogger. // Приложение не может логировать события без логгера. LoggerUndefinedError = errors.New("logger is undefined") // AppIsRunningError возникает при попытке изменить конфигурацию или компоненты // после запуска приложения (вызова Serve). AppIsRunningError = errors.New("app is running") )
Ошибки, возвращаемые при работе с приложением Compogo.
var ( // StepUndefinedError возникает при попытке получить функцию для несуществующего этапа. StepUndefinedError = errors.New("step is undefined") )
Ошибки, возвращаемые при работе с компонентами.
Functions ¶
This section is empty.
Types ¶
type App ¶
type App struct {
// contains filtered or unexported fields
}
App — главный объект приложения Compogo. Управляет жизненным циклом всех компонентов, обеспечивает:
- Инициализацию и конфигурацию компонентов в правильном порядке (с учётом зависимостей)
- Привязку флагов командной строки
- Graceful shutdown через контекст и WaitGroup
- Иерархию приложений (под-приложения через Clone)
App потокобезопасен и может использоваться из нескольких горутин.
func NewApp ¶
NewApp создаёт новое приложение Compogo с указанным именем. Имя используется в логах и сообщениях об ошибках.
Опции могут быть переданы для конфигурации приложения:
- WithConfigurator — установка загрузчика конфигурации
- WithLogger — установка логгера
- WithContainer — установка DI-контейнера
- WithCloser — установка менеджера завершения
Пример:
app := NewApp("myapp",
WithLogger(logrusLogger),
WithConfigurator(viperConfigurator),
)
func (*App) AddComponents ¶
AddComponents добавляет компоненты в приложение. Компоненты добавляются рекурсивно вместе со всеми зависимостями. Дубликаты автоматически исключаются.
Важно: компоненты нельзя добавлять после запуска приложения (вызова Serve). В этом случае возвращается ошибка AppIsRunningError.
Пример:
app := NewApp("myapp")
err := app.AddComponents(
&component.Component{Name: "db", Init: initDB},
&component.Component{Name: "api", Dependencies: component.Components{dbComponent}},
)
func (*App) BindFlags ¶
BindFlags выполняет привязку флагов командной строки для всех компонентов. Метод рекурсивно обходит все компоненты и зависимости, вызывая их BindFlags-функции.
Порядок выполнения:
- Сначала выполняются Init-функции компонентов (для регистрации в DI-контейнере)
- Затем в компонентах с учётом зависимостей выполняются BindFlags
Каждый компонент выполняется только один раз (отслеживается через steps).
Пример:
flagSet := pflag.NewFlagSet("myapp", pflag.ExitOnError)
if err := app.BindFlags(flagSet); err != nil {
log.Fatal(err)
}
flagSet.Parse(os.Args[1:])
func (*App) Clone ¶
Clone создаёт дочернее приложение с указанным именем. Дочернее приложение наследует от родителя:
- DI-контейнер
- Конфигуратор
- Closer (менеджер завершения)
- Логгер (с вложенным именем)
Используется для создания модульных приложений, где каждый модуль может иметь свои компоненты, но разделяет общие сервисы.
func (*App) Serve ¶
Serve запускает приложение и все его компоненты. Это основной метод, который блокирует выполнение до завершения всех компонентов.
Порядок выполнения этапов:
- Init (инициализация компонентов)
- Configuration (загрузка конфигурации)
- PreExecute → Execute → PostExecute (код однопоточного выполнения)
- PreWait → Wait → PostWait (код для выполнения в Go рутинах)
- PreStop → Stop → PostStop (остановка компонентов)
Wait-функции компонентов выполняются конкурентно в отдельных горутинах. При получении сигнала завершения (через Closer) или ошибке в любом Wait-компоненте, инициируется graceful shutdown.
type BindFlags ¶
BindFlags — функция для привязки флагов командной строки. Получает FlagSet для регистрации флагов и DI-контейнер для доступа к конфигурации.
type Closer ¶
Closer объединяет интерфейс io.Closer с возможностью получения контекста и проверки состояния закрытия.
Используется для graceful shutdown приложения:
- Close() инициирует завершение работы
- GetContext() возвращает контекст, который отменяется при вызове Close()
- IsClosed() позволяет проверить, был ли уже вызван Close()
type CloserOsSignal ¶
type CloserOsSignal struct {
// contains filtered or unexported fields
}
CloserOsSignal реализует интерфейс Closer для graceful shutdown по сигналам операционной системы (SIGINT, SIGTERM, SIGABRT).
При получении одного из этих сигналов вызывается Close(), который отменяет контекст и переводит Closer в закрытое состояние.
func NewCloserOsSignal ¶
func NewCloserOsSignal() *CloserOsSignal
NewCloserOsSignal создаёт новый CloserOsSignal. Контекст создаётся через context.WithCancel, канал для сигналов — с буфером 1.
Пример:
closer := NewCloserOsSignal() go closer.Serve() // запускаем ожидание сигналов <-closer.GetContext().Done() // блокируемся до получения сигнала
func (*CloserOsSignal) Close ¶
func (closer *CloserOsSignal) Close() error
Close отменяет контекст и устанавливает флаг isClosed в true. Реализует интерфейс io.Closer.
func (*CloserOsSignal) GetContext ¶
func (closer *CloserOsSignal) GetContext() context.Context
GetContext возвращает контекст, который отменяется при вызове Close().
func (*CloserOsSignal) IsClosed ¶
func (closer *CloserOsSignal) IsClosed() bool
IsClosed возвращает true, если Close() уже был вызван.
func (*CloserOsSignal) Serve ¶
func (closer *CloserOsSignal) Serve()
Serve запускает ожидание сигналов ОС. При получении SIGINT, SIGTERM или SIGABRT вызывает Close(). Обычно запускается в отдельной горутине.
Пример:
closer := NewCloserOsSignal() go closer.Serve() <-closer.GetContext().Done() // приложение завершается
type Component ¶
type Component struct {
// Name — уникальное имя компонента. Используется в логах и сообщениях об ошибках.
Name string
// Dependencies — компоненты, от которых зависит текущий компонент.
// Compogo автоматически обеспечивает правильный порядок запуска и остановки.
// Если компонент A зависит от B, то B будет запущен раньше A и остановлен позже.
Dependencies Components
// Init — инициализация компонента.
// Здесь следует регистрировать сервисы в DI-контейнере через container.Provide().
Init StepFunc
// BindFlags — привязка флагов командной строки.
// Используйте flagSet для регистрации флагов компонента.
BindFlags BindFlags
// Configuration — загрузка конфигурации.
Configuration StepFunc
// PreExecute — подготовка к выполнению.
PreExecute StepFunc
// Execute — выполнение рабочего кода в однопоточном режиме.
// Здесь не должно быть долгих блокирующих вызовов по типу ListenAndServe().
Execute StepFunc
// PostExecute — завершение после однопоточного рабочего кода.
PostExecute StepFunc
// PreWait — подготовка к ожиданию.
PreWait StepFunc
// Wait — код который должен быть выполнен в отдельной GO рутине.
// Получает контекст, который отменяется при завершении приложения.
// Здесь уже можно вызывать блокирующие вызовы по типу ListenAndServe().
Wait WaitFunc
// PostWait — код который должен выполнится после выполнения блокирующего вызова.
PostWait StepFunc
// PreStop — подготовка к остановке.
PreStop StepFunc
// Stop — остановка компонента.
// Здесь следует завершить все рабочие горутины и освободить ресурсы.
Stop StepFunc
// PostStop — завершение остановки, финальная очистка.
PostStop StepFunc
}
Component представляет собой единицу приложения Compogo. Каждый компонент имеет имя, может зависеть от других компонентов и реализовывать функции для различных этапов жизненного цикла.
Компоненты должны быть декларативными — описывать ЧТО делать, а не КАК. DI-контейнер предоставляет все необходимые зависимости.
type Components ¶
type Components []*Component
Components — слайс компонентов для удобного группового добавления.
type Config ¶
type Configurator ¶
type Configurator interface {
GetString(string) string
GetBool(string) bool
GetInt(string) int
GetInt8(string) int8
GetInt16(string) int16
GetInt32(string) int32
GetInt64(string) int64
GetUint(string) uint
GetUint8(string) uint8
GetUint16(string) uint16
GetUint32(string) uint32
GetUint64(string) uint64
GetFloat32(string) float32
GetFloat64(string) float64
GetTime(string) time.Time
GetDuration(string) time.Duration
GetIntSlice(string) []int
GetStringSlice(string) []string
GetStringMap(string) map[string]any
GetStringMapString(string) map[string]string
GetStringMapStringSlice(string) map[string][]string
GetSizeInBytes(string) uint
SetDefault(string, any)
ReadConfig() error
With(string) Configurator
}
Configurator определяет интерфейс для загрузки и доступа к конфигурации приложения. Предоставляет методы для получения значений различных типов по строковому ключу.
Конфигуратор поддерживает:
- Установку значений по умолчанию через SetDefault
- Вложенные конфигурации через With()
- Различные типы данных: строки, числа, булевы, время, длительности, срезы и мапы
type Container ¶
type Container interface {
Provide(interface{}) error
Provides(...interface{}) error
Invoke(interface{}) error
}
Container определяет интерфейс DI-контейнера для управления зависимостями. Обеспечивает регистрацию сервисов и их получение через внедрение зависимостей.
Основные операции:
- Provide — регистрация одного конструктора сервиса
- Provides — регистрация нескольких конструкторов
- Invoke — выполнение функции с внедрёнными зависимостями
Пример использования:
container := // реализация Container
// Регистрация сервисов
container.Provide(func() *Config { return &Config{Port: 8080} })
container.Provide(func(cfg *Config) *http.Server {
return &http.Server{Addr: fmt.Sprintf(":%d", cfg.Port)}
})
// Получение сервиса
container.Invoke(func(srv *http.Server) {
srv.ListenAndServe()
})
type Debuger ¶
type Debuger interface {
Debugf(string, ...interface{})
Debug(...interface{})
}
Debuger определяет интерфейс для логирования отладочных сообщений. Используется для детальной диагностики и отладки приложения.
type Errorer ¶
type Errorer interface {
Errorf(string, ...interface{})
Error(...interface{})
}
Errorer определяет интерфейс для логирования ошибок. Используется для сообщений об ошибках, которые не должны приводить к панике.
type Informer ¶
type Informer interface {
Infof(string, ...interface{})
Info(...interface{})
}
Informer определяет интерфейс для логирования информационных сообщений. Используется для сообщений о нормальном ходе выполнения приложения.
type Logger ¶
type Logger interface {
Panicer
Errorer
Warner
Informer
Debuger
Printer
// GetLogger возвращает вложенный логгер с указанным именем.
// Имя используется для добавления префикса или контекста к сообщениям.
// Позволяет создавать иерархию логгеров для разных компонентов.
//
// Пример:
//
// appLogger := logger.GetLogger("app")
// dbLogger := appLogger.GetLogger("database")
// dbLogger.Info("Connected to database")
GetLogger(name string) Logger
}
Logger объединяет все интерфейсы логирования и предоставляет возможность создания вложенных логгеров с префиксами.
Logger реализует уровни логирования:
- Panic: критическая ошибка, вызывающая панику
- Error: ошибка, требующая внимания
- Warn: предупреждение о потенциальной проблеме
- Info: информационное сообщение
- Debug: отладочная информация
- Print: простой вывод
Пример использования:
logger := // реализация Logger
logger.Info("Application started")
logger.WithField("port", 8080).Info("Server listening")
// Вложенные логгеры для модулей
httpLogger := logger.GetLogger("http")
httpLogger.Info("HTTP server initialized")
type Option ¶
type Option func(app *App)
Option — функция настройки приложения Compogo. Используется для внедрения зависимостей и конфигурации при создании App через NewApp.
Пример:
app := NewApp("myapp",
WithLogger(myLogger, loggerComponent),
WithContainer(myContainer, containerComponent),
WithConfigurator(myConfigurator, configuratorComponent),
)
func WithCloser ¶
WithCloser устанавливает менеджер завершения и компонент Closer в приложение. Компонент должен регистрировать Closer в DI-контейнере и запускать его в Wait.
Пример:
closer := NewCloserOsSignal()
closerCmp := &Component{
Name: "closer",
Init: func(c Container) error {
return c.Provide(func() Closer { return closer })
},
Wait: func(ctx context.Context, c Container) error {
return c.Invoke(func(cl *CloserOsSignal) {
cl.Serve()
})
},
}
app := NewApp("myapp", WithCloser(closer, closerCmp))
func WithComponents ¶
WithComponents добавляет компоненты в приложение при создании. Является удобной обёрткой над AddComponents. Если добавление компонентов вызывает ошибку, паникует.
Пример:
app := NewApp("myapp",
WithComponents(
dbComponent,
httpComponent,
metricsComponent,
),
)
func WithConfigurator ¶
func WithConfigurator(configurator Configurator, cmp *Component) Option
WithConfigurator устанавливает конфигуратор и компонент конфигуратора в приложение. Компонент должен регистрировать конфигуратор в DI-контейнере.
Пример:
configurator := viper.New()
configuratorCmp := &Component{
Name: "configurator",
Init: func(c Container) error {
return c.Provide(func() Configurator { return configurator })
},
}
app := NewApp("myapp", WithConfigurator(configurator, configuratorCmp))
func WithContainer ¶
WithContainer устанавливает DI-контейнер и компонент контейнера в приложение. Компонент должен регистрировать контейнер в DI-контейнере (самого себя).
Пример:
container := fx.New()
containerCmp := &Component{
Name: "container",
Init: func(c Container) error {
return c.Provide(func() Container { return container })
},
}
app := NewApp("myapp", WithContainer(container, containerCmp))
func WithLogger ¶
WithLogger устанавливает логгер и компонент логгера в приложение. Компонент должен регистрировать логгер в DI-контейнере.
Пример:
logger := logrus.New()
loggerCmp := &Component{
Name: "logger",
Init: func(c Container) error {
return c.Provide(func() Logger { return logger })
},
}
app := NewApp("myapp", WithLogger(logger, loggerCmp))
func WithOsSignalCloser ¶
func WithOsSignalCloser() Option
WithOsSignalCloser возвращает Option для добавления CloserOsSignal в приложение. Опция:
- Создаёт новый CloserOsSignal
- Устанавливает его как Closer через WithCloser
- Добавляет компонент, который регистрирует CloserOsSignal в DI-контейнере
- В Wait-функции компонента запускает Serve() для ожидания сигналов ОС
Пример использования в приложении:
app := NewApp("myapp",
WithOsSignalCloser(),
// другие опции...
)
type Panicer ¶
type Panicer interface {
Panicf(string, ...interface{})
Panic(...interface{})
}
Panicer определяет интерфейс для логирования паник и критических ошибок. Используется для сообщений, после которых приложение должно завершиться.
type Printer ¶
type Printer interface {
Printf(string, ...interface{})
Print(...interface{})
}
Printer определяет интерфейс для простого вывода сообщений. Используется для вывода без дополнительных уровней логирования.
type Step ¶
type Step uint8
Step представляет этап жизненного цикла компонента.
const ( // Init — начальный этап инициализации компонента. // На этом этапе компонент регистрирует свои зависимости и сервисы в DI-контейнере. Init Step = iota // BindFlag — этап привязки флагов командной строки. // Компонент определяет свои флаги и связывает их с полями конфигурации. BindFlag // Configuration — этап загрузки конфигурации. // Компонент читает и валидирует свою конфигурацию. Configuration // PreExecute — подготовка к выполнению. // Выполняется перед основным рабочим циклом компонента. PreExecute // Execute — основной рабочий цикл компонента. // Обычно содержит блокирующую логику (например, запуск HTTP-сервера). Execute // PostExecute — завершение рабочего цикла. // Выполняется после завершения Execute. PostExecute // PreWait — подготовка к ожиданию сигналов. PreWait // Wait — ожидание сигналов завершения (например, SIGINT, SIGTERM). // Компонент может ожидать свой сигнал или использовать общий контекст приложения. Wait // PostWait — завершение ожидания. PostWait // PreStop — подготовка к остановке. PreStop // Stop — остановка компонента. // Здесь компонент должен корректно завершить все рабочие горутины. Stop // PostStop — завершение остановки, финальная очистка. PostStop )
Step определяет этапы жизненного цикла компонента. Каждый компонент может реализовать функции для любого из этих этапов.
Жизненный цикл компонента:
Init → BindFlag → Configuration
↓
PreExecute → Execute → PostExecute
↓
PreWait → Wait → PostWait
↓
PreStop → Stop → PostStop
Где:
- Init: инициализация компонента, регистрация зависимостей в DI-контейнере
- BindFlag: привязка флагов командной строки
- Configuration: загрузка конфигурации
- PreExecute/Execute/PostExecute: основной рабочий цикл
- PreWait/Wait/PostWait: ожидание сигналов завершения
- PreStop/Stop/PostStop: graceful shutdown
type StepFunc ¶
StepFunc — функция, выполняемая на определённом этапе жизненного цикла компонента. Принимает DI-контейнер для получения зависимостей. Возвращает ошибку, если этап не может быть завершён успешно.
type WaitFunc ¶
WaitFunc — специальная функция для этапа Wait. Отличается от StepFunc наличием контекста, который может быть отменён при завершении приложения. Позволяет компоненту корректно завершить работу по сигналу.
Пример:
func wait(ctx context.Context, c container.Container) error {
<-ctx.Done() // ожидание сигнала завершения
return nil
}