Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STAC-21205: add topology exporter based on metrics #10

Merged
merged 5 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ RUN apk add --no-cache git
WORKDIR /go/src/github.com/stackvista/sts-opentelemetry-collector
COPY . .

RUN go install go.opentelemetry.io/collector/cmd/builder@v0.96.0
RUN go install go.opentelemetry.io/collector/cmd/builder@v0.99.0
RUN builder --config ./sts-otel-builder.yaml

FROM gcr.io/distroless/static-debian11
Expand Down
21 changes: 21 additions & 0 deletions common/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,24 @@ package auth

const StsAPIKeyHeader = "Sts-Api-Key"
const StsTenantContextKey = "Sts-Tenant"

type AuthData struct {
ApiKey string
}

func (a *AuthData) GetApiKey() string {
return a.ApiKey
}

func (a *AuthData) GetAttribute(name string) any {
switch name {
case "apiKey":
return a.ApiKey
default:
return nil
}
}

func (*AuthData) GetAttributeNames() []string {
return []string{"apiKey"}
}
4 changes: 2 additions & 2 deletions common/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect
google.golang.org/grpc v1.63.2 // indirect
google.golang.org/protobuf v1.33.0 // indirect
)
4 changes: 2 additions & 2 deletions common/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand All @@ -46,7 +46,7 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be h1:LG9vZxsWGOmUKieR8wPAUR3u3MpnYFQZROPIMaXh7/A=
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
16 changes: 8 additions & 8 deletions exporter/clickhousestsexporter/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ module github.com/stackvista/sts-opentelemetry-collector/exporter/clickhousestse
go 1.21.6

