Database and Cache
A database or a cache reports no traces of its own. The trace analysis names it after the address a client’s span
reports: the OpenTelemetry trace analysis by the peer a CLIENT span names, under OTLP_VIRTUAL_DATABASE, or
OTLP_VIRTUAL_CACHE for Redis, Valkey and memcached, see Topology; the native trace
analysis by an exit span’s peer, under VIRTUAL_DATABASE or VIRTUAL_CACHE. A server that clients reach at more
than one address shows as one node per address, and can be named as one cluster in server
clusters.
Naming a database or cache cluster
Only an address a span reports is renamed, so what to list follows from the agent.
The SkyWalking Java agent:
| Client | Reports | List |
|---|---|---|
| JDBC with one host, Jedis, Lettuce, Redisson with a single server, Neo4j | the node | every node, as members |
| JDBC with several hosts: MySQL, MariaDB, PostgreSQL, SQL Server, an Oracle address list | every host, joined by ,, with the default port added where the URL has none |
every host |
| JedisCluster 2.x and 3.x | every seed, each followed by ; |
every seed |
| Jedis 4.x cluster or sharded | every node, joined by , |
every node |
| Redisson cluster, replicated, or master and slaves | the configured nodes, joined by ;; in sentinel mode, the sentinels |
every node, or every sentinel |
| MongoDB | the servers it knows of, joined by ; |
every server |
| Elasticsearch | the nodes, joined by ,; the 5.x transport client, each followed by ; |
every node |
| Cassandra | the contact points, joined by , |
every contact point |
| spymemcached, xmemcached | the servers, joined by ; |
every server |
JedisCluster 2.x and 3.x and Redisson cut what they report to the agent’s plugin.peer_max_length
(SW_PLUGIN_PEER_MAX_LENGTH), 200 characters by default, and end it with .... A longer list, four nodes named
redis-0.redis-headless.prod.svc.cluster.local:6379 already, ends in part of an address and is not renamed; raise the
limit above the length of the whole list.
The OpenTelemetry agents:
| Client | Reports | List |
|---|---|---|
| Java agent: Jedis, Lettuce, Redisson, MongoDB, Cassandra, Spymemcached, Elasticsearch REST | the node it contacted | every node, as members |
| Java agent with its stable database conventions on | the configured hosts joined by ,, at most five: in the configured order, sorted for a Redis cluster and Cassandra, with a port only where one is not the default; a Redis sentinel target as s1,s2/mymaster |
every host, in each spelling it is reported in; a sentinel target whole, as an alias |
| Python DB-API drivers and SQLAlchemy; JavaScript pg, mysql, mysql2, ioredis and redis; .NET SqlClient | the host and port of the connection, as configured | that address, an alias when it names a Service |
| pymongo, asyncpg; JavaScript mongodb, cassandra-driver and memcached | the node it contacted | every node, as members |
A span that reports no address the trace analysis reads keeps its name: the OpenTelemetry Java agent’s Elasticsearch
transport and OpenSearch clients and Go’s otelmongo report the node only as network.peer.address, and .NET’s
Entity Framework Core only as peer.service.
Renaming a cluster only for its own system
The shipped rules call findServerClusterName(address) without a kind, and the native trace analysis does not use
kinds, so a client span of any database or cache system is renamed to the cluster that lists its address. A TAL rule
file of your own can rename a cluster only for the clients of its own system. Give each cluster, as kinds, the system
its clients report as db.system.name or db.system:
clusters:
- name: orders-db
kinds: [postgresql]
members:
- pg-0.pg.db.svc.cluster.local:5432
- pg-1.pg.db.svc.cluster.local:5432
- name: session-cache
kinds: [redis]
members:
- redis-0.redis.cache.svc.cluster.local:6379
- redis-1.redis.cache.svc.cluster.local:6379
Then copy config/tal/otlp-general.yaml to a file of your own, such as config/tal/otlp-custom.yaml, list that file
in talFiles in place of otlp-general, see Configuration, and pass the system
at each of its three calls:
// otlp-general, the consumer block: the broker a message came through
def cluster = findServerClusterName(broker, attr("messaging.system.name", "messaging.system"))
// otlp-general, the outbound block: the database, cache or broker a client or producer calls
def cluster = findServerClusterName(peer, attr("db.system.name", "db.system", "messaging.system.name", "messaging.system"))
// otlp-slow-sql: the database a slow statement is filed under; system is the span's db.system.name or db.system
def cluster = findServerClusterName(peer, system)
Change the three together. The outbound call names databases, caches and brokers alike, so a rule that passes a kind
there and not at the consumer, or not in otlp-slow-sql, names one server two ways. Each passes the system as the span
reports it, so the two sides of a call meet at the same cluster. Kinds are compared as written. A system the conventions
renamed needs both spellings when its clients report both, such as SQL Server’s kinds: [mssql, microsoft.sql_server].
A cluster that lists no kinds is still renamed for every system. The OAP reads the rule files at start, so restart it
after the change.