Skip to content

Commit

Permalink
chore(service_name): add service schema grpc (#5808)
Browse files Browse the repository at this point in the history
What's changing in this PR?
This PR introduces the initial changes for "(2) Standardizing all tracer
libraries to using the current application name as a default for
existing services (service naming)". The major changes in this revision
are:

Create a new concept, 'span attribute schema,' which controls the
service naming behavior and control it with a new environment variable
DD_TRACE_SPAN_ATTRIBUTE_SCHEMA.
Create 'v0' (existing behavior) and 'v1' (new behavior) schemas and
behaviors:
v0 (Default) - The existing behavior
v1 - Default integration service names are now set to the value of
$DD_SERVICE (config().service) instead of the prior default values

Specifically for the GRPC integration. Other PRs are being merged for
the other integrations.

## Checklist

- [x] Change(s) are motivated and described in the PR description.
- [x] Testing strategy is described if automated tests are not included
in the PR.
- [x] Risk is outlined (performance impact, potential for breakage,
maintainability, etc).
- [x] Change is maintainable (easy to change, telemetry, documentation).
- [x] [Library release note
guidelines](https://ddtrace.readthedocs.io/en/stable/contributing.html#Release-Note-Guidelines)
are followed.
- [x] Documentation is included (in-code, generated user docs, [public
corp docs](https://github.com/DataDog/documentation/)).
- [x] OPTIONAL: PR description includes explicit acknowledgement of the
performance implications of the change as reported in the benchmarks PR
comment.

## Reviewer Checklist

- [x] Title is accurate.
- [x] No unnecessary changes are introduced.
- [x] Description motivates each change.
- [x] Avoids breaking
[API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces)
changes unless absolutely necessary.
- [x] Testing strategy adequately addresses listed risk(s).
- [x] Change is maintainable (easy to change, telemetry, documentation).
- [x] Release note makes sense to a user of the library.
- [x] Reviewer has explicitly acknowledged and discussed the performance
implications of this PR as reported in the benchmarks PR comment.

---------

Co-authored-by: Zachary Groves <32471391+ZStriker19@users.noreply.github.com>
  • Loading branch information
divyatagauchan and ZStriker19 authored Jun 1, 2023
1 parent 9146377 commit bee95d6
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 61 deletions.
18 changes: 13 additions & 5 deletions ddtrace/contrib/grpc/patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from ddtrace import Pin
from ddtrace import config
from ddtrace.internal.schema import schematize_service_name
from ddtrace.vendor.wrapt import wrap_function_wrapper as _w

from . import constants
Expand Down Expand Up @@ -31,11 +32,18 @@
GRPC_AIO_PIN_MODULE_SERVER = None
GRPC_AIO_PIN_MODULE_CLIENT = None


config._add(
"grpc_server",
dict(
_default_service=constants.GRPC_SERVICE_SERVER,
_default_service=schematize_service_name(constants.GRPC_SERVICE_SERVER),
distributed_tracing_enabled=True,
),
)

config._add(
"grpc_client",
dict(
_default_service=schematize_service_name(constants.GRPC_SERVICE_CLIENT),
distributed_tracing_enabled=True,
),
)
Expand All @@ -46,7 +54,7 @@
config._add(
"grpc",
dict(
_default_service=constants.GRPC_SERVICE_CLIENT,
_default_service=schematize_service_name(constants.GRPC_SERVICE_CLIENT),
distributed_tracing_enabled=True,
),
)
Expand All @@ -56,15 +64,15 @@
config._add(
"grpc_aio_server",
dict(
_default_service=constants.GRPC_AIO_SERVICE_SERVER,
_default_service=schematize_service_name(constants.GRPC_AIO_SERVICE_SERVER),
distributed_tracing_enabled=True,
),
)

config._add(
"grpc_aio_client",
dict(
_default_service=constants.GRPC_AIO_SERVICE_CLIENT,
_default_service=schematize_service_name(constants.GRPC_AIO_SERVICE_CLIENT),
distributed_tracing_enabled=True,
),
)
Expand Down
144 changes: 88 additions & 56 deletions tests/contrib/grpc/test_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from ddtrace.contrib.grpc import patch
from ddtrace.contrib.grpc import unpatch
from ddtrace.contrib.grpc.patch import _unpatch_server
from ddtrace.internal.schema import DEFAULT_SPAN_SERVICE_NAME
from tests.utils import TracerTestCase
from tests.utils import snapshot

Expand All @@ -39,6 +40,93 @@ def setUp(self):
Pin.override(constants.GRPC_PIN_MODULE_CLIENT, tracer=self.tracer)
self._start_server()

@TracerTestCase.run_in_subprocess(env_overrides=dict(DD_SERVICE="mysvc", DD_TRACE_SPAN_ATTRIBUTE_SCHEMA="v1"))
def test_user_specified_service_v1(self):
with grpc.insecure_channel("localhost:%d" % (_GRPC_PORT)) as channel:
stub = HelloStub(channel)
stub.SayHello(HelloRequest(name="propogator"))

spans = self.get_spans_with_sync_and_assert(size=2)
client_span, server_span = spans
assert client_span.service == "mysvc"

@TracerTestCase.run_in_subprocess(env_overrides=dict(DD_SERVICE="mysvc", DD_TRACE_SPAN_ATTRIBUTE_SCHEMA="v0"))
def test_user_specified_service_v0(self):
from ddtrace import config

assert config.service == "mysvc"
with grpc.insecure_channel("localhost:%d" % (_GRPC_PORT)) as channel:
stub = HelloStub(channel)
stub.SayHello(HelloRequest(name="propogator"))

spans = self.get_spans_with_sync_and_assert(size=2)
client_span, server_span = spans
assert spans[0].service == "grpc-client"

@TracerTestCase.run_in_subprocess(env_overrides=dict(DD_TRACE_SPAN_ATTRIBUTE_SCHEMA="v1"))
def test_unspecified_service_v1(self):
with grpc.insecure_channel("localhost:%d" % (_GRPC_PORT)) as channel:
stub = HelloStub(channel)
stub.SayHello(HelloRequest(name="propogator"))

spans = self.get_spans_with_sync_and_assert(size=2)
client_span, server_span = spans
assert spans[0].service == DEFAULT_SPAN_SERVICE_NAME

@TracerTestCase.run_in_subprocess(env_overrides=dict(DD_TRACE_SPAN_ATTRIBUTE_SCHEMA="v0"))
def test_unspecified_service_v0(self):
with grpc.insecure_channel("localhost:%d" % (_GRPC_PORT)) as channel:
stub = HelloStub(channel)
stub.SayHello(HelloRequest(name="propogator"))

spans = self.get_spans_with_sync_and_assert(size=2)
client_span, server_span = spans
assert client_span.service == "grpc-client"

@TracerTestCase.run_in_subprocess(env_overrides=dict(DD_GRPC_SERVICE="mygrpc", DD_TRACE_SPAN_ATTRIBUTE_SCHEMA="v0"))
def test_client_service_name_config_env_override_v0(self):
with grpc.insecure_channel("localhost:%d" % (_GRPC_PORT)) as channel:
stub = HelloStub(channel)
stub.SayHello(HelloRequest(name="propogator"))

spans = self.get_spans_with_sync_and_assert(size=2)
client_span, server_span = spans
assert spans[0].service == "mygrpc"

@TracerTestCase.run_in_subprocess(env_overrides=dict(DD_GRPC_SERVICE="mygrpc", DD_TRACE_SPAN_ATTRIBUTE_SCHEMA="v1"))
def test_client_service_name_config_env_override_v1(self):
with grpc.insecure_channel("localhost:%d" % (_GRPC_PORT)) as channel:
stub = HelloStub(channel)
stub.SayHello(HelloRequest(name="propogator"))

spans = self.get_spans_with_sync_and_assert(size=2)
client_span, server_span = spans
assert client_span.service == "mygrpc"

@TracerTestCase.run_in_subprocess(
env_overrides=dict(DD_SERVICE="mysvc", DD_GRPC_SERVICE="mygrpc", DD_TRACE_SPAN_ATTRIBUTE_SCHEMA="v1")
)
def test_service_precedence_v1(self):
with grpc.insecure_channel("localhost:%d" % (_GRPC_PORT)) as channel:
stub = HelloStub(channel)
stub.SayHello(HelloRequest(name="propogator"))

spans = self.get_spans_with_sync_and_assert(size=2)
client_span, server_span = spans
assert client_span.service == "mygrpc"

@TracerTestCase.run_in_subprocess(
env_overrides=dict(DD_SERVICE="mysvc", DD_GRPC_SERVICE="mygrpc", DD_TRACE_SPAN_ATTRIBUTE_SCHEMA="v0")
)
def test_service_precedence_v0(self):
with grpc.insecure_channel("localhost:%d" % (_GRPC_PORT)) as channel:
stub = HelloStub(channel)
stub.SayHello(HelloRequest(name="propogator"))

spans = self.get_spans_with_sync_and_assert(size=2)
client_span, server_span = spans
assert client_span.service == "mygrpc"

def tearDown(self):
self._stop_server()
# Remove any remaining spans
Expand Down Expand Up @@ -513,62 +601,6 @@ def test_unknown_servicer(self):
rpc_error = exception_context.exception
assert grpc.StatusCode.UNIMPLEMENTED == rpc_error.code()

@TracerTestCase.run_in_subprocess(env_overrides=dict(DD_SERVICE="mysvc"))
def test_app_service_name(self):
"""
When a service name is specified by the user
It should be used for grpc server spans
It should be included in grpc client spans
"""
# Ensure that the service name was configured
from ddtrace import config

assert config.service == "mysvc"

channel1 = grpc.insecure_channel("localhost:%d" % (_GRPC_PORT))
stub1 = HelloStub(channel1)
stub1.SayHello(HelloRequest(name="test"))
channel1.close()

# DEV: make sure we have two spans before proceeding
spans = self.get_spans_with_sync_and_assert(size=2)

self._check_server_span(spans[1], "mysvc", "SayHello", "unary")
self._check_client_span(spans[0], "grpc-client", "SayHello", "unary")

@TracerTestCase.run_in_subprocess(env_overrides=dict(DD_SERVICE="mysvc"))
def test_service_name_config_override(self):
"""
When a service name is specified by the user in config.grpc{_server}
It should be used in grpc client spans
It should be used in grpc server spans
"""
with self.override_config("grpc", dict(service_name="myclientsvc")):
with self.override_config("grpc_server", dict(service_name="myserversvc")):
channel1 = grpc.insecure_channel("localhost:%d" % (_GRPC_PORT))
stub1 = HelloStub(channel1)
stub1.SayHello(HelloRequest(name="test"))
channel1.close()

spans = self.get_spans_with_sync_and_assert(size=2)

self._check_server_span(spans[1], "myserversvc", "SayHello", "unary")
self._check_client_span(spans[0], "myclientsvc", "SayHello", "unary")

@TracerTestCase.run_in_subprocess(env_overrides=dict(DD_GRPC_SERVICE="myclientsvc"))
def test_client_service_name_config_env_override(self):
"""
When a service name is specified by the user in the DD_GRPC_SERVICE env var
It should be used in grpc client spans
"""
channel1 = grpc.insecure_channel("localhost:%d" % (_GRPC_PORT))
stub1 = HelloStub(channel1)
stub1.SayHello(HelloRequest(name="test"))
channel1.close()

spans = self.get_spans_with_sync_and_assert(size=2)
self._check_client_span(spans[0], "myclientsvc", "SayHello", "unary")


class _HelloServicer(HelloServicer):
def SayHello(self, request, context):
Expand Down

0 comments on commit bee95d6

Please sign in to comment.