feat: opentelemetry for tracing and metrics
This commit is contained in:
@@ -9,7 +9,11 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/tidwall/wal"
|
||||
"go.opentelemetry.io/otel/metric/instrument/syncint64"
|
||||
"go.uber.org/multierr"
|
||||
|
||||
"github.com/sour-is/ev/internal/logz"
|
||||
"github.com/sour-is/ev/pkg/cache"
|
||||
"github.com/sour-is/ev/pkg/es"
|
||||
"github.com/sour-is/ev/pkg/es/driver"
|
||||
"github.com/sour-is/ev/pkg/es/event"
|
||||
@@ -17,25 +21,49 @@ import (
|
||||
"github.com/sour-is/ev/pkg/math"
|
||||
)
|
||||
|
||||
const CachSize = 1000
|
||||
|
||||
type lockedWal = locker.Locked[wal.Log]
|
||||
type openlogs struct {
|
||||
logs map[string]*locker.Locked[wal.Log]
|
||||
logs *cache.Cache[string, *lockedWal]
|
||||
}
|
||||
type diskStore struct {
|
||||
path string
|
||||
openlogs *locker.Locked[openlogs]
|
||||
|
||||
Mdisk_open syncint64.Counter
|
||||
Mdisk_evict syncint64.Counter
|
||||
}
|
||||
|
||||
const AppendOnly = es.AppendOnly
|
||||
const AllEvents = es.AllEvents
|
||||
|
||||
func Init(ctx context.Context) error {
|
||||
es.Register(ctx, "file", &diskStore{})
|
||||
return nil
|
||||
m := logz.Meter(ctx)
|
||||
var err, errs error
|
||||
|
||||
Mdisk_open, err := m.SyncInt64().Counter("disk_open")
|
||||
errs = multierr.Append(errs, err)
|
||||
|
||||
Mdisk_evict, err := m.SyncInt64().Counter("disk_evict")
|
||||
errs = multierr.Append(errs, err)
|
||||
|
||||
es.Register(ctx, "file", &diskStore{
|
||||
Mdisk_open: Mdisk_open,
|
||||
Mdisk_evict: Mdisk_evict,
|
||||
})
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
var _ driver.Driver = (*diskStore)(nil)
|
||||
|
||||
func (diskStore) Open(_ context.Context, dsn string) (driver.Driver, error) {
|
||||
func (d *diskStore) Open(ctx context.Context, dsn string) (driver.Driver, error) {
|
||||
ctx, span := logz.Span(ctx)
|
||||
defer span.End()
|
||||
|
||||
d.Mdisk_open.Add(ctx, 1)
|
||||
|
||||
scheme, path, ok := strings.Cut(dsn, ":")
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected scheme")
|
||||
@@ -51,16 +79,34 @@ func (diskStore) Open(_ context.Context, dsn string) (driver.Driver, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
c, err := cache.NewWithEvict(CachSize, func(ctx context.Context, s string, l *lockedWal) {
|
||||
l.Modify(ctx, func(w *wal.Log) error {
|
||||
// logz.Mdisk_evict.Add(ctx, 1)
|
||||
|
||||
logs := &openlogs{logs: make(map[string]*locker.Locked[wal.Log])}
|
||||
return &diskStore{path: path, openlogs: locker.New(logs)}, nil
|
||||
err := w.Close()
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logs := &openlogs{logs: c}
|
||||
return &diskStore{
|
||||
path: path,
|
||||
openlogs: locker.New(logs),
|
||||
Mdisk_open: d.Mdisk_open,
|
||||
Mdisk_evict: d.Mdisk_evict,
|
||||
}, nil
|
||||
}
|
||||
func (ds *diskStore) EventLog(ctx context.Context, streamID string) (driver.EventLog, error) {
|
||||
el := &eventLog{streamID: streamID}
|
||||
|
||||
return el, ds.openlogs.Modify(ctx, func(openlogs *openlogs) error {
|
||||
if events, ok := openlogs.logs[streamID]; ok {
|
||||
el.events = events
|
||||
if events, ok := openlogs.logs.Get(streamID); ok {
|
||||
el.events = *events
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -69,7 +115,7 @@ func (ds *diskStore) EventLog(ctx context.Context, streamID string) (driver.Even
|
||||
return err
|
||||
}
|
||||
el.events = locker.New(l)
|
||||
openlogs.logs[streamID] = el.events
|
||||
openlogs.logs.Add(ctx, streamID, el.events)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
69
pkg/es/es.go
69
pkg/es/es.go
@@ -6,9 +6,12 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/sour-is/ev/internal/logz"
|
||||
"github.com/sour-is/ev/pkg/es/driver"
|
||||
"github.com/sour-is/ev/pkg/es/event"
|
||||
"github.com/sour-is/ev/pkg/locker"
|
||||
"go.opentelemetry.io/otel/metric/instrument/syncint64"
|
||||
"go.uber.org/multierr"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
@@ -23,20 +26,56 @@ var (
|
||||
)
|
||||
|
||||
func Register(ctx context.Context, name string, d driver.Driver) error {
|
||||
return drivers.Modify(ctx, func(c *config) error {
|
||||
ctx, span := logz.Span(ctx)
|
||||
defer span.End()
|
||||
|
||||
m := logz.Meter(ctx)
|
||||
|
||||
var err, errs error
|
||||
Mes_open, err = m.SyncInt64().Counter("es_open")
|
||||
errs = multierr.Append(errs, err)
|
||||
|
||||
Mes_read, err = m.SyncInt64().Counter("es_read")
|
||||
errs = multierr.Append(errs, err)
|
||||
|
||||
Mes_load, err = m.SyncInt64().Counter("es_load")
|
||||
errs = multierr.Append(errs, err)
|
||||
|
||||
Mes_save, err = m.SyncInt64().Counter("es_save")
|
||||
errs = multierr.Append(errs, err)
|
||||
|
||||
Mes_append, err = m.SyncInt64().Counter("es_append")
|
||||
errs = multierr.Append(errs, err)
|
||||
|
||||
err = drivers.Modify(ctx, func(c *config) error {
|
||||
if _, set := c.drivers[name]; set {
|
||||
return fmt.Errorf("driver %s already set", name)
|
||||
}
|
||||
c.drivers[name] = d
|
||||
return nil
|
||||
})
|
||||
|
||||
return multierr.Append(errs, err)
|
||||
}
|
||||
|
||||
type EventStore struct {
|
||||
driver.Driver
|
||||
}
|
||||
|
||||
var (
|
||||
Mes_open syncint64.Counter
|
||||
Mes_read syncint64.Counter
|
||||
Mes_load syncint64.Counter
|
||||
Mes_save syncint64.Counter
|
||||
Mes_append syncint64.Counter
|
||||
)
|
||||
|
||||
func Open(ctx context.Context, dsn string, options ...Option) (*EventStore, error) {
|
||||
ctx, span := logz.Span(ctx)
|
||||
defer span.End()
|
||||
|
||||
Mes_open.Add(ctx, 1)
|
||||
|
||||
name, _, ok := strings.Cut(dsn, ":")
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%w: no scheme", ErrNoDriver)
|
||||
@@ -68,6 +107,11 @@ type Option interface {
|
||||
}
|
||||
|
||||
func (es *EventStore) Save(ctx context.Context, agg event.Aggregate) (uint64, error) {
|
||||
ctx, span := logz.Span(ctx)
|
||||
defer span.End()
|
||||
|
||||
Mes_save.Add(ctx, 1)
|
||||
|
||||
l, err := es.EventLog(ctx, agg.StreamID())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -83,6 +127,11 @@ func (es *EventStore) Save(ctx context.Context, agg event.Aggregate) (uint64, er
|
||||
return count, err
|
||||
}
|
||||
func (es *EventStore) Load(ctx context.Context, agg event.Aggregate) error {
|
||||
ctx, span := logz.Span(ctx)
|
||||
defer span.End()
|
||||
|
||||
Mes_load.Add(ctx, 1)
|
||||
|
||||
l, err := es.Driver.EventLog(ctx, agg.StreamID())
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -97,6 +146,11 @@ func (es *EventStore) Load(ctx context.Context, agg event.Aggregate) error {
|
||||
return nil
|
||||
}
|
||||
func (es *EventStore) Read(ctx context.Context, streamID string, pos, count int64) (event.Events, error) {
|
||||
ctx, span := logz.Span(ctx)
|
||||
defer span.End()
|
||||
|
||||
Mes_read.Add(ctx, 1)
|
||||
|
||||
l, err := es.Driver.EventLog(ctx, streamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -104,6 +158,11 @@ func (es *EventStore) Read(ctx context.Context, streamID string, pos, count int6
|
||||
return l.Read(ctx, pos, count)
|
||||
}
|
||||
func (es *EventStore) Append(ctx context.Context, streamID string, events event.Events) (uint64, error) {
|
||||
ctx, span := logz.Span(ctx)
|
||||
defer span.End()
|
||||
|
||||
Mes_append.Add(ctx, 1)
|
||||
|
||||
l, err := es.Driver.EventLog(ctx, streamID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -111,6 +170,9 @@ func (es *EventStore) Append(ctx context.Context, streamID string, events event.
|
||||
return l.Append(ctx, events, AppendOnly)
|
||||
}
|
||||
func (es *EventStore) FirstIndex(ctx context.Context, streamID string) (uint64, error) {
|
||||
ctx, span := logz.Span(ctx)
|
||||
defer span.End()
|
||||
|
||||
l, err := es.Driver.EventLog(ctx, streamID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -118,6 +180,9 @@ func (es *EventStore) FirstIndex(ctx context.Context, streamID string) (uint64,
|
||||
return l.FirstIndex(ctx)
|
||||
}
|
||||
func (es *EventStore) LastIndex(ctx context.Context, streamID string) (uint64, error) {
|
||||
ctx, span := logz.Span(ctx)
|
||||
defer span.End()
|
||||
|
||||
l, err := es.Driver.EventLog(ctx, streamID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -138,7 +203,7 @@ func (es *EventStore) EventStream() driver.EventStream {
|
||||
}
|
||||
|
||||
func Unwrap[T any](t T) T {
|
||||
if unwrap, ok := any(t).(interface{Unwrap() T}); ok {
|
||||
if unwrap, ok := any(t).(interface{ Unwrap() T }); ok {
|
||||
return unwrap.Unwrap()
|
||||
} else {
|
||||
var zero T
|
||||
|
||||
Reference in New Issue
Block a user