in ecs_logging/_utils.py [0:0]
def json_dumps(value: Dict[str, Any]) -> str:
# Ensure that the first three fields are '@timestamp',
# 'log.level', and 'message' per ECS spec
ordered_fields = []
try:
ordered_fields.append(("@timestamp", value.pop("@timestamp")))
except KeyError:
pass
# log.level can either be nested or not nested so we have to try both
try:
ordered_fields.append(("log.level", value["log"].pop("level")))
if not value["log"]: # Remove the 'log' dictionary if it's now empty
value.pop("log", None)
except KeyError:
try:
ordered_fields.append(("log.level", value.pop("log.level")))
except KeyError:
pass
try:
ordered_fields.append(("message", value.pop("message")))
except KeyError:
pass
json_dumps = functools.partial(
json.dumps, sort_keys=True, separators=(",", ":"), default=_json_dumps_fallback
)
# Because we want to use 'sorted_keys=True' we manually build
# the first three keys and then build the rest with json.dumps()
if ordered_fields:
# Need to call json.dumps() on values just in
# case the given values aren't strings (even though
# they should be according to the spec)
ordered_json = ",".join(f'"{k}":{json_dumps(v)}' for k, v in ordered_fields)
if value:
return "{{{},{}".format(
ordered_json,
json_dumps(value)[1:],
)
else:
return "{%s}" % ordered_json
# If there are no fields with ordering requirements we
# pass everything into json.dumps()
else:
return json_dumps(value)