def aggregated_records(all_records, key_fields=KEY_FIELDS):
flow_table = defaultdict(_FlowStats)<EOL>for flow_record in all_records:<EOL><INDENT>key = tuple(getattr(flow_record, attr) for attr in key_fields)<EOL>if any(x is None for x in key):<EOL><INDENT>continue<EOL><DEDENT>flow_table[key].update(flow_record)<EOL><DEDENT>for key in flow_table:<EOL><INDENT>item = {k: v for k, v in zip(key_fields, key)}<EOL>item.update(flow_table[key].to_dict())<EOL>yield item<EOL><DEDENT>
Yield dicts that correspond to aggregates of the flow records given by
the sequence of FlowRecords in `all_records`. Skips incomplete records.
This will consume the `all_records` iterator, and requires enough memory to
be able to read it entirely.
`key_fields` optionally contains the fields over which to aggregate. By
default it's the typical flow 5-tuple.