Hi,
I believe when you get the first result like this:
chunk_size": 1,
"next_stream_position": ***number removed for privacy***9819,
"entries": ........
For the next call, you would still specify limit but use the stream position value to be the value of "next_stream_position". so, your stream position will be "***number removed for privacy***9819" for the next call. And you should do while loop or any loop until the next_stream_position gets to current.
let me know if this makes sense.
thanks,
Bibek
Here's some code:
static void Main(string[] args)
{
Task t = MainAsync();
t.Wait();
Console.WriteLine("Done...");
Console.ReadKey();
}
static async Task MainAsync()
{
var privateKey = File.ReadAllText(PRIVATE_KEY_FILE);
var boxConfig = new BoxConfig(CLIENT_ID, CLIENT_SECRET, ENTERPRISE_ID, privateKey, JWT_PRIVATE_KEY_PASSWORD, JWT_PUBLIC_KEY_ID);
var boxJWT = new BoxJWTAuth(boxConfig);
var adminToken = boxJWT.AdminToken();
var adminClient = boxJWT.AdminClient(adminToken);
DateTime createdAfter = DateTime.Parse("2016-12-01T01:00:00-7:00"); // 2014-05-17T13:35:01-07:00
DateTime createdBefore = DateTime.Parse("2016-12-01T01:05:00-7:00");
string streamPosition = null;
await loadEvents(adminClient, createdAfter, createdBefore, streamPosition);
}
static async Task loadEvents(BoxClient adminClient,
DateTime createdAfter, DateTime createdBefore, string streamPosition)
{
Console.WriteLine("stream position: " + streamPosition);
BoxEventCollection events =
await adminClient.EventsManager.EnterpriseEventsAsync(
500,
streamPosition,
null,
createdAfter,
createdBefore);
events.Entries.ForEach(i =>
{
// get your events
});
string nextStreamPosition = events.NextStreamPosition;
if ((null != nextStreamPosition) && (nextStreamPosition != streamPosition))
{
BoxEnterpriseEvent be = events.Entries.Last();
Console.WriteLine(be.CreatedAt);
await loadEvents(adminClient, createdAfter, createdBefore, nextStreamPosition);
}
}
And here's the output:
stream position:
12/1/2016 4:01:10 PM
stream position: 1152922985214917947
12/1/2016 4:02:16 PM
stream position: 1152922985214983518
12/1/2016 4:03:09 PM
stream position: 1152922985215036862
12/1/2016 4:04:16 PM
stream position: 1152922985215103558
12/1/2016 4:04:59 PM
stream position: 1152922985215146913
Done...
Thank you. This is pretty much what I eventually did... I think it is working. (My code is in powershell.. but looks very similar).
However, what is confusing to me is that once you start using stream position, you can no longer user the created before and created after dates. So if you want to get the events for a time period, wouldn't you also need to make sure that you stop at the "created before" date?
Here's what I ended up with (that definitely needs cleaned up) :
function Get-BoxAdminLog($token,$eventtype,$createdafter, $createdbefore, $limit=500){
$head = @{}
$head.Add("Authorization","Bearer $token")
if($createdafter -and $createdbefore){
$uri = "https://api.box.com/2.0/events?stream_type=admin_logs&event_type=$eventtype&created_after=$createdafter&created_before=$createdbefore&limit=$limit"
}
elseif($createdafter){
$uri = "https://api.box.com/2.0/events?stream_type=admin_logs&event_type=$eventtype&created_after=$createdafter&limit=$limit"
}
elseif($createdbefore){
$uri = "https://api.box.com/2.0/events?stream_type=admin_logs&event_type=$eventtype&created_before=$createdbefore&limit=$limit"
}
else{
return "Please provide createdbefore, createdafter, or both"
}
$return = Invoke-RestMethod -Uri $uri -Method Get -Headers $head -ContentType "application/x-www-form-urlencoded"
if($return.next_stream_position -eq 0){
#get-date | out-file c:\temp\test.txt
return $return.entries
}
else{
$streampos = $return.next_stream_position
$items = $return.entries
while($return.next_stream_position -ne 0){
$uri = "https://api.box.com/2.0/events?stream_type=admin_logs&event_type=$eventtype&stream_position=$streampos&limit=$limit"
$return = Invoke-RestMethod -Uri $uri -Method Get -Headers $head -ContentType "application/x-www-form-urlencoded"
if($return.next_stream_position -eq $streampos){
break
}
$items += $return.entries
$streampos = $return.next_stream_position
if($createdbefore){
if($return.entriesi-1].created_at -gt $createdbefore){
break
}
}
}
return $items
}
}
I believe it uses all 3. When it first starts, it has no stream position and only createdAfter & createdBefore. Then after the first loop, you'll get a stream_position but it will stop once it reaches createdBefore.
I changed the code to output all 3 variables on the above test...
stream position:
createdAfter: 12/1/2016 8:00:00 AM
createdBefore: 12/1/2016 8:05:00 AM
-------------------------------------
12/1/2016 4:01:10 PM
stream position: 1152922985214917947
createdAfter: 12/1/2016 8:00:00 AM
createdBefore: 12/1/2016 8:05:00 AM
-------------------------------------
12/1/2016 4:02:16 PM
stream position: 1152922985214983518
createdAfter: 12/1/2016 8:00:00 AM
createdBefore: 12/1/2016 8:05:00 AM
-------------------------------------
12/1/2016 4:03:09 PM
stream position: 1152922985215036862
createdAfter: 12/1/2016 8:00:00 AM
createdBefore: 12/1/2016 8:05:00 AM
-------------------------------------
12/1/2016 4:04:16 PM
stream position: 1152922985215103558
createdAfter: 12/1/2016 8:00:00 AM
createdBefore: 12/1/2016 8:05:00 AM
-------------------------------------
12/1/2016 4:04:59 PM
stream position: 1152922985215146913
createdAfter: 12/1/2016 8:00:00 AM
createdBefore: 12/1/2016 8:05:00 AM
-------------------------------------
Done...
Can you share the code? In the original code, createdAfter and createdBefore were variables that you defined... so I would expect that the output is just printing variables you defined and not data returned from the API call.
Also, the documentation specifically says:
Important
Box responds to the created_before and created_after parameters only if the stream_position parameter is not included.
static async Task MainAsync()
{
var privateKey = File.ReadAllText(PRIVATE_KEY_FILE);
var boxConfig = new BoxConfig(CLIENT_ID, CLIENT_SECRET, ENTERPRISE_ID, privateKey, JWT_PRIVATE_KEY_PASSWORD, JWT_PUBLIC_KEY_ID);
var boxJWT = new BoxJWTAuth(boxConfig);
var adminToken = boxJWT.AdminToken();
var adminClient = boxJWT.AdminClient(adminToken);
DateTime createdAfter = DateTime.Parse("2016-12-01T01:00:00-7:00");
DateTime createdBefore = DateTime.Parse("2016-12-01T01:05:00-7:00");
string streamPosition = null;
await loadEvents(adminClient, createdAfter, createdBefore, streamPosition);
}
static async Task loadEvents(BoxClient adminClient,
DateTime createdAfter, DateTime createdBefore, string streamPosition)
{
Console.WriteLine("stream position: " + streamPosition);
Console.WriteLine("createdAfter: " + createdAfter);
Console.WriteLine("createdBefore: " + createdBefore);
Console.WriteLine("-------------------------------------");
BoxEventCollection events =
await adminClient.EventsManager.EnterpriseEventsAsync(
500,
streamPosition,
null,
createdAfter,
createdBefore);
events.Entries.ForEach(i =>
{
// get your events
});
string nextStreamPosition = events.NextStreamPosition;
if ((null != nextStreamPosition) && (nextStreamPosition != streamPosition))
{
BoxEnterpriseEvent be = events.Entries.Last();
Console.WriteLine(be.CreatedAt);
await loadEvents(adminClient, createdAfter, createdBefore, nextStreamPosition);
}
}
If your events actually stop at the "created_before" datetime... then the API call has to be using the created_before parameter still even though you are providing the stream_position... this goes opposite of what the documentation says.
Because... the only thing stopping your loop is if the steamposition returned is null or if the stream position returned is the same as the last call... right?
Yes. It's behaving that way.