-
Notifications
You must be signed in to change notification settings - Fork 156
Refactor for future span sending over http #176
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
# Copyright (c) 2018 Uber Technologies, Inc. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
from __future__ import absolute_import | ||
|
||
import logging | ||
from threadloop import ThreadLoop | ||
|
||
from .local_agent_net import LocalAgentSender | ||
from thrift.protocol import TCompactProtocol | ||
|
||
from jaeger_client.thrift_gen.agent import Agent | ||
|
||
|
||
DEFAULT_SAMPLING_PORT = 5778 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This default should probably be moved to |
||
|
||
logger = logging.getLogger('jaeger_tracing') | ||
|
||
|
||
class Sender(object): | ||
def __init__(self, host, port, io_loop=None): | ||
self.host = host | ||
self.port = port | ||
self.io_loop = io_loop or self._create_new_thread_loop() | ||
|
||
def send(self, batch): | ||
raise NotImplementedError('This method should be implemented by subclasses') | ||
|
||
def _create_new_thread_loop(self): | ||
""" | ||
Create a daemonized thread that will run Tornado IOLoop. | ||
:return: the IOLoop backed by the new thread. | ||
""" | ||
self._thread_loop = ThreadLoop() | ||
if not self._thread_loop.is_ready(): | ||
self._thread_loop.start() | ||
return self._thread_loop._io_loop | ||
|
||
|
||
class UDPSender(Sender): | ||
def __init__(self, host, port, io_loop=None): | ||
super(UDPSender, self).__init__( | ||
host=host, | ||
port=port, | ||
io_loop=io_loop | ||
) | ||
self.channel = self._create_local_agent_channel(self.io_loop) | ||
self.agent = Agent.Client(self.channel, self) | ||
|
||
def send(self, batch): | ||
""" Send batch of spans out via thrift transport. | ||
|
||
Any exceptions thrown will be caught by the caller. | ||
""" | ||
|
||
return self.agent.emitBatch(batch) | ||
|
||
def _create_local_agent_channel(self, io_loop): | ||
""" | ||
Create an out-of-process channel communicating to local jaeger-agent. | ||
Spans are submitted as SOCK_DGRAM Thrift, sampling strategy is polled | ||
via JSON HTTP. | ||
|
||
:param self: instance of Config | ||
""" | ||
logger.info('Initializing Jaeger Tracer with UDP reporter') | ||
return LocalAgentSender( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I said earlier here I would like to split responsibility between There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did all but this one. This will touch a lot of things (Sampler and Config), so it's probably better do it in a separate PR |
||
host=self.host, | ||
sampling_port=DEFAULT_SAMPLING_PORT, | ||
reporting_port=self.port, | ||
io_loop=io_loop | ||
) | ||
|
||
# method for protocol factory | ||
def getProtocol(self, transport): | ||
""" | ||
Implements Thrift ProtocolFactory interface | ||
:param: transport: | ||
:return: Thrift compact protocol | ||
""" | ||
return TCompactProtocol.TCompactProtocol(transport) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# Copyright (c) 2018 Uber Technologies, Inc. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
from __future__ import print_function | ||
|
||
|
||
import mock | ||
from tornado import ioloop | ||
|
||
from jaeger_client import senders | ||
from jaeger_client.local_agent_net import LocalAgentSender | ||
from jaeger_client.thrift_gen.agent import Agent | ||
from thrift.protocol import TCompactProtocol | ||
|
||
|
||
def test_base_sender_create_io_loop_if_not_provided(): | ||
|
||
sender = senders.Sender(host='mock', port=4242) | ||
|
||
assert sender.io_loop is not None | ||
assert isinstance(sender.io_loop, ioloop.IOLoop) | ||
|
||
def test_udp_sender_instantiate_thrift_agent(): | ||
|
||
sender = senders.UDPSender(host='mock', port=4242) | ||
|
||
assert sender.agent is not None | ||
assert isinstance(sender.agent, Agent.Client) | ||
|
||
|
||
def test_udp_sender_intantiate_local_agent_channel(): | ||
|
||
sender = senders.UDPSender(host='mock', port=4242) | ||
|
||
assert sender.channel is not None | ||
assert sender.channel.io_loop == sender.io_loop | ||
assert isinstance(sender.channel, LocalAgentSender) | ||
|
||
def test_udp_sender_calls_agent_emitBatch_on_sending(): | ||
|
||
test_data = {'foo': 'bar'} | ||
sender = senders.UDPSender(host='mock', port=4242) | ||
sender.agent = mock.Mock() | ||
|
||
sender.send(test_data) | ||
|
||
sender.agent.emitBatch.assert_called_once_with(test_data) | ||
|
||
|
||
def test_udp_sender_implements_thrift_protocol_factory(): | ||
|
||
sender = senders.UDPSender(host='mock', port=4242) | ||
|
||
assert callable(sender.getProtocol) | ||
protocol = sender.getProtocol(mock.MagicMock()) | ||
assert isinstance(protocol, TCompactProtocol.TCompactProtocol) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@black-adder renaming the field is a breaking change. Are you sure this can be merged?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doh reverting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's find a way to let this PR to get merged, but in backwards compatible way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did changes to make it backwards compatible. Should I open another PR?
edit: Still I don't like much the workaround I did. If you got better ideas I'm open