TechnologyNovember 6, 2019

A New Feature of the DataStax C# Drivers: Metrics

João Reis
João Reis
A New Feature of the DataStax C# Drivers: Metrics

On October 30, we published a new version for both DataStax C# drivers, version 3.12.0 of the DataStax C# Driver for Apache Cassandra™ and version 2.9.0 of the DataStax Enterprise C# Driver, that includes the latest metrics feature. This blog post will help you quickly get started with this new feature.

Getting Started

Metrics are disabled by default. To enable this feature, client applications need to provide a metrics provider implementation. DataStax offers an implementation based on App.Metrics, but you can also implement your own metrics provider and plug it in.

In this post, I’m going to show you how to run a simple console application that exports the driver metrics to Graphite using our extension based on App.Metrics and how to set up a Grafana dashboard that queries the driver metrics on Graphite. To set up Graphite and Grafana you will need Docker.

You will also need a running Cassandra-compatible cluster. I’m running a cluster locally so I’ll be using the 127.0.0.1 address as a contact point.

Launch Graphite Docker Container

Let’s start by launching a Graphite Docker container to which the driver will export metrics:

docker run -d --name graphite -p 80:80 -p 2003-2004:2003-2004 -p 2023-2024:2023-2024 -p 8125:8125/udp -p 8126:8126 graphiteapp/graphite-statsd

If you are already using port 80, then you need to change the port mapping on the previous command.

Create Project and Install the Required Packages

The snippets here use the .NET Core CLI; you can download the .NET Core SDK here.

First, let’s create a C# console application. The following command creates a project in the current directory so you might want to create a new directory before running this command:

dotnet new console

To get started with the DataStax C# driver for Cassandra in a C# project, install the driver package:

dotnet add package CassandraCSharpDriver -v 3.*

To use the DataStax metrics provider based on App.Metrics, install the extension package:

dotnet add package CassandraCSharpDriver.AppMetrics

The extension package depends on App.Metrics.Abstractions but not the App.Metrics core package, so you will need to install it in your application in order to use this library:

dotnet add package App.Metrics -v 3.2.0

In this example, we will export metrics to Graphite, so let’s install an App.Metrics extension package that integrates App.Metrics with Graphite:

dotnet add package App.Metrics.Reporting.Graphite -v 3.2.0

Configuring App.Metrics

Open Program.cs in your preferred editor and add the following snippet to the Main method:

var metrics = new MetricsBuilder()
    .Report.ToGraphite("net.tcp://127.0.0.1:2003")
    .Build();

The previous snippet configures an App.Metrics’ IMetricsRoot object with the Graphite reporter.

You also need to start the reporter. This can be done using a Task-based scheduler that App.Metrics provides like this:

var scheduler = new AppMetricsTaskScheduler(
           TimeSpan.FromMilliseconds(10000),
           async () => { await Task.WhenAll(metrics.ReportRunner.RunAllAsync()); });

scheduler.Start();

Note that in this example, the reporter is reporting metrics to Graphite every 10 seconds.

Creating a Metrics-Enabled Session

To create a driver session with the default metrics enabled, you can add the following snippet to the Main method in Program.cs:

var session = Cluster.Builder()            
            // cassandra running on localhost
            .AddContactPoint("127.0.0.1")
            .WithMetrics(metrics.CreateDriverMetricsProvider())
            .Build()
            .Connect();

And it’s done! You now have an application that is exporting the default driver metrics to Graphite. Just run the following to launch the application:

dotnet run

Note that in this example we haven’t included any code that executes requests. You can add something like this to generate some metrics data:

