diff --git a/_meta/fields.common.yml b/_meta/fields.common.yml index 262e4a41b56..8e1ff2fbcb1 100644 --- a/_meta/fields.common.yml +++ b/_meta/fields.common.yml @@ -139,7 +139,7 @@ - name: name type: keyword description: > - Immutable unique name of the service emitting this event. + Immutable name of the service emitting this event. overwrite: true - name: version @@ -153,6 +153,15 @@ description: > Service environment. + - name: node + type: group + fields: + - name: name + type: keyword + description: > + Unique meaningful name of the service node. + overwrite: true + - name: language type: group fields: diff --git a/beater/test_approved_es_documents/TestPublishIntegrationErrors.approved.json b/beater/test_approved_es_documents/TestPublishIntegrationErrors.approved.json index dfe9357b1f0..80fa4c16c24 100644 --- a/beater/test_approved_es_documents/TestPublishIntegrationErrors.approved.json +++ b/beater/test_approved_es_documents/TestPublishIntegrationErrors.approved.json @@ -298,6 +298,9 @@ "version": "1.2" }, "name": "service1", + "node": { + "name": "1234_service-12a3-acgh" + }, "runtime": { "name": "node", "version": "8.0.0" @@ -404,6 +407,9 @@ "version": "8" }, "name": "1234_service-12a3", + "node": { + "name": "1234_service-12a3-hx4ff" + }, "runtime": { "name": "node", "version": "8.0.0" @@ -501,6 +507,9 @@ "version": "2.5" }, "name": "service1", + "node": { + "name": "1234_service-12a3-hx4ff" + }, "runtime": { "name": "cruby", "version": "2.5" @@ -600,6 +609,9 @@ "version": "8" }, "name": "1234_service-12a3", + "node": { + "name": "1234_service-12a3-hx4ff" + }, "runtime": { "name": "node", "version": "8.0.0" diff --git a/beater/test_approved_es_documents/TestPublishIntegrationEvents.approved.json b/beater/test_approved_es_documents/TestPublishIntegrationEvents.approved.json index 4889d2ba412..345595edbaf 100644 --- a/beater/test_approved_es_documents/TestPublishIntegrationEvents.approved.json +++ b/beater/test_approved_es_documents/TestPublishIntegrationEvents.approved.json @@ -63,7 +63,10 @@ "language": { "name": "ecmascript" }, - "name": "1234_service-12a3" + "name": "1234_service-12a3", + "node": { + "name": "container-id" + } }, "timestamp": { "us": 1533827045999000 @@ -179,7 +182,10 @@ "language": { "name": "ecmascript" }, - "name": "1234_service-12a3" + "name": "1234_service-12a3", + "node": { + "name": "container-id" + } }, "timestamp": { "us": 1535655207154000 @@ -264,7 +270,10 @@ "language": { "name": "ecmascript" }, - "name": "1234_service-12a3" + "name": "1234_service-12a3", + "node": { + "name": "container-id" + } } } ] diff --git a/beater/test_approved_es_documents/TestPublishIntegrationMetricsets.approved.json b/beater/test_approved_es_documents/TestPublishIntegrationMetricsets.approved.json index 74e5e80e713..b147b9d2f19 100644 --- a/beater/test_approved_es_documents/TestPublishIntegrationMetricsets.approved.json +++ b/beater/test_approved_es_documents/TestPublishIntegrationMetricsets.approved.json @@ -64,7 +64,10 @@ "language": { "name": "ecmascript" }, - "name": "1234_service-12a3" + "name": "1234_service-12a3", + "node": { + "name": "service-a-node-1" + } }, "short_counter": 227, "span": { @@ -149,7 +152,10 @@ "language": { "name": "ecmascript" }, - "name": "1234_service-12a3" + "name": "1234_service-12a3", + "node": { + "name": "service-a-node-1" + } }, "user": { "email": "user@mail.com", diff --git a/beater/test_approved_es_documents/TestPublishIntegrationTransactions.approved.json b/beater/test_approved_es_documents/TestPublishIntegrationTransactions.approved.json index 8cb662ffdc9..77138069a41 100644 --- a/beater/test_approved_es_documents/TestPublishIntegrationTransactions.approved.json +++ b/beater/test_approved_es_documents/TestPublishIntegrationTransactions.approved.json @@ -76,6 +76,9 @@ "version": "8" }, "name": "1234_service-12a3", + "node": { + "name": "1234_service-12a3" + }, "runtime": { "name": "node", "version": "8.0.0" @@ -241,6 +244,9 @@ "version": "8" }, "name": "1234_service-12a3", + "node": { + "name": "1234_service-12a3" + }, "runtime": { "name": "node", "version": "7.0" @@ -378,6 +384,9 @@ "version": "2.5" }, "name": "service1", + "node": { + "name": "1234_service-12a3-yuewß" + }, "runtime": { "name": "cruby", "version": "2.5" diff --git a/changelogs/head.asciidoc b/changelogs/head.asciidoc index cef5d86d458..30a11bc4a1e 100644 --- a/changelogs/head.asciidoc +++ b/changelogs/head.asciidoc @@ -3,5 +3,6 @@ [float] ==== Added +- Add `service.node.configured_name` to Intake API and transform to `service.node.name` for ES output {pull}2746[2746]. https://github.com/elastic/apm-server/compare/7.4\...master[View commits] diff --git a/docs/data/elasticsearch/generated/errors.json b/docs/data/elasticsearch/generated/errors.json index c4a9d8796fa..cd590fdb4b1 100644 --- a/docs/data/elasticsearch/generated/errors.json +++ b/docs/data/elasticsearch/generated/errors.json @@ -281,6 +281,9 @@ "version": "1.2" }, "name": "service1", + "node": { + "name": "1234_service-12a3-acgh" + }, "runtime": { "name": "node", "version": "8.0.0" @@ -370,6 +373,9 @@ "version": "8" }, "name": "1234_service-12a3", + "node": { + "name": "1234_service-12a3-hx4ff" + }, "runtime": { "name": "node", "version": "8.0.0" @@ -450,6 +456,9 @@ "version": "2.5" }, "name": "service1", + "node": { + "name": "1234_service-12a3-hx4ff" + }, "runtime": { "name": "cruby", "version": "2.5" @@ -532,6 +541,9 @@ "version": "8" }, "name": "1234_service-12a3", + "node": { + "name": "1234_service-12a3-hx4ff" + }, "runtime": { "name": "node", "version": "8.0.0" diff --git a/docs/data/elasticsearch/generated/metricsets.json b/docs/data/elasticsearch/generated/metricsets.json index 2b66b908d5e..3943ab86422 100644 --- a/docs/data/elasticsearch/generated/metricsets.json +++ b/docs/data/elasticsearch/generated/metricsets.json @@ -47,7 +47,10 @@ "language": { "name": "ecmascript" }, - "name": "1234_service-12a3" + "name": "1234_service-12a3", + "node": { + "name": "service-a-node-1" + } }, "short_counter": 227, "span": { @@ -115,7 +118,10 @@ "language": { "name": "ecmascript" }, - "name": "1234_service-12a3" + "name": "1234_service-12a3", + "node": { + "name": "service-a-node-1" + } }, "user": { "email": "user@mail.com", diff --git a/docs/data/elasticsearch/generated/transactions.json b/docs/data/elasticsearch/generated/transactions.json index f9c7529788a..e364256be61 100644 --- a/docs/data/elasticsearch/generated/transactions.json +++ b/docs/data/elasticsearch/generated/transactions.json @@ -59,6 +59,9 @@ "version": "8" }, "name": "1234_service-12a3", + "node": { + "name": "1234_service-12a3" + }, "runtime": { "name": "node", "version": "8.0.0" @@ -207,6 +210,9 @@ "version": "8" }, "name": "1234_service-12a3", + "node": { + "name": "1234_service-12a3" + }, "runtime": { "name": "node", "version": "7.0" @@ -327,6 +333,9 @@ "version": "2.5" }, "name": "service1", + "node": { + "name": "1234_service-12a3-yuewß" + }, "runtime": { "name": "cruby", "version": "2.5" diff --git a/docs/fields.asciidoc b/docs/fields.asciidoc index dff6549345d..23f92771aa6 100644 --- a/docs/fields.asciidoc +++ b/docs/fields.asciidoc @@ -227,7 +227,7 @@ Service fields. *`service.name`*:: + -- -Immutable unique name of the service emitting this event. +Immutable name of the service emitting this event. type: keyword @@ -255,6 +255,17 @@ type: keyword -- +*`service.node.name`*:: ++ +-- +Unique meaningful name of the service node. + + +type: keyword + +-- + + *`service.language.name`*:: + -- diff --git a/docs/spec/service.json b/docs/spec/service.json index f844b1acb6a..290862a8fd8 100644 --- a/docs/spec/service.json +++ b/docs/spec/service.json @@ -81,6 +81,16 @@ "description": "Version of the service emitting this event", "type": ["string", "null"], "maxLength": 1024 + }, + "node": { + "description": "Unique meaningful name of the service node.", + "type": ["object", "null"], + "properties": { + "configured_name": { + "type": ["string", "null"], + "maxLength": 1024 + } + } } } } diff --git a/include/fields.go b/include/fields.go index 7fe22b447d8..728ab88de9c 100644 --- a/include/fields.go +++ b/include/fields.go @@ -32,5 +32,5 @@ func init() { // AssetFieldsYml returns asset data. // This is the base64 encoded gzipped contents of fields.yml. func AssetFieldsYml() string { - return "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" + return "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" } diff --git a/model/error/event.go b/model/error/event.go index 35fd33d5016..4e54afcb73e 100644 --- a/model/error/event.go +++ b/model/error/event.go @@ -56,6 +56,7 @@ var ( const ( processorName = "error" errorDocType = "error" + emptyString = "" ) var cachedModelSchema = validation.CreateSchema(schema.ModelSchema, processorName) @@ -195,7 +196,7 @@ func (e *Event) Transform(tctx *transform.Context) []beat.Event { utility.Update(fields, "user", e.User.Fields()) utility.DeepUpdate(fields, "client", e.Http.ClientFields(e.User.ClientFields())) utility.DeepUpdate(fields, "user_agent", e.User.UserAgentFields()) - utility.DeepUpdate(fields, "service", e.Service.Fields()) + utility.DeepUpdate(fields, "service", e.Service.Fields(emptyString, emptyString)) utility.DeepUpdate(fields, "agent", e.Service.AgentFields()) // merges with metadata labels, overrides conflicting keys utility.DeepUpdate(fields, "labels", e.Labels.Fields()) diff --git a/model/error/event_test.go b/model/error/event_test.go index f91e555c7a8..2b144998e12 100644 --- a/model/error/event_test.go +++ b/model/error/event_test.go @@ -561,10 +561,11 @@ func TestEvents(t *testing.T) { timestamp := time.Date(2019, 1, 3, 15, 17, 4, 908.596*1e6, time.FixedZone("+0100", 3600)) timestampUs := timestamp.UnixNano() / 1000 - serviceName, agentName, version := "myservice", "go", "1.0" + serviceName, agentName, agentVersion := "myservice", "go", "1.0" service := metadata.Service{ - Name: &serviceName, Agent: metadata.Agent{Name: &agentName, Version: &version}, + Name: &serviceName, Agent: metadata.Agent{Name: &agentName, Version: &agentVersion}, } + serviceVersion := "1.2.3" exMsg := "exception message" trId := "945254c5-67a5-417e-8a4e-aa29efcbfb79" sampledTrue, sampledFalse := true, false @@ -676,6 +677,19 @@ func TestEvents(t *testing.T) { }, Msg: "Payload with Event with Context.", }, + { + Transformable: &Event{Timestamp: timestamp, Service: &metadata.Service{Version: &serviceVersion}}, + Output: common.MapStr{ + "service": common.MapStr{"name": serviceName, "version": serviceVersion}, + "labels": common.MapStr{"label": 101}, + "agent": common.MapStr{"name": "go", "version": "1.0"}, + "user": common.MapStr{"id": uid}, + "error": common.MapStr{"grouping_key": "d41d8cd98f00b204e9800998ecf8427e"}, + "processor": common.MapStr{"event": "error", "name": "error"}, + "timestamp": common.MapStr{"us": timestampUs}, + }, + Msg: "Deep update service fields", + }, } me := metadata.NewMetadata(&service, nil, nil, &metadata.User{Id: &uid}, metadataLabels) diff --git a/model/error/generated/schema/error.go b/model/error/generated/schema/error.go index 1030c1e8e0d..d193c5a22c3 100644 --- a/model/error/generated/schema/error.go +++ b/model/error/generated/schema/error.go @@ -347,6 +347,16 @@ const ModelSchema = `{ "description": "Version of the service emitting this event", "type": ["string", "null"], "maxLength": 1024 + }, + "node": { + "description": "Unique meaningful name of the service node.", + "type": ["object", "null"], + "properties": { + "configured_name": { + "type": ["string", "null"], + "maxLength": 1024 + } + } } } } diff --git a/model/metadata/generated/schema/metadata.go b/model/metadata/generated/schema/metadata.go index 83e641be953..9d9d9f96235 100644 --- a/model/metadata/generated/schema/metadata.go +++ b/model/metadata/generated/schema/metadata.go @@ -106,6 +106,16 @@ const ModelSchema = `{ "description": "Version of the service emitting this event", "type": ["string", "null"], "maxLength": 1024 + }, + "node": { + "description": "Unique meaningful name of the service node.", + "type": ["object", "null"], + "properties": { + "configured_name": { + "type": ["string", "null"], + "maxLength": 1024 + } + } } }, "type": "object", diff --git a/model/metadata/metadata.go b/model/metadata/metadata.go index 1ffc586fc4d..4ad7767b309 100644 --- a/model/metadata/metadata.go +++ b/model/metadata/metadata.go @@ -22,10 +22,11 @@ import ( "github.com/santhosh-tekuri/jsonschema" + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/apm-server/model/metadata/generated/schema" "github.com/elastic/apm-server/utility" "github.com/elastic/apm-server/validation" - "github.com/elastic/beats/libbeat/common" ) var cachedModelSchema = validation.CreateSchema(schema.ModelSchema, "metadata") @@ -80,14 +81,16 @@ func NewMetadata(service *Service, system *System, process *Process, user *User, } func (m *Metadata) Set(fields common.MapStr) common.MapStr { - utility.Set(fields, "service", m.Service.Fields()) + containerFields := m.System.containerFields() + hostFields := m.System.fields() + utility.Set(fields, "service", m.Service.Fields(fetch(containerFields, "id"), fetch(hostFields, "name"))) utility.Set(fields, "agent", m.Service.AgentFields()) - utility.Set(fields, "host", m.System.fields()) + utility.Set(fields, "host", hostFields) utility.Set(fields, "process", m.Process.fields()) utility.Set(fields, "user", m.User.Fields()) utility.Set(fields, "client", m.User.ClientFields()) utility.Set(fields, "user_agent", m.User.UserAgentFields()) - utility.Set(fields, "container", m.System.containerFields()) + utility.Set(fields, "container", containerFields) utility.Set(fields, "kubernetes", m.System.kubernetesFields()) // to be merged with specific event labels, these should be overwritten in case of conflict utility.Set(fields, "labels", m.Labels) @@ -99,3 +102,10 @@ func (m *Metadata) SetMinimal(fields common.MapStr) common.MapStr { utility.Set(fields, "service", m.Service.MinimalFields()) return fields } + +func fetch(m common.MapStr, key string) string { + if val, ok := m[key].(string); ok { + return val + } + return "" +} diff --git a/model/metadata/metadata_test.go b/model/metadata/metadata_test.go index 4dc80567203..9a67569d83f 100644 --- a/model/metadata/metadata_test.go +++ b/model/metadata/metadata_test.go @@ -29,7 +29,7 @@ import ( func TestDecodeMetadata(t *testing.T) { pid := 1234 host := "host" - serviceName := "myservice" + serviceName, serviceNodeName := "myservice", "serviceABC" uid := "12321" mail := "user@email.com" agentName := "elastic-node" @@ -74,10 +74,11 @@ func TestDecodeMetadata(t *testing.T) { }, "service": map[string]interface{}{ "name": "myservice", + "node": map[string]interface{}{ + "configured_name": serviceNodeName}, "agent": map[string]interface{}{ "name": agentName, - "version": agentVersion, - }, + "version": agentVersion}, }, "system": map[string]interface{}{ "hostname": host, @@ -90,11 +91,10 @@ func TestDecodeMetadata(t *testing.T) { }, }, output: NewMetadata( - &Service{Name: &serviceName, - Agent: Agent{ - Name: &agentName, - Version: &agentVersion, - }, + &Service{ + Name: &serviceName, + Agent: Agent{Name: &agentName, Version: &agentVersion}, + node: node{name: &serviceNodeName}, }, &System{DetectedHostname: &host}, &Process{Pid: pid}, @@ -113,7 +113,8 @@ func TestDecodeMetadata(t *testing.T) { func TestMetadata_Set(t *testing.T) { pid := 1234 host := "host" - serviceName := "myservice" + containerID := "container-123" + serviceName, serviceNodeName := "myservice", "serviceABC" uid := "12321" mail := "user@email.com" agentName := "elastic-node" @@ -127,12 +128,13 @@ func TestMetadata_Set(t *testing.T) { input: NewMetadata( &Service{ Name: &serviceName, + node: node{name: &serviceNodeName}, Agent: Agent{ Name: &agentName, Version: &agentVersion, }, }, - &System{DetectedHostname: &host}, + &System{DetectedHostname: &host, Container: &Container{ID: containerID}}, &Process{Pid: pid}, &User{Id: &uid, Email: &mail}, nil, @@ -144,16 +146,35 @@ func TestMetadata_Set(t *testing.T) { }, }, output: common.MapStr{ - "foo": "bar", - "agent": common.MapStr{"version": "1.0.0", "name": "elastic-node"}, - "host": common.MapStr{"hostname": host, "name": host}, - "process": common.MapStr{"pid": pid}, + "foo": "bar", + "agent": common.MapStr{"version": "1.0.0", "name": "elastic-node"}, + "container": common.MapStr{"id": containerID}, + "host": common.MapStr{"hostname": host, "name": host}, + "process": common.MapStr{"pid": pid}, "service": common.MapStr{ "name": "myservice", + "node": common.MapStr{"name": serviceNodeName}, }, "user": common.MapStr{"id": "12321", "email": "user@email.com"}, }, }, + { + input: NewMetadata(&Service{}, + &System{DetectedHostname: &host, Container: &Container{ID: containerID}}, + nil, nil, nil), + fields: common.MapStr{}, + output: common.MapStr{ + "host": common.MapStr{"hostname": host, "name": host}, + "container": common.MapStr{"id": containerID}, + "service": common.MapStr{"node": common.MapStr{"name": containerID}}}, + }, + { + input: NewMetadata(&Service{}, &System{DetectedHostname: &host}, nil, nil, nil), + fields: common.MapStr{}, + output: common.MapStr{ + "host": common.MapStr{"hostname": host, "name": host}, + "service": common.MapStr{"node": common.MapStr{"name": host}}}, + }, } { assert.Equal(t, test.output, test.input.Set(test.fields)) } @@ -162,7 +183,8 @@ func TestMetadata_Set(t *testing.T) { func TestMetadata_SetMinimal(t *testing.T) { pid := 1234 host := "host" - serviceName := "myservice" + containerID := "container-123" + serviceName, serviceNodeName := "myservice", "serviceABC" uid := "12321" mail := "user@email.com" agentName := "elastic-node" @@ -176,22 +198,21 @@ func TestMetadata_SetMinimal(t *testing.T) { input: NewMetadata( &Service{ Name: &serviceName, + node: node{name: &serviceNodeName}, Agent: Agent{ Name: &agentName, Version: &agentVersion, }, }, - &System{DetectedHostname: &host}, + &System{DetectedHostname: &host, Container: &Container{ID: containerID}}, &Process{Pid: pid}, &User{Id: &uid, Email: &mail}, nil, ), fields: common.MapStr{}, output: common.MapStr{ - "agent": common.MapStr{"version": "1.0.0", "name": "elastic-node"}, - "service": common.MapStr{ - "name": "myservice", - }, + "agent": common.MapStr{"version": "1.0.0", "name": "elastic-node"}, + "service": common.MapStr{"name": "myservice"}, }, }, { @@ -203,7 +224,7 @@ func TestMetadata_SetMinimal(t *testing.T) { Version: &agentVersion, }, }, - &System{DetectedHostname: &host}, + &System{DetectedHostname: &host, Container: &Container{ID: containerID}}, &Process{Pid: pid}, &User{Id: &uid}, common.MapStr{}, @@ -212,11 +233,9 @@ func TestMetadata_SetMinimal(t *testing.T) { "foo": "bar", }, output: common.MapStr{ - "agent": common.MapStr{"version": "1.0.0", "name": "elastic-node"}, - "foo": "bar", - "service": common.MapStr{ - "name": "myservice", - }, + "agent": common.MapStr{"version": "1.0.0", "name": "elastic-node"}, + "foo": "bar", + "service": common.MapStr{"name": "myservice"}, }, }, } { diff --git a/model/metadata/service.go b/model/metadata/service.go index 34f1f00b5b3..41aaa192360 100644 --- a/model/metadata/service.go +++ b/model/metadata/service.go @@ -20,10 +20,12 @@ package metadata import ( "errors" - "github.com/elastic/apm-server/utility" "github.com/elastic/beats/libbeat/common" + + "github.com/elastic/apm-server/utility" ) +//Service bundles together information related to the monitored service and the agent used for monitoring type Service struct { Name *string Version *string @@ -32,26 +34,39 @@ type Service struct { Runtime Runtime Framework Framework Agent Agent + node node } +//Language has an optional version and name type Language struct { Name *string Version *string } + +//Runtime has an optional version and name type Runtime struct { Name *string Version *string } + +//Framework has an optional version and name type Framework struct { Name *string Version *string } + +//Agent has an optional version, name and an ephemeral id type Agent struct { Name *string Version *string EphemeralId *string } +type node struct { + name *string +} + +//DecodeService decodes a given input into a Service instance func DecodeService(input interface{}, err error) (*Service, error) { if input == nil || err != nil { return nil, err @@ -82,10 +97,14 @@ func DecodeService(input interface{}, err error) (*Service, error) { Name: decoder.StringPtr(raw, "name", "runtime"), Version: decoder.StringPtr(raw, "version", "runtime"), }, + node: node{ + name: decoder.StringPtr(raw, "configured_name", "node"), + }, } return &service, decoder.Err } +//MinimalFields transforms a defined subset of a service instance into a common.MapStr func (s *Service) MinimalFields() common.MapStr { if s == nil { return nil @@ -96,11 +115,13 @@ func (s *Service) MinimalFields() common.MapStr { return svc } -func (s *Service) Fields() common.MapStr { +//Fields transforms a service instance into a common.MapStr +func (s *Service) Fields(containerID, hostName string) common.MapStr { if s == nil { return nil } svc := s.MinimalFields() + utility.Set(svc, "node", s.node.fields(containerID, hostName)) utility.Set(svc, "version", s.Version) lang := common.MapStr{} @@ -121,6 +142,7 @@ func (s *Service) Fields() common.MapStr { return svc } +//AgentFields transforms all agent related information of a service into a common.MapStr func (s *Service) AgentFields() common.MapStr { if s == nil { return nil @@ -128,6 +150,19 @@ func (s *Service) AgentFields() common.MapStr { return s.Agent.fields() } +func (n *node) fields(containerID, hostName string) common.MapStr { + if n.name != nil && *n.name != "" { + return common.MapStr{"name": *n.name} + } + if containerID != "" { + return common.MapStr{"name": containerID} + } + if hostName != "" { + return common.MapStr{"name": hostName} + } + return nil +} + func (a *Agent) fields() common.MapStr { if a == nil { return nil diff --git a/model/metadata/service_test.go b/model/metadata/service_test.go index b6566bdb6af..8b0cd247594 100644 --- a/model/metadata/service_test.go +++ b/model/metadata/service_test.go @@ -23,8 +23,9 @@ import ( "github.com/stretchr/testify/assert" - "github.com/elastic/apm-server/utility" "github.com/elastic/beats/libbeat/common" + + "github.com/elastic/apm-server/utility" ) var ( @@ -36,17 +37,29 @@ var ( ) func TestServiceTransform(t *testing.T) { - serviceName := "myService" + serviceName, serviceNodeName := "myService", "abc" tests := []struct { - Service Service - Fields common.MapStr - AgentFields common.MapStr + Service Service + ContainerID, HostName string + Fields common.MapStr + AgentFields common.MapStr }{ { Service: Service{}, AgentFields: common.MapStr{}, Fields: common.MapStr{}, + }, { + Service: Service{}, + ContainerID: "foo", + HostName: "bar", + AgentFields: common.MapStr{}, + Fields: common.MapStr{"node": common.MapStr{"name": "foo"}}, + }, { + Service: Service{}, + HostName: "bar", + AgentFields: common.MapStr{}, + Fields: common.MapStr{"node": common.MapStr{"name": "bar"}}, }, { Service: Service{ @@ -69,7 +82,10 @@ func TestServiceTransform(t *testing.T) { Name: &agentName, Version: &agentVersion, }, + node: node{name: &serviceNodeName}, }, + ContainerID: "foo", + HostName: "bar", AgentFields: common.MapStr{ "name": "elastic-node", "version": "1.0.0", @@ -90,12 +106,13 @@ func TestServiceTransform(t *testing.T) { "name": "Express", "version": "1.2.3", }, + "node": common.MapStr{"name": serviceNodeName}, }, }, } for _, test := range tests { - assert.Equal(t, test.Fields, test.Service.Fields()) + assert.Equal(t, test.Fields, test.Service.Fields(test.ContainerID, test.HostName)) assert.Equal(t, test.AgentFields, test.Service.AgentFields()) } } diff --git a/model/span/event.go b/model/span/event.go index 80506c7be7f..3ac707cda6c 100644 --- a/model/span/event.go +++ b/model/span/event.go @@ -26,14 +26,19 @@ import ( "github.com/santhosh-tekuri/jsonschema" + "github.com/elastic/beats/libbeat/beat" + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/monitoring" + m "github.com/elastic/apm-server/model" "github.com/elastic/apm-server/model/span/generated/schema" "github.com/elastic/apm-server/transform" "github.com/elastic/apm-server/utility" "github.com/elastic/apm-server/validation" - "github.com/elastic/beats/libbeat/beat" - "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/monitoring" +) + +const ( + spanDocType = "span" ) var ( @@ -43,8 +48,6 @@ var ( stacktraceCounter = monitoring.NewInt(Metrics, "stacktraces") frameCounter = monitoring.NewInt(Metrics, "frames") - spanDocType = "span" - processorEntry = common.MapStr{"name": "transaction", "event": spanDocType} cachedModelSchema = validation.CreateSchema(schema.ModelSchema, "span") diff --git a/model/transaction/event.go b/model/transaction/event.go index a859074924a..c258296de2e 100644 --- a/model/transaction/event.go +++ b/model/transaction/event.go @@ -23,20 +23,22 @@ import ( "github.com/santhosh-tekuri/jsonschema" + "github.com/elastic/beats/libbeat/beat" + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/monitoring" + m "github.com/elastic/apm-server/model" "github.com/elastic/apm-server/model/metadata" "github.com/elastic/apm-server/model/transaction/generated/schema" "github.com/elastic/apm-server/transform" "github.com/elastic/apm-server/utility" "github.com/elastic/apm-server/validation" - "github.com/elastic/beats/libbeat/beat" - "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/monitoring" ) const ( processorName = "transaction" transactionDocType = "transaction" + emptyString = "" ) var ( @@ -182,7 +184,7 @@ func (e *Event) Transform(tctx *transform.Context) []beat.Event { utility.Update(fields, "user", e.User.Fields()) utility.DeepUpdate(fields, "client", e.Http.ClientFields(e.User.ClientFields())) utility.DeepUpdate(fields, "user_agent", e.User.UserAgentFields()) - utility.DeepUpdate(fields, "service", e.Service.Fields()) + utility.DeepUpdate(fields, "service", e.Service.Fields(emptyString, emptyString)) utility.DeepUpdate(fields, "agent", e.Service.AgentFields()) utility.AddId(fields, "parent", e.ParentId) utility.AddId(fields, "trace", &e.TraceId) diff --git a/model/transaction/event_test.go b/model/transaction/event_test.go index 1ccf1fef42b..0dbe119c63f 100644 --- a/model/transaction/event_test.go +++ b/model/transaction/event_test.go @@ -31,9 +31,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/apm-server/model/metadata" "github.com/elastic/apm-server/transform" - "github.com/elastic/beats/libbeat/common" ) func TestTransactionEventDecodeFailure(t *testing.T) { @@ -299,7 +300,7 @@ func TestEventsTransformWithMetadata(t *testing.T) { id, name, ip, userAgent := "123", "jane", "63.23.123.4", "node-js-2.3" user := metadata.User{Id: &id, Name: &name, IP: &ip, UserAgent: &userAgent} url, referer := "https://localhost", "http://localhost" - serviceName := "myservice" + serviceName, serviceNodeName, serviceVersion := "myservice", "service-123", "2.1.3" metadataLabels := common.MapStr{"a": true} service := metadata.Service{Name: &serviceName} system := func() *metadata.System { @@ -317,7 +318,7 @@ func TestEventsTransformWithMetadata(t *testing.T) { "name": "transaction", }, "service": common.MapStr{ - "name": "myservice", + "name": serviceName, }, "transaction": common.MapStr{ "duration": common.MapStr{"us": 0}, @@ -329,7 +330,7 @@ func TestEventsTransformWithMetadata(t *testing.T) { "timestamp": common.MapStr{"us": timestampUs}, } - txValidWithSystem := common.MapStr{ + txValidWithSystemES := common.MapStr{ "host": common.MapStr{ "architecture": architecture, "hostname": hostname, @@ -343,7 +344,7 @@ func TestEventsTransformWithMetadata(t *testing.T) { "name": "transaction", }, "service": common.MapStr{ - "name": "myservice", + "name": serviceName, "node": common.MapStr{"name": hostname}, }, "labels": common.MapStr{"a": true}, "timestamp": common.MapStr{"us": timestampUs}, @@ -383,7 +384,7 @@ func TestEventsTransformWithMetadata(t *testing.T) { "name": "transaction", }, "service": common.MapStr{ - "name": "myservice", + "name": "myservice", "node": common.MapStr{"name": "jane"}, }, "timestamp": common.MapStr{"us": timestampUs}, "transaction": common.MapStr{ @@ -442,14 +443,13 @@ func TestEventsTransformWithMetadata(t *testing.T) { Output: []common.MapStr{txValidEs, spanEs}, Msg: "Payload with multiple Events", }, - { Metadata: metadata.NewMetadata( &service, system(), nil, nil, metadataLabels, ), Event: &txValid, - Output: []common.MapStr{txValidWithSystem}, + Output: []common.MapStr{txValidWithSystemES}, Msg: "Payload with System and Event", }, { @@ -461,6 +461,36 @@ func TestEventsTransformWithMetadata(t *testing.T) { Output: []common.MapStr{txWithContextEs}, Msg: "Payload with Service, System and Event with context", }, + { + Metadata: metadata.NewMetadata( + &service, func() *metadata.System { s := system(); s.ConfiguredHostname = &name; return s }(), + nil, nil, metadataLabels, + ), + Event: &txWithContext, + Output: []common.MapStr{txWithContextEs}, + Msg: "Payload with Service, System and Event with context", + }, + { + Metadata: metadata.NewMetadata( + func() *metadata.Service { + s, err := metadata.DecodeService(map[string]interface{}{ + "name": "m-name", + "version": "m-version", + "node": map[string]interface{}{"configured_name": serviceNodeName}}, nil) + require.NoError(t, err) + return s + }(), + nil, nil, nil, nil, + ), + Event: &Event{Timestamp: timestamp, Service: &metadata.Service{Version: &serviceVersion}}, + Output: []common.MapStr{{ + "processor": common.MapStr{"event": "transaction", "name": "transaction"}, + "service": common.MapStr{"name": "m-name", "version": serviceVersion, "node": common.MapStr{"name": serviceNodeName}}, + "timestamp": common.MapStr{"us": timestampUs}, + "transaction": common.MapStr{"duration": common.MapStr{"us": 0}, "id": "", "type": "", "sampled": true}, + }}, + Msg: "Deep update service fields", + }, } for idx, test := range tests { diff --git a/model/transaction/generated/schema/transaction.go b/model/transaction/generated/schema/transaction.go index b9e352036a9..80495d618b3 100644 --- a/model/transaction/generated/schema/transaction.go +++ b/model/transaction/generated/schema/transaction.go @@ -363,6 +363,16 @@ const ModelSchema = `{ "description": "Version of the service emitting this event", "type": ["string", "null"], "maxLength": 1024 + }, + "node": { + "description": "Unique meaningful name of the service node.", + "type": ["object", "null"], + "properties": { + "configured_name": { + "type": ["string", "null"], + "maxLength": 1024 + } + } } } } diff --git a/processor/stream/package_tests/metadata_attrs_test.go b/processor/stream/package_tests/metadata_attrs_test.go index 6254c5f914d..66b019a4ca4 100644 --- a/processor/stream/package_tests/metadata_attrs_test.go +++ b/processor/stream/package_tests/metadata_attrs_test.go @@ -118,6 +118,7 @@ func TestMetadataPayloadAttrsMatchFields(t *testing.T) { {Template: "user.username", Mapping: "user.name"}, {Template: "process.argv", Mapping: "process.args"}, {Template: "labels.*", Mapping: "labels"}, + {Template: "service.node.configured_name", Mapping: "service.node.name"}, } setup.EventFieldsMappedToTemplateFields(t, eventFields, mappingFields) } @@ -153,6 +154,7 @@ func TestKeywordLimitationOnMetadataAttrs(t *testing.T) { {Template: "host.name", Mapping: "system.configured_hostname"}, {Template: "host.", Mapping: "system."}, {Template: "user.name", Mapping: "user.username"}, + {Template: "service.node.name", Mapping: "service.node.configured_name"}, //{Template: "url.", Mapping:"context.request.url."}, }, ) diff --git a/processor/stream/test_approved_es_documents/testIntakeIntegrationErrors.approved.json b/processor/stream/test_approved_es_documents/testIntakeIntegrationErrors.approved.json index c4a9d8796fa..cd590fdb4b1 100644 --- a/processor/stream/test_approved_es_documents/testIntakeIntegrationErrors.approved.json +++ b/processor/stream/test_approved_es_documents/testIntakeIntegrationErrors.approved.json @@ -281,6 +281,9 @@ "version": "1.2" }, "name": "service1", + "node": { + "name": "1234_service-12a3-acgh" + }, "runtime": { "name": "node", "version": "8.0.0" @@ -370,6 +373,9 @@ "version": "8" }, "name": "1234_service-12a3", + "node": { + "name": "1234_service-12a3-hx4ff" + }, "runtime": { "name": "node", "version": "8.0.0" @@ -450,6 +456,9 @@ "version": "2.5" }, "name": "service1", + "node": { + "name": "1234_service-12a3-hx4ff" + }, "runtime": { "name": "cruby", "version": "2.5" @@ -532,6 +541,9 @@ "version": "8" }, "name": "1234_service-12a3", + "node": { + "name": "1234_service-12a3-hx4ff" + }, "runtime": { "name": "node", "version": "8.0.0" diff --git a/processor/stream/test_approved_es_documents/testIntakeIntegrationEvents.approved.json b/processor/stream/test_approved_es_documents/testIntakeIntegrationEvents.approved.json index c654b58a9b7..f78830bf810 100644 --- a/processor/stream/test_approved_es_documents/testIntakeIntegrationEvents.approved.json +++ b/processor/stream/test_approved_es_documents/testIntakeIntegrationEvents.approved.json @@ -46,7 +46,10 @@ "language": { "name": "ecmascript" }, - "name": "1234_service-12a3" + "name": "1234_service-12a3", + "node": { + "name": "container-id" + } }, "timestamp": { "us": 1533827045999000 @@ -128,7 +131,10 @@ "language": { "name": "ecmascript" }, - "name": "1234_service-12a3" + "name": "1234_service-12a3", + "node": { + "name": "container-id" + } }, "timestamp": { "us": 1535655207154000 @@ -196,7 +202,10 @@ "language": { "name": "ecmascript" }, - "name": "1234_service-12a3" + "name": "1234_service-12a3", + "node": { + "name": "container-id" + } } } ] diff --git a/processor/stream/test_approved_es_documents/testIntakeIntegrationMetricsets.approved.json b/processor/stream/test_approved_es_documents/testIntakeIntegrationMetricsets.approved.json index 2b66b908d5e..3943ab86422 100644 --- a/processor/stream/test_approved_es_documents/testIntakeIntegrationMetricsets.approved.json +++ b/processor/stream/test_approved_es_documents/testIntakeIntegrationMetricsets.approved.json @@ -47,7 +47,10 @@ "language": { "name": "ecmascript" }, - "name": "1234_service-12a3" + "name": "1234_service-12a3", + "node": { + "name": "service-a-node-1" + } }, "short_counter": 227, "span": { @@ -115,7 +118,10 @@ "language": { "name": "ecmascript" }, - "name": "1234_service-12a3" + "name": "1234_service-12a3", + "node": { + "name": "service-a-node-1" + } }, "user": { "email": "user@mail.com", diff --git a/processor/stream/test_approved_es_documents/testIntakeIntegrationOptionalTimestamps.approved.json b/processor/stream/test_approved_es_documents/testIntakeIntegrationOptionalTimestamps.approved.json index c516bc9b4e9..a8593b7165c 100644 --- a/processor/stream/test_approved_es_documents/testIntakeIntegrationOptionalTimestamps.approved.json +++ b/processor/stream/test_approved_es_documents/testIntakeIntegrationOptionalTimestamps.approved.json @@ -39,6 +39,9 @@ "version": "8" }, "name": "backendspans", + "node": { + "name": "prod1.example.com" + }, "runtime": { "name": "node", "version": "8.0.0" @@ -147,6 +150,9 @@ "version": "8" }, "name": "backendspans", + "node": { + "name": "prod1.example.com" + }, "runtime": { "name": "node", "version": "8.0.0" diff --git a/processor/stream/test_approved_es_documents/testIntakeIntegrationTransactions.approved.json b/processor/stream/test_approved_es_documents/testIntakeIntegrationTransactions.approved.json index f9c7529788a..e364256be61 100644 --- a/processor/stream/test_approved_es_documents/testIntakeIntegrationTransactions.approved.json +++ b/processor/stream/test_approved_es_documents/testIntakeIntegrationTransactions.approved.json @@ -59,6 +59,9 @@ "version": "8" }, "name": "1234_service-12a3", + "node": { + "name": "1234_service-12a3" + }, "runtime": { "name": "node", "version": "8.0.0" @@ -207,6 +210,9 @@ "version": "8" }, "name": "1234_service-12a3", + "node": { + "name": "1234_service-12a3" + }, "runtime": { "name": "node", "version": "7.0" @@ -327,6 +333,9 @@ "version": "2.5" }, "name": "service1", + "node": { + "name": "1234_service-12a3-yuewß" + }, "runtime": { "name": "cruby", "version": "2.5" diff --git a/testdata/intake-v2/errors.ndjson b/testdata/intake-v2/errors.ndjson index 995228aa222..83a96ba2991 100644 --- a/testdata/intake-v2/errors.ndjson +++ b/testdata/intake-v2/errors.ndjson @@ -1,5 +1,5 @@ -{"metadata": {"process": {"ppid": 6789, "pid": 1234, "argv": ["node", "server.js"], "title": "node"}, "user": { "id": 123, "username": "bar", "email": "bar@example.com"}, "system": {"platform": "darwin", "hostname": "prod1.example.com", "configured_hostname": "prod.example", "detected_hostname": "myhostname", "architecture": "x64", "container": {"id": "container-id"}, "kubernetes": {"namespace": "namespace1", "pod": {"uid": "pod-uid", "name": "pod-name"}, "node": {"name": "node-name"}}}, "service": {"name": "1234_service-12a3", "language": {"version": "8", "name": "ecmascript"}, "agent": {"version": "3.14.0", "name": "elastic-node", "ephemeral_id":"abcdef123"}, "environment": "staging", "framework": {"version": "1.2.3", "name": "Express"}, "version": "5.1.3", "runtime": {"version": "8.0.0", "name": "node"}}}} -{"error": {"id": "0123456789012345", "timestamp": 1494342245999999, "culprit": "my.module.function_name","log": { "message": "My service could not talk to the database named foobar", "param_message": "My service could not talk to the database named %s", "logger_name": "my.logger.name", "level": "warning", "stacktrace": [ { "abs_path": "/real/file/name.py", "filename": "/webpack/file/name.py", "function": "foo", "vars": { "key": "value" }, "pre_context": ["line1", "line2"], "context_line": "line3","library_frame": false,"lineno": 3,"module": "App::MyModule","colno": 4,"post_context": ["line4","line5" ]},{"filename": "lib/instrumentation/index.js","lineno": 102,"function": "instrumented","abs_path": "/Users/watson/code/node_modules/elastic/lib/instrumentation/index.js","vars": {"key": "value"},"pre_context": [" var trans = this.currentTransaction",""," return instrumented",""," function instrumented () {"," var prev = ins.currentTransaction", " ins.currentTransaction = trans"],"context_line": " var result = original.apply(this, arguments)","post_context": [" ins.currentTransaction = prev"," return result","}","}","","Instrumentation.prototype._recoverTransaction = function (trans) {"," if (this.currentTransaction === trans) return"]}]},"exception": {"message": "The username root is unknown","type": "DbError","module": "__builtins__","code": 42,"handled": false,"attributes": {"foo": "bar" }, "cause":[{"type":"InternalDbError", "message":"something wrong writing a file", "cause":[{"type":"VeryInternalDbError", "message":"disk spinning way too fast"}, {"type":"ConnectionError", "message":"on top of it, internet doesn't work", "parent": 0}]}], "stacktrace": [{ "abs_path": "/real/file/name.py","filename": "file/name.py","function": "foo","vars": {"key": "value"},"pre_context": ["line1","line2"],"context_line": "line3", "library_frame": true,"lineno": 3,"module": "App::MyModule","colno": 4,"post_context": ["line4","line5"]},{"filename": "lib/instrumentation/index.js","lineno": 102,"function": "instrumented","abs_path": "/Users/watson/code/node_modules/elastic/lib/instrumentation/index.js","vars": {"key": "value"},"pre_context": [" var trans = this.currentTransaction",""," return instrumented",""," function instrumented () {", " var prev = ins.currentTransaction"," ins.currentTransaction = trans"],"context_line": " var result = original.apply(this, arguments)","post_context": [" ins.currentTransaction = prev"," return result","}","}","","Instrumentation.prototype._recoverTransaction = function (trans) {"," if (this.currentTransaction === trans) return"]}]},"context": {"page":{"referer":"http://localhost:8000/test/e2e/","url":"http://localhost:8000/test/e2e/general-usecase/"}, "request": {"socket": {"remote_address": "12.53.12.1","encrypted": true},"http_version": "1.1","method": "POST","url": {"protocol": "https:","full": "https://www.example.com/p/a/t/h?query=string#hash","hostname": "www.example.com","port": 8080,"pathname": "/p/a/t/h","search": "?query=string", "hash": "#hash","raw": "/p/a/t/h?query=string#hash"},"headers": {"user-agent": "Mozilla Chrome Edge","content-type": "text/html","cookie": "c1=v1,c2=v2","some-other-header": "foo","array": ["foo","bar","baz"]}, "cookies": {"c1": "v1", "c2": "v2" },"env": {"SERVER_SOFTWARE": "nginx", "GATEWAY_INTERFACE": "CGI/1.1"},"body": "Hello World"},"response": { "status_code": 200, "headers": { "content-type": "application/json" },"headers_sent": true, "finished": true }, "user": { "id": 99, "username": "foo"},"tags": {"organization_uuid": "9f0e9d64-c185-4d21-a6f4-4673ed561ec8"}, "custom": {"my_key": 1,"some_other_value": "foo bar","and_objects": {"foo": ["bar","baz" ] }},"service": {"name": "service1", "language": {"version": "1.2"}, "framework": {"version": "1", "name": "Node"}}}}} +{"metadata": {"process": {"ppid": 6789, "pid": 1234, "argv": ["node", "server.js"], "title": "node"}, "user": { "id": 123, "username": "bar", "email": "bar@example.com"}, "system": {"platform": "darwin", "hostname": "prod1.example.com", "configured_hostname": "prod.example", "detected_hostname": "myhostname", "architecture": "x64", "container": {"id": "container-id"}, "kubernetes": {"namespace": "namespace1", "pod": {"uid": "pod-uid", "name": "pod-name"}, "node": {"name": "node-name"}}}, "service": {"name": "1234_service-12a3","node": {"configured_name": "1234_service-12a3-hx4ff"},"language": {"version": "8", "name": "ecmascript"}, "agent": {"version": "3.14.0", "name": "elastic-node", "ephemeral_id":"abcdef123"}, "environment": "staging", "framework": {"version": "1.2.3", "name": "Express"}, "version": "5.1.3", "runtime": {"version": "8.0.0", "name": "node"}}}} +{"error": {"id": "0123456789012345", "timestamp": 1494342245999999, "culprit": "my.module.function_name","log": { "message": "My service could not talk to the database named foobar", "param_message": "My service could not talk to the database named %s", "logger_name": "my.logger.name", "level": "warning", "stacktrace": [ { "abs_path": "/real/file/name.py", "filename": "/webpack/file/name.py", "function": "foo", "vars": { "key": "value" }, "pre_context": ["line1", "line2"], "context_line": "line3","library_frame": false,"lineno": 3,"module": "App::MyModule","colno": 4,"post_context": ["line4","line5" ]},{"filename": "lib/instrumentation/index.js","lineno": 102,"function": "instrumented","abs_path": "/Users/watson/code/node_modules/elastic/lib/instrumentation/index.js","vars": {"key": "value"},"pre_context": [" var trans = this.currentTransaction",""," return instrumented",""," function instrumented () {"," var prev = ins.currentTransaction", " ins.currentTransaction = trans"],"context_line": " var result = original.apply(this, arguments)","post_context": [" ins.currentTransaction = prev"," return result","}","}","","Instrumentation.prototype._recoverTransaction = function (trans) {"," if (this.currentTransaction === trans) return"]}]},"exception": {"message": "The username root is unknown","type": "DbError","module": "__builtins__","code": 42,"handled": false,"attributes": {"foo": "bar" }, "cause":[{"type":"InternalDbError", "message":"something wrong writing a file", "cause":[{"type":"VeryInternalDbError", "message":"disk spinning way too fast"}, {"type":"ConnectionError", "message":"on top of it, internet doesn't work", "parent": 0}]}], "stacktrace": [{ "abs_path": "/real/file/name.py","filename": "file/name.py","function": "foo","vars": {"key": "value"},"pre_context": ["line1","line2"],"context_line": "line3", "library_frame": true,"lineno": 3,"module": "App::MyModule","colno": 4,"post_context": ["line4","line5"]},{"filename": "lib/instrumentation/index.js","lineno": 102,"function": "instrumented","abs_path": "/Users/watson/code/node_modules/elastic/lib/instrumentation/index.js","vars": {"key": "value"},"pre_context": [" var trans = this.currentTransaction",""," return instrumented",""," function instrumented () {", " var prev = ins.currentTransaction"," ins.currentTransaction = trans"],"context_line": " var result = original.apply(this, arguments)","post_context": [" ins.currentTransaction = prev"," return result","}","}","","Instrumentation.prototype._recoverTransaction = function (trans) {"," if (this.currentTransaction === trans) return"]}]},"context": {"page":{"referer":"http://localhost:8000/test/e2e/","url":"http://localhost:8000/test/e2e/general-usecase/"}, "request": {"socket": {"remote_address": "12.53.12.1","encrypted": true},"http_version": "1.1","method": "POST","url": {"protocol": "https:","full": "https://www.example.com/p/a/t/h?query=string#hash","hostname": "www.example.com","port": 8080,"pathname": "/p/a/t/h","search": "?query=string", "hash": "#hash","raw": "/p/a/t/h?query=string#hash"},"headers": {"user-agent": "Mozilla Chrome Edge","content-type": "text/html","cookie": "c1=v1,c2=v2","some-other-header": "foo","array": ["foo","bar","baz"]}, "cookies": {"c1": "v1", "c2": "v2" },"env": {"SERVER_SOFTWARE": "nginx", "GATEWAY_INTERFACE": "CGI/1.1"},"body": "Hello World"},"response": { "status_code": 200, "headers": { "content-type": "application/json" },"headers_sent": true, "finished": true }, "user": { "id": 99, "username": "foo"},"tags": {"organization_uuid": "9f0e9d64-c185-4d21-a6f4-4673ed561ec8"}, "custom": {"my_key": 1,"some_other_value": "foo bar","and_objects": {"foo": ["bar","baz" ] }},"service": {"name": "service1", "node": {"configured_name": "1234_service-12a3-acgh"}, "language": {"version": "1.2"}, "framework": {"version": "1", "name": "Node"}}}}} { "error": {"id": "cdefab0123456789", "trace_id": null, "timestamp": 1533826745999000,"exception": {"message": "Cannot read property 'baz' no defined"}}} { "error": {"id": "cdefab0123456780", "trace_id": "0123456789abcdeffedcba0123456789", "parent_id": "9632587410abcdef", "exception": {"type": "DbError"}, "context":{"service": {"name": "service1", "environment":"testing","language": {"version": "2.5", "name": "ruby"}, "agent": {"version": "2.1.3", "name": "elastic-ruby", "ephemeral_id":"justanid"}, "framework": {"version": "5.0", "name": "Rails"}, "version": "2", "runtime": {"version": "2.5", "name": "cruby"}}}}} { "error": {"id": "abcdef0123456789", "trace_id": "0123456789abcdeffedcba0123456789", "parent_id": "9632587410abcdef", "transaction_id": "1234567890987654", "transaction": { "sampled": true, "type": "request"}, "timestamp": 1533827045999000,"log": {"level": "custom log level","message": "Cannot read property 'baz' of undefined"}}} diff --git a/testdata/intake-v2/errors_2.ndjson b/testdata/intake-v2/errors_2.ndjson index a131c602701..e455b7f2bca 100644 --- a/testdata/intake-v2/errors_2.ndjson +++ b/testdata/intake-v2/errors_2.ndjson @@ -1,5 +1,5 @@ -{"metadata":{"service":{"name":"1234_service-12a3","version":"5.1.3","environment":"staging","language":{"name":"ecmascript","version":"8"},"runtime":{"name":"node","version":"8.0.0"},"framework":{"name":"Express","version":"1.2.3"},"agent":{"name":"elastic-node","version":"3.14.0"}},"process":{"pid":1234,"ppid":7788,"title":"node","argv":["node","server.js"]},"labels": {"tag0": null, "tag1": "one", "tag2": 2},"system":{"hostname":"prod1.example.com","architecture":"x64","platform":"darwin","container":{"id":"container-id"},"kubernetes":{"namespace":"namespace1","pod":{"uid":"pod-uid","name":"pod-name"}}}}} -{"error":{"id":"5f0e9d64c1854d21a6f44673ed561ec8","timestamp":1494342245999999,"culprit":"my.module.function_name","log":{"message":"My service could not talk to the database named foobar","param_message":"My service could not talk to the database named %s","logger_name":"my.logger.name","level":"warning","stacktrace":[{"abs_path":"/real/file/name.py","filename":"/webpack/file/name.py","function":"foo","vars":{"key":"value"},"pre_context":["line1","line2"],"context_line":"line3","library_frame":false,"lineno":3,"module":"App::MyModule","colno":4,"post_context":["line4","line5"]},{"filename":"lib/instrumentation/index.js","lineno":102,"function":"instrumented","abs_path":"/Users/watson/code/node_modules/elastic/lib/instrumentation/index.js","vars":{"key":"value"},"pre_context":[" var trans = this.currentTransaction",""," return instrumented",""," function instrumented () {"," var prev = ins.currentTransaction"," ins.currentTransaction = trans"],"context_line":" var result = original.apply(this, arguments)","post_context":[" ins.currentTransaction = prev"," return result","}","}","","Instrumentation.prototype._recoverTransaction = function (trans) {"," if (this.currentTransaction === trans) return"]}]},"exception":{"message":"The username root is unknown","type":"DbError","module":"__builtins__","code":42,"handled":false,"attributes":{"foo":"bar"},"stacktrace":[{"abs_path":"/real/file/name.py","filename":"file/name.py","function":"foo","vars":{"key":"value"},"pre_context":["line1","line2"],"context_line":"line3","library_frame":true,"lineno":3,"module":"App::MyModule","colno":4,"post_context":["line4","line5"]},{"filename":"lib/instrumentation/index.js","lineno":102,"function":"instrumented","abs_path":"/Users/watson/code/node_modules/elastic/lib/instrumentation/index.js","vars":{"key":"value"},"pre_context":[" var trans = this.currentTransaction",""," return instrumented",""," function instrumented () {"," var prev = ins.currentTransaction"," ins.currentTransaction = trans"],"context_line":" var result = original.apply(this, arguments)","post_context":[" ins.currentTransaction = prev"," return result","}","}","","Instrumentation.prototype._recoverTransaction = function (trans) {"," if (this.currentTransaction === trans) return"]}]},"context":{"service":{"name": "abc","agent":{"name":"python","version":"4.3"},"language":null,"framework":{},"runtime":{"version":"1.2"}},"page":{"referer":"http://localhost:8000/test/e2e/","url":"http://localhost:8000/test/e2e/general-usecase/"},"request":{"socket":{"remote_address":"12.53.12.1","encrypted":true},"http_version":"1.1","method":"POST","url":{"protocol":"https:","full":"https://www.example.com/p/a/t/h?query=string#hash","hostname":"www.example.com","port":"8080","pathname":"/p/a/t/h","search":"?query=string","hash":"#hash","raw":"/p/a/t/h?query=string#hash"},"headers":{"User-Agent":"Mozilla Chrome Edge","Content-Type":"text/html","cookie":"c1=v1,c2=v2","some-other-header":"foo","array":["foo","bar","baz"]},"cookies":{"c1":"v1","c2":"v2"},"env":{"SERVER_SOFTWARE":"nginx","GATEWAY_INTERFACE":"CGI/1.1"},"body":"Hello World"},"response":{"status_code":200,"headers":{"Content-Type":"application/json"},"headers_sent":true,"finished":true},"user":{"id":99,"username":"foo","email":"foo@example.com"},"tags":{"organization_uuid":"9f0e9d64-c185-4d21-a6f4-4673ed561ec8"},"foo": "bar","custom":{"my_key":1,"some_other_value":"foo bar","and_objects":{"foo":["bar","baz"]}}},"transaction":{"id":"945254c5-67a5-417e-8a4e-aa29efcbfb79"}}} +{"metadata":{"service":{"name":"1234_service-12a3","node":{"configured_name":"myservice-node"},"version":"5.1.3","environment":"staging","language":{"name":"ecmascript","version":"8"},"runtime":{"name":"node","version":"8.0.0"},"framework":{"name":"Express","version":"1.2.3"},"agent":{"name":"elastic-node","version":"3.14.0"}},"process":{"pid":1234,"ppid":7788,"title":"node","argv":["node","server.js"]},"labels": {"tag0": null, "tag1": "one", "tag2": 2},"system":{"hostname":"prod1.example.com","architecture":"x64","platform":"darwin","container":{"id":"container-id"},"kubernetes":{"namespace":"namespace1","pod":{"uid":"pod-uid","name":"pod-name"}}}}} +{"error":{"id":"5f0e9d64c1854d21a6f44673ed561ec8","timestamp":1494342245999999,"culprit":"my.module.function_name","log":{"message":"My service could not talk to the database named foobar","param_message":"My service could not talk to the database named %s","logger_name":"my.logger.name","level":"warning","stacktrace":[{"abs_path":"/real/file/name.py","filename":"/webpack/file/name.py","function":"foo","vars":{"key":"value"},"pre_context":["line1","line2"],"context_line":"line3","library_frame":false,"lineno":3,"module":"App::MyModule","colno":4,"post_context":["line4","line5"]},{"filename":"lib/instrumentation/index.js","lineno":102,"function":"instrumented","abs_path":"/Users/watson/code/node_modules/elastic/lib/instrumentation/index.js","vars":{"key":"value"},"pre_context":[" var trans = this.currentTransaction",""," return instrumented",""," function instrumented () {"," var prev = ins.currentTransaction"," ins.currentTransaction = trans"],"context_line":" var result = original.apply(this, arguments)","post_context":[" ins.currentTransaction = prev"," return result","}","}","","Instrumentation.prototype._recoverTransaction = function (trans) {"," if (this.currentTransaction === trans) return"]}]},"exception":{"message":"The username root is unknown","type":"DbError","module":"__builtins__","code":42,"handled":false,"attributes":{"foo":"bar"},"stacktrace":[{"abs_path":"/real/file/name.py","filename":"file/name.py","function":"foo","vars":{"key":"value"},"pre_context":["line1","line2"],"context_line":"line3","library_frame":true,"lineno":3,"module":"App::MyModule","colno":4,"post_context":["line4","line5"]},{"filename":"lib/instrumentation/index.js","lineno":102,"function":"instrumented","abs_path":"/Users/watson/code/node_modules/elastic/lib/instrumentation/index.js","vars":{"key":"value"},"pre_context":[" var trans = this.currentTransaction",""," return instrumented",""," function instrumented () {"," var prev = ins.currentTransaction"," ins.currentTransaction = trans"],"context_line":" var result = original.apply(this, arguments)","post_context":[" ins.currentTransaction = prev"," return result","}","}","","Instrumentation.prototype._recoverTransaction = function (trans) {"," if (this.currentTransaction === trans) return"]}]},"context":{"service":{"name": "abc","node":{"configured_name":"myservice-xz"},"agent":{"name":"python","version":"4.3"},"language":null,"framework":{},"runtime":{"version":"1.2"}},"page":{"referer":"http://localhost:8000/test/e2e/","url":"http://localhost:8000/test/e2e/general-usecase/"},"request":{"socket":{"remote_address":"12.53.12.1","encrypted":true},"http_version":"1.1","method":"POST","url":{"protocol":"https:","full":"https://www.example.com/p/a/t/h?query=string#hash","hostname":"www.example.com","port":"8080","pathname":"/p/a/t/h","search":"?query=string","hash":"#hash","raw":"/p/a/t/h?query=string#hash"},"headers":{"User-Agent":"Mozilla Chrome Edge","Content-Type":"text/html","cookie":"c1=v1,c2=v2","some-other-header":"foo","array":["foo","bar","baz"]},"cookies":{"c1":"v1","c2":"v2"},"env":{"SERVER_SOFTWARE":"nginx","GATEWAY_INTERFACE":"CGI/1.1"},"body":"Hello World"},"response":{"status_code":200,"headers":{"Content-Type":"application/json"},"headers_sent":true,"finished":true},"user":{"id":99,"username":"foo","email":"foo@example.com"},"tags":{"organization_uuid":"9f0e9d64-c185-4d21-a6f4-4673ed561ec8"},"foo": "bar","custom":{"my_key":1,"some_other_value":"foo bar","and_objects":{"foo":["bar","baz"]}}},"transaction":{"id":"945254c5-67a5-417e-8a4e-aa29efcbfb79"}}} {"error":{"id":"8f0e9d68c1854d21a6f44673ed561ec8","timestamp":1494342245000000,"exception":{"message":"foo is not defined","code":"35"},"context":{"service":null}}} {"error":{"id":"7f0e9d68c1854d21a6f44673ed561ec8","timestamp":1494342245000000,"exception":{"type":"connection error"}}} {"error":{"id":"0f0e9d67c1854d21a6f44673ed561ec8","timestamp":1494342245999000,"log":{"level":"custom log level","message":"Cannot read property 'baz' of undefined"}}} diff --git a/testdata/intake-v2/metricsets.ndjson b/testdata/intake-v2/metricsets.ndjson index 9b8ca7dc207..ce74cf63059 100644 --- a/testdata/intake-v2/metricsets.ndjson +++ b/testdata/intake-v2/metricsets.ndjson @@ -1,4 +1,3 @@ -{"metadata": {"user": {"username": "logged-in-user", "id": "axb123hg", "email": "user@mail.com"}, "labels": {"tag0": null, "tag1": "one", "tag2": 2}, "process": {"ppid": null, "pid": 1234, "argv": null, "title": null}, "system": null, "service": {"name": "1234_service-12a3", "language": {"version": null, "name":"ecmascript"}, "agent": {"version": "3.14.0", "name": "elastic-node"}, "environment": null, "framework": null,"version": null, "runtime": null}}} +{"metadata": {"user": {"username": "logged-in-user", "id": "axb123hg", "email": "user@mail.com"}, "labels": {"tag0": null, "tag1": "one", "tag2": 2}, "process": {"ppid": null, "pid": 1234, "argv": null, "title": null}, "system": null, "service": {"name": "1234_service-12a3", "node": {"configured_name": "service-a-node-1"},"language": {"version": null, "name":"ecmascript"}, "agent": {"version": "3.14.0", "name": "elastic-node"}, "environment": null, "framework": null,"version": null, "runtime": null}}} {"metricset": { "samples": { "transaction.breakdown.count":{"value":12}, "transaction.duration.sum.us":{"value":12}, "transaction.duration.count":{"value":2}, "transaction.self_time.sum.us":{"value":10}, "transaction.self_time.count":{"value":2}, "span.self_time.count":{"value":1},"span.self_time.sum.us":{"value":633.288}, "byte_counter": { "value": 1 }, "short_counter": { "value": 227 }, "integer_gauge": { "value": 42767 }, "long_gauge": { "value": 3147483648 }, "float_gauge": { "value": 9.16 }, "double_gauge": { "value": 3.141592653589793 }, "dotted.float.gauge": { "value": 6.12 }, "negative.d.o.t.t.e.d": { "value": -1022 } }, "tags": { "some": "abc", "code": 200, "success": true }, "transaction":{"type":"request","name":"GET /"},"span":{"type":"db","subtype":"mysql"},"timestamp": 1496170422281000 }} {"metricset": { "samples": { "go.memstats.heap.sys.bytes": { "value": 6.520832e+06 } } }} - diff --git a/testdata/intake-v2/only-metadata.ndjson b/testdata/intake-v2/only-metadata.ndjson index 868b7b8a312..e0d865e0396 100644 --- a/testdata/intake-v2/only-metadata.ndjson +++ b/testdata/intake-v2/only-metadata.ndjson @@ -1 +1 @@ -{"metadata": {"process": {"ppid": 6789, "pid": 1234, "argv": ["node", "server.js"], "title": "node"}, "system": {"platform": "darwin", "hostname": "prod1.example.com", "configured_hostname": "foo", "detected_hostname": "myhostname" ,"architecture": "x64", "container": {"id": "container-id"}, "kubernetes": {"namespace": "namespace1", "pod": {"uid": "pod-uid", "name": "pod-name"}, "node": {"name": "node-name"}}}, "service": {"name": "1234_service-12a3", "language": {"version": "8", "name": "ecmascript"}, "agent": {"version": "3.14.0", "name": "elastic-node", "ephemeral_id": "123abcdef"}, "environment": "staging", "framework": {"version": "1.2.3", "name": "Express"}, "version": "5.1.3", "runtime": {"version": "8.0.0", "name": "node"}}, "labels": {"tag0": null, "tag1": "one", "tag2": 2}, "user": {"id": "99","username": "foo","email": "foo@example.com"}}} +{"metadata": {"process": {"ppid": 6789, "pid": 1234, "argv": ["node", "server.js"], "title": "node"}, "system": {"platform": "darwin", "hostname": "prod1.example.com", "configured_hostname": "foo", "detected_hostname": "myhostname" ,"architecture": "x64", "container": {"id": "container-id"}, "kubernetes": {"namespace": "namespace1", "pod": {"uid": "pod-uid", "name": "pod-name"}, "node": {"name": "node-name"}}}, "service": {"name": "1234_service-12a3","node":{"configured_name":"abc-xyz"},"language": {"version": "8", "name": "ecmascript"}, "agent": {"version": "3.14.0", "name": "elastic-node", "ephemeral_id": "123abcdef"}, "environment": "staging", "framework": {"version": "1.2.3", "name": "Express"}, "version": "5.1.3", "runtime": {"version": "8.0.0", "name": "node"}}, "labels": {"tag0": null, "tag1": "one", "tag2": 2}, "user": {"id": "99","username": "foo","email": "foo@example.com"}}} diff --git a/testdata/intake-v2/transactions.ndjson b/testdata/intake-v2/transactions.ndjson index 678c2dd7168..a57bfc39b5e 100644 --- a/testdata/intake-v2/transactions.ndjson +++ b/testdata/intake-v2/transactions.ndjson @@ -1,4 +1,4 @@ -{"metadata": {"service": {"name": "1234_service-12a3","version": "5.1.3","environment": "staging","language": {"name": "ecmascript","version": "8"},"runtime": {"name": "node","version": "8.0.0"},"framework": {"name": "Express","version": "1.2.3"},"agent": {"name": "elastic-node","version": "3.14.0"}},"user": {"id": "123user", "username": "bar", "email": "bar@user.com"}, "labels": {"tag0": null, "tag1": "one", "tag2": 2}, "process": {"pid": 1234,"ppid": 6789,"title": "node","argv": ["node","server.js"]},"system": {"hostname": "prod1.example.com","architecture": "x64","platform": "darwin", "container": {"id": "container-id"}, "kubernetes": {"namespace": "namespace1", "pod": {"uid": "pod-uid", "name": "pod-name"}, "node": {"name": "node-name"}}}}} +{"metadata": {"service": {"name": "1234_service-12a3","node": {"configured_name": "1234_service-12a3"},"version": "5.1.3","environment": "staging","language": {"name": "ecmascript","version": "8"},"runtime": {"name": "node","version": "8.0.0"},"framework": {"name": "Express","version": "1.2.3"},"agent": {"name": "elastic-node","version": "3.14.0"}},"user": {"id": "123user", "username": "bar", "email": "bar@user.com"}, "labels": {"tag0": null, "tag1": "one", "tag2": 2}, "process": {"pid": 1234,"ppid": 6789,"title": "node","argv": ["node","server.js"]},"system": {"hostname": "prod1.example.com","architecture": "x64","platform": "darwin", "container": {"id": "container-id"}, "kubernetes": {"namespace": "namespace1", "pod": {"uid": "pod-uid", "name": "pod-name"}, "node": {"name": "node-name"}}}}} {"transaction": { "id": "945254c567a5417e", "trace_id": "0123456789abcdef0123456789abcdef", "parent_id": "abcdefabcdef01234567", "type": "request", "duration": 32.592981, "span_count": { "started": 43 }}} {"transaction": {"id": "4340a8e0df1906ecbfa9", "trace_id": "0acd456789abcdef0123456789abcdef", "name": "GET /api/types","type": "request","duration": 32.592981,"result": "success", "timestamp": 1496170407154000, "sampled": true, "span_count": {"started": 17},"context": {"service": {"runtime": {"version": "7.0"}},"page":{"referer":"http://localhost:8000/test/e2e/","url":"http://localhost:8000/test/e2e/general-usecase/"}, "request": {"socket": {"remote_address": "12.53.12.1","encrypted": true},"http_version": "1.1","method": "POST","url": {"protocol": "https:","full": "https://www.example.com/p/a/t/h?query=string#hash","hostname": "www.example.com","port": "8080","pathname": "/p/a/t/h","search": "?query=string","hash": "#hash","raw": "/p/a/t/h?query=string#hash"},"headers": {"user-agent":["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36","Mozilla Chrome Edge"],"content-type": "text/html","cookie": "c1=v1, c2=v2","some-other-header": "foo","array": ["foo","bar","baz"]},"cookies": {"c1": "v1","c2": "v2"},"env": {"SERVER_SOFTWARE": "nginx","GATEWAY_INTERFACE": "CGI/1.1"},"body": {"str": "hello world","additional": { "foo": {},"bar": 123,"req": "additional information"}}},"response": {"status_code": 200,"headers": {"content-type": "application/json"},"headers_sent": true,"finished": true}, "user": {"id": "99","username": "foo"},"tags": {"organization_uuid": "9f0e9d64-c185-4d21-a6f4-4673ed561ec8", "tag2": 12, "tag3": 12.45, "tag4": false, "tag5": null },"custom": {"my_key": 1,"some_other_value": "foo bar","and_objects": {"foo": ["bar","baz"]},"(": "not a valid regex and that is fine"}}}} -{"transaction": { "id": "cdef4340a8e0df19", "trace_id": "0acd456789abcdef0123456789abcdef", "type": "request", "duration": 13.980558, "timestamp": 1532976822281000, "sampled": null, "span_count": { "dropped": 55, "started": 436 }, "marks": {"navigationTiming": {"appBeforeBootstrap": 608.9300000000001,"navigationStart": -21},"another_mark": {"some_long": 10,"some_float": 10.0}, "performance": {}}, "context": { "request": { "socket": { "remote_address": null, "encrypted": null }, "method": "POST", "headers": { "user-agent": null, "content-type": null, "cookie": null }, "url": { "protocol": null, "full": null, "hostname": null, "port": null, "pathname": null, "search": null, "hash": null, "raw": null } }, "response": { "headers": { "content-type": null } }, "service": {"environment":"testing","name": "service1", "language": {"version": "2.5", "name": "ruby"}, "agent": {"version": "2.2", "name": "elastic-ruby", "ephemeral_id": "justanid"}, "framework": {"version": "5.0", "name": "Rails"}, "version": "2", "runtime": {"version": "2.5", "name": "cruby"}}}}} +{"transaction": { "id": "cdef4340a8e0df19", "trace_id": "0acd456789abcdef0123456789abcdef", "type": "request", "duration": 13.980558, "timestamp": 1532976822281000, "sampled": null, "span_count": { "dropped": 55, "started": 436 }, "marks": {"navigationTiming": {"appBeforeBootstrap": 608.9300000000001,"navigationStart": -21},"another_mark": {"some_long": 10,"some_float": 10.0}, "performance": {}}, "context": { "request": { "socket": { "remote_address": null, "encrypted": null }, "method": "POST", "headers": { "user-agent": null, "content-type": null, "cookie": null }, "url": { "protocol": null, "full": null, "hostname": null, "port": null, "pathname": null, "search": null, "hash": null, "raw": null } }, "response": { "headers": { "content-type": null } }, "service": {"environment":"testing","name": "service1","node": {"configured_name": "1234_service-12a3-yuewß"}, "language": {"version": "2.5", "name": "ruby"}, "agent": {"version": "2.2", "name": "elastic-ruby", "ephemeral_id": "justanid"}, "framework": {"version": "5.0", "name": "Rails"}, "version": "2", "runtime": {"version": "2.5", "name": "cruby"}}}}} diff --git a/testdata/intake-v2/transactions_spans.ndjson b/testdata/intake-v2/transactions_spans.ndjson index 076145680fe..ac849865f91 100644 --- a/testdata/intake-v2/transactions_spans.ndjson +++ b/testdata/intake-v2/transactions_spans.ndjson @@ -1,5 +1,5 @@ {"metadata":{"service":{"name":"1234_service-12a3","version":"5.1.3","environment":"staging","language":{"name":"ecmascript","version":"8"},"runtime":{"name":"node","version":"8.0.0"},"framework":{"name":"Express","version":"1.2.3"},"agent":{"name":"elastic-node","version":"3.14.0"}},"process":{"pid":1234,"ppid":6789,"title":"node","argv":["node","server.js"]},"system":{"hostname":"prod1.example.com","architecture":"x64","platform":"darwin","container":{"id":"container-id"},"kubernetes":{"namespace":"namespace1","pod":{"uid":"pod-uid","name":"pod-name"}}},"user": {"id": "123user", "username": "foo", "email": "foo@bar.com"}}} -{"transaction":{"id":"945254c567a5417e","name":"GET /api/types","type":"request","duration":32.592981,"result":"success","timestamp":1496170407154000,"sampled":true,"span_count":{"dropped":2,"started":4},"context":{"service":{"name": "serviceabc","agent":{"name":"js-base","version":"1.3"},"language":{},"framework":null,"runtime":{"name":"javascript"}},"foo": "bar","page":{"referer":"http://localhost:8000/test/e2e/","url":"http://localhost:8000/test/e2e/general-usecase/"},"request":{"socket":{"remote_address":"12.53.12.1","encrypted":true},"http_version":"1.1","method":"POST","url":{"protocol":"https:","full":"https://www.example.com/p/a/t/h?query=string#hash","hostname":"www.example.com","port":"8080","pathname":"/p/a/t/h","search":"?query=string","hash":"#hash","raw":"/p/a/t/h?query=string#hash"},"headers":{"User-Agent":"Mozilla Chrome Edge","Content-Type":"text/html","cookie":"c1=v1,c2=v2","some-other-header":"foo","array":["foo","bar","baz"]},"cookies":{"c1":"v1","c2":"v2"},"env":{"SERVER_SOFTWARE":"nginx","GATEWAY_INTERFACE":"CGI/1.1"},"body":{"str":"hello world","additional":{"foo":{},"bar":123,"req":"additional information"}}},"response":{"status_code":200,"headers":{"content-type":"application/json"},"headers_sent":true,"finished":true},"user":{"id":"99","email":"foo@example.com"},"tags":{"organization_uuid":"9f0e9d64-c185-4d21-a6f4-4673ed561ec8", "number_code": 2, "bool_error": false},"custom":{"my_key":1,"some_other_value":"foo bar","and_objects":{"foo":["bar","baz"]},"(":"not a valid regex and that is fine"}},"marks":{"navigationTiming":{"appBeforeBootstrap":608.9300000000001,"navigationStart":-21},"another_mark":{"some_long":10,"some_float":10.0},"performance":{}},"trace_id":"945254c567a5417eaaaaaaaaaaaaaaaa"}} +{"transaction":{"id":"945254c567a5417e","name":"GET /api/types","type":"request","duration":32.592981,"result":"success","timestamp":1496170407154000,"sampled":true,"span_count":{"dropped":2,"started":4},"context":{"service":{"name": "serviceabc","node":{"configured_name":"special-name"},"agent":{"name":"js-base","version":"1.3"},"language":{},"framework":null,"runtime":{"name":"javascript"}},"foo": "bar","page":{"referer":"http://localhost:8000/test/e2e/","url":"http://localhost:8000/test/e2e/general-usecase/"},"request":{"socket":{"remote_address":"12.53.12.1","encrypted":true},"http_version":"1.1","method":"POST","url":{"protocol":"https:","full":"https://www.example.com/p/a/t/h?query=string#hash","hostname":"www.example.com","port":"8080","pathname":"/p/a/t/h","search":"?query=string","hash":"#hash","raw":"/p/a/t/h?query=string#hash"},"headers":{"User-Agent":"Mozilla Chrome Edge","Content-Type":"text/html","cookie":"c1=v1,c2=v2","some-other-header":"foo","array":["foo","bar","baz"]},"cookies":{"c1":"v1","c2":"v2"},"env":{"SERVER_SOFTWARE":"nginx","GATEWAY_INTERFACE":"CGI/1.1"},"body":{"str":"hello world","additional":{"foo":{},"bar":123,"req":"additional information"}}},"response":{"status_code":200,"headers":{"content-type":"application/json"},"headers_sent":true,"finished":true},"user":{"id":"99","email":"foo@example.com"},"tags":{"organization_uuid":"9f0e9d64-c185-4d21-a6f4-4673ed561ec8", "number_code": 2, "bool_error": false},"custom":{"my_key":1,"some_other_value":"foo bar","and_objects":{"foo":["bar","baz"]},"(":"not a valid regex and that is fine"}},"marks":{"navigationTiming":{"appBeforeBootstrap":608.9300000000001,"navigationStart":-21},"another_mark":{"some_long":10,"some_float":10.0},"performance":{}},"trace_id":"945254c567a5417eaaaaaaaaaaaaaaaa"}} {"span":{"id":"0aaaaaaaaaaaaaaa","timestamp":1496170407154000,"parent":null,"name":"SELECT FROM product_types","type":"db.postgresql.query","start":2.83092,"duration":3.781912,"sync":false,"stacktrace":[{"function":"onread","abs_path":"net.js","filename":"net.js","lineno":547,"library_frame":true,"vars":{"key":"value"},"module":"some module","colno":4,"context_line":"line3","pre_context":[" var trans = this.currentTransaction",""],"post_context":[" ins.currentTransaction = prev"," return result","}"]},{"filename":"my2file.js","lineno":10}],"context":{"db":{"instance":"customers","statement":"SELECT * FROM product_types WHERE user_id=?","type":"sql","user":"readonly_user"},"http":{"url":"http://localhost:8000","status_code":200,"method":"GET"},"tags":{"span_tag":"something"}},"transaction_id":"945254c567a5417e","parent_id":"945254c567a5417e","trace_id":"945254c567a5417eaaaaaaaaaaaaaaaa"}} {"span":{"id":"1aaaaaaaaaaaaaaa","timestamp":1496170407154000,"parent":0,"name":"GET /api/types","type":"request.external","start":0,"duration":32.592981,"transaction_id":"945254c567a5417e","parent_id":"945254c567a5417e","trace_id":"945254c567a5417eaaaaaaaaaaaaaaaa", "context":{"service":null}}} {"span":{"id":"2aaaaaaaaaaaaaaa","timestamp":1496170407154000,"parent":1,"name":"GET /api/types","type":"request","subtype":"http","action":"post","start":1.845,"duration":3.5642981,"stacktrace":[],"context":{},"transaction_id":"945254c567a5417e","parent_id":"945254c567a5417e","trace_id":"945254c567a5417eaaaaaaaaaaaaaaaa"}} diff --git a/tests/system/error.approved.json b/tests/system/error.approved.json index 1ce65b38c8f..0c23e9c50fd 100644 --- a/tests/system/error.approved.json +++ b/tests/system/error.approved.json @@ -54,6 +54,9 @@ }, "service": { "name": "1234_service-12a3", + "node": { + "name": "myservice-node" + }, "language": { "version": "8", "name": "ecmascript" @@ -139,6 +142,9 @@ }, "service": { "name": "abc", + "node": { + "name": "myservice-xz" + }, "language": { "version": "8", "name": "ecmascript" @@ -458,6 +464,9 @@ }, "service": { "name": "1234_service-12a3", + "node": { + "name": "myservice-node" + }, "language": { "version": "8", "name": "ecmascript" @@ -548,6 +557,9 @@ }, "service": { "name": "1234_service-12a3", + "node": { + "name": "myservice-node" + }, "language": { "version": "8", "name": "ecmascript" diff --git a/tests/system/transaction.approved.json b/tests/system/transaction.approved.json index 2dea832c3a9..5c7c8961695 100644 --- a/tests/system/transaction.approved.json +++ b/tests/system/transaction.approved.json @@ -54,6 +54,9 @@ }, "service": { "name": "serviceabc", + "node": { + "name": "special-name" + }, "language": { "version": "8", "name": "ecmascript" @@ -264,6 +267,9 @@ "version": "8" }, "name": "1234_service-12a3", + "node": { + "name": "container-id" + }, "environment": "staging" }, "transaction": { @@ -359,6 +365,9 @@ "version": "8" }, "name": "1234_service-12a3", + "node": { + "name": "container-id" + }, "environment": "staging" }, "transaction": { @@ -453,7 +462,10 @@ "version": "8" }, "environment": "staging", - "name": "1234_service-12a3" + "name": "1234_service-12a3", + "node": { + "name": "container-id" + } }, "transaction": { "type": "request",