|
5 | 5 | from typing import List |
6 | 6 |
|
7 | 7 | from aiohttp.web import Request |
| 8 | +from jsonschema import ValidationError |
| 9 | +from jsonschema import validate |
8 | 10 | from multidict import CIMultiDictProxy |
| 11 | +import requests |
9 | 12 |
|
10 | 13 | from .checks import Check |
11 | 14 | from .trace import Span |
@@ -221,3 +224,36 @@ def check(self, trace: List[Span], dd_config_env: Dict[str, str]) -> None: |
221 | 224 | else: |
222 | 225 | log.debug(f"Successfully completed ``service`` name Span Check for Span: {span['name']}") |
223 | 226 | return |
| 227 | + |
| 228 | + |
| 229 | +SCHEMA_URL = "https://raw.githubusercontent.com/DataDog/schema/main/semantic-core/v1/schema.json" |
| 230 | + |
| 231 | + |
| 232 | +class CheckTraceSemantics(Check): |
| 233 | + name = "trace_semantics" |
| 234 | + description = """ |
| 235 | +The trace should follow semantic conventions defined by semantic-core. |
| 236 | +More info here: https://github.com/datadog/semantic-core. |
| 237 | +""".strip() |
| 238 | + schema = None |
| 239 | + |
| 240 | + def __init__(self): |
| 241 | + log.debug("Initializing CheckTraceSemantics") |
| 242 | + |
| 243 | + resp = requests.get(SCHEMA_URL) |
| 244 | + if resp.status_code != 200: |
| 245 | + log.fatal(f"Failed to download trace semantics schema: {resp}") |
| 246 | + |
| 247 | + log.debug("Successfully downloaded semantic-core JSON Schema") |
| 248 | + |
| 249 | + self.schema = resp.json() |
| 250 | + super().__init__() |
| 251 | + |
| 252 | + def check(self, span: Span) -> None: |
| 253 | + log.info("Performing ``Trace Semantics`` Span Check") |
| 254 | + |
| 255 | + try: |
| 256 | + validate(instance=span, schema=self.schema) |
| 257 | + log.debug(f"Span Check ``trace_semantics`` succeeded for Span {span['name']}") |
| 258 | + except ValidationError as err: |
| 259 | + self.fail(json.dumps(span, indent=4) + f"\nSpan '{span['name']}' failed semantic validation: {err}.") |
0 commit comments