Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining DocumentDB Request Charge per query via .NET

I'm trying to figure out if it's possible to get the "request charge" when performing DocumentDB query requests via the supplied .NET client library. The details come back in the underlying HTTP header "x-ms-request-charge" which I can monitor via Fiddler etc but would prefer if I could get it directly via .NET.

Has anyone done this? Or at least able to confirm if it's simply not possible?

Update:

Added clarification that I'm after request charge when performing queries and not other operations.

like image 486
Ken Faulkner Avatar asked Nov 09 '14 19:11

Ken Faulkner


2 Answers

You should be able to get that through .Net library. For example, take a look at the screenshot below which shows you the response of a Create New User operation. The result is of type Microsoft.Azure.Client.ResourceResponse<T> which has a property called RequestCharge.

enter image description here

UPDATE

So I checked the query result and you're correct that this is not exposed directly in the .Net library. However this is available in ResponseHeaders property and you could possibly find it out using something like below:

FeedResponse<Microsoft.Azure.Documents.Document> queryResult = await documentClient.CreateDocumentQuery<Microsoft.Azure.Documents.Document>(collectio‌​nSelfLink, query, options).AsDocumentQuery().ExecuteNextAsync<Microsoft.Azure.Documents.Document>(‌​);
var requestCharge = queryResult.ResponseHeaders["x-ms-request-charge"];

instead of inspecting it in Fiddler.

NOTE

ExecuteNextAsync may return a subset of results with a continuation token. If you want all the results, you'd have to iterate till document db doesnt send abck a continuation token.

var docDbQueryable = documentClient.CreateDocumentQuery<Document>(collectio‌​nSelfLink, query, options).AsDocumentQuery();
var docDbResults = new List<Document>();
do
{
    var batchResult = await docDbQueryable.ExecuteNextAsync<Document>(‌​);;
    docDbResults.AddRange(batchResult);
}
while (docDbQueryable.HasMoreResults);
return docDbResults;
like image 173
Gaurav Mantri Avatar answered Nov 11 '22 16:11

Gaurav Mantri


Here's what you need to log the cost for each query and also handle paging:

public async Task<IEnumerable<T>> Query<T>(string databaseId, string collectionId, SqlQuerySpec sqlQuery, int take)
where T : Resource
{
    double queryCost = 0;
    const int maxPageSize = 100;

    var query = _client.CreateDocumentQuery<T>(
        UriFactory.CreateDocumentCollectionUri(databaseId, collectionId),
        sqlQuery,
        new FeedOptions() {MaxItemCount = Math.Min(maxPageSize, take)}).AsDocumentQuery();

    var response = await query.ExecuteNextAsync<T>();
    queryCost += response.RequestCharge;
    var entities = response.ToList();

    while (entities.Count < take && query.HasMoreResults)
    {
        var nextResponse = await query.ExecuteNextAsync<T>();
        queryCost += nextResponse.RequestCharge;
        entities.AddRange(nextResponse);
    }

    Debug.WriteLine(
        "Query [{0}] for {1} documents in collection [{2}] cost {3} RUs.",
        sqlQuery.QueryText,
        take,
        collectionId,
        queryCost);

    return entities.Take(take).ToList(); // We may end up with more than the requested number of items.
}
like image 34
Mr. Bungle Avatar answered Nov 11 '22 14:11

Mr. Bungle