Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logging #60

Open
andrzejkrzywda opened this issue Oct 27, 2016 · 5 comments
Open

Logging #60

andrzejkrzywda opened this issue Oct 27, 2016 · 5 comments

Comments

@andrzejkrzywda
Copy link
Contributor

andrzejkrzywda commented Oct 27, 2016

I'd like to start a discussion about the concept of logging around the event stores.

RailsEventStore is meant to help Rails people to start being event-driven. That's a great thing. Events do introduce indirection of the control flow. They also make debugging different.

One thing I'm wondering about is to have some automatic logging for some important places in the lifecycle of the event store:

  • initialization
  • setup of subscribers
  • publishing
  • notifying subscribers
  • warnings (for example when event is published but nothing is handling it), this may be a separate concern, though

Given that RailsEventStore is an umbrella which automates things for Rails, we could have the Rails.logger being a default dependency. However, it's possible that the EventStore is also run without Rails (my current case) and then it should be possible to inject my own logger (probably via constructor?).

Anyone else felt the need for having logs around the events?

@gottfrois
Copy link
Contributor

From my usage (within a rails app) I have not felt the need to log many things beside event handling. This is already possible by simply adding a subscriber to all events and log them myself using Rails.logger.

@andrzejkrzywda
Copy link
Contributor Author

Some more thoughts here, after recent problems:

One of the potential failures in RES-driven apps is the problem when people initialize more than one RailsEventStore::Client (as I did stupidly just recently). This leads to situations where one of the instances has less/no knowledge about subscribers, resulting in a confusing lack of reactions to events.

Adding a logging (optional, by turning the VerboseMode on) could show:

  • the event_store_client.object_id
  • the currently published event (event_type + data)
  • the number of subscribers which are being called
  • in case of AggregateRoot it could show which apply_ method/strategy is being used

@andrzejsliwa
Copy link
Member

I think the problem partially is related to lack of recommended way of setup/configuration.
This problems can be solved by providing nice defaults. But providing more logging would be useful (same as providing standard set of rspec/unit matchers)

In my case I made global configuration instance:

    config.to_prepare do
      Rails.configuration.core = CoreConfiguration.new
    end

connected to_prepare handler in order to support reloading of environment in rails console.

example config:

class CoreConfiguration
  def initialize(event_store:      RailsEventStore::Client.new,
                 command_bus:      EventSourcing::CommandBus.new,
                 command_injector: EventSourcing::CommandInjector.new(command_bus: command_bus))
    @event_store      = event_store
    @command_bus     = command_bus
    @command_injector = command_injector

    configure_aggregate_root(event_store)
    setup_read_models(event_store)
    register_event_handlers(event_store)
    register_command_handlers(command_bus)

    EventSourcing::ReadModelSwitcher.init!
  end

  ...

  attr_reader :event_store,
              :command_bus,
              :all_command_handlers,
              :all_read_models,
              :all_event_handlers,
              :command_injector
end

and use it in constructor injections:

    def initialize(number_generator: NumberGenerator.new, command_injector: Rails.configuration.core.command_injector)
      super(command_injector: command_injector)
      @number_generator = number_generator
    end

or method level injections:

    def register(event_store: Rails.configuration.core.event_store)
      configs.flatten.each do |c|
        event_store.subscribe(c.fetch(:handler), c.fetch(:events))
      end
    end

@andrzejkrzywda
Copy link
Contributor Author

andrzejkrzywda commented Aug 8, 2017

There's a common need to see 2 things somehow, which can be partially solved with logging, IMO:

  1. For a given event, see what handlers are subscribed
  2. For a given handler, see what events is it reacting to (if any)

One way to solve it is runtime, with something like:

event_store.handlers_for_event(event_name)

and

event_store.events_for_handler(handler_name)

Optionally, it may require that when we subscribe to the events, we also pass the name, as the third argument:

event_store.subscribe(event, handler, "HandlerName")

@mostlyobvious
Copy link
Member

Logging (and in production monitoring/metrics) can be solved by adding instrumentation (see #73).

Then logging would be a matter of:

class LogRailsEventStore
  def call(name, started, finished, unique_id, payload)
    Rails.logger.debug(['RailsEventStore:', name, started, finished, unique_id, payload].join(' '))
  end
end

ActiveSupport::Notifications.subscribe(/rails_event_store/, LogRailsEventStore)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants