18
18
from opentelemetry .instrumentation .celery import CeleryInstrumentor
19
19
from opentelemetry .semconv .trace import SpanAttributes
20
20
from opentelemetry .test .test_base import TestBase
21
- from opentelemetry .trace import SpanKind
21
+ from opentelemetry .trace import SpanKind , StatusCode
22
22
23
- from .celery_test_tasks import app , task_add
23
+ from .celery_test_tasks import app , task_add , task_raises
24
24
25
25
26
26
class TestCeleryInstrumentation (TestBase ):
@@ -66,6 +66,10 @@ def test_task(self):
66
66
},
67
67
)
68
68
69
+ self .assertEqual (consumer .status .status_code , StatusCode .UNSET )
70
+
71
+ self .assertEqual (0 , len (span .events ))
72
+
69
73
self .assertEqual (
70
74
producer .name , "apply_async/tests.celery_test_tasks.task_add"
71
75
)
@@ -84,6 +88,68 @@ def test_task(self):
84
88
self .assertEqual (consumer .parent .span_id , producer .context .span_id )
85
89
self .assertEqual (consumer .context .trace_id , producer .context .trace_id )
86
90
91
+ def test_task_raises (self ):
92
+ CeleryInstrumentor ().instrument ()
93
+
94
+ result = task_raises .delay ()
95
+
96
+ timeout = time .time () + 60 * 1 # 1 minutes from now
97
+ while not result .ready ():
98
+ if time .time () > timeout :
99
+ break
100
+ time .sleep (0.05 )
101
+
102
+ spans = self .sorted_spans (self .memory_exporter .get_finished_spans ())
103
+ self .assertEqual (len (spans ), 2 )
104
+
105
+ consumer , producer = spans
106
+
107
+ self .assertEqual (consumer .name , "run/tests.celery_test_tasks.task_raises" )
108
+ self .assertEqual (consumer .kind , SpanKind .CONSUMER )
109
+ self .assertSpanHasAttributes (
110
+ consumer ,
111
+ {
112
+ "celery.action" : "run" ,
113
+ "celery.state" : "FAILURE" ,
114
+ SpanAttributes .MESSAGING_DESTINATION : "celery" ,
115
+ "celery.task_name" : "tests.celery_test_tasks.task_raises" ,
116
+ },
117
+ )
118
+
119
+ self .assertEqual (consumer .status .status_code , StatusCode .ERROR )
120
+
121
+ self .assertEqual (1 , len (span .events ))
122
+ event = span .events [0 ]
123
+
124
+ self .assertIn (SpanAttributes .EXCEPTION_STACKTRACE , event .attributes )
125
+ self .assertEqual (
126
+ event .attributes [SpanAttributes .EXCEPTION_TYPE ],
127
+ "CustomError"
128
+ )
129
+
130
+ self .assertEqual (
131
+ event .attributes [SpanAttributes .EXCEPTION_TYPE ],
132
+ "The task failed!"
133
+ )
134
+
135
+ self .assertEqual (
136
+ producer .name , "apply_async/tests.celery_test_tasks.task_raises"
137
+ )
138
+ self .assertEqual (producer .kind , SpanKind .PRODUCER )
139
+ self .assertSpanHasAttributes (
140
+ producer ,
141
+ {
142
+ "celery.action" : "apply_async" ,
143
+ "celery.task_name" : "tests.celery_test_tasks.task_raises" ,
144
+ SpanAttributes .MESSAGING_DESTINATION_KIND : "queue" ,
145
+ SpanAttributes .MESSAGING_DESTINATION : "celery" ,
146
+ },
147
+ )
148
+
149
+ self .assertNotEqual (consumer .parent , producer .context )
150
+ self .assertEqual (consumer .parent .span_id , producer .context .span_id )
151
+ self .assertEqual (consumer .context .trace_id , producer .context .trace_id )
152
+
87
153
def test_uninstrument (self ):
88
154
CeleryInstrumentor ().instrument ()
89
155
CeleryInstrumentor ().uninstrument ()
0 commit comments