foreach (var i in Enumerable.Range(0, 20000))
{
    session.Execute("SELECT * FROM system.local");

Source Code of This Example

Here’s how the previous code snippets look when put together in a small console application:

using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

using App.Metrics;
using App.Metrics.Scheduling;

using Cassandra;
using Cassandra.Metrics;

namespace DataStaxDemoMetrics
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            //// App Metrics configuration

               // Build metrics root
               var metrics = new MetricsBuilder()
                         .Report.ToGraphite("net.tcp://127.0.0.1:2003")
                         .Build();

               // Build and run scheduler
            var scheduler = new AppMetricsTaskScheduler(
                 TimeSpan.FromMilliseconds(5000),
                 async () => { await Task.WhenAll(metrics.ReportRunner.RunAllAsync()); });

            scheduler.Start();
            //// DataStax C# Driver configuration

            var session = Cluster.Builder()
                   .AddContactPoint("127.0.0.1")
                    .WithMetrics(metrics.CreateDriverMetricsProvider())
                    .Build()
                   .Connect();
      
            //// Execute some requests
            foreach (var i in Enumerable.Range(0, 20000))
            {
                session.Execute("SELECT * FROM system.local");
            }
        }
    }
}

If you’re interested in a complete example project that you can leave running while you inspect the metrics that are being exported, head over to the section “Full example project on GitHub” toward the end of this post.

Configure Grafana Dashboard

If you want to inspect the driver metrics with Grafana, you can start by launching a Grafana Docker container:

docker run -d --name -p 3000:3000 grafana grafana/grafana

Open Grafana using the http://127.0.0.1:3000 URL on your favorite web browser. The default username and password are admin. Set up a Graphite datasource using the http://127.0.0.1:80 URL. You might need to select “Browser” access mode, depending on how you are running Docker. You also need to change the datasource port if you mapped another port to the container’s port 80 when you launched the Graphite Docker container.

When adding a query to your dashboard, you can use this as an example of a session metric:

gauge.*.connected-nodes

App.Metrics adds a prefix to the path related to the metric type. Here, * is a wild card for the session name, which you can customize while initializing the driver connection with the Builder (Builder.WithSessionName(string)). If you prefer, you can also use a * as the metric type prefix instead of specifying it since the driver metric names are unique.

Here is an example of a node metric:

gauge.*.nodes.*.pool.open-connections.Value

Here, the second * is a wild card for the node’s address.

I have uploaded an example dashboard to Grafana.com which you can use to test this feature. It uses Timer metrics which are not enabled by default in the driver. To enable all metrics you can do this:
           
var cluster = Cluster.Builder()
                     .AddContactPoint("127.0.0.1")
                     .WithMetrics(
                         metrics.CreateDriverMetricsProvider(),
                         new DriverMetricsOptions()
                            .SetEnabledNodeMetrics(NodeMetric.AllNodeMetrics)
                            .SetEnabledSessionMetrics(SessionMetric.AllSessionMetrics))
                     .Build();

Full Example Project on GitHub

You can find a small example project on the driver’s repository that contains the full source code of a small console application that exports metrics to Graphite while executing requests until the user presses ENTER. It is a useful application to leave running while analyzing the metrics on the Grafana dashboard, for example.

Here is a screenshot of the dashboard I’ve mentioned previously while running this example project:

<img alt="Dashboard Running Example Project" data-entity-type="file" data-entity-uuid="b4eee7da-b624-461c-8829-0dbd643cef8c" src="https://www.datastax.com/sites/default/files/inline-images/EINZh7tWkAENuwK.png" />

Acknowledgements

A special thanks to Sivukhin Nikita for kick-starting the discussion and developing a prototype in the initial development stages of this feature which helped us move forward and make this available to everyone in the community.

Wrapping Up

In this post, I showcased a way to use this metrics feature but you can use this feature in a variety of ways with a variety of technologies. You can even implement your own metrics provider instead of using our App.Metrics-based provider.

If you are interested in finding out more about this topic, you can go here to read more about metrics in the DataStax C# Driver for Apache Cassandra and here to read more about metrics in the DataStax Enterprise C# Driver.

Discover more
DriversC# / .NET
Share

One-stop Data API for Production GenAI

Astra DB gives JavaScript developers a complete data API and out-of-the-box integrations that make it easier to build production RAG apps with high relevancy and low latency.