'Gets data records from a shard.
Specify a shard iterator using the `ShardIterator` parameter.
The shard iterator specifies the position in the shard from
which you want to start reading data records sequentially. If
there are no records available in the portion of the shard
that the iterator points to, `GetRecords` returns an empty
list. Note that it might take multiple calls to get to a
portion of the shard that contains records.
You can scale by provisioning multiple shards. Your
application should have one thread per shard, each reading
continuously from its stream. To read from a stream
continually, call `GetRecords` in a loop. Use GetShardIterator
to get the shard iterator to specify in the first `GetRecords`
call. `GetRecords` returns a new shard iterator in
`NextShardIterator`. Specify the shard iterator returned in
`NextShardIterator` in subsequent calls to `GetRecords`. Note
that if the shard has been closed, the shard iterator can\'t
return more data and `GetRecords` returns `null` in
`NextShardIterator`. You can terminate the loop when the shard
is closed, or when the shard iterator reaches the record with
the sequence number or other attribute that marks it as the
last record to process.
Each data record can be up to 50 KB in size, and each shard
can read up to 2 MB per second. You can ensure that your calls
don\'t exceed the maximum supported size or throughput by using
the `Limit` parameter to specify the maximum number of records
that `GetRecords` can return. Consider your average record
size when determining this limit. For example, if your average
record size is 40 KB, you can limit the data returned to about
1 MB per call by specifying 25 as the limit.
The size of the data returned by `GetRecords` will vary
depending on the utilization of the shard. The maximum size of
data that `GetRecords` can return is 10 MB. If a call returns
10 MB of data, subsequent calls made within the next 5 seconds
throw `ProvisionedThroughputExceededException`. If there is
insufficient provisioned throughput on the shard, subsequent
calls made within the next 1 second throw
`ProvisionedThroughputExceededException`. Note that
`GetRecords` won\'t return any data when it throws an
exception. For this reason, we recommend that you wait one
second between calls to `GetRecords`; however, it\'s possible
that the application will get exceptions for longer than 1
second.
To detect whether the application is falling behind in
processing, add a timestamp to your records and note how long
it takes to process them. You can also monitor how much data
is in a stream using the CloudWatch metrics for write
operations ( `PutRecord` and `PutRecords`). For more
information, see `Monitoring Amazon Kinesis with Amazon
CloudWatch`_ in the Amazon Kinesis Developer Guide .
:type shard_iterator: string
:param shard_iterator: The position in the shard from which you want to
start sequentially reading data records. A shard iterator specifies
this position using the sequence number of a data record in the
shard.
:type limit: integer
:param limit: The maximum number of records to return. Specify a value
of up to 10,000. If you specify a value that is greater than
10,000, `GetRecords` throws `InvalidArgumentException`.
:type b64_decode: boolean
:param b64_decode: Decode the Base64-encoded ``Data`` field of records.'

def get_records(self, shard_iterator, limit=None, b64_decode=True):

    params = {'ShardIterator': shard_iterator}
    if (limit is not None):
        params['Limit'] = limit
    response = self.make_request(action='GetRecords', body=json.dumps(params))
    if b64_decode:
        for record in response.get('Records', []):
            record['Data'] = base64.b64decode(record['Data'].encode('utf-8')).decode('utf-8')
    return response
