Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lightstep.hostname tag #98

Merged
merged 7 commits into from
Aug 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion lightstep/http_converter.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import socket
import sys

from lightstep.collector_pb2 import Auth, ReportRequest, Span, Reporter, KeyValue, Reference, SpanContext
from lightstep.converter import Converter
from . import util
from . import version as tracer_version
import sys
from google.protobuf.timestamp_pb2 import Timestamp


Expand All @@ -22,6 +24,7 @@ def create_runtime(self, component_name, tags, guid):
if tags is None:
tags = {}
tracer_tags = tags.copy()
tracer_tags['lightstep.hostname'] = tracer_tags.get('lightstep.hostname', socket.gethostname())

tracer_tags.update({
'lightstep.tracer_platform': 'python',
Expand Down
5 changes: 4 additions & 1 deletion lightstep/thrift_converter.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import socket
import sys

from lightstep import constants
from lightstep.converter import Converter
from .crouton import ttypes
import sys
from . import util
from . import version as tracer_version
import jsonpickle
Expand All @@ -22,6 +24,7 @@ def create_runtime(self, component_name, tags, guid):
if tags is None:
tags = {}
tracer_tags = tags.copy()
tracer_tags['lightstep.hostname'] = tracer_tags.get('lightstep.hostname', socket.gethostname())

tracer_tags.update({
'lightstep.tracer_platform': 'python',
Expand Down
249 changes: 135 additions & 114 deletions tests/recorder_test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import socket
import time
import unittest

Expand All @@ -15,6 +16,7 @@
class MockConnection(object):
"""MockConnection is used to debug and test Runtime.
"""

def __init__(self):
self.reports = []
self.ready = False
Expand All @@ -40,121 +42,140 @@ def clear(self):

@pytest.fixture(params=[True, False])
def recorder(request):
runtime_args = {'collector_encryption': 'none',
'collector_host': 'localhost',
'collector_port': 9998,
'access_token': '{your_access_token}',
'component_name': 'python/runtime_test',
'periodic_flush_seconds': 0,
'use_thrift': request.param,
'use_http': not request.param}
recorder = lightstep.recorder.Recorder(runtime_args)
yield recorder


# ------_
# HELPERS
# ------_
def check_spans(converter, report):
"""Checks spans' name.
"""
def setUp(self):
self.mock_connection = MockConnection()
self.mock_connection.open()
self.runtime_args = {'collector_encryption': 'none',
'collector_host': 'localhost',
'collector_port': 9998,
'access_token': '{your_access_token}',
'component_name': 'python/runtime_test',
'periodic_flush_seconds': 0}

def create_test_recorder(self):
"""Returns a LightStep Recorder based on self.runtime_args.
"""
return lightstep.recorder.Recorder(**self.runtime_args)

# -------------
# SHUTDOWN TESTS
# -------------
def test_send_spans_after_shutdown(self):
recorder = self.create_test_recorder()

# Send 10 spans
for i in range(10):
recorder.record_span(self.dummy_basic_span(recorder, i))
self.assertTrue(recorder.flush(self.mock_connection))

# Check 10 spans
self.check_spans(self.mock_connection.reports[0].span_records)

# Delete current logs and shutdown runtime
self.mock_connection.clear()
recorder.shutdown()

# Send 10 spans, though none should get through
for i in range(10):
recorder.record_span(self.dummy_basic_span(recorder, i))
self.assertFalse(recorder.flush(self.mock_connection))
self.assertEqual(len(self.mock_connection.reports), 0)

def test_shutdown_twice(self):
recorder = self.create_test_recorder()
runtime_args = {
"collector_encryption": "none",
"collector_host": "localhost",
"collector_port": 9998,
"access_token": "{your_access_token}",
"component_name": "python/runtime_test",
"periodic_flush_seconds": 0,
"use_thrift": request.param,
"use_http": not request.param,
}
yield lightstep.recorder.Recorder(**runtime_args)


def test_default_tags_set_correctly(recorder):
mock_connection = MockConnection()
mock_connection.open()
tags = getattr(recorder._runtime, "tags", None)
if tags is None:
tags = getattr(recorder._runtime, "attrs")
for tag in tags:
if hasattr(tag, "key"):
if tag.key == "lightstep.hostname":
assert tag.string_value == socket.gethostname()
elif tag.key == "lightstep.tracer_platform":
assert tag.string_value == "python"
else:
if tag.Key == "lightstep.hostname":
assert tag.Value == socket.gethostname()
elif tag.Key == "lightstep.tracer_platform":
assert tag.Value == "python"
assert len(tags) == 6
runtime_args = {
"collector_encryption": "none",
"collector_host": "localhost",
"collector_port": 9998,
"access_token": "{your_access_token}",
"component_name": "python/runtime_test",
"periodic_flush_seconds": 0,
"tags": {
"lightstep.hostname": "hostname",
},
}
new_recorder = lightstep.recorder.Recorder(**runtime_args)
for tag in new_recorder._runtime.tags:
if tag.key == "lightstep.hostname":
assert tag.string_value == "hostname"
assert len(new_recorder._runtime.tags) == 6


# --------------
# SHUTDOWN TESTS
# --------------
def test_send_spans_after_shutdown(recorder):
mock_connection = MockConnection()
mock_connection.open()
# Send 10 spans
for i in range(10):
dummy_basic_span(recorder, i)
assert recorder.flush(mock_connection)

# Check 10 spans
check_spans(recorder.converter, mock_connection.reports[0])

# Delete current logs and shutdown runtime
mock_connection.clear()
recorder.shutdown()

# Send 10 spans, though none should get through
for i in range(10):
recorder.record_span(dummy_basic_span(recorder, i))
assert not recorder.flush(mock_connection)
assert len(mock_connection.reports) == 0


def test_shutdown_twice(recorder):
try:
recorder.shutdown()
recorder.shutdown()
except Exception as error:
self.fail("Unexpected exception raised: {}".format(error))


# ------------
# STRESS TESTS
# ------------
def test_stress_logs(recorder):
mock_connection = MockConnection()
mock_connection.open()
for i in range(1000):
dummy_basic_span(recorder, i)
assert recorder.flush(mock_connection)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is recorder.flush(mock_connection) expected to return a boolean value?

assert recorder.converter.num_span_records(mock_connection.reports[0]) == 1000
check_spans(recorder.converter, mock_connection.reports[0])


def test_stress_spans(recorder):
mock_connection = MockConnection()
mock_connection.open()
for i in range(1000):
dummy_basic_span(recorder, i)
assert recorder.flush(mock_connection)
assert recorder.converter.num_span_records(mock_connection.reports[0]) == 1000
check_spans(recorder.converter, mock_connection.reports[0])


# -------------
# RUNTIME TESTS
# -------------
def test_buffer_limits(recorder):
mock_connection = MockConnection()
mock_connection.open()
recorder._max_span_records = 88

assert len(recorder._span_records) == 0
for i in range(0, 100):
dummy_basic_span(recorder, i)
assert len(recorder._span_records) == 88
assert recorder.flush(mock_connection)

# ------------
# STRESS TESTS
# ------------
def test_stress_logs(self):
recorder = self.create_test_recorder()
for i in range(1000):
recorder.record_span(self.dummy_basic_span(recorder, i))
self.assertTrue(recorder.flush(self.mock_connection))
self.assertEqual(len(self.mock_connection.reports[0].span_records), 1000)
self.check_spans(self.mock_connection.reports[0].span_records)

def test_stress_spans(self):
recorder = self.create_test_recorder()
for i in range(1000):
recorder.record_span(self.dummy_basic_span(recorder, i))
self.assertTrue(recorder.flush(self.mock_connection))
self.assertEqual(len(self.mock_connection.reports[0].span_records), 1000)
self.check_spans(self.mock_connection.reports[0].span_records)

# -------------
# RUNTIME TESTS
# -------------

def test_buffer_limits(self):
self.runtime_args.update({
'max_span_records': 88,
})
recorder = self.create_test_recorder()

self.assertEqual(len(recorder._span_records), 0)
for i in range(0, 10000):
recorder.record_span(self.dummy_basic_span(recorder, i))
self.assertEqual(len(recorder._span_records), 88)
self.assertTrue(recorder.flush(self.mock_connection))

# ------
# HELPER
# ------
def check_spans(self, spans):
"""Checks spans' name.
"""
for i, span in enumerate(spans):
self.assertEqual(span.span_name, str(i))

def dummy_basic_span(self, recorder, i):
return BasicSpan(
lightstep.tracer._LightstepTracer(False, recorder, None),
operation_name=str(i),
context=SpanContext(
trace_id=1000+i,
span_id=2000+i),
start_time=time.time())


if __name__ == '__main__':
unittest.main()
def check_spans(converter, report):
"""Checks spans' name.
"""
spans = converter.get_span_records(report)
for i, span in enumerate(spans):
assert converter.get_span_name(span) == str(i)


def dummy_basic_span(recorder, i):
span = BasicSpan(
lightstep.tracer._LightstepTracer(False, recorder, None),
operation_name=str(i),
context=SpanContext(trace_id=1000 + i, span_id=2000 + i),
start_time=time.time() - 100,
)
span.finish()
return span