|
4 | 4 | import time
|
5 | 5 | import string
|
6 | 6 |
|
7 |
| -import jsonpickle |
| 7 | +import json |
8 | 8 |
|
9 | 9 | from ..utils.compat import annotation_value_types, string_types
|
| 10 | +from ..utils.conversion import metadata_to_dict |
10 | 11 | from .throwable import Throwable
|
11 | 12 | from . import http
|
12 | 13 | from ..exceptions.exceptions import AlreadyEndedException
|
@@ -256,36 +257,42 @@ def get_origin_trace_header(self):
|
256 | 257 | def serialize(self):
|
257 | 258 | """
|
258 | 259 | Serialize to JSON document that can be accepted by the
|
259 |
| - X-Ray backend service. It uses jsonpickle to perform |
260 |
| - serialization. |
| 260 | + X-Ray backend service. It uses json to perform serialization. |
261 | 261 | """
|
262 | 262 | try:
|
263 |
| - return jsonpickle.encode(self, unpicklable=False) |
| 263 | + return json.dumps(self.to_dict(), default=str) |
264 | 264 | except Exception:
|
265 |
| - log.exception("got an exception during serialization") |
| 265 | + log.exception("Failed to serialize %s", self.name) |
266 | 266 |
|
267 |
| - def _delete_empty_properties(self, properties): |
| 267 | + def to_dict(self): |
268 | 268 | """
|
269 |
| - Delete empty properties before serialization to avoid |
270 |
| - extra keys with empty values in the output json. |
| 269 | + Convert Entity(Segment/Subsegment) object to dict |
| 270 | + with required properties that have non-empty values. |
271 | 271 | """
|
272 |
| - if not self.parent_id: |
273 |
| - del properties['parent_id'] |
274 |
| - if not self.subsegments: |
275 |
| - del properties['subsegments'] |
276 |
| - if not self.aws: |
277 |
| - del properties['aws'] |
278 |
| - if not self.http: |
279 |
| - del properties['http'] |
280 |
| - if not self.cause: |
281 |
| - del properties['cause'] |
282 |
| - if not self.annotations: |
283 |
| - del properties['annotations'] |
284 |
| - if not self.metadata: |
285 |
| - del properties['metadata'] |
286 |
| - properties.pop(ORIGIN_TRACE_HEADER_ATTR_KEY, None) |
287 |
| - |
288 |
| - del properties['sampled'] |
| 272 | + entity_dict = {} |
| 273 | + |
| 274 | + for key, value in vars(self).items(): |
| 275 | + if isinstance(value, bool) or value: |
| 276 | + if key == 'subsegments': |
| 277 | + # child subsegments are stored as List |
| 278 | + subsegments = [] |
| 279 | + for subsegment in value: |
| 280 | + subsegments.append(subsegment.to_dict()) |
| 281 | + entity_dict[key] = subsegments |
| 282 | + elif key == 'cause': |
| 283 | + entity_dict[key] = {} |
| 284 | + entity_dict[key]['working_directory'] = self.cause['working_directory'] |
| 285 | + # exceptions are stored as List |
| 286 | + throwables = [] |
| 287 | + for throwable in value['exceptions']: |
| 288 | + throwables.append(throwable.to_dict()) |
| 289 | + entity_dict[key]['exceptions'] = throwables |
| 290 | + elif key == 'metadata': |
| 291 | + entity_dict[key] = metadata_to_dict(value) |
| 292 | + elif key != 'sampled' and key != ORIGIN_TRACE_HEADER_ATTR_KEY: |
| 293 | + entity_dict[key] = value |
| 294 | + |
| 295 | + return entity_dict |
289 | 296 |
|
290 | 297 | def _check_ended(self):
|
291 | 298 | if not self.in_progress:
|
|
0 commit comments