0

I'm attempting to use Google's .Net client library (Analytics v3) to get data using my GA service account. Everything is working fine, except I am receiving occasional timeouts during the requests to the GA API (using the client library). I would like to adjust the timeout logic (and add retry logic through the library, if possible - but this is a smaller concern).

Currently I cannot figure out how to modify the timeout settings through the client library. From reading their source code (as I cannot find anything resembling useful documentation on the .net side of the house), it is looking like I'll need to implement "IConfigurableHttpClientInitializer". Below is an example of what I was thinking of, but I'm not sure if it is correct or how to integrate it with my existing code. An extract of my relevant code is also below.

Class to set timeout

public class TimeoutInitializer : IConfigurableHttpClientInitializer
{
    public void Initialize(ConfigurableHttpClient httpClient)
    {
        httpClient.Timeout = TimeSpan.FromMinutes(3);
    }
}

Existing Code

private async Task<GaData> GetAnalyticsData(string profileId, DateTime begin, DateTime end, string metrics, string dimensions)
    {
        GoogleCredential credential = AnalyticsHelper.GetCredentials(options.GoogleAnalyticsOptions);

        var service = new AnalyticsService(new BaseClientService.Initializer() { HttpClientInitializer = credential });
        DataResource.GaResource.GetRequest request = service.Data.Ga.Get($"ga:{profileId}", AnalyticsHelper.FormatDate(begin), AnalyticsHelper.FormatDate(end), metrics);
        if (!string.IsNullOrEmpty(dimensions))
        {
            request.Dimensions = dimensions;
        }

        return await request.ExecuteAsync();
    }

public class AnalyticsHelper
{
    public static GoogleCredential GetCredentials(AnalyticsOptions options)
    {
        using (Stream stream = new FileStream(options.ServiceAccountKeyPath, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            return GoogleCredential.FromStream(stream).CreateScoped(AnalyticsService.Scope.AnalyticsReadonly);
        }
    }
}

I am thinking that

var service = new AnalyticsService(new BaseClientService.Initializer() { HttpClientInitializer = credential });

would be replaced with something like

var service = new AnalyticsService(new BaseClientService.Initializer() { HttpClientInitializer = new TimeoutInitializer() });

However, I'm not positive and am unsure of how to combine the original credential logic with it. I considered creating a new class which implements GoogleCredential, but I feel there has to be a better way.

Any pointers would be greatly appreciated. I couldn't find any other posts related to this same problem. I'm going to continue to read through the source and attempt to decipher the correct approach for this, and will update this post if I find a solution.

1 Answer 1

7

After creating the service as normal with the credential as the initializer:

var service = new AnalyticsService(new BaseClientService.Initializer()
{
    HttpClientInitializer = credential
});

Then access the HttpClient directly and set the timeout:

service.HttpClient.Timeout = TimeSpan.FromMinutes(3);
Sign up to request clarification or add additional context in comments.

1 Comment

Wow, talk about a prime example of over complicating a simple process. I'm not sure how I missed that I could directly access the HttpClient...I guess I was thrown off by the comment on IConfigurableHttpClientInitializer "Use this initializer to change default values like timeout" and ran down the wrong rabbit hole. Thank you, Chris!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.