Adam Wegscheid
04/03/2026, 3:44 PMdef get_child_context(self, record: dict, context: Context | None) -> dict:
"""Return context for child streams."""
child_context = {
"org": record.get("org"),
"day": record.get("day") or record.get("date"),
"copilot_metrics_record": record,
}
if context:
return {**context, **child_context}
return child_context
The consequence is three fold: (1) The logging prints the context so it gets absolutely littered, (2) the parent stream records get sent over to the target (we only want the child stream records), and (3) the child streams begin anew for each record:
> Beginning sync of 'copilot_usage_totals_by_ide' in full_table mode with context: ...
As you can see, clearly my understanding of how this works is lacking but I am not sure what other options are available to meet this goal. Does anyone have any advice or example projects that do something similar?
EDIT: I found documentation on inline stream maps that could offer a different path: https://sdk.meltano.com/en/latest/stream_maps.html#duplicating-or-splitting-a-stream-using-source
My only issue is I would prefer to define everything in the tap itself rather than meltano.yml so it is consistent with our other taps.Reuben (Matatika)
04/07/2026, 8:46 AMhiddendict to wrap a record passed via context and obfuscate its contents in the logs as `***`:
• https://github.com/Matatika/tap-aptem/blob/712fc0870f79a759b2afddaff2dfce0a93622d72/tap_aptem/__init__.py#L8
• https://github.com/Matatika/tap-aptem/blob/712fc0870f79a759b2afddaff2dfce0a93622d72/tap_aptem/client.py#L143
You'll also want to set stream_partitioning_keys = () on your child stream classes to prevent an explosion of bookmark contexts in state, as a result of having been passed an entire record.
2 I'm not sure what you mean? Only data synced by a stream (as per defined schemas) will be consumed by a target.
3 I think you can solve if you can make the parent stream incremental - child streams will then implicitly behave incrementally also. If the parent stream is already incremental, I don't think this is an issue (although logs may indicate otherwise, i.e. in full_table mode).Adam Wegscheid
04/07/2026, 7:14 PMhiddendict implementation and see if that will provide a solution! I have never made use of the built-in state capabilities of Meltano but if I ever do, I will look into stream_partitioning_keys=() as well.
In regards to (2), it is probably confusing because it is a design flaw on my part that is difficult for me to express due to lack of understanding.
My design at the time of writing my comment was the "parent" stream retrieved the data and then passed the full records to the child streams. Each child stream would take the array it was designed for from the record and sync it to the target.
However, I do not want that high level record that the "parent" stream handled to be loaded into the target. So (2) was asking how I can prevent the "parent" stream from syncing its records over but still have the children. I do not expect a solution to this because that goes fundamentally against Meltano's design and has since been scrapped. I was essentially trying to use the "parent" as an intermediate data source that the children read from.
For (3), it was set to incremental but I discovered that the parent-child model is really designed as a way to send a small list of records (containing parameters) and the child syncs once per record. There is no way to make the child collect all of the records first and then process them because that is not its intended design (at least that is my understanding). If the parent sends over 10k records to the child, that means the child stream will start up and shut down 10k times and same with the target. That is a lot of waste.Adam Wegscheid
04/07/2026, 7:31 PMReuben (Matatika)
04/08/2026, 9:57 AMHowever, I do not want that high level record that the "parent" stream handled to be loaded into the target.You could set
selected = False or selected_by_default = False on the parent stream class:
• selected
• selected_by_default
There is no way to make the child collect all of the records first and then process them because that is not its intended design (at least that is my understanding). If the parent sends over 10k records to the child, that means the child stream will start up and shut down 10k times and same with the target. That is a lot of waste.Correct 👍 I don't know if I would call it wasteful, but certainly there are cases when you want to collect child contexts together and apply them all at once (and have implemented this as a buffer system in a couple of taps - definitely hacky).@Edgar Ramírez (Arch.dev) may have more insight here.
Reuben (Matatika)
04/08/2026, 10:08 AMrequests-cache for this? That fits in quite nicely with the SDK model in overriding `requests_session`: https://github.com/ReubenFrankel/tap-f1/blob/95b75335f728f81a1a4e9eb24eeea24d293c4950/tap_f1/client.py#L20-L28Adam Wegscheid
04/08/2026, 12:09 PMrequests-cache for my solution (never heard of it!). I am being a brute and just making the call and storing the parsed result in a class scope variable. Let me look into that! That may help bring back the elegance I was hoping for. Greatly appreciate the tip!Edgar Ramírez (Arch.dev)
04/08/2026, 2:07 PMAdam Wegscheid
04/08/2026, 2:49 PM