diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 347db2d..39c1b25 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -46,3 +46,22 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + test: + runs-on: ubuntu-latest + services: + clickhouse: + image: clickhouse/clickhouse-server:latest + ports: + - "9000:9000" + - "8123:8123" + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Go + uses: actions/setup-go@v5 + - name: Run tests + run: | + go test ./exporter/clickhousestsexporter/... + go test ./exporter/ststopologyexporter/... + go test ./extension/ingestionapikeyauthextension/... + go test ./connector/stsservicegraphconnector/... diff --git a/connector/stsservicegraphconnector/generated_component_test.go b/connector/stsservicegraphconnector/generated_component_test.go index 5772f43..602cf44 100644 --- a/connector/stsservicegraphconnector/generated_component_test.go +++ b/connector/stsservicegraphconnector/generated_component_test.go @@ -16,7 +16,7 @@ import ( ) func TestComponentFactoryType(t *testing.T) { - require.Equal(t, "servicegraph", NewFactory().Type().String()) + require.Equal(t, "stsservicegraph", NewFactory().Type().String()) } func TestComponentConfigStruct(t *testing.T) { diff --git a/exporter/clickhousestsexporter/config_test.go b/exporter/clickhousestsexporter/config_test.go index 94f9460..6e0972e 100644 --- a/exporter/clickhousestsexporter/config_test.go +++ b/exporter/clickhousestsexporter/config_test.go @@ -73,6 +73,8 @@ func TestLoadConfig(t *testing.T) { QueueSize: 100, StorageID: &storageID, }, + CreateResourcesTable: true, + CreateTracesTable: true, }, }, } diff --git a/exporter/clickhousestsexporter/exporter_traces_test.go b/exporter/clickhousestsexporter/exporter_traces_test.go index 03c5760..4889f09 100644 --- a/exporter/clickhousestsexporter/exporter_traces_test.go +++ b/exporter/clickhousestsexporter/exporter_traces_test.go @@ -44,8 +44,7 @@ func TestExporter_pushTracesData(t *testing.T) { t.Run("check insert resources with service name and attributes", func(t *testing.T) { initClickhouseTestServer(t, func(query string, values []driver.Value) error { if strings.HasPrefix(query, "INSERT") && strings.Contains(query, "otel_resources") { - require.Equal(t, "test-service", values[2]) - require.Equal(t, map[string]string{"service.name": "test-service"}, values[3]) + require.Equal(t, map[string]string{"service.name": "test-service"}, values[2]) } return nil }) diff --git a/exporter/ststopologyexporter/internal/topology.go b/exporter/ststopologyexporter/internal/topology.go index 3305c75..daef656 100644 --- a/exporter/ststopologyexporter/internal/topology.go +++ b/exporter/ststopologyexporter/internal/topology.go @@ -31,9 +31,12 @@ func (c *ComponentsCollection) AddResource(attrs *pcommon.Map) bool { if !ok { return false } - serviceNamespace, ok := attrs.Get("service.namespace") + serviceNamespaceValue, ok := attrs.Get("service.namespace") + var serviceNamespace string if !ok { - return false + serviceNamespace = "default" + } else { + serviceNamespace = serviceNamespaceValue.AsString() } instanceId, ok := attrs.Get("service.instance.id") var serviceInstanceId pcommon.Value @@ -46,7 +49,7 @@ func (c *ComponentsCollection) AddResource(attrs *pcommon.Map) bool { serviceInstanceName = fmt.Sprintf("%s - %s", serviceName.AsString(), instanceId.AsString()) } - namespaceIdentifier := fmt.Sprintf("urn:opentelemetry:namespace/%s", serviceNamespace.AsString()) + namespaceIdentifier := fmt.Sprintf("urn:opentelemetry:namespace/%s", serviceNamespace) if _, ok := c.components[namespaceIdentifier]; !ok { c.components[namespaceIdentifier] = &Component{ namespaceIdentifier, @@ -56,11 +59,11 @@ func (c *ComponentsCollection) AddResource(attrs *pcommon.Map) bool { newComponentData(). withLayer("urn:stackpack:common:layer:applications"). withEnvironment(attrs). - withNameFromAttr(attrs, "service.namespace"), + withName(serviceNamespace), } } - serviceIdentifier := fmt.Sprintf("urn:opentelemetry:namespace/%s:service/%s", serviceNamespace.AsString(), serviceName.AsString()) + serviceIdentifier := fmt.Sprintf("urn:opentelemetry:namespace/%s:service/%s", serviceNamespace, serviceName.AsString()) c.components[serviceIdentifier] = &Component{ serviceIdentifier, ComponentType{ @@ -72,11 +75,11 @@ func (c *ComponentsCollection) AddResource(attrs *pcommon.Map) bool { withNameFromAttr(attrs, "service.name"). withVersion(attrs, "service.version"). withTag(attrs, "service.name"). - withTag(attrs, "service.namespace"). + withTagValue("service.namespace", serviceNamespace). withTag(attrs, "service.version"). withTagPrefix(attrs, "telemetry.sdk"), } - serviceInstanceIdentifier := fmt.Sprintf("urn:opentelemetry:namespace/%s:service/%s:serviceInstance/%s", serviceNamespace.AsString(), serviceName.AsString(), serviceInstanceId.AsString()) + serviceInstanceIdentifier := fmt.Sprintf("urn:opentelemetry:namespace/%s:service/%s:serviceInstance/%s", serviceNamespace, serviceName.AsString(), serviceInstanceId.AsString()) c.components[serviceInstanceIdentifier] = &Component{ serviceInstanceIdentifier, ComponentType{ @@ -87,7 +90,7 @@ func (c *ComponentsCollection) AddResource(attrs *pcommon.Map) bool { withEnvironment(attrs). withName(serviceInstanceName). withVersion(attrs, "service.version"). - withTag(attrs, "service.namespace"). + withTagValue("service.namespace", serviceNamespace). withTags(attrs), } c.addRelation(serviceIdentifier, serviceInstanceIdentifier, "provided-by") diff --git a/exporter/ststopologyexporter/internal/topology_test.go b/exporter/ststopologyexporter/internal/topology_test.go index 330b558..06baaec 100644 --- a/exporter/ststopologyexporter/internal/topology_test.go +++ b/exporter/ststopologyexporter/internal/topology_test.go @@ -81,7 +81,7 @@ func TestTopology_addResource(t *testing.T) { SourceId: "urn:opentelemetry:namespace/demo:service/demo 1", TargetId: "urn:opentelemetry:namespace/demo:service/demo 1:serviceInstance/demo 1", Type: RelationType{ - Name: "provided by", + Name: "provided-by", }, Data: &RelationData{ Tags: map[string]string{}, @@ -313,7 +313,7 @@ func TestTopology_addHost(t *testing.T) { SourceId: "urn:opentelemetry:namespace/ns:service/ye-service", TargetId: "urn:opentelemetry:namespace/ns:service/ye-service:serviceInstance/ye-service", Type: RelationType{ - Name: "provided by", + Name: "provided-by", }, Data: &RelationData{ Tags: map[string]string{}, @@ -422,7 +422,7 @@ func TestTopology_addFaas(t *testing.T) { SourceId: "urn:opentelemetry:namespace/ns:service/ye-service", TargetId: "urn:opentelemetry:namespace/ns:service/ye-service:serviceInstance/ye-service", Type: RelationType{ - Name: "provided by", + Name: "provided-by", }, Data: &RelationData{ Tags: map[string]string{}, @@ -527,7 +527,7 @@ func TestTopology_addKubernetes(t *testing.T) { SourceId: "urn:opentelemetry:kubernetes:/ye-cluster:ye-k8s-namespace:pod/ye-pod-name", TargetId: "urn:opentelemetry:namespace/ns:service/ye-service:serviceInstance/ye-service", Type: RelationType{ - Name: "kubernetes to otel", + Name: "kubernetes-to-otel", }, Data: &RelationData{ Tags: map[string]string{}, @@ -538,7 +538,89 @@ func TestTopology_addKubernetes(t *testing.T) { SourceId: "urn:opentelemetry:namespace/ns:service/ye-service", TargetId: "urn:opentelemetry:namespace/ns:service/ye-service:serviceInstance/ye-service", Type: RelationType{ - Name: "provided by", + Name: "provided-by", + }, + Data: &RelationData{ + Tags: map[string]string{}, + }, + }, + }, relations) +} + +func TestTopology_addResourceWithoutNamespace(t *testing.T) { + collection := NewCollection() + attrs := pcommon.NewMap() + attrs.PutStr("service.name", "demo 1") + attrs.PutStr("telemetry.sdk.language", "go") + attrs.PutStr("Resource Attributes 1", "value1") + collection.AddResource(&attrs) + + components := collection.GetComponents() + require.Equal(t, []*Component{ + { + ExternalId: "urn:opentelemetry:namespace/default", + Type: ComponentType{ + Name: "namespace", + }, + Data: &ComponentData{ + Name: "default", + Version: "", + Layer: "urn:stackpack:common:layer:applications", + Domain: "", + Environment: "", + Identifiers: []string{}, + Tags: map[string]string{}, + }, + }, + { + ExternalId: "urn:opentelemetry:namespace/default:service/demo 1", + Type: ComponentType{ + Name: "service", + }, + Data: &ComponentData{ + Name: "demo 1", + Version: "", + Layer: "urn:stackpack:common:layer:services", + Domain: "", + Environment: "", + Identifiers: []string{}, + Tags: map[string]string{ + "service.name": "demo 1", + "service.namespace": "default", + "telemetry.sdk.language": "go", + }, + }, + }, + { + ExternalId: "urn:opentelemetry:namespace/default:service/demo 1:serviceInstance/demo 1", + Type: ComponentType{ + Name: "service-instance", + }, + Data: &ComponentData{ + Name: "demo 1 - instance", + Version: "", + Layer: "urn:stackpack:common:layer:containers", + Domain: "", + Environment: "", + Identifiers: []string{}, + Tags: map[string]string{ + "Resource Attributes 1": "value1", + "service.name": "demo 1", + "service.namespace": "default", + "telemetry.sdk.language": "go", + }, + }, + }, + }, components) + + relations := collection.GetRelations() + require.Equal(t, []*Relation{ + { + ExternalId: "urn:opentelemetry:namespace/default:service/demo 1-urn:opentelemetry:namespace/default:service/demo 1:serviceInstance/demo 1", + SourceId: "urn:opentelemetry:namespace/default:service/demo 1", + TargetId: "urn:opentelemetry:namespace/default:service/demo 1:serviceInstance/demo 1", + Type: RelationType{ + Name: "provided-by", }, Data: &RelationData{ Tags: map[string]string{}, diff --git a/extension/ingestionapikeyauthextension/extension.go b/extension/ingestionapikeyauthextension/extension.go index d9d3b7d..503deee 100644 --- a/extension/ingestionapikeyauthextension/extension.go +++ b/extension/ingestionapikeyauthextension/extension.go @@ -129,7 +129,8 @@ type AuthorizeRequestBody struct { // Authorizes an Ingestion API Key (value of Authorization header) with the remote authorization server. // The function stores the result (valid keys but also non-transient errors) in the cache. func checkAuthorizationHeader(authorizationHeader string, exCtx *extensionContext) error { - log.Printf("Sending authorization request for ...%s\n", authorizationHeader[len(authorizationHeader)-4:]) + headerSample := authorizationHeader[max(0, len(authorizationHeader) - 4):] + log.Printf("Sending authorization request for ...%s\n", headerSample) request := AuthorizeRequestBody{ ApiKey: authorizationHeader, } @@ -152,7 +153,7 @@ func checkAuthorizationHeader(authorizationHeader string, exCtx *extensionContex return errAuthServerUnavailable } - log.Printf("Result for ...%s: %d\n", authorizationHeader[len(authorizationHeader)-4:], res.StatusCode) + log.Printf("Result for ...%s: %d\n", headerSample, res.StatusCode) if res.StatusCode == 403 { exCtx.invalidKeysCache.Add(authorizationHeader, errForbidden) return errForbidden