diff --git a/README.md b/README.md index 7509bb417ec54cbddf9dfaabeb388523f2572bbd..af16be63b1b50893c67baed12f392e9672ca6474 100755 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ Environment Variable | Description | Default | `SW_MYSQL_SQL_PARAMETERS_MAX_LENGTH` | The maximum length of the collected parameter, parameters longer than the specified length will be truncated | `512` | | `SW_IGNORE_SUFFIX` | If the operation name of the first span is included in this set, this segment should be ignored. | `.jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg` | | `SW_FLASK_COLLECT_HTTP_PARAMS`| This config item controls that whether the Flask plugin should collect the parameters of the request.| `false` | +| `SW_DJANGO_COLLECT_HTTP_PARAMS`| This config item controls that whether the Django plugin should collect the parameters of the request.| `false` | | `SW_HTTP_PARAMS_LENGTH_THRESHOLD`| When `COLLECT_HTTP_PARAMS` is enabled, how many characters to keep and send to the OAP backend, use negative values to keep and send the complete parameters, NB. this config item is added for the sake of performance. | `1024` | diff --git a/skywalking/config/__init__.py b/skywalking/config/__init__.py index 919bd7fd46acd4971ada14973d2507c2909f1043..e6e09203ea256691f21628df5e612dfa42296f3c 100644 --- a/skywalking/config/__init__.py +++ b/skywalking/config/__init__.py @@ -34,6 +34,8 @@ ignore_suffix = os.getenv('SW_IGNORE_SUFFIX') or '.jpg,.jpeg,.js,.css,.png,.bmp, flask_collect_http_params = True if os.getenv('SW_FLASK_COLLECT_HTTP_PARAMS') and \ os.getenv('SW_FLASK_COLLECT_HTTP_PARAMS') == 'True' else False # type: bool http_params_length_threshold = int(os.getenv('SW_HTTP_PARAMS_LENGTH_THRESHOLD') or '1024') # type: int +django_collect_http_params = True if os.getenv('SW_DJANGO_COLLECT_HTTP_PARAMS') and \ + os.getenv('SW_DJANGO_COLLECT_HTTP_PARAMS') == 'True' else False # type: bool def init( diff --git a/skywalking/plugins/sw_django/__init__.py b/skywalking/plugins/sw_django/__init__.py index 042b16fb13372bbc2c37aba8501b55b15ae1b913..0b226217f1f8d70ec215fbcb6ae407f596642b71 100644 --- a/skywalking/plugins/sw_django/__init__.py +++ b/skywalking/plugins/sw_django/__init__.py @@ -16,7 +16,7 @@ # import logging -from skywalking import Layer, Component +from skywalking import Layer, Component, config from skywalking.trace import tags from skywalking.trace.carrier import Carrier from skywalking.trace.context import get_context @@ -50,7 +50,13 @@ def install(): span.peer = '%s:%s' % (request.META.get('REMOTE_ADDR'), request.META.get('REMOTE_PORT') or "80") span.tag(Tag(key=tags.HttpMethod, val=request.method)) - span.tag(Tag(key=tags.HttpUrl, val=request.build_absolute_uri())) + span.tag(Tag(key=tags.HttpUrl, val=request.build_absolute_uri().split("?")[0])) + + # you can get request parameters by `request.GET` even though client are using POST or other methods + if config.django_collect_http_params and request.GET: + span.tag(Tag(key=tags.HttpParams, + val=params_tostring(request.GET)[0:config.http_params_length_threshold])) + resp = _get_response(this, request) span.tag(Tag(key=tags.HttpStatus, val=resp.status_code)) if resp.status_code >= 400: @@ -70,3 +76,7 @@ def install(): exception.handle_uncaught_exception = _sw_handle_uncaught_exception except Exception: logger.warning('failed to install plugin %s', __name__) + + +def params_tostring(params): + return "\n".join([k + '=[' + ",".join(params.getlist(k)) + ']' for k, _ in params.items()]) diff --git a/tests/plugin/sw_django/expected.data.yml b/tests/plugin/sw_django/expected.data.yml index c946a3c58b18c9e3b94357f3aa7cb654f4d19d30..fafebed3089434f14075a712f1db1e26526f887a 100644 --- a/tests/plugin/sw_django/expected.data.yml +++ b/tests/plugin/sw_django/expected.data.yml @@ -26,6 +26,12 @@ segmentItems: parentSpanId: -1 spanId: 0 spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 7004 + spanType: Entry + peer: not null + skipAnalysis: false tags: - key: http.method value: POST @@ -42,12 +48,6 @@ segmentItems: parentServiceInstance: not null parentService: consumer traceId: not null - startTime: gt 0 - endTime: gt 0 - componentId: 7004 - spanType: Entry - peer: not null - skipAnalysis: false - serviceName: consumer segmentSize: 1 segments: @@ -58,6 +58,12 @@ segmentItems: parentSpanId: 0 spanId: 1 spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 7002 + spanType: Exit + peer: provider:9091 + skipAnalysis: false tags: - key: http.method value: POST @@ -65,27 +71,23 @@ segmentItems: value: http://provider:9091/users - key: status.code value: '200' - startTime: gt 0 - endTime: gt 0 - componentId: 7002 - spanType: Exit - peer: provider:9091 - skipAnalysis: false - operationName: /users operationId: 0 parentSpanId: -1 spanId: 0 spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 7004 + spanType: Entry + peer: not null + skipAnalysis: false tags: - key: http.method value: GET - key: url value: http://0.0.0.0:9090/users + - key: http.params + value: "test=[test1,test2]\ntest2=[test2]" - key: status.code value: '200' - startTime: gt 0 - endTime: gt 0 - componentId: 7004 - spanType: Entry - peer: not null - skipAnalysis: false \ No newline at end of file diff --git a/tests/plugin/sw_django/services/consumer.py b/tests/plugin/sw_django/services/consumer.py index 60c9328251df854f6c2d33d7d5b3009b8dec3bf3..194122c6df5694b1248a4f37190bfb7c09c0e814 100644 --- a/tests/plugin/sw_django/services/consumer.py +++ b/tests/plugin/sw_django/services/consumer.py @@ -27,6 +27,7 @@ from django.http import JsonResponse config.service_name = "consumer" config.logging_level = "DEBUG" +config.django_collect_http_params = True agent.start() diff --git a/tests/plugin/sw_django/test_django.py b/tests/plugin/sw_django/test_django.py index 81874514baed781225cd2ba97cf7b4089fabbef2..79827f58b1103e0b4dae20c7d9da8624314a1e21 100644 --- a/tests/plugin/sw_django/test_django.py +++ b/tests/plugin/sw_django/test_django.py @@ -30,7 +30,7 @@ class TestPlugin(BasePluginTest): cls.compose = DockerCompose(filepath=dirname(inspect.getfile(cls))) cls.compose.start() - cls.compose.wait_for(cls.url(('consumer', '9090'), 'users')) + cls.compose.wait_for(cls.url(('consumer', '9090'), 'users?test=test1&test=test2&test2=test2')) def test_plugin(self): time.sleep(3)