-
Notifications
You must be signed in to change notification settings - Fork 5
Match actions to events on the fly #235
Comments
Also responding to this here. Indeed I'm also afraid of breaking some OSS setups - but submitted the PR as per the conversation on Slack. I think you have more context here and the approach makes sense. Plus I guess the idea was to do this anyway #157. Wondering now about the short-term, given that we wanted to even push a patch release. Realistically we won't get this done super soon I'm guessing. Should we then maybe just change that webhook task to use The action mapping will still happen periodically and I guess the minor problem is that a user might receive a message via the webhook, go to the PostHog action, and the event isn't there yet. |
Forgot to add: there are also filters/selectors on |
We want to tackle this this week. Here's how I think we can go about this: It looks like we can't feasibly do action matching in the plugin server, because we'd have to port all filtering logic to JS and maintain that all times (so new action definition or filtering options would not only need to be done for Postgres and for ClickHouse, but in fact for Postgres in Django, for ClickHouse in Django, for Postgres in Node, and for ClickHouse in Node). That sounds nigthmarish. Keeping this in the main Python repo is hugely simpler. So, how can we tell the plugin servers about actions matched to an event? The above is a plan. I can foresee performance issues and other problems may come up too. But, this can be tried out in a few days, while porting action matching/filtering/cohorts logic (along with all tests) would take weeks. |
I'd say the goal for this week is to realistically scope out how big of a task this would be. Nobody has yet asked for an The thing is: servers are not free. My hypothesis is that if we move action mapping, or at least part of it, into the plugin server, we will drastically cut down on cost. We can cut down on workers by an order of magnitude... with virtually no extra muscle spent by the plugin server. That's worth spending a few weeks on. Regarding the filtering, unless we find some creative shortcuts, like storing computed filter sql inside the actions... (probably a bad idea, but think outside the box), we will need to port some of it over. However, I don't think the plugin server needs to run any queries for most actions/filters. The data should already be there. That means the plugin server port won't be maintaining two database filters, but just some It's not trivial work, but let's at least spec it out. What filters are there? How can we do this with the least amount of resources? What could we do to make sure the filters stay in sync in both projects? Is there a way to at least split the work, or at least do the simple ones on the plugin server? Can we exclude most events that match nothing? What's the real world usage for all of these different types of actions? Maybe we should write the filters inside the That all said, what are the plans for team core experience regarding filters, actions, etc? Are there plans on implementing LUA scripts inside nested property filters soon? How stable is the filters API? Is our plan of doing real time action matching in the plugin server a brave one ... or a brave and foolish one? Tagging @EDsCODE for this :). If we can somehow avoid another round trip to django after ingesting an event, all the network cables and servers will be happy. Think of the servers. And the environment. And the cables. |
Alright, actually right now actions only use the |
I see problems with precalculating actions for clickhouse. Needing to recalculate them might become annoying (solvable with some unique ids and lots of disk space). Plus I'm not sure if calculating them dynamically is actually a problem. It could be. If so, having the discussion makes sense. Otherwise we'd be creating more work than we should. For postgres, we will need code which recalculates all the events for an action from scratch and stores those in the database. That logic is now and can remain in Django. For both postgres and clickhouse, we need to detect when an event is being ingested, if it currently matches any action, and trigger relevant, uhm, actions on our part. Such as webhooks and possibly This latter part is the code I'd like to port over to the plugin server. Because the plugin server is a long running process, we can cache all the actions and match them against incoming events with a few javascript Now, again, this should be specced out a bit more :). |
Alright, more specifically:
Currently
CrossroadsLaying out 3 options to consider. "Implementation work" values below don't list "building
As always – this is only what I have identified, and I may be missing something, so if you're thinking about any other way, would love to hear (and I may have mixed something up in the 4 tables above, it took some tinkering to present this somewhat nicely). |
Hey! Thanks for this! It's a great tool to aid us in comparing the approaches, plus great documentation for later. However, I'm still not seeing the approach I keep advocating for for months now 😛 . I'm not sure what gets lost in the translation, or what am I missing that makes it impossible to work. I'll use the table structure to describe the changes I'd make:
Now, again, I might be missing something, so I'd really love for this approach to be specced out. What filters do we need. What are we missing. However this approach has so many benefits that I'd really love to get some MVP out: there will be no celery/kafka round trips. There will be no extra queries per action. No longer do we make 100 queries per event if we have 100 actions. Etc. As discussed here, we need to get a handle on server costs and this will bring massive savings. We could scale down celery workers from ~50 tasks to ~2. From what I was able to gather (and copy/pasting from the first post), we have three ActionSteps that we can match immediately:
Filters on all three of them add some complexity:
Plus the logic to keep actionsteps in sync in the plugin server, probably via some redis pubsub. That's not THAT much work to get in to JS? And that's not that much effort to keep in sync with core, I think. What am I missing? I mean, yes, we will need to port these guys, but that's 20 lines of code: I'm up for a call to discuss this in more detail if needed :). |
Okay, I get what you're going for more or less. |
And yes, you're pretty much on point with the specific features to port, I don't have anything to add to that list. |
Sorry, typo for CH, should have been "no need to save in db" . Why do we need a query for the regex? Just because of incompatible regex implementations? Definitely fine for webhooks not to be a plugin. I'm not really following after the BTW. Again, we would not do any postgres matching in JS. No databases, just comparing javascript variables on events as they fly by. We'd maintain the two filters as they are now in python, and call What's the bridge table? |
Yep, the regex implementations differ slightly between all of JS, ClickHouse and Postgres. No, sorry, I definitely don't mean "Postgres matching" as in "matching done with Postgres SQL", but as "matching done in the Postgres pipeline of ingestion > analytics" – as there's a significant degree separation between Postgres and CH in this regard, particularly with the current setup. I do see that doing matching in JS ingestion can eliminate a lot of this separation though – so actually really the logic is only 2x. OK, I like that. A bridge table is one name for a table connecting two tables with a many-to-many relationship. Specifically interested in OK, so here's a revised approach:
Comments? |
That seems perfect to me! Regarding cohorts, 2.7GB is obviously too much to keep in memory. And always multiply these numbers 10x just in case and it's then definitely too much. I think the system should be smart enough to first even know if it needs cohorts for any action, and if so, we can just inline them with a subquery when fetching the person. Similarly we should also know if there's any need to fetch the person, and skip if not. |
Ah, crap, I also forgot one other ugly complication for Zapier: it's a premium feature, meaning it does some convoluted stuff to get features available for the organization (both on Cloud and self-hosted), using the |
I think for this it makes sense to have an |
We should probably match actions to events on the fly in the plugin server.
At the highest level:
There are three different types of ActionSteps that we can match directly:
Filters on all three of them add some complexity:
Person
for this. We areselect
ing it for all posthog-js events due to some automatic$set
properties, so it's probably fine to also fetch the person (if not already fetched) to match a property for an actionIn addition:
PluginConfig
s now.However:
Shouldn't be that hard to pull off?
Next step after this: automatically update cohorts after ingesting events.
The text was updated successfully, but these errors were encountered: