Skip to content

Commit

Permalink
Added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
oandreeva-nv committed Jun 22, 2023
1 parent b5e5de5 commit 9d3e278
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 31 deletions.
161 changes: 161 additions & 0 deletions qa/L0_trace/opentelemetry_unittest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# Copyright 2019-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of NVIDIA CORPORATION nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import sys

sys.path.append("../common")

import test_util as tu
import unittest
import json

class OpenTelemetryTest(tu.TestResultCollector):

def setUp(self):
with open('trace_collector.log', 'rt') as f:
data = f.read()

data = data.split('\n')
full_spans = [entry for entry in data if "resource_spans" in entry]
self.spans = []
for span in full_spans:
span = json.loads(span)
self.spans.append(
span["resource_spans"][0]['scope_spans'][0]['spans'][0])

self.model_name = "simple"
self.root_span = "InferRequest"

def _check_events(self, span_name, events):
root_events_http =\
["HTTP_RECV_START",
"HTTP_RECV_END",
"INFER_RESPONSE_COMPLETE",
"HTTP_SEND_START",
"HTTP_SEND_END"]
root_events_grpc =\
["GRPC_WAITREAD_START",
"GRPC_WAITREAD_END",
"INFER_RESPONSE_COMPLETE",
"GRPC_SEND_START",
"GRPC_SEND_END"]
request_events =\
["REQUEST_START",
"QUEUE_START",
"REQUEST_END"]
compute_events =\
["COMPUTE_START",
"COMPUTE_INPUT_END",
"COMPUTE_OUTPUT_START",
"COMPUTE_END"]

if span_name == "compute":
# Check that all compute related events (and only them)
# are recorded in compute span
self.assertTrue(all(entry in events for entry in compute_events))
self.assertFalse(all(entry in events for entry in request_events))
self.assertFalse(
all(entry in events
for entry in root_events_http + root_events_grpc))

elif span_name == self.root_span:
# Check that root span has INFER_RESPONSE_COMPLETE, _RECV/_WAITREAD
# and _SEND events (and only them)
if "HTTP" in events:
self.assertTrue(
all(entry in events for entry in root_events_http))
self.assertFalse(
all(entry in events for entry in root_events_grpc))

elif "GRPC" in events:
self.assertTrue(
all(entry in events for entry in root_events_grpc))
self.assertFalse(
all(entry in events for entry in root_events_http))
self.assertFalse(
all(entry in events for entry in request_events))
self.assertFalse(
all(entry in events for entry in compute_events))

elif span_name == self.model_name:
# Check that all request related events (and only them)
# are recorded in request span
self.assertTrue(all(entry in events for entry in request_events))
self.assertFalse(
all(entry in events
for entry in root_events_http + root_events_grpc))
self.assertFalse(all(entry in events for entry in compute_events))

def _check_parent(self, child_span, parent_span):
# Check that child and parent span have the same trace_id
# and child's `parent_span_id` is the same as parent's `span_id`
self.assertEqual(child_span['trace_id'], parent_span['trace_id'])
self.assertTrue('parent_span_id' in child_span)
self.assertEqual(child_span['parent_span_id'], parent_span['span_id'])

def test_spans(self):
parsed_spans = []

# Check that collected spans have proper events recorded
for span in self.spans:
span_name = span['name']
self._check_events(span_name, json.dumps(span['events']))
parsed_spans.append(span_name)

# There should be 6 spans in total:
# 3 for http request and 3 for grpc request.
self.assertTrue(len(self.spans) == 6)
# We should have 2 compute spans
self.assertTrue(parsed_spans.count("compute"), 2)
# 2 request spans (named simple - same as our model name)
self.assertTrue(parsed_spans.count(self.model_name), 2)
# 2 root spans
self.assertTrue(parsed_spans.count(self.root_span), 2)

def test_nested_spans(self):

# First 3 spans in `self.spans` belong to HTTP request
# They are recorded in the following order:
# compute_span [idx 0] , request_span [idx 1], root_span [idx 2].
# compute_span should be a child of request_span
# request_span should be a child of root_span
for child, parent in zip(self.spans[:3], self.spans[1:3]):
self._check_parent(child, parent)

# root_span should not have `parent_span_id` field
self.assertFalse('parent_span_id' in self.spans[2])

# Last 3 spans in `self.spans` belong to GRPC request
# Order of spans and their relationship described earlier
for child, parent in zip(self.spans[3:], self.spans[4:]):
self._check_parent(child, parent)

# root_span should not have `parent_span_id` field
self.assertFalse('parent_span_id' in self.spans[5])


if __name__ == '__main__':
unittest.main()
50 changes: 19 additions & 31 deletions qa/L0_trace/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -655,9 +655,15 @@ wait $SERVER_PID

# Check opentelemetry trace exporter sends proper info.
# A helper python script starts listenning on $OTLP_PORT, where
# OTLP exporter sends traces. It then check that received data contains
# expected entries
# OTLP exporter sends traces.
# Unittests then check that produced spans have expected format and events
# FIXME: Redesign this test to remove time sensitivity

OPENTELEMETRY_TEST=opentelemetry_unittest.py
OPENTELEMETRY_LOG="opentelemetry_unittest.log"
TEST_RESULT_FILE="opentelemetry_results.txt"
EXPECTED_NUM_TESTS="2"

SERVER_ARGS="--trace-config=triton,file=some_file.log --trace-config=level=TIMESTAMPS \
--trace-config=rate=1 --trace-config=count=6 --trace-config=mode=opentelemetry --trace-config=opentelemetry,url=localhost:$OTLP_PORT --model-repository=$MODELSDIR"
SERVER_LOG="./inference_server_trace_config.log"
Expand All @@ -674,7 +680,7 @@ COLLECTOR_PID=$!

set +e

# To make sure receiver is ready log gets all data
# To make sure receiver is ready
sleep 3

# Send http request and collect trace
Expand All @@ -696,38 +702,20 @@ sleep 3
kill $COLLECTOR_PID
wait $COLLECTOR_PID

EXPECTED_ENTRIES=${EXPECTED_ENTRIES:="REQUEST_START QUEUE_START INFER_RESPONSE_COMPLETE COMPUTE_START COMPUTE_INPUT_END COMPUTE_OUTPUT_START COMPUTE_END REQUEST_END"}
HTTP_ENTRIES=${HTTP_ENTRIES:="HTTP_RECV_START HTTP_RECV_END HTTP_SEND_START HTTP_SEND_END"}
GRPC_ENTRIES=${GRPC_ENTRIES:="GRPC_WAITREAD_START GRPC_WAITREAD_END GRPC_SEND_START GRPC_SEND_END"}

for ENTRY in $EXPECTED_ENTRIES; do
if [ `grep -c $ENTRY $TRACE_COLLECTOR_LOG` != "2" ]; then
RET=1
fi
done

for ENTRY in $HTTP_ENTRIES; do
if [ `grep -c $ENTRY $TRACE_COLLECTOR_LOG` != "1" ]; then
RET=1
fi
done

for ENTRY in $GRPC_ENTRIES; do
if [ `grep -c $ENTRY $TRACE_COLLECTOR_LOG` != "1" ]; then
RET=1
fi
done

#Check that we have 2 nested spans
set +e

if [ `grep -c 'parent_span_id' $TRACE_COLLECTOR_LOG` != "4" ]; then
python $OPENTELEMETRY_TEST >>$OPENTELEMETRY_LOG 2>&1
if [ $? -ne 0 ]; then
cat $OPENTELEMETRY_LOG
RET=1
fi

if [ $RET -eq 0 ]; then
echo -e "\n***\n*** Test Passed\n***"
else
echo -e "\n***\n*** Test FAILED\n***"
check_test_results $TEST_RESULT_FILE $EXPECTED_NUM_TESTS
if [ $? -ne 0 ]; then
cat $OPENTELEMETRY_LOG
echo -e "\n***\n*** Test Result Verification Failed\n***"
RET=1
fi
fi

set -e
Expand Down

0 comments on commit 9d3e278

Please sign in to comment.