How to build an Activity Tracker

I built an OTP app and now I need to add something like https://github.com/chaps-io/public_activity where I could create logs of what is happening on the system.

But,

My OTP app functions do not depends of any user, so I am confused how I could log that specific user change something to the next state.

Where do I put this use case now.

1 Like

Maybe structure your OTP app with Command structs and handler modules?

Then you can log the Commands as they are processed to the DB.

Could you post some links to what you are talking about? Or some example.

I don’t understand/know what you mean by that.

Instead of making change, generate an event, that has enough information to be applied by handler… Having this stream of events allows easy log. For example at the handler level.

A command could look like…

%Command{type: :create, payload: whatever}

See Command pattern.

an object is used to encapsulate all information needed to perform an action or trigger an event at a later time

or

but my OTP app is already done without this pattern (which I am still confused who is the one that actually triggers the event to happen)

Where this Commander would sit?

The gem You mentionned is triggerred by active record on create/del/update…

In the case of Event Sourcing You would need to intercept all db call, and replace by an event. The commander would sit between the requested action and the db call.

The closest You could find would be database trigger, probably. Or use RethinkDB.

The commands would be constructed in the top level module of your OTP app. It’s a pattern that fits nicely with BEAM messaging - you can send a command struct to a GenServer for instance.

If that feels like too much re-structuring, another approach would be to find all the places you are submitting Changesets to the Repo. Replace these Changesets with Ecto.Multi, which includes an additional logging operation.

1 Like

I can’t do any of those mentioned thing because the OTP app is done.

@mbuhot basically what you are saying is that,

In my phoenix apps I will pass every action throw the commander so it will log before and after I do the actions.

Right?!

The only concern is to know what actually changed.

Yes, you can possibly take inpiration from the commanded package.

Yes if it isn’t clear from the Command payloads what the effects on the system were, then you might need something based on database triggers.

How could yo rely on database triggers if the db alone can’t know who made the change for be able to log? Unless I am missing something (definitely possible)

I would like to have messages like Github Audits, so I am confused about that

Yes, that also requires injecting the current user into a transaction scoped postgres app setting:

MyApp.repo.transaction(fn ->
  SQL.query(MyApp.Repo, "SELECT set_config('app.user', $1, true)", [user_id])
  ... do updates here ...
end)

Then in triggers, access the current user with current_setting('app.user'));