No1Lives4Ever
No1Lives4Ever

Reputation: 6883

Google Custom Metrics tracking of latency data

I'm using external service, based on REST calls, and I want to track the time that took the service to respond to my requests. My code is written with C# (core v2.2)

I planning to count times for all the HTTP requests (with Stopwatch) and keep this information in a List<long>. Every 60 seconds I will write the tracked information from the list to Google Custom Metrics.

In the end, I expect to see the AVERAGE time of execution in a graph.

This is my code so far:

public class CustomMetricsWritter
{
    public CustomMetricsWritter(string projectId)
    {
        this.Client = MetricServiceClient.Create();
        this.ProjectId = projectId;
    }

    private MetricServiceClient Client { get; set; }

    public string ProjectId { get; private set; }

    public object CreateMetric(string metricType, string title, string description, string unit)
    {
        // Prepare custom metric descriptor.      
        MetricDescriptor metricDescriptor = new MetricDescriptor();
        metricDescriptor.DisplayName = title;
        metricDescriptor.Description = description;
        metricDescriptor.MetricKind = MetricKind.Gauge;
        metricDescriptor.ValueType = MetricDescriptor.Types.ValueType.Double;
        metricDescriptor.Type = metricType;
        metricDescriptor.Unit = unit;

        CreateMetricDescriptorRequest request = new CreateMetricDescriptorRequest
        {
            ProjectName = new ProjectName(this.ProjectId),
        };
        request.MetricDescriptor = metricDescriptor;
        // Make the request.
        return Client.CreateMetricDescriptor(request);
    }

    public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    public async Task WriteTimeSeriesDataAsync(string metricDescriptor, TypedValue[] points, string machineName)
    {
        // Initialize request argument(s).
        ProjectName name = new ProjectName(this.ProjectId);
        // Prepare a data point. 

        Timestamp timeStamp = new Timestamp();
        timeStamp.Seconds = (long)(DateTime.UtcNow - UnixEpoch).TotalSeconds;
        TimeInterval interval = new TimeInterval();
        interval.EndTime = timeStamp;

        // Prepare monitored resource.
        MonitoredResource resource = new MonitoredResource();
        resource.Type = "global";
        resource.Labels.Add("project_id", this.ProjectId);

        // Add newly created time series to list of time series to be written.
        List<TimeSeries> timeSeries = new List<TimeSeries>(points.Length);

        // Prepare custom metric.
        Metric metric = new Metric();
        metric.Type = metricDescriptor;
        metric.Labels.Add("machine", machineName);

        // Create a new time series using inputs.
        TimeSeries timeSeriesData = new TimeSeries();
        timeSeriesData.Metric = metric;
        timeSeriesData.Resource = resource;
        foreach (var point in points)
        {
            Point dataPoint = new Point();
            dataPoint.Value = point;
            dataPoint.Interval = interval;
            timeSeriesData.Points.Add(dataPoint);
        }
        timeSeries.Add(timeSeriesData);

        // Write time series data.
        await this.Client.CreateTimeSeriesAsync(name, timeSeries).ConfigureAwait(false);
    }
}

I running this class with this code (create the metric and then fill it with dummy values):

try
{
    CustomMetricsWritter customMetricsWriter = new CustomMetricsWritter(Consts.GOOGLE_CLOUD_PROJECT);
    string metric = "custom.googleapis.com/web/latency";
    customMetricsWriter.CreateMetric(metric, "Execution Latency", "Calling REST service (MS).", "{INT64}");

    // Exception thrown in the next line ----->
    await customMetricsWriter.WriteTimeSeriesDataAsync(
        metric,
        new TypedValue[] {
        new TypedValue(){ Int64Value = 150},
        new TypedValue(){ Int64Value = 250},
        new TypedValue(){ Int64Value = 350},
        },
        "my-machine-type");
}
catch (Exception ex)
{
    Console.WriteLine(ex.ToString());
    throw;
}

I getting back this thrown exception:

Grpc.Core.RpcException: Status(StatusCode=InvalidArgument, Detail="One or more TimeSeries could not be written: Field timeSeries[0].points had an invalid value: Only one point can be written per TimeSeries per request.: timeSeries[0]")
   at Google.Api.Gax.Grpc.ApiCallRetryExtensions.<>c__DisplayClass0_0`2.<<WithRetry>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at ***.CustomMetricsWritter.WriteTimeSeriesDataAsync(String metricDescriptor, TypedValue[] points, String machineName) in ***\GoogleCloud\CustomMetricsWritter.cs:line 131
   at Test.Program.MainAsync() in ***\Test\Program.cs:line 156

What I'm doing wrong?

Upvotes: 0

Views: 361

Answers (1)

Related Questions