require (
github.com/ClickHouse/clickhouse-go/v2 v2.23.0
github.com/ClickHouse/clickhouse-go/v2 v2.23.1
github.com/cenkalti/backoff/v4 v4.3.0
github.com/google/uuid v1.6.0
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.99.0
github.com/stretchr/testify v1.9.0
go.opentelemetry.io/collector/component v0.99.0
go.opentelemetry.io/collector/config/configopaque v1.3.0
go.opentelemetry.io/collector/config/configopaque v1.6.0
go.opentelemetry.io/collector/config/configretry v0.99.0
go.opentelemetry.io/collector/confmap v0.99.0
go.opentelemetry.io/collector/exporter v0.99.0
Expand All @@ -34,7 +34,7 @@ require (
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/klauspost/compress v1.17.8 // indirect
github.com/knadh/koanf/maps v0.1.1 // indirect
github.com/knadh/koanf/providers/confmap v0.1.0 // indirect
github.com/knadh/koanf/v2 v2.1.1 // indirect
Expand All @@ -48,10 +48,10 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.19.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.52.3 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/common v0.53.0 // indirect
github.com/prometheus/procfs v0.14.0 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
go.opentelemetry.io/collector v0.99.0 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.99.0 // indirect
go.opentelemetry.io/collector/consumer v0.99.0 // indirect
Expand All @@ -62,10 +62,10 @@ require (
go.opentelemetry.io/otel/sdk v1.25.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.25.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect
google.golang.org/grpc v1.63.2 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
29 changes: 13 additions & 16 deletions exporter/clickhousestsexporter/go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github.com/ClickHouse/ch-go v0.61.5 h1:zwR8QbYI0tsMiEcze/uIMK+Tz1D3XZXLdNrlaOpeEI4=
github.com/ClickHouse/ch-go v0.61.5/go.mod h1:s1LJW/F/LcFs5HJnuogFMta50kKDO0lf9zzfrbl0RQg=
github.com/ClickHouse/clickhouse-go/v2 v2.23.0 h1:srmRrkS0BR8gEut87u8jpcZ7geOob6nGj9ifrb+aKmg=
github.com/ClickHouse/clickhouse-go/v2 v2.23.0/go.mod h1:tBhdF3f3RdP7sS59+oBAtTyhWpy0024ZxDMhgxra0QE=
github.com/ClickHouse/clickhouse-go/v2 v2.23.1 h1:h+wOAjtycWeR8gNh0pKip+P4/Lyp9x9Ol5KyqaIJDeM=
github.com/ClickHouse/clickhouse-go/v2 v2.23.1/go.mod h1:aNap51J1OM3yxQJRgM+AlP/MPkGBCL8A74uQThoQhR0=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand Down Expand Up @@ -40,8 +40,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs=
github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU=
Expand Down Expand Up @@ -80,16 +80,15 @@ github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7km
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.52.3 h1:5f8uj6ZwHSscOGNdIQg6OiZv/ybiK2CO2q2drVZAQSA=
github.com/prometheus/common v0.52.3/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE=
github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
github.com/prometheus/procfs v0.14.0 h1:Lw4VdGGoKEZilJsayHf0B+9YgLGREba2C6xr+Fdfq6s=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
Expand All @@ -107,8 +106,8 @@ go.opentelemetry.io/collector v0.99.0 h1:O3EtCr+Bp2FoYI4KZCcC10FbMOjtRPXN1JBgFmi
go.opentelemetry.io/collector v0.99.0/go.mod h1:rdrDdSy+184UZ7YhJEo7aq9KHdrq6J46WWC//Tg7FBo=
go.opentelemetry.io/collector/component v0.99.0 h1:uU8m9d19Jf+zaf7T8Bl12Mm1qozqTZkDISCnnBnS0u4=
go.opentelemetry.io/collector/component v0.99.0/go.mod h1:sGAyyOtJRlqqt396jisIQxsOW7cOIKOTLi+iCarx++s=
go.opentelemetry.io/collector/config/configopaque v1.3.0 h1:J60RL/XxGmBF+OX2+Gx+yAo/p7YwjSsOOlPlo1yXotA=
go.opentelemetry.io/collector/config/configopaque v1.3.0/go.mod h1:+vgBSjB0aSA5SnYAbLlWAcfqgNsrX/65/8EjMKCBGyk=
go.opentelemetry.io/collector/config/configopaque v1.6.0 h1:MVlbCzVln1+8+VWxKVCLWONZNISVrSkbIz0+Q/bneOc=
go.opentelemetry.io/collector/config/configopaque v1.6.0/go.mod h1:i5d1RN7jwmChc78dCCF5ZE4Sm5EXXpksHbf1/tOBXho=
go.opentelemetry.io/collector/config/configretry v0.99.0 h1:ZVt2NVFaUn+wtNvvr9uU45tN59tc6qQUQBRgCslWSfQ=
go.opentelemetry.io/collector/config/configretry v0.99.0/go.mod h1:uRdmPeCkrW9Zsadh2WEbQ1AGXGYJ02vCfmmT+0g69nY=
go.opentelemetry.io/collector/config/configtelemetry v0.99.0 h1:Fks8xkTUnxw1nEcTyYOXnIHttI9BGgjOCB0bwBH3LcU=
Expand Down Expand Up @@ -158,8 +157,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand Down Expand Up @@ -187,8 +185,7 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be h1:LG9vZxsWGOmUKieR8wPAUR3u3MpnYFQZROPIMaXh7/A=
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
Expand Down
22 changes: 22 additions & 0 deletions exporter/ststopologyexporter/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package ststopologyexporter

import (
"fmt"

"go.opentelemetry.io/collector/exporter/exporterhelper"
)

type Config struct {
exporterhelper.TimeoutSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct.
exporterhelper.QueueSettings `mapstructure:"sending_queue"`

Endpoint string `mapstructure:"endpoint"`
}

func (c *Config) Validate() error {
if c.Endpoint == "" {
return fmt.Errorf("hostname is required")
}

return nil
}
114 changes: 114 additions & 0 deletions exporter/ststopologyexporter/exporter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright StackState B.V.
// SPDX-License-Identifier: Apache-2.0
package ststopologyexporter

import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"time"

"github.com/stackvista/sts-opentelemetry-collector/exporter/ststopologyexporter/internal"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.uber.org/zap"
)

var (
errInternal = errors.New("internal error")
)

type topologyExporter struct {
logger *zap.Logger
httpClient http.Client
cfg *Config
}

func newTopologyExporter(logger *zap.Logger, cfg component.Config) (*topologyExporter, error) {
stsCfg, ok := cfg.(*Config)
if !ok {
return nil, fmt.Errorf("invalid config passed to stackstateexporter: %T", cfg)
}
httpClient := http.Client{
Timeout: 5 * time.Second,
}

return &topologyExporter{logger: logger, httpClient: httpClient, cfg: stsCfg}, nil
}
func (t *topologyExporter) ConsumeMetrics(ctx context.Context, md pmetric.Metrics) error {
log := t.logger

componentsByApiKey := make(map[string]*internal.ComponentsCollection, 0)
rms := md.ResourceMetrics()
for i := 0; i < rms.Len(); i++ {
rs := rms.At(i)
resource := rs.Resource()
sts_api_key_value, key_exists := resource.Attributes().Get("sts_api_key")
if !key_exists {
log.Warn("No sts_api_key attribute found on resource")
continue
}
sts_api_key := sts_api_key_value.AsString()
attrs := resource.Attributes()
attrs.Remove("sts_api_key")
collection, has_siblings := componentsByApiKey[sts_api_key]
if !has_siblings {
collection = internal.NewCollection()
componentsByApiKey[sts_api_key] = collection
}
if !collection.AddResource(&attrs) {
log.Warn("Skipping resource without necessary attributes")
}
}

for apiKey, collection := range componentsByApiKey {
components := collection.GetComponents()
relations := collection.GetRelations()
request := internal.IntakeTopology{
CollectionTimestamp: time.Now().UnixMilli(),
InternalHostname: "sts-otel-collector",
Topologies: []internal.Topology{{
Instance: internal.Instance{
Type: "opentelemetry",
URL: "collector",
},
Components: components,
Relations: relations,
}},
}
jsonData, err := json.Marshal(request)
if err != nil {
log.Error("Can't encode api request to JSON", zap.Error(err))
return errInternal //it shouldn't happen, something is wrong with the implementation
}

req, err := http.NewRequest(http.MethodPost, t.cfg.Endpoint, bytes.NewReader(jsonData))
if err != nil {
log.Error("Can't create topology intake request ", zap.Error(err))
return errInternal
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("sts-api-key", apiKey)

res, err := t.httpClient.Do(req)
if err != nil {
log.Error("Receiver endpoint returned an error ", zap.Error(err))
}

if res.StatusCode == 403 {
log.Error("API Key was not valid", zap.Error(err))
}
log.Debug(
fmt.Sprintf("Sent %d components for key ...%s (status %d)",
len(components),
apiKey[len(apiKey)-4:],
res.StatusCode,
),
)
}

return nil
}
61 changes: 61 additions & 0 deletions exporter/ststopologyexporter/exporter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package ststopologyexporter

import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"

"github.com/stackvista/sts-opentelemetry-collector/exporter/ststopologyexporter/internal"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/exporter/exporterhelper"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.uber.org/zap/zaptest"
)

func TestExporter_pushResourcesData(t *testing.T) {
testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
require.Equal(t, "APIKEY", req.Header[http.CanonicalHeaderKey("sts-api-key")][0])

var payload internal.IntakeTopology
err := json.NewDecoder(req.Body).Decode(&payload)
require.NoError(t, err)
require.Equal(t, 1, len(payload.Topologies))
require.Equal(t, 3, len(payload.Topologies[0].Components))
res.WriteHeader(200)
}))
exporter := newTestExporter(t, testServer.URL)
err := exporter.ConsumeMetrics(context.TODO(), simpleMetrics())
require.NoError(t, err)
}

