When planning to build a distributed application, developers often find a lot to think about beyond the application’s business logic. For instance, how to ensure multiple microservices communicate with each other, integrate with external systems, and, if the microservices are stateful, how to save their state in a resilient way that allows them to recover from potential failures.

There are, of course, multiple patterns that address these issues and both open source or cloud-provider-specific technologies that help you implement them. Examples of intra-service communication methods include service-to-service invocation via HTTP or gRPC and pub/sub using message brokers such as Kafka or RabbitMQ. State stores are a good way to keep the state of an app decoupled, and common ones include in-memory stores such as Redis and databases such as MongoDB. Add to that securing connection strings and certificates in secret stores such as HashiCorp Vault and the specifics of cloud provider services that offer similar solutions on Azure, AWS, and GCP, and it is clear that there is a lot to do even before you get to the specific logic of what you are trying to build.

On top of having to choose, ramp up, and integrate various SDKs into the code, you also need to keep in mind that your application may need to be deployed to different environments (e.g., local dev box, on-prem, multi-cloud), so you may need to replace some of these solutions on deployment, depending on the hosting infrastructure.

Last and arguably most important, you and your development team need to build these distributed applications securely (e.g., encrypt communication, implement access control) and instrument them so they can be observed. Here, specific cloud infrastructure details add to the complexity.

What is Dapr?

The Distributed Application Runtime (Dapr) open source project aims to help developers solve the challenges that come with building distributed applications. Dapr defines a set of building blocks that map to specific capabilities, such as service-to-service method invocation, state management, secret stores, and pub/sub messaging. These building blocks offer APIs that abstract the specific implementations (called components) and save you the need to add SDKs and/or libraries to your code, or even know the specifics of the technology implementing the capability. The Dapr runtime uses the sidecar pattern and runs as a separate process, so it is language agnostic and lets your app make all API calls via HTTP or gRPC (although specific language SDKs are available).

With the release of Dapr v1.0, Dapr is now production-ready, and several large and small companies are already using it to build business-critical applications. You can try Dapr yourself with this getting started guide.

 

Some of the benefits of using Dapr in a distributed application include:

  • Simpler code: You no longer need to integrate various SDKs or interact with the component directly in a custom way (to create a client, manage a connection, etc.), nor do you need to account for cases where a different implementation is used if the same code is deployed elsewhere.
  • Language agnostic: The Dapr API uses HTTP / gRPC, so an application written in any language can use it with no dependency. Dapr does offer SDKs for .NET, Java, Go, Python, Javascript, and more if you wish to use them.
  • High portability: There is no dependency in the code on the underlying hosting technology. When you switch cloud providers or move to environments that may use different state stores, secret stores, message brokers, or bindings, you don’t need to change the code, only the component files that configure Dapr.
  • Security: Dapr offers secured communication between sidecars via mTLS authentication and includes namespaces and scopes to allow access control for secrets, service invocation, and pub/sub subscription topics.
  • Observability: The Dapr sidecar can be configured to send tracing data, so just by using Dapr, you’re already instrumenting your application.

Screenshot of Dapr distributed application runtime

How does Dapr observability work?

Many Dapr users find the observability capabilities it provides to be a real game-changer. Using the Dapr API for all of your service-to-service calls and pub/sub messaging, you get automatic application-aware instrumentation. The Dapr sidecar takes care of tracing based on a configuration file, so instrumentation doesn’t require any additional code. Because Dapr conforms to standards such as W3C trace context and OpenTelemetry and uses the Zipkin protocol to emit tracing, it can integrate with any tooling that supports it. Alternatively, you can use the OpenTelemetry Collector to integrate it with any other monitoring tools.

With its W3C trace context compatibility, Dapr gives you flexibility in trace context management; you can let Dapr generate and propagate the trace context automatically or do either generation or propagation yourself. This allows you to use a trace context that was generated outside your application or propagate it in additional custom flows.

Configuring Dapr for tracing

Dapr configuration is defined using YAML configuration files that set the tracing sample rate (Dapr uses probabilistic sampling) and endpoint URL for tracing collection:

apiVersion: dapr.io/v1alpha1

kind: Configuration

metadata:

  name: myconfig

  namespace: default

spec:

  tracing:

     samplingRate: "1"

     zipkin:

     endpointAddress: "http://..."

When you deploy a Dapr application, it will use the above configuration. For example, on a Kubernetes deployment, the Dapr annotation dapr.io/config defines the configuration to be associated with the application (learn more about deploying Dapr applications to Kubernetes).

Using Dapr with New Relic One

Because New Relic One supports Zipkin, you can use it as an endpoint for tracing in a Dapr application with no need to add anything in the code. This makes it extremely easy to use New Relic One as a backend for tracing and take full advantage of trace visualization, insights, and more.

All you need to do is set the endpoint in the configuration file to point to the New Relic Tracing API:

apiVersion: dapr.io/v1alpha1

kind: Configuration

metadata:

  name: appconfig

  namespace: default

spec:

  tracing:

     samplingRate: "1"

     zipkin:

     endpointAddress: "https://trace-api.newrelic.com/trace/v1?Api-Key=<NR-INSIGHTS-INSERT-API-KEY>&Data-Format=zipkin&Data-Format-Version=2"

Note that you’ll need to include your API key here. Additionally, the URL includes an argument that defines the data format to Zipkin (since that is the protocol Dapr will be using).

distributed tracing screenshot

Next steps

Sign up for New Relic’s free tier and explore how to configure it to work with Dapr.