+123
-50
@@ -50,6 +50,10 @@ func emitContextError(ctx *MessageContext, event ErrorEvent) {
|
||||
if ctx.Logger != nil {
|
||||
ctx.Logger.Errorln(event.Err)
|
||||
}
|
||||
if ctx.eventEmitter != nil {
|
||||
ctx.eventEmitter(ctx.Context(), event)
|
||||
return
|
||||
}
|
||||
if ctx.observer == nil {
|
||||
return
|
||||
}
|
||||
@@ -63,94 +67,150 @@ func emitContextError(ctx *MessageContext, event ErrorEvent) {
|
||||
|
||||
// UpdateReceivedEvent describes an update entering the bot runtime.
|
||||
type UpdateReceivedEvent struct {
|
||||
UpdateID int
|
||||
// UpdateID identifies the Telegram update.
|
||||
UpdateID int
|
||||
// UpdateType identifies the normalized update kind.
|
||||
UpdateType tgapi.UpdateType
|
||||
FromID int64
|
||||
ChatID int64
|
||||
// FromID identifies the originating user when available.
|
||||
FromID int64
|
||||
// ChatID identifies the originating chat when available.
|
||||
ChatID int64
|
||||
}
|
||||
|
||||
// UpdateHandledEvent describes a completed update execution path.
|
||||
type UpdateHandledEvent struct {
|
||||
UpdateID int
|
||||
// UpdateID identifies the Telegram update.
|
||||
UpdateID int
|
||||
// UpdateType identifies the normalized update kind.
|
||||
UpdateType tgapi.UpdateType
|
||||
FromID int64
|
||||
ChatID int64
|
||||
Duration time.Duration
|
||||
Handled bool
|
||||
// FromID identifies the originating user when available.
|
||||
FromID int64
|
||||
// ChatID identifies the originating chat when available.
|
||||
ChatID int64
|
||||
// Duration is the total framework handling time.
|
||||
Duration time.Duration
|
||||
// Handled reports whether a registered path handled the update.
|
||||
Handled bool
|
||||
}
|
||||
|
||||
// HandlerStartedEvent describes a handler about to execute.
|
||||
type HandlerStartedEvent struct {
|
||||
UpdateID int
|
||||
UpdateType tgapi.UpdateType
|
||||
Plugin string
|
||||
// UpdateID identifies the Telegram update.
|
||||
UpdateID int
|
||||
// UpdateType identifies the normalized update kind.
|
||||
UpdateType tgapi.UpdateType
|
||||
// Plugin names the plugin that owns the handler.
|
||||
Plugin string
|
||||
// HandlerKind classifies the handler.
|
||||
HandlerKind HandlerEventKind
|
||||
// HandlerName identifies the handler within its plugin and kind.
|
||||
HandlerName string
|
||||
FromID int64
|
||||
ChatID int64
|
||||
// FromID identifies the originating user when available.
|
||||
FromID int64
|
||||
// ChatID identifies the originating chat when available.
|
||||
ChatID int64
|
||||
}
|
||||
|
||||
// HandlerFinishedEvent describes a handler that has completed.
|
||||
type HandlerFinishedEvent struct {
|
||||
UpdateID int
|
||||
UpdateType tgapi.UpdateType
|
||||
Plugin string
|
||||
// UpdateID identifies the Telegram update.
|
||||
UpdateID int
|
||||
// UpdateType identifies the normalized update kind.
|
||||
UpdateType tgapi.UpdateType
|
||||
// Plugin names the plugin that owns the handler.
|
||||
Plugin string
|
||||
// HandlerKind classifies the handler.
|
||||
HandlerKind HandlerEventKind
|
||||
// HandlerName identifies the handler within its plugin and kind.
|
||||
HandlerName string
|
||||
FromID int64
|
||||
ChatID int64
|
||||
Duration time.Duration
|
||||
Err error
|
||||
UserFacing bool
|
||||
// FromID identifies the originating user when available.
|
||||
FromID int64
|
||||
// ChatID identifies the originating chat when available.
|
||||
ChatID int64
|
||||
// Duration is the handler execution time.
|
||||
Duration time.Duration
|
||||
// Err is the error returned or recovered from the handler.
|
||||
Err error
|
||||
// UserFacing reports whether Err is safe to show to the user.
|
||||
UserFacing bool
|
||||
}
|
||||
|
||||
// SceneTransitionEvent describes a scene state transition.
|
||||
type SceneTransitionEvent struct {
|
||||
// Plugin names the plugin that owns the scene.
|
||||
Plugin string
|
||||
Scene string
|
||||
From string
|
||||
To string
|
||||
// Scene names the transitioning scene.
|
||||
Scene string
|
||||
// From is the previous scene step.
|
||||
From string
|
||||
// To is the resulting scene step.
|
||||
To string
|
||||
// Action identifies the requested state transition.
|
||||
Action SceneAction
|
||||
// FromID identifies the session user when available.
|
||||
FromID int64
|
||||
// ChatID identifies the session chat when available.
|
||||
ChatID int64
|
||||
}
|
||||
|
||||
// PolicyCheckedEvent describes the result of a policy evaluation.
|
||||
type PolicyCheckedEvent struct {
|
||||
Name string
|
||||
Plugin string
|
||||
FromID int64
|
||||
ChatID int64
|
||||
Passed bool
|
||||
Err error
|
||||
// Name identifies the evaluated policy.
|
||||
Name string
|
||||
// Plugin names the plugin that requested the policy check.
|
||||
Plugin string
|
||||
// FromID identifies the evaluated user when available.
|
||||
FromID int64
|
||||
// ChatID identifies the evaluated chat when available.
|
||||
ChatID int64
|
||||
// Passed reports whether the policy accepted the context.
|
||||
Passed bool
|
||||
// Err is the policy evaluation error, if any.
|
||||
Err error
|
||||
// Internal reports whether evaluation failed internally rather than denying access.
|
||||
Internal bool
|
||||
}
|
||||
|
||||
// RunnerFinishedEvent describes a completed background runner execution.
|
||||
type RunnerFinishedEvent struct {
|
||||
Name string
|
||||
// Name identifies the runner.
|
||||
Name string
|
||||
// Duration is the callback execution time.
|
||||
Duration time.Duration
|
||||
Err error
|
||||
// Err is the callback error or recovered panic.
|
||||
Err error
|
||||
}
|
||||
|
||||
// PollingRetryEvent describes a polling retry after a failed getUpdates call.
|
||||
type PollingRetryEvent struct {
|
||||
// Attempt is the one-based retry number.
|
||||
Attempt int
|
||||
Delay time.Duration
|
||||
Err error
|
||||
// Delay is the time before the next polling attempt.
|
||||
Delay time.Duration
|
||||
// Err is the polling error that triggered the retry.
|
||||
Err error
|
||||
}
|
||||
|
||||
// ErrorEvent describes an error routed through framework error handling.
|
||||
type ErrorEvent struct {
|
||||
UpdateID int
|
||||
UpdateType tgapi.UpdateType
|
||||
Plugin string
|
||||
// UpdateID identifies the Telegram update when available.
|
||||
UpdateID int
|
||||
// UpdateType identifies the normalized update kind when available.
|
||||
UpdateType tgapi.UpdateType
|
||||
// Plugin names the component that reported the error.
|
||||
Plugin string
|
||||
// HandlerKind classifies the failing handler or runtime component.
|
||||
HandlerKind HandlerEventKind
|
||||
// HandlerName identifies the failing handler within its kind.
|
||||
HandlerName string
|
||||
FromID int64
|
||||
ChatID int64
|
||||
Err error
|
||||
UserFacing bool
|
||||
// FromID identifies the originating user when available.
|
||||
FromID int64
|
||||
// ChatID identifies the originating chat when available.
|
||||
ChatID int64
|
||||
// Err is the reported error.
|
||||
Err error
|
||||
// UserFacing reports whether Err is safe to show to the user.
|
||||
UserFacing bool
|
||||
}
|
||||
|
||||
func (UpdateReceivedEvent) isEvent() {}
|
||||
@@ -164,6 +224,11 @@ func (PollingRetryEvent) isEvent() {}
|
||||
func (ErrorEvent) isEvent() {}
|
||||
|
||||
// Observer receives best-effort runtime instrumentation events.
|
||||
//
|
||||
// During RunWithContext and RunWebhookWithContext, callbacks execute on a
|
||||
// dedicated dispatcher goroutine in enqueue order and never block update
|
||||
// handlers. The queue is bounded; overload drops events and emits sampled
|
||||
// warnings. Runtime shutdown drains events that were already queued.
|
||||
type Observer interface {
|
||||
OnUpdateReceived(ctx context.Context, event UpdateReceivedEvent)
|
||||
OnUpdateHandled(ctx context.Context, event UpdateHandledEvent)
|
||||
@@ -180,6 +245,10 @@ func (bot *Bot[T]) safeEmitEvent(ctx context.Context, event Event) {
|
||||
if bot.observer == nil {
|
||||
return
|
||||
}
|
||||
if bot.observerAsync != nil {
|
||||
bot.observerAsync.enqueue(ctx, event)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if bot.logger != nil {
|
||||
@@ -191,24 +260,28 @@ func (bot *Bot[T]) safeEmitEvent(ctx context.Context, event Event) {
|
||||
}
|
||||
|
||||
func (bot *Bot[T]) emitEvent(ctx context.Context, event Event) {
|
||||
emitObserverEvent(bot.observer, ctx, event)
|
||||
}
|
||||
|
||||
func emitObserverEvent(observer Observer, ctx context.Context, event Event) {
|
||||
switch e := event.(type) {
|
||||
case UpdateReceivedEvent:
|
||||
bot.observer.OnUpdateReceived(ctx, e)
|
||||
observer.OnUpdateReceived(ctx, e)
|
||||
case UpdateHandledEvent:
|
||||
bot.observer.OnUpdateHandled(ctx, e)
|
||||
observer.OnUpdateHandled(ctx, e)
|
||||
case HandlerStartedEvent:
|
||||
bot.observer.OnHandlerStarted(ctx, e)
|
||||
observer.OnHandlerStarted(ctx, e)
|
||||
case HandlerFinishedEvent:
|
||||
bot.observer.OnHandlerFinished(ctx, e)
|
||||
observer.OnHandlerFinished(ctx, e)
|
||||
case SceneTransitionEvent:
|
||||
bot.observer.OnSceneTransition(ctx, e)
|
||||
observer.OnSceneTransition(ctx, e)
|
||||
case PolicyCheckedEvent:
|
||||
bot.observer.OnPolicyChecked(ctx, e)
|
||||
observer.OnPolicyChecked(ctx, e)
|
||||
case RunnerFinishedEvent:
|
||||
bot.observer.OnRunnerFinished(ctx, e)
|
||||
observer.OnRunnerFinished(ctx, e)
|
||||
case PollingRetryEvent:
|
||||
bot.observer.OnPollingRetry(ctx, e)
|
||||
observer.OnPollingRetry(ctx, e)
|
||||
case ErrorEvent:
|
||||
bot.observer.OnError(ctx, e)
|
||||
observer.OnError(ctx, e)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user