You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

130 lines
4.2 KiB

// Package subscribers provides domain event subscriber implementations.
package subscribers
import (
"encoding/hex"
"lol.mleku.dev/log"
"next.orly.dev/pkg/domain/events"
)
// LoggingSubscriber logs domain events for analytics and debugging.
type LoggingSubscriber struct {
logLevel string // "debug", "info", "trace"
}
// NewLoggingSubscriber creates a new logging subscriber.
// logLevel controls verbosity: "trace" logs all events, "debug" logs important events,
// "info" logs only significant events like membership changes.
func NewLoggingSubscriber(logLevel string) *LoggingSubscriber {
if logLevel == "" {
logLevel = "debug"
}
return &LoggingSubscriber{logLevel: logLevel}
}
// Handle processes a domain event by logging it.
func (s *LoggingSubscriber) Handle(event events.DomainEvent) {
switch e := event.(type) {
case *events.EventSaved:
s.logEventSaved(e)
case *events.EventDeleted:
s.logEventDeleted(e)
case *events.FollowListUpdated:
s.logFollowListUpdated(e)
case *events.ACLMembershipChanged:
s.logACLMembershipChanged(e)
case *events.PolicyConfigUpdated:
s.logPolicyConfigUpdated(e)
case *events.UserAuthenticated:
s.logUserAuthenticated(e)
case *events.MemberJoined:
s.logMemberJoined(e)
case *events.MemberLeft:
s.logMemberLeft(e)
case *events.ConnectionOpened:
s.logConnectionOpened(e)
case *events.ConnectionClosed:
s.logConnectionClosed(e)
default:
if s.logLevel == "trace" {
log.T.F("domain event: %s", event.EventType())
}
}
}
// Supports returns true for all event types.
func (s *LoggingSubscriber) Supports(eventType string) bool {
return true
}
func (s *LoggingSubscriber) logEventSaved(e *events.EventSaved) {
if s.logLevel == "trace" {
pubkeyHex := hex.EncodeToString(e.Event.Pubkey)
log.T.F("event saved: kind=%d pubkey=%s admin=%v owner=%v",
e.Event.Kind, pubkeyHex[:16], e.IsAdmin, e.IsOwner)
}
}
func (s *LoggingSubscriber) logEventDeleted(e *events.EventDeleted) {
if s.logLevel == "trace" || s.logLevel == "debug" {
eventIDHex := hex.EncodeToString(e.EventID)
deletedByHex := hex.EncodeToString(e.DeletedBy)
log.D.F("event deleted: id=%s by=%s", eventIDHex[:16], deletedByHex[:16])
}
}
func (s *LoggingSubscriber) logFollowListUpdated(e *events.FollowListUpdated) {
if s.logLevel == "trace" || s.logLevel == "debug" {
adminHex := hex.EncodeToString(e.AdminPubkey)
log.D.F("follow list updated: admin=%s added=%d removed=%d",
adminHex[:16], len(e.AddedFollows), len(e.RemovedFollows))
}
}
func (s *LoggingSubscriber) logACLMembershipChanged(e *events.ACLMembershipChanged) {
// Always log ACL changes at info level - they're significant
pubkeyHex := hex.EncodeToString(e.Pubkey)
log.I.F("ACL membership changed: pubkey=%s %s->%s reason=%s",
pubkeyHex[:16], e.PrevLevel, e.NewLevel, e.Reason)
}
func (s *LoggingSubscriber) logPolicyConfigUpdated(e *events.PolicyConfigUpdated) {
// Always log policy changes at info level
updatedByHex := hex.EncodeToString(e.UpdatedBy)
log.I.F("policy config updated by %s: %d changes", updatedByHex[:16], len(e.Changes))
}
func (s *LoggingSubscriber) logUserAuthenticated(e *events.UserAuthenticated) {
if s.logLevel == "trace" || s.logLevel == "debug" {
pubkeyHex := hex.EncodeToString(e.Pubkey)
log.D.F("user authenticated: pubkey=%s level=%s firstTime=%v",
pubkeyHex[:16], e.AccessLevel, e.IsFirstTime)
}
}
func (s *LoggingSubscriber) logMemberJoined(e *events.MemberJoined) {
// Always log member joins at info level
pubkeyHex := hex.EncodeToString(e.Pubkey)
log.I.F("member joined: pubkey=%s invite=%s", pubkeyHex[:16], e.InviteCode)
}
func (s *LoggingSubscriber) logMemberLeft(e *events.MemberLeft) {
// Always log member departures at info level
pubkeyHex := hex.EncodeToString(e.Pubkey)
log.I.F("member left: pubkey=%s", pubkeyHex[:16])
}
func (s *LoggingSubscriber) logConnectionOpened(e *events.ConnectionOpened) {
if s.logLevel == "trace" {
log.T.F("connection opened: id=%s remote=%s", e.ConnectionID, e.RemoteAddr)
}
}
func (s *LoggingSubscriber) logConnectionClosed(e *events.ConnectionClosed) {
if s.logLevel == "trace" || s.logLevel == "debug" {
log.D.F("connection closed: id=%s duration=%v events_rx=%d events_tx=%d",
e.ConnectionID, e.Duration, e.EventsReceived, e.EventsPublished)
}
}