From 0f2a1d3a375ee288af3cac9b812b14b15a466b71 Mon Sep 17 00:00:00 2001 From: YANGDB Date: Fri, 7 Apr 2023 01:07:46 -0700 Subject: [PATCH] Add queries & query templates for serviceMap integration add jaeger data provider to the existing data-prepper update integration.schema to reflect mapping fields for specific templates Signed-off-by: YANGDB --- docs/Integration-API.md | 8 +- docs/Integration-structure.md | 6 +- docs/schema/system/samples/integration.json | 69 +- integrations/nginx/config.json | 8 +- .../assets/mapping/jaeger-services.mapping | 38 + .../assets/mapping/jaeger-traces.mapping | 239 ++++++ .../getTraceGroupPercentilesQuery.json | 137 ++++ .../assets/scripts/getPayloadQuery.json | 25 + .../scripts/getServiceBreakdownQuery.json | 53 ++ .../assets/scripts/getSpanDetailQuery.json | 49 ++ .../assets/scripts/getSpanFlyoutQuery.json | 25 + .../assets/scripts/getSpansQuery.json | 23 + .../assets/scripts/getTracesQuery.json | 68 ++ .../assets/scripts/getValidTraceIdsQuery.json | 33 + integrations/service-map/config.json | 87 +- .../{ => providers/data-prepper}/README.md | 11 +- .../data-prepper}/dataPrepper.svg | 0 .../info/providers/jaeger/README.md | 121 +++ .../info/providers/jaeger/jaeger-logo.png | Bin 0 -> 46281 bytes .../service-map/samples/preloaded/README.md | 16 +- ...ces.json => data_prepper_bulk_traces.json} | 0 .../samples/preloaded/jaeger_bulk_traces.json | 758 ++++++++++++++++++ .../schema/system/integration.schema | 26 +- 23 files changed, 1720 insertions(+), 80 deletions(-) create mode 100644 integrations/service-map/assets/mapping/jaeger-services.mapping create mode 100644 integrations/service-map/assets/mapping/jaeger-traces.mapping create mode 100644 integrations/service-map/assets/queries/getTraceGroupPercentilesQuery.json create mode 100644 integrations/service-map/assets/scripts/getPayloadQuery.json create mode 100644 integrations/service-map/assets/scripts/getServiceBreakdownQuery.json create mode 100644 integrations/service-map/assets/scripts/getSpanDetailQuery.json create mode 100644 integrations/service-map/assets/scripts/getSpanFlyoutQuery.json create mode 100644 integrations/service-map/assets/scripts/getSpansQuery.json create mode 100644 integrations/service-map/assets/scripts/getTracesQuery.json create mode 100644 integrations/service-map/assets/scripts/getValidTraceIdsQuery.json rename integrations/service-map/info/{ => providers/data-prepper}/README.md (95%) rename integrations/service-map/info/{ => providers/data-prepper}/dataPrepper.svg (100%) create mode 100644 integrations/service-map/info/providers/jaeger/README.md create mode 100644 integrations/service-map/info/providers/jaeger/jaeger-logo.png rename integrations/service-map/samples/preloaded/{bulk_traces.json => data_prepper_bulk_traces.json} (100%) create mode 100644 integrations/service-map/samples/preloaded/jaeger_bulk_traces.json diff --git a/docs/Integration-API.md b/docs/Integration-API.md index 89bedf85d..d5121f6ca 100644 --- a/docs/Integration-API.md +++ b/docs/Integration-API.md @@ -25,9 +25,9 @@ GET _integration/repository?filter=category:logs&component:web **Response**: ```jsoon { - "name": "nginx", + "template-name": "nginx", "version": { - "integ": "0.1.0", + "integration": "0.1.0", "schema": "1.0.0", "resource": "^1.23.0" }, @@ -143,7 +143,7 @@ each representing different domain / aspect such as geographic. { "template-name": "nginx", "version": { - "integ": "0.1.0", + "integration": "0.1.0", "schema": "1.0.0", "resource": "^1.23.0" }, @@ -181,7 +181,7 @@ each representing different domain / aspect such as geographic. }] } ], - "repo": { + "repository": { "github": "https://github.com/opensearch-project/observability/tree/main/integrarions/nginx" } } diff --git a/docs/Integration-structure.md b/docs/Integration-structure.md index 949eeb043..f16475c70 100644 --- a/docs/Integration-structure.md +++ b/docs/Integration-structure.md @@ -115,7 +115,7 @@ nginX { "template_name": "nginx", "version": { - "integ": "0.1.0", + "integration": "0.1.0", "schema": "1.0.0", "resource": "^1.23.0", } @@ -149,7 +149,7 @@ nginX }] } ], - "repo": { + "repository": { "github": "https://github.com/opensearch-project/observability/tree/main/integrations/nginx" } } @@ -159,7 +159,7 @@ nginX ``` "version": { - "integ": "0.1.0", + "integration": "0.1.0", "schema": "1.0.0", "resource": "^1.23.0", } diff --git a/docs/schema/system/samples/integration.json b/docs/schema/system/samples/integration.json index bfae1f5e8..23d81c585 100644 --- a/docs/schema/system/samples/integration.json +++ b/docs/schema/system/samples/integration.json @@ -9,34 +9,59 @@ "identification": "instrumentationScope.attributes.identification", "catalog": "observability", "components": [ - "web","http" + "web", + "http" ], - "collection":[ + "collection": [ { - "logs": [{ - "info": "access logs", - "input_type":"logfile", - "dataset":"nginx.access", - "labels" :["nginx","access"], - "fields-mapping" : [ - {"alias":"http.url","field":"request_url"} , - {"alias":"http.request.body.content","field":"request_body"} - ] - }, + "logs": [ + { + "info": "access logs", + "input_type": "logfile", + "dataset": "nginx.access", + "labels": [ + "nginx", + "access" + ], + "fields-mapping": [ + { + "template": "my-custom-http_logs", + "fields": [ + { + "alias": "http.url", + "field": "request_url" + }, + { + "alias": "http.request.body.content", + "field": "request_body" + } + ] + } + ] + }, { "info": "error logs", - "input_type":"logfile", - "labels" :["nginx","error"], - "dataset":"nginx.error" - }] + "input_type": "logfile", + "labels": [ + "nginx", + "error" + ], + "dataset": "nginx.error" + } + ] }, { - "metrics": [{ - "info": "status metrics", - "input_type":"metrics", - "dataset":"nginx.status", - "labels" :["nginx","status"] - }] + "metrics": [ + { + "info": "status metrics", + "input_type": "metrics", + "dataset": "nginx.status", + "labels": [ + "nginx", + "status" + ] + } + ] } ], "repository": { diff --git a/integrations/nginx/config.json b/integrations/nginx/config.json index fe3e7cc8c..31886b184 100644 --- a/integrations/nginx/config.json +++ b/integrations/nginx/config.json @@ -1,7 +1,7 @@ { - "name": "nginx", + "template-name": "nginx", "version": { - "integ": "0.1.0", + "integration": "0.1.0", "schema": "1.0.0", "resource": "^1.23.0" }, @@ -35,8 +35,8 @@ }] } ], - "repo": { - "github": "https://github.com/opensearch-project/observability/tree/main/integrarions/nginx" + "repository": { + "url": "https://github.com/opensearch-project/observability/tree/main/integrarions/nginx" } } diff --git a/integrations/service-map/assets/mapping/jaeger-services.mapping b/integrations/service-map/assets/mapping/jaeger-services.mapping new file mode 100644 index 000000000..652c48c05 --- /dev/null +++ b/integrations/service-map/assets/mapping/jaeger-services.mapping @@ -0,0 +1,38 @@ +{ + "index_patterns": [ + "jaeger-service-v1*" + ], + "mappings": { + "properties": { + "operationName": { + "type": "keyword", + "ignore_above": 256 + }, + "serviceName": { + "type": "keyword", + "ignore_above": 256 + } + }, + "dynamic_templates": [ + { + "span_tags_map": { + "path_match": "tag.*", + "mapping": { + "ignore_above": 256, + "type": "keyword" + } + } + }, + { + "process_tags_map": { + "path_match": "process.tag.*", + "mapping": { + "ignore_above": 256, + "type": "keyword" + } + } + } + ] + }, + "version": 1 +} \ No newline at end of file diff --git a/integrations/service-map/assets/mapping/jaeger-traces.mapping b/integrations/service-map/assets/mapping/jaeger-traces.mapping new file mode 100644 index 000000000..2ebaf25fa --- /dev/null +++ b/integrations/service-map/assets/mapping/jaeger-traces.mapping @@ -0,0 +1,239 @@ +{ + "index_patterns": [ + "jaeger-span-v1*" + ], + "data_stream": {}, + "template": { + "mappings": { + "properties": { + "duration": { + "type": "long" + }, + "flags": { + "type": "integer" + }, + "logs": { + "type": "nested", + "dynamic": "false", + "properties": { + "fields": { + "type": "nested", + "dynamic": "false", + "properties": { + "key": { + "type": "keyword", + "ignore_above": 256 + }, + "tagType": { + "type": "keyword", + "ignore_above": 256 + }, + "value": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "timestamp": { + "type": "long" + } + } + }, + "operationName": { + "type": "keyword", + "ignore_above": 256 + }, + "parentSpanID": { + "type": "keyword", + "ignore_above": 256 + }, + "process": { + "properties": { + "serviceName": { + "type": "keyword", + "ignore_above": 256 + }, + "tag": { + "properties": { + "client-uuid": { + "type": "keyword", + "ignore_above": 256 + }, + "hostname": { + "type": "keyword", + "ignore_above": 256 + }, + "ip": { + "type": "keyword", + "ignore_above": 256 + }, + "jaeger@version": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "tags": { + "type": "nested", + "dynamic": "false", + "properties": { + "key": { + "type": "keyword", + "ignore_above": 256 + }, + "tagType": { + "type": "keyword", + "ignore_above": 256 + }, + "value": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "references": { + "type": "nested", + "dynamic": "false", + "properties": { + "refType": { + "type": "keyword", + "ignore_above": 256 + }, + "spanID": { + "type": "keyword", + "ignore_above": 256 + }, + "traceID": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "spanID": { + "type": "keyword", + "ignore_above": 256 + }, + "startTime": { + "type": "long" + }, + "startTimeMillis": { + "type": "date", + "format": "epoch_millis" + }, + "tag": { + "properties": { + "component": { + "type": "keyword", + "ignore_above": 256 + }, + "error": { + "type": "keyword", + "ignore_above": 256 + }, + "http@method": { + "type": "keyword", + "ignore_above": 256 + }, + "http@status_code": { + "type": "keyword", + "ignore_above": 256 + }, + "http@url": { + "type": "keyword", + "ignore_above": 256 + }, + "internal@span@format": { + "type": "keyword", + "ignore_above": 256 + }, + "net/http@reused": { + "type": "keyword", + "ignore_above": 256 + }, + "net/http@was_idle": { + "type": "keyword", + "ignore_above": 256 + }, + "param@driverID": { + "type": "keyword", + "ignore_above": 256 + }, + "param@location": { + "type": "keyword", + "ignore_above": 256 + }, + "peer@service": { + "type": "keyword", + "ignore_above": 256 + }, + "request": { + "type": "keyword", + "ignore_above": 256 + }, + "sampler@param": { + "type": "keyword", + "ignore_above": 256 + }, + "sampler@type": { + "type": "keyword", + "ignore_above": 256 + }, + "span@kind": { + "type": "keyword", + "ignore_above": 256 + }, + "sql@query": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "tags": { + "type": "nested", + "dynamic": "false", + "properties": { + "key": { + "type": "keyword", + "ignore_above": 256 + }, + "tagType": { + "type": "keyword", + "ignore_above": 256 + }, + "value": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "traceID": { + "type": "keyword", + "ignore_above": 256 + } + }, + "dynamic_templates": [ + { + "span_tags_map": { + "path_match": "tag.*", + "mapping": { + "ignore_above": 256, + "type": "keyword" + } + } + }, + { + "process_tags_map": { + "path_match": "process.tag.*", + "mapping": { + "ignore_above": 256, + "type": "keyword" + } + } + } + ] + } + }, + "version": 1 +} diff --git a/integrations/service-map/assets/queries/getTraceGroupPercentilesQuery.json b/integrations/service-map/assets/queries/getTraceGroupPercentilesQuery.json new file mode 100644 index 000000000..a41a09509 --- /dev/null +++ b/integrations/service-map/assets/queries/getTraceGroupPercentilesQuery.json @@ -0,0 +1,137 @@ +{ + "size": 0, + "query": { + "bool": { + "must": [ + { + "term": { + "parentSpanId": { + "value": "" + } + } + } + ], + "filter": [], + "should": [], + "must_not": [] + } + }, + "aggs": { + "trace_group_name": { + "terms": { + "field": "name", + "size": 10000 + }, + "aggs": { + "percentiles": { + "percentiles": { + "field": "durationInNanos", + "percents": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100 + ] + } + } + } + } + } +} diff --git a/integrations/service-map/assets/scripts/getPayloadQuery.json b/integrations/service-map/assets/scripts/getPayloadQuery.json new file mode 100644 index 000000000..bfdb5db73 --- /dev/null +++ b/integrations/service-map/assets/scripts/getPayloadQuery.json @@ -0,0 +1,25 @@ +{ + "script": { + "lang": "mustache", + "source": { + "size": 1000, + "query": { + "bool": { + "must": [ + { + "term": { + "traceId": "{{traceId}}" + } + } + ], + "filter": [], + "should": [], + "must_not": [] + } + } + }, + "params": { + "traceId": "traceId" + } + } +} diff --git a/integrations/service-map/assets/scripts/getServiceBreakdownQuery.json b/integrations/service-map/assets/scripts/getServiceBreakdownQuery.json new file mode 100644 index 000000000..4b14d43e3 --- /dev/null +++ b/integrations/service-map/assets/scripts/getServiceBreakdownQuery.json @@ -0,0 +1,53 @@ +{ + "script": { + "lang": "mustache", + "source": { + "size": 0, + "query": { + "bool": { + "must": [ + { + "term": { + "traceId": "{{traceId}}" + } + } + ], + "filter": [], + "should": [], + "must_not": [] + } + }, + "aggs": { + "service_type": { + "terms": { + "field": "attributes.serviceName", + "order": [ + { + "total_latency_nanos": "desc" + } + ] + }, + "aggs": { + "total_latency_nanos": { + "sum": { + "field": "durationInNanos" + } + }, + "total_latency": { + "bucket_script": { + "buckets_path": { + "count": "_count", + "latency": "total_latency_nanos.value" + }, + "script": "Math.round(params.latency / 10000) / 100.0" + } + } + } + } + } + }, + "params": { + "traceId": "traceId" + } + } +} diff --git a/integrations/service-map/assets/scripts/getSpanDetailQuery.json b/integrations/service-map/assets/scripts/getSpanDetailQuery.json new file mode 100644 index 000000000..83affa87e --- /dev/null +++ b/integrations/service-map/assets/scripts/getSpanDetailQuery.json @@ -0,0 +1,49 @@ +{ + "script": { + "lang": "mustache", + "source": { + "size": 3000, + "query": { + "bool": { + "must": [ + { + "term": { + "traceId": "{{traceId}}" + } + }, + { + "exists": { + "field": "attributes.serviceName" + } + } + ], + "filter": [], + "should": [], + "must_not": [] + } + }, + "sort": [ + { + "startTime": { + "order": "desc" + } + } + ], + "_source": { + "includes": [ + "attributes.serviceName", + "name", + "startTime", + "endTime", + "spanId", + "status.code", + "durationInNanos" + ] + } + }, + "params": { + "traceId": "traceId" + } + } +} + diff --git a/integrations/service-map/assets/scripts/getSpanFlyoutQuery.json b/integrations/service-map/assets/scripts/getSpanFlyoutQuery.json new file mode 100644 index 000000000..100370f39 --- /dev/null +++ b/integrations/service-map/assets/scripts/getSpanFlyoutQuery.json @@ -0,0 +1,25 @@ +{ + "script": { + "lang": "mustache", + "source": { + "size": 1000, + "query": { + "bool": { + "must": [ + { + "term": { + "spanID": "{{spanId}}" + } + } + ], + "filter": [], + "should": [], + "must_not": [] + } + } + }, + "params": { + "traceId": "spanId" + } + } +} \ No newline at end of file diff --git a/integrations/service-map/assets/scripts/getSpansQuery.json b/integrations/service-map/assets/scripts/getSpansQuery.json new file mode 100644 index 000000000..4404f3651 --- /dev/null +++ b/integrations/service-map/assets/scripts/getSpansQuery.json @@ -0,0 +1,23 @@ +{ + "script": { + "lang": "mustache", + "source": { + "size": "{{size}}", + "from": "{{from}}", + "query": { + "bool": { + "must": [], + "filter": [], + "should": [], + "must_not": [] + } + }, + "sort": "{{sortingColumns}}" + }, + "params": { + "size": "100", + "from": "0", + "sort": "asc" + } + } +} \ No newline at end of file diff --git a/integrations/service-map/assets/scripts/getTracesQuery.json b/integrations/service-map/assets/scripts/getTracesQuery.json new file mode 100644 index 000000000..8f5b20ca5 --- /dev/null +++ b/integrations/service-map/assets/scripts/getTracesQuery.json @@ -0,0 +1,68 @@ +{ + "script": { + "lang": "mustache", + "source": { + "size": 0, + "query": { + "bool": { + "must": [ + { + "term": { + "traceId": "{{traceId}}" + } + } + ], + "filter": [], + "should": [], + "must_not": [] + } + }, + "aggs": { + "traces": { + "terms": { + "field": "traceId", + "size": 100, + "order": { + "_key": "{{direction}}" + } + }, + "aggs": { + "latency": { + "max": { + "script": { + "source": "\n if (doc.containsKey('duration') && !doc['duration'].empty) {\n return Math.round(doc['duration'].value) / 1000.0\n }\n\n return 0\n ", + "lang": "painless" + } + } + }, + "trace_group": { + "terms": { + "field": "traceGroup", + "size": 1 + } + }, + "error_count": { + "filter": { + "term": { + "tag.error": true + } + } + }, + "last_updated": { + "max": { + "script": { + "source": "\n if (doc.containsKey('startTime') && !doc['startTime'].empty && doc.containsKey('duration') && !doc['duration'].empty) {\n return (Math.round(doc['duration'].value) + Math.round(doc['startTime'].value)) / 1000.0\n }\n\n return 0\n ", + "lang": "painless" + } + } + } + } + } + } + }, + "params": { + "traceId": "traceId", + "direction": "asc" + } + } +} diff --git a/integrations/service-map/assets/scripts/getValidTraceIdsQuery.json b/integrations/service-map/assets/scripts/getValidTraceIdsQuery.json new file mode 100644 index 000000000..24f189566 --- /dev/null +++ b/integrations/service-map/assets/scripts/getValidTraceIdsQuery.json @@ -0,0 +1,33 @@ +{ + "script": { + "lang": "mustache", + "source": { + "size": 0, + "query": { + "bool": { + "must": [], + "filter": [ + { + "term": { "traceGroupName.keyword": "{{traceGroupName}}"} + }, + { + "term": { "serviceName": "{{serviceName}}" } + } + ] + } + }, + "aggs": { + "traces": { + "terms": { + "field": "traceId", + "size": 10000 + } + } + } + }, + "params": { + "traceGroup": "traceGroupName", + "serviceName": "serviceName" + } + } +} diff --git a/integrations/service-map/config.json b/integrations/service-map/config.json index d082b0027..bc0583ec4 100644 --- a/integrations/service-map/config.json +++ b/integrations/service-map/config.json @@ -1,47 +1,84 @@ { - "name": "data-prepper", + "template-name": "service-map", "version": { - "integ": "0.1.0", + "integration": "0.1.0", "schema": "1.0.0", "resource": "^2.6.0" }, - "description": "Data-Prepper Service Map and Tracing correlations Integration", + "description": "Service Map and Tracing correlations Integration", "catalog": "observability", "components": [ "traces,traceGroups,metrics" ], - "collection":[ + "collection": [ { - "traces": [{ - "info": "traces signals", - "input_type":"traces", - "dataset":"spans", - "labels" :["traceGroups","traces"], - "fields-mapping" : [ - {"alias":"attributes.serviceName","field":"serviceName"} , - {"alias":"events.@timestamp","field":"events.time"} - ] - }] + "traces": [ + { + "info": "traces signals", + "input_type": "traces", + "dataset": "spans", + "labels": [ + "traceGroups", + "traces" + ], + "fields-mapping": [ + { + "template": "data-prepper-traces", + "fields": [ + { + "alias": "attributes.serviceName", + "field": "serviceName" + }, + { + "alias": "events.@timestamp", + "field": "events.time" + } + ] + }, + { + "template": "jaeger-traces", + "fields": [ + { + "alias": "attributes.serviceName", + "field": "serviceName" + }, + { + "alias": "events.@timestamp", + "field": "events.time" + } + ] + } + ] + } + ] }, { - "services": [{ + "services": [ + { "info": "service map", "input_type": "services", "dataset": "service", - "labels": ["services"] - }] + "labels": [ + "services" + ] + } + ] }, { - "metrics": [{ - "info": "status metrics", - "input_type":"metrics", - "dataset":"metrics", - "labels" :["metrics"] - }] + "metrics": [ + { + "info": "status metrics", + "input_type": "metrics", + "dataset": "metrics", + "labels": [ + "metrics" + ] + } + ] } ], - "repo": { - "github": "https://github.com/opensearch-project/observability/tree/main/integrarions/service-map" + "repository": { + "url": "https://github.com/opensearch-project/observability/tree/main/integrarions/service-map" } } diff --git a/integrations/service-map/info/README.md b/integrations/service-map/info/providers/data-prepper/README.md similarity index 95% rename from integrations/service-map/info/README.md rename to integrations/service-map/info/providers/data-prepper/README.md index 5ce6e454a..c28dbeca7 100644 --- a/integrations/service-map/info/README.md +++ b/integrations/service-map/info/providers/data-prepper/README.md @@ -58,10 +58,15 @@ To compensate for the minor differences in fields naming between the [Data-Prepp We will define the next mapping alias that will be part of the [config.json](../config.json) for this integration ```json5 - ... + ... "fields-mapping" : [ - {"alias":"attributes.serviceName","field":"serviceName"} , - {"alias":"events.@timestamp","field":"events.time"} + { + "template": "data-prepper-traces", + "fields": [ + {"alias":"attributes.serviceName","field":"serviceName"} , + {"alias":"events.@timestamp","field":"events.time"} + ] + } ] ... ``` diff --git a/integrations/service-map/info/dataPrepper.svg b/integrations/service-map/info/providers/data-prepper/dataPrepper.svg similarity index 100% rename from integrations/service-map/info/dataPrepper.svg rename to integrations/service-map/info/providers/data-prepper/dataPrepper.svg diff --git a/integrations/service-map/info/providers/jaeger/README.md b/integrations/service-map/info/providers/jaeger/README.md new file mode 100644 index 000000000..926736ab1 --- /dev/null +++ b/integrations/service-map/info/providers/jaeger/README.md @@ -0,0 +1,121 @@ +![jaeger](jaeger-logo.png) + +# What is Jaeger + +[Jaeger](https://github.com/jaegertracing/jaeger) Jaeger, inspired by Dapper and OpenZipkin, is a distributed tracing platform created by Uber Technologies and donated to Cloud Native Computing Foundation. It can be used for monitoring microservices-based distributed systems: + +- Distributed context propagation +- Distributed transaction monitoring +- Root cause analysis +- Service dependency analysis +- Performance / latency optimization + + +# What is Jaeger Integration + +Jaeger integration is concerned with the following aspects + + - Allow simple and automatic generation of all schematic structured + - traces ( including specific fields mapping to map to SS4O schema) + - services ( adding support for specific service mapping category) + - metrics (using the standard SS4O schema) + + - Add Dashboard Assets for correlation between traces-services-metrics + + - Add correlation queries to investigate traces based metrics + +# Jaeger Trace Fields +Jaeger uses the following [Traces](../schema/jaeger-traces.mapping) mapping file + +The next fields are used: +```text + +- traceId - A unique identifier for a trace. All spans from the same trace share the same traceId. +- spanId - A unique identifier for a span within a trace, assigned when the span is created. +- traceState - Conveys information about request position in multiple distributed tracing graphs. +- parentSpanId - The spanId of this span's parent span. If this is a root span, then this field must be empty. +- name - A description of the span's operation. +- kind - The type of span. See OpenTelemetry - SpanKind. +- startTime - The start time of the span. +- endTime - The end time of the span. +- durationInNanos - Difference in nanoseconds between startTime and endTime. +- serviceName - Currently derived from the opentelemetry.proto.resource.v1.Resource associated with the span, the resource from the span originates. +- events - A list of events. See OpenTelemetry - Events. +- links - A list of linked spans. See OpenTelemetry - Links. +- droppedAttributesCount - The number of attributes that were discarded. +- droppedEventsCount - The number of events that were discarded. +- droppedLinksCount - The number of links that were dropped. +- span.attributes.* - All span attributes are split into a list of keywords. +- resource.attributes.* - All resource attributes are split into a list of keywords. +- status.code - The status of the span. See OpenTelemetry - Status. + +``` +These fields have a high overlap with the [`sso_traces`](../../../schema/observability/traces/README.md) fields from the observability catalog + +There are some additional `trace.group` related fields which are not part of the [OTEL spec](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md) for traces +```text +- traceGroup - A derived field, the name of the trace's root span. +- traceGroupFields.endTime - A derived field, the endTime of the trace's root span. +- traceGroupFields.statusCode - A derived field, the status.code of the trace's root span. +- traceGroupFields.durationInNanos - A derived field, the durationInNanos of the trace's root span. + +``` + +# Jaeger Trace Fields Mapping to SSO Trace Schema +To compensate for the minor differences in fields naming between the [Jaeger -Trace mapping](../schema/jaeger-traces.mapping) and [SSO Traces mapping](../../../schema/observability/traces/traces.mapping) +We will define the next mapping alias that will be part of the [config.json](../config.json) for this integration + +```json5 + ... + "fields-mapping" : [ + { + "template": "jaeger-services.mapping", + "fields": [ + {"alias":"attributes.serviceName","field":"serviceName"} , + {"alias":"events.@timestamp","field":"events.time"} + ] + } + ] + ... +``` + + + +To address this difference, the `trace` signal can be augmented with additional trace-component - in this case it will be the [traceGroup](../../../schema/observability/traces/traceGroup). + +## Service dashboard +Service will have a dashboard comprised of the following visualizations: + - Latency per service with traces / metrics links + - Latency per trace-group with traces / metrics links + - Error rate per service with traces / metrics links + - Error rate per trace-group with traces / metrics links + - Throughput rate per service with traces / metrics links + - Throughput rate per trace-group with traces / metrics links + + - Services view including error rate, latency, throughput, connected-services, traces, metrics + +```text ++--------------------------------+--------------------------------+ +| | | +| Latency per service | Latency per trace-group | +| with traces/metrics links | with traces/metrics links | +| | | ++--------------------------------+--------------------------------+ +| | | +| Error rate per service | Error rate per trace-group | +| with traces/metrics links | with traces/metrics links | +| | | ++--------------------------------+--------------------------------+ +| | | +| Throughput rate per service | Throughput rate per trace-group| +| with traces/metrics links | with traces/metrics links | +| | | ++--------------------------------+--------------------------------+ +| | +| Services view with error rate, latency, | +| throughput, connected-services, traces, | +| and metrics | +| | ++--------------------------------------------------------+ + +``` \ No newline at end of file diff --git a/integrations/service-map/info/providers/jaeger/jaeger-logo.png b/integrations/service-map/info/providers/jaeger/jaeger-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1e4753d05e80d56ed306fab98bb3d695527d7592 GIT binary patch literal 46281 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