It is generally important for a user to be able to specify a peer service name for each client they use in an app. For example (this example will apply to many different databases), a user may access two caches with Redis, CatCache and DogCache. In Redis, it is not uncommon for an endpoint to be defined as an IP address. This means that spans will have net.peer.ip set to this IP address and no identifying information at all otherwise - this makes traces far less readable, especially since Redis itself will not have server spans showing up and the client spans must have as much utility as possible.
With manual instrumentation, users would generally set CatCache, DogCache as service names when registering each client with a tracer. But with auto instrumentation, we can't expect user apps to do this. A way to work around this would be for us to have a configuration, which is a mapping from endpoint -> service name. The endpoint could be matched against net.peer.name and net.peer.ip, and for any span that matches, we populate peer.service, a new convention which I'm pretty sure will be approved since this use case is too important, with the name in the config.
Some points to ponder
- Will be the first configuration option of
Map type. Format? Maybe
PEER_ENDPOINT_NAME_MAPPING=1.2.3.4=CatCache,dogs.com=DogCache
peer.endpoint.name.mapping=1.2.3.4=CatCache,dogs.com=DogCache (though I think there's some convention to use [key] for a map in properties, but I'd probably stick with the simpler
peer.endpoint.name.mapping:
1.2.3.4: CatCache
2.3.4.5: DogCache
-
For sharded, config has to have every endpoint mapped to the same name. Can't think of a way to avoid this though with auto instrumentation.
-
Endpoint groups are often dynamically updatable, but this configuration isn't. Probably have to give up on this point
For the harder cases where sharding is involved, we could additionally provide an entrypoint for a user app to use, it removes the "total auto instrumentation" but maybe is still an ok compromise.
@Bean
public AsyncCommands catsCache() {
try (SafeCloseable unused = AutoOpenTelemetry.withPeerService("CatCache")) {
// Or something dynamic like RedisClient.create(ZookeeperEndpointGroup.of("cat-cache")), it doesn't matter
return RedisClient.create("redis://1.2.3.4").sync();
}
}
@Bean
public AsyncCommands dogsCache() {
try (SafeCloseable unused = AutoOpenTelemetry.withPeerService("DogCache")) {
return RedisClient.create("redis://2.3.4.5").sync();
}
}
Let me know any thoughts. After thinking about the sharded case, I'm starting to lean towards not bothering with a static config since it seems like it could miss a lot of use cases. If it was trivial, yeah, but there will be infrastructure for supporting a map configuration.
It is generally important for a user to be able to specify a peer service name for each client they use in an app. For example (this example will apply to many different databases), a user may access two caches with Redis,
CatCacheandDogCache. In Redis, it is not uncommon for an endpoint to be defined as an IP address. This means that spans will havenet.peer.ipset to this IP address and no identifying information at all otherwise - this makes traces far less readable, especially since Redis itself will not have server spans showing up and the client spans must have as much utility as possible.With manual instrumentation, users would generally set
CatCache,DogCacheas service names when registering each client with a tracer. But with auto instrumentation, we can't expect user apps to do this. A way to work around this would be for us to have a configuration, which is a mapping from endpoint -> service name. The endpoint could be matched againstnet.peer.nameandnet.peer.ip, and for any span that matches, we populatepeer.service, a new convention which I'm pretty sure will be approved since this use case is too important, with the name in the config.Some points to ponder
Maptype. Format? MaybePEER_ENDPOINT_NAME_MAPPING=1.2.3.4=CatCache,dogs.com=DogCachepeer.endpoint.name.mapping=1.2.3.4=CatCache,dogs.com=DogCache(though I think there's some convention to use[key]for a map in properties, but I'd probably stick with the simplerFor sharded, config has to have every endpoint mapped to the same name. Can't think of a way to avoid this though with auto instrumentation.
Endpoint groups are often dynamically updatable, but this configuration isn't. Probably have to give up on this point
For the harder cases where sharding is involved, we could additionally provide an entrypoint for a user app to use, it removes the "total auto instrumentation" but maybe is still an ok compromise.
Let me know any thoughts. After thinking about the sharded case, I'm starting to lean towards not bothering with a static config since it seems like it could miss a lot of use cases. If it was trivial, yeah, but there will be infrastructure for supporting a map configuration.