Docs » Overview of SignalFx Microservices APM » Service Maps

Service Maps 🔗

SignalFx Microservices APM (µAPM) automatically discovers your instrumented services and their interactions to present dynamic and real-time service maps of your application’s architecture. To get the most out of SignalFx’s service maps, especially when manually instrumenting your applications for tracing, it’s important to understand which data semantics SignalFx relies on to identify the dependencies between services and render your service maps.

Service names 🔗

The nodes in SignalFx’s service maps represent the logical services that make up your architecture, and their dependencies, by identifying the distinct service names that your trace spans represent. Service names should be unique within a process, and are typically set when configuring the application’s tracer or from the SIGNALFX_SERVICE_NAME environment variable. For more details on configuring an application’s service name, see the µAPM Instrumentation Guide for the relevant programming language.

A service is intended to represent a component of your distributed application’s architecture. For example, you may have an api web service, which queries a login service to authenticate users (itself querying a backend store like a database – a distinct service in this architecture), enqueues tasks onto a Kafka topic that are later processed by another task_worker service.

You may of course be running multiple instances of each service for high availability or redundancy purposes; the service name reported by those instances should nonetheless remain the same logical service name.

Service dependencies 🔗

SignalFx identifies service dependencies by looking for specific patterns in your trace spans that represent interactions between two services. There are two possible types of interactions: direct client-to-server interactions (typically RPCs or synchronous requests), and indirect producer-to-consumer interactions (through a pub-sub or queueing system).

In both cases, this information is primarily carried by the span’s kind. Depending on your instrumentation library, you may have methods to set a span kind directly, or you may need to rely on the span.kind metadata tag. The server-side or consumer-side span should also be a child of the client-side or producer-side span, creating direct client/server or producer/consumer pairs. The service name on either side of this interaction does not need to be different, as a service may be calling into itself (common in distributed systems for example where members of the cluster of a logical service interact with each other).

RPCs and direct interactions 🔗

RPCs are represented by a first span of kind client on the calling service and by a child span of kind server. For example a request from an instance of the api service to an instance of the login service would be represented by the following two spans:

[ api:check-user-auth (client)           ]
+--- [ login:authenticate (server) ]

Queues and pub-sub systems 🔗

Similarly, producer/consumer interactions over a pub-sub system are represented by a first span of kind producer on the service producing the message and by a child span of kind consumer on the service consuming and processing that message. For example, a message produced by an api service instance representing a task to execute by a task_worker instance would be captured by the following two spans:

[ api:generate-report (producer) ]
+--------------------------------- [ task_worker:process (consumer) ]

Note that this type of interaction is by nature asynchronous; the consumer span may execute after the producer span completes.

If you leverage an existing pub-sub client library and its instrumentation, your trace is likely to contain more detail as in the example below:

[ api:generate-report       ]
+- [ api:produce (producer) ]
   +----------------------------- [ task_worker:consume (consumer) ]
                                  +- [ task_worker:process         ]

Additionally, you can add the message_bus.destination to the producer and consumer spans to provide additional information about the name of the queue or topic the message was published on. This is done automatically in supported library instrumentations.