// simpleMetrics there will be added two ResourceMetrics and each of them have count data point
func simpleMetrics() pmetric.Metrics {
metrics := pmetric.NewMetrics()
rm := metrics.ResourceMetrics().AppendEmpty()
rm.Resource().Attributes().PutStr("service.name", "demo 1")
rm.Resource().Attributes().PutStr("service.namespace", "demo")
rm.Resource().Attributes().PutStr("sts_api_key", "APIKEY")
rm.Resource().Attributes().PutStr("Resource Attributes 1", "value1")
rm.SetSchemaUrl("Resource SchemaUrl 1")

rm = metrics.ResourceMetrics().AppendEmpty()
rm.Resource().Attributes().PutStr("service.name", "demo 2")
rm.Resource().Attributes().PutStr("service.namespace", "demo")
rm.Resource().Attributes().PutStr("Resource Attributes 2", "value2")
return metrics
}

func newTestExporter(t *testing.T, url string) *topologyExporter {
exporter, err := newTopologyExporter(zaptest.NewLogger(t), &Config{
TimeoutSettings: exporterhelper.TimeoutSettings{
Timeout: 15 * time.Millisecond,
},
QueueSettings: exporterhelper.NewDefaultQueueSettings(),
Endpoint: url,
})
require.NoError(t, err)
return exporter
}
Loading