main v0.1.0-rc0
William Perron 10 months ago
parent f525a6642a
commit 27cda64d90
Signed by: wperron
GPG Key ID: BFDB4EF72D73C5F2

@ -0,0 +1,5 @@
# Copyright 2023 William Perron. All rights reserved. MIT License.
dist:
name: otelcol-dev
description: Basic Otel Collector for development
output_path: ./bin/otelcol-dev

@ -3,6 +3,9 @@ package sqliteexporter
import (
"context"
"database/sql"
_ "embed"
"fmt"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/consumer"
@ -11,6 +14,9 @@ import (
"go.wperron.io/sqliteexporter/internal/metadata"
)
//go:embed migrations/20240120195122_init.up.sql
var initScript string
func NewFactory() exporter.Factory {
return exporter.NewFactory(
metadata.Type,
@ -32,7 +38,10 @@ func createTracesExporter(
) (exporter.Traces, error) {
conf := cfg.(*Config)
se := newSqliteExporter(conf)
se, err := newSqliteExporter(conf)
if err != nil {
return nil, fmt.Errorf("failed to create sqlite exporter: %w", err)
}
return exporterhelper.NewTracesExporter(
ctx, set, cfg,
@ -43,6 +52,20 @@ func createTracesExporter(
)
}
func newSqliteExporter(cfg *Config) *sqliteExporter {
return &sqliteExporter{}
func newSqliteExporter(cfg *Config) (*sqliteExporter, error) {
db, err := sql.Open("sqlite3", cfg.Path)
if err != nil {
return nil, fmt.Errorf("couldn't open sqlite3 database: %w", err)
}
tx, _ := db.Begin()
defer tx.Commit()
if _, err := tx.Exec(initScript); err != nil {
return nil, fmt.Errorf("failed to run migrations: %w", err)
}
return &sqliteExporter{
db: db,
}, nil
}

@ -2,18 +2,22 @@ module go.wperron.io/sqliteexporter
go 1.20
require go.opentelemetry.io/collector/component v0.84.0
require (
go.opentelemetry.io/collector/component v0.92.0
go.opentelemetry.io/collector/consumer v0.92.0
)
require (
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mattn/go-sqlite3 v1.14.19 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/collector/consumer v0.84.0 // indirect
go.opentelemetry.io/collector/extension v0.84.0 // indirect
go.opentelemetry.io/collector/processor v0.84.0 // indirect
go.opentelemetry.io/collector/receiver v0.84.0 // indirect
go.opentelemetry.io/collector/config/configretry v0.92.0 // indirect
go.opentelemetry.io/collector/extension v0.92.0 // indirect
go.opentelemetry.io/collector/receiver v0.92.0 // indirect
)
require (
@ -26,26 +30,25 @@ require (
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent v0.84.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/stretchr/testify v1.8.4 // indirect
go.opentelemetry.io/collector v0.84.0 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect
go.opentelemetry.io/collector/confmap v0.84.0 // indirect
go.opentelemetry.io/collector/exporter v0.84.0
go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect
go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect
go.opentelemetry.io/otel v1.16.0 // indirect
go.opentelemetry.io/otel/metric v1.16.0 // indirect
go.opentelemetry.io/otel/trace v1.16.0 // indirect
github.com/stretchr/testify v1.8.4
go.opentelemetry.io/collector v0.92.0 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.92.0 // indirect
go.opentelemetry.io/collector/confmap v0.92.0
go.opentelemetry.io/collector/exporter v0.92.0
go.opentelemetry.io/collector/featuregate v1.0.1 // indirect
go.opentelemetry.io/collector/pdata v1.0.1
go.opentelemetry.io/otel v1.22.0 // indirect
go.opentelemetry.io/otel/metric v1.22.0 // indirect
go.opentelemetry.io/otel/sdk v1.22.0 // indirect
go.opentelemetry.io/otel/trace v1.22.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.25.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/grpc v1.57.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
go.uber.org/zap v1.26.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect
google.golang.org/grpc v1.60.1 // indirect
google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

119
go.sum

@ -1,8 +1,11 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -12,10 +15,15 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -36,8 +44,11 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@ -48,10 +59,13 @@ github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPgh
github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU=
github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g=
github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY=
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
@ -61,14 +75,17 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent v0.84.0 h1:EivvMHRis/wMhyeAo8FfGk1NS739w5+dK+qUz3TSE+E=
github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent v0.84.0/go.mod h1:R7lpqmyo0OYBeu5OaFUwzVaO0ihMoaGGxd5BIxbl0jU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@ -80,38 +97,43 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/collector v0.84.0 h1:zzsegdPlDR0iJufPsHTJhXkv9q2kbpTTTI6nTyya2wA=
go.opentelemetry.io/collector v0.84.0/go.mod h1:+cv/zxludfiiDuK3z+5eXkxAJhkCCcy8Chtvv0nOlr0=
go.opentelemetry.io/collector/component v0.84.0 h1:bh4Is5Z7TjuyF7Mab0rSNh2q3y15fImdNDRXqrqGlbA=
go.opentelemetry.io/collector/component v0.84.0/go.mod h1:uXteRaacYXXYhzeCJe5ClLz5gLzleXWz01IZ730w7FA=
go.opentelemetry.io/collector/config/configtelemetry v0.84.0 h1:pnZiYtppJN6SlzJNcrkA8R+Ur63e33qMO260m8JbK18=
go.opentelemetry.io/collector/config/configtelemetry v0.84.0/go.mod h1:+LAXM5WFMW/UbTlAuSs6L/W72WC+q8TBJt/6z39FPOU=
go.opentelemetry.io/collector/confmap v0.84.0 h1:fS62yIRrsTQwe1gyuEc8TQM0yUNfSAzPVi0A1665ZpQ=
go.opentelemetry.io/collector/confmap v0.84.0/go.mod h1:/SNHqYkLagF0TjBjQyCy2Gt3ZF6hTK8VKbaan/ZHuJs=
go.opentelemetry.io/collector/consumer v0.84.0 h1:sz8mXIdPACJArlRyFNXA1SScVoo954IU1qp9V78VUxc=
go.opentelemetry.io/collector/consumer v0.84.0/go.mod h1:Mu+KeuorwHHWd6iGxU7DMAhgsHZmmzmQgf3sSWkugmM=
go.opentelemetry.io/collector/exporter v0.84.0 h1:OWvHJghs7/R6Qwr2fh7HrgEqsIUbCgLddLQsmqN95kM=
go.opentelemetry.io/collector/exporter v0.84.0/go.mod h1:Bz7MTaVosTIz6ZISszKYLDOewjathUJuVgT5W4Ee/wU=
go.opentelemetry.io/collector/extension v0.84.0 h1:HN4otmncTE/eaeRcvBGTf0ApcX+dIQWsnShs6bgiKYA=
go.opentelemetry.io/collector/extension v0.84.0/go.mod h1:FoUzonXMAjVbFuSLM06F1260iVcbnMLMAEQk/xBfN1Y=
go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 h1:C9o0mbP0MyygqFnKueVQK/v9jef6zvuttmTGlKaqhgw=
go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014/go.mod h1:0mE3mDLmUrOXVoNsuvj+7dV14h/9HFl/Fy9YTLoLObo=
go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 h1:iT5qH0NLmkGeIdDtnBogYDx7L58t6CaWGL378DEo2QY=
go.opentelemetry.io/collector/pdata v1.0.0-rcv0014/go.mod h1:BRvDrx43kiSoUx3mr7SoA7h9B8+OY99mUK+CZSQFWW4=
go.opentelemetry.io/collector/processor v0.84.0 h1:6VM5HLdkroeqNZ/jvjxA4nsgweJ87FDMsnNnzVBHpcY=
go.opentelemetry.io/collector/processor v0.84.0/go.mod h1:KWgBNQuA6wmmRqJwfvPaRybK2Di9X8nE2fraGuVLNJo=
go.opentelemetry.io/collector/receiver v0.84.0 h1:5bN0A18UMAVu9AsFv5AYDgzEFEJ/nFaD1OK2rk7Ygy0=
go.opentelemetry.io/collector/receiver v0.84.0/go.mod h1:QvjpfmMUA4tW59QJBagoNEbRT5JGYZN333GAOuWIRr4=
go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s=
go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs=
go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
go.opentelemetry.io/collector v0.92.0 h1:XiC0ptaT1EmOkK2RI0gt3n2tkzLAkNQGf0E7hrGdyeA=
go.opentelemetry.io/collector v0.92.0/go.mod h1:wbksjM63DTKA1BbdUVS7gAFzAngCZTWb46RBpKdtsPw=
go.opentelemetry.io/collector/component v0.92.0 h1:/tRgPT1hr4KNB8ABHa0oJsjJFRZ5oiCIYHcTpZGwm9s=
go.opentelemetry.io/collector/component v0.92.0/go.mod h1:C2JwPTjauu36UCAzwX71/glNnOc5BR18p8FVccCFsqc=
go.opentelemetry.io/collector/config/configretry v0.92.0 h1:3WUabmCRIBHSkOLGCHGieUGchlHkBw3Fa4Cj9Do5Xdw=
go.opentelemetry.io/collector/config/configretry v0.92.0/go.mod h1:gt1HRYyMxcMca9lbDLPbivQzsUCjVjkPAn/3S6fiD14=
go.opentelemetry.io/collector/config/configtelemetry v0.92.0 h1:iCfxJ2DhWVOAHpGgkWUZRfUvUPyWGhpVRCqjPQ2D87Y=
go.opentelemetry.io/collector/config/configtelemetry v0.92.0/go.mod h1:2XLhyR/GVpWeZ2K044vCmrvH/d4Ewt0aD/y46avZyMU=
go.opentelemetry.io/collector/confmap v0.92.0 h1:xz20zNIvF9ZA1eWE+MZmZunmdXPIP/fr33ZvU0QUSxg=
go.opentelemetry.io/collector/confmap v0.92.0/go.mod h1:CmqTszB2uwiJ9ieEqISdecuoVuyt3jMnJ/9kD53GYHs=
go.opentelemetry.io/collector/consumer v0.92.0 h1:twa8T0iR9KVglvRbwZ5OPKLXPCC2DO6gVhrgDZ47MPE=
go.opentelemetry.io/collector/consumer v0.92.0/go.mod h1:fBZqP7bou3I7pDhWjleBuzdaLfQgJBc92wPJVOcKaGU=
go.opentelemetry.io/collector/exporter v0.92.0 h1:z6u+/hswJUuZbuPYIF2gXMZsqjIDd/tJO60XjLM850U=
go.opentelemetry.io/collector/exporter v0.92.0/go.mod h1:54ODYn1weY/Wr0bdxESj4P1fgyX+zaUsnJJnafORqIY=
go.opentelemetry.io/collector/extension v0.92.0 h1:zaehgW+LXCMNEb1d6Af/VHWphh5ZwX9aZl+NuQLGhpQ=
go.opentelemetry.io/collector/extension v0.92.0/go.mod h1:5EYwiaGU6deSY8YWqT5gvlnD850yJXP3NqFRKVVbYLs=
go.opentelemetry.io/collector/featuregate v1.0.1 h1:ok//hLSXttBbyu4sSV1pTx1nKdr5udSmrWy5sFMIIbM=
go.opentelemetry.io/collector/featuregate v1.0.1/go.mod h1:QQXjP4etmJQhkQ20j4P/rapWuItYxoFozg/iIwuKnYg=
go.opentelemetry.io/collector/pdata v1.0.1 h1:dGX2h7maA6zHbl5D3AsMnF1c3Nn+3EUftbVCLzeyNvA=
go.opentelemetry.io/collector/pdata v1.0.1/go.mod h1:jutXeu0QOXYY8wcZ/hege+YAnSBP3+jpTqYU1+JTI5Y=
go.opentelemetry.io/collector/receiver v0.92.0 h1:TRz4ufr5bFEszpAWgYVEx/b7VPZzEcECsyMzztf5PsQ=
go.opentelemetry.io/collector/receiver v0.92.0/go.mod h1:bYAAYbMuUVj3wx7ave2iyyJ+aGUpACliYOQ5xI92I7k=
go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y=
go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI=
go.opentelemetry.io/otel/exporters/prometheus v0.44.1-0.20231201153405-6027c1ae76f2 h1:TnhkxGJ5qPHAMIMI4r+HPT/BbpoHxqn4xONJrok054o=
go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg=
go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY=
go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw=
go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc=
go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0=
go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0=
go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@ -130,8 +152,8 @@ 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-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -142,12 +164,12 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@ -165,16 +187,15 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc h1:8DyZCyvI8mE1IdLy/60bS+52xfymkE72wv1asokgtao=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw=
google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@ -186,9 +207,11 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

@ -0,0 +1,4 @@
-- Copyright 2023 William Perron. All rights reserved. MIT License.
DROP TABLE links;
DROP TABLE events;
DROP TABLE spans;

@ -0,0 +1,38 @@
-- Copyright 2023 William Perron. All rights reserved. MIT License.
CREATE TABLE IF NOT EXISTS spans(
"span_id" BLOB,
"trace_id" BLOB,
"parent_span_id" BLOB,
"tracestate" TEXT,
"__service_name" TEXT,
"__duration" INTEGER,
"name" TEXT,
"kind" TEXT,
"start_time" INTEGER,
"end_time" INTEGER,
"status_code" INTEGER,
"status_description" TEXT,
"attributes" TEXT,
"dropped_attributes_count" INTEGER,
"resource_attributes" TEXT,
"resource_dropped_attributes_count" INTEGER,
PRIMARY KEY ("span_id", "trace_id")
);
CREATE TABLE IF NOT EXISTS events(
"span_id" BLOB,
"timestamp" INTEGER,
"name" TEXT,
"attributes" TEXT,
"dropped_attributes_count" INTEGER,
FOREIGN KEY ("span_id") REFERENCES spans("span_id")
);
CREATE TABLE IF NOT EXISTS links(
"parent_span_id" BLOB,
"span_id" BLOB,
"trace_id" BLOB,
"tracestate" TEXT,
"attributes" TEXT,
"dropped_attributes_count" INTEGER
);

@ -3,12 +3,19 @@ package sqliteexporter
import (
"context"
"database/sql"
"encoding/json"
"fmt"
_ "github.com/mattn/go-sqlite3"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/ptrace"
)
type sqliteExporter struct{}
type sqliteExporter struct {
db *sql.DB
}
// Start tells the component to start. Host parameter can be used for communicating
// with the host after Start() has already returned. If an error is returned by
@ -22,7 +29,7 @@ type sqliteExporter struct{}
// to Start() function since that context will be cancelled soon and can abort the long-running
// operation. Create a new context from the context.Background() for long-running operations.
func (e *sqliteExporter) Start(ctx context.Context, host component.Host) error {
panic("not implemented") // TODO: Implement
return nil
}
// Shutdown is invoked during service shutdown. After Shutdown() is called, if the component
@ -42,9 +49,199 @@ func (e *sqliteExporter) Start(ctx context.Context, host component.Host) error {
// the same or different configuration may be created and started (this may happen
// for example if we want to restart the component).
func (e *sqliteExporter) Shutdown(ctx context.Context) error {
panic("not implemented") // TODO: Implement
return e.db.Close()
}
const insertSpanQ string = `INSERT INTO spans
(
span_id,
trace_id,
parent_span_id,
tracestate,
__service_name,
__duration,
name,
kind,
start_time,
end_time,
status_code,
status_description,
attributes,
dropped_attributes_count,
resource_attributes,
resource_dropped_attributes_count
)
VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, json(?), ?, json(?), ?
);
`
const insertEventQ string = `INSERT INTO events
(
span_id,
timestamp,
name,
attributes,
dropped_attributes_count
)
VALUES (
?, ?, ?, json(?), ?
);
`
const insertLinkQ string = `INSERT INTO links
(
parent_span_id,
span_id,
trace_id,
tracestate,
attributes,
dropped_attributes_count
)
VALUES (
?, ?, ?, ?, json(?), ?
)`
func (e *sqliteExporter) ConsumeTraces(ctx context.Context, traces ptrace.Traces) error {
panic("not implemented")
tx, err := e.db.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("failed to start transaction: %w", err)
}
defer tx.Commit()
e.db.Begin()
for i := 0; i < traces.ResourceSpans().Len(); i++ {
resource := traces.ResourceSpans().At(i)
svc := "unknown"
resource.Resource().Attributes().Range(func(k string, v pcommon.Value) bool {
if k == "service.name" {
svc = v.Str()
if svc == "" { // protect against service name being another type for some reason
svc = "unknown"
}
return false
}
return true
})
rattrs, err := pcommonMapAsJSON(resource.Resource().Attributes())
if err != nil {
return fmt.Errorf("failed to marshal resource attributes as json: %w", err)
}
for j := 0; j < resource.ScopeSpans().Len(); j++ {
scope := resource.ScopeSpans().At(j)
for k := 0; k < scope.Spans().Len(); k++ {
span := scope.Spans().At(k)
dur := span.EndTimestamp().AsTime().Sub(span.StartTimestamp().AsTime())
stmt, err := tx.PrepareContext(ctx, insertSpanQ)
if err != nil {
return fmt.Errorf("failed to prepare span insert stmt: %w", err)
}
attrs, err := pcommonMapAsJSON(span.Attributes())
if err != nil {
return fmt.Errorf("failed to marshal attributes as json: %w", err)
}
spanidraw := [8]byte(span.SpanID())
spanidbs := spanidraw[:]
traceidraw := [16]byte(span.TraceID())
traceidbs := traceidraw[:]
parentidraw := [8]byte(span.ParentSpanID())
parentidbs := parentidraw[:]
if span.ParentSpanID().IsEmpty() {
parentidbs = nil
}
_, err = stmt.ExecContext(ctx,
spanidbs,
traceidbs,
parentidbs,
span.TraceState().AsRaw(),
svc,
dur.Microseconds(),
span.Name(),
span.Kind().String(),
span.StartTimestamp().AsTime().Unix(),
span.EndTimestamp().AsTime().Unix(),
span.Status().Code(),
span.Status().Message(),
attrs,
span.DroppedAttributesCount(),
rattrs,
resource.Resource().DroppedAttributesCount(),
)
if err != nil {
return fmt.Errorf("error occured while inserting span: %w", err)
}
for l := 0; l < span.Events().Len(); l++ {
event := span.Events().At(l)
attrs, err := pcommonMapAsJSON(event.Attributes())
if err != nil {
return fmt.Errorf("failed to marshal event attributes as json: %w", err)
}
stmt, err := tx.PrepareContext(ctx, insertEventQ)
if err != nil {
return fmt.Errorf("failed to prepare event insert query: %w", err)
}
_, err = stmt.ExecContext(ctx,
spanidbs,
event.Timestamp().AsTime().Unix(),
event.Name(),
attrs,
event.DroppedAttributesCount(),
)
if err != nil {
return fmt.Errorf("error occured while inserting event: %w", err)
}
}
for l := 0; l < span.Links().Len(); l++ {
link := span.Links().At(l)
attrs, err := pcommonMapAsJSON(link.Attributes())
if err != nil {
return fmt.Errorf("failed to marshal link attributes as json: %w", err)
}
stmt, err := tx.PrepareContext(ctx, insertLinkQ)
if err != nil {
return fmt.Errorf("failed to prepare link insert query: %w", err)
}
linkidraw := [8]byte(link.SpanID())
linkidbs := linkidraw[:]
linktraceraw := [16]byte(link.TraceID())
linetracebs := linktraceraw[:]
_, err = stmt.ExecContext(ctx,
spanidbs,
linkidbs,
linetracebs,
link.TraceState().AsRaw(),
attrs,
link.DroppedAttributesCount(),
)
if err != nil {
return fmt.Errorf("error occured while inserting link: %w", err)
}
}
}
}
}
return nil
}
func pcommonMapAsJSON(m pcommon.Map) ([]byte, error) {
return json.Marshal(m.AsRaw())
}

@ -0,0 +1,257 @@
// Copyright 2023 William Perron. All rights reserved. MIT License.
package sqliteexporter
import (
"context"
"database/sql"
"reflect"
"testing"
"time"
_ "github.com/mattn/go-sqlite3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/ptrace"
)
func Test_ExporterExportSpan(t *testing.T) {
ctx := context.Background()
now := time.Now()
// manually build the exporter so we can inspect the database
db, err := sql.Open("sqlite3", ":memory:")
require.NoError(t, err)
tx, _ := db.Begin()
_, err = tx.Exec(initScript)
require.NoError(t, err)
err = tx.Commit()
require.NoError(t, err)
ex := sqliteExporter{db: db}
// build the trace
testTrace := ptrace.NewTraces()
rs := testTrace.ResourceSpans().AppendEmpty()
r := rs.Resource()
r.Attributes().PutStr("service.name", "test-service")
ss := rs.ScopeSpans().AppendEmpty()
// define a first server span
span1 := ss.Spans().AppendEmpty()
span1.SetTraceID(pcommon.TraceID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01})
span1.SetSpanID(pcommon.SpanID{0xee, 0xbc, 0x00, 0x00, 0x00, 0x00, 0xab, 0x01})
ts := span1.TraceState()
ts.FromRaw("rojo=00f067aa0ba902b7")
span1.SetName("span1")
span1.SetKind(ptrace.SpanKindServer)
span1.SetStartTimestamp(pcommon.NewTimestampFromTime(now.Add(-5 * time.Millisecond)))
span1.SetEndTimestamp(pcommon.NewTimestampFromTime(now))
span1.Status().SetCode(ptrace.StatusCodeOk)
span1.Status().SetMessage(ptrace.StatusCodeOk.String())
span1.Attributes().PutStr("http.method", "GET")
span1.Attributes().PutInt("http.status_code", 200)
span1event1 := span1.Events().AppendEmpty()
span1event1.SetTimestamp(pcommon.NewTimestampFromTime(now.Add(-3 * time.Millisecond)))
span1event1.SetName("this_happened")
span1event1.Attributes().PutStr("value", "example")
span1event2 := span1.Events().AppendEmpty()
span1event2.SetTimestamp(pcommon.NewTimestampFromTime(now.Add(-4 * time.Millisecond)))
span1event2.SetName("that_happened")
span1event2.Attributes().PutStr("value", "example")
// define an internal child span for span1
span2 := ss.Spans().AppendEmpty()
span2.SetTraceID(pcommon.TraceID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01})
span2.SetSpanID(pcommon.SpanID{0xee, 0xbc, 0x00, 0x00, 0x00, 0x00, 0xab, 0x02})
span2.SetParentSpanID(pcommon.SpanID{0xee, 0xbc, 0x00, 0x00, 0x00, 0x00, 0xab, 0x01})
span2.SetName("span2")
span2.SetKind(ptrace.SpanKindInternal)
span2.SetStartTimestamp(pcommon.NewTimestampFromTime(now.Add(-4 * time.Millisecond)))
span2.SetEndTimestamp(pcommon.NewTimestampFromTime(now.Add(-1 * time.Millisecond)))
span2.Status().SetCode(ptrace.StatusCodeOk)
span2.Status().SetMessage(ptrace.StatusCodeOk.String())
span2.Attributes().PutStr("custom.key", "custom-value")
span2event1 := span2.Events().AppendEmpty()
span2event1.SetTimestamp(pcommon.NewTimestampFromTime(now.Add(-3 * time.Millisecond)))
span2event1.SetName("this_happened")
span2event1.Attributes().PutStr("value", "example")
span2event2 := span2.Events().AppendEmpty()
span2event2.SetTimestamp(pcommon.NewTimestampFromTime(now.Add(-4 * time.Millisecond)))
span2event2.SetName("that_happened")
span2event2.Attributes().PutStr("value", "example")
span2link1 := span2.Links().AppendEmpty()
span2link1.SetSpanID(span1.SpanID())
span2link1.SetTraceID(span1.TraceID())
span2link1.Attributes().PutStr("relation", "follows_from")
err = ex.ConsumeTraces(ctx, testTrace)
require.Nil(t, err)
row := db.QueryRow("select count(1) from spans;")
require.NoError(t, err)
var total int
err = row.Scan(&total)
require.NoError(t, err)
assert.Equal(t, 2, total)
rows, err := db.Query(`select
span_id,
trace_id,
parent_span_id,
tracestate,
__service_name,
__duration,
name,
kind,
start_time,
end_time,
status_code,
status_description,
attributes,
dropped_attributes_count,
resource_attributes,
resource_dropped_attributes_count
from spans order by name asc;`)
require.NoError(t, err)
ok := rows.Next()
require.True(t, ok)
var rspanId, rtraceId, rparentSpanId sql.RawBytes
var tracestate, serviceName, name, kind, statusDescription, attributes, resourceAttributes string
var duration, startTime, endTime, statusCode, droppedAttributesCount, resourceDroppedAttributesCount int
err = rows.Scan(
&rspanId,
&rtraceId,
&rparentSpanId,
&tracestate,
&serviceName,
&duration,
&name,
&kind,
&startTime,
&endTime,
&statusCode,
&statusDescription,
&attributes,
&droppedAttributesCount,
&resourceAttributes,
&resourceDroppedAttributesCount,
)
require.NoError(t, err)
assert.Equal(t, sql.RawBytes([]byte{0xee, 0xbc, 0x00, 0x00, 0x00, 0x00, 0xab, 0x01}), rspanId)
assert.Equal(t, sql.RawBytes([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}), rtraceId)
assert.Nil(t, rparentSpanId)
assert.Equal(t, "rojo=00f067aa0ba902b7", tracestate)
assert.Equal(t, "test-service", serviceName)
assert.Equal(t, 5000, duration)
assert.Equal(t, "span1", name)
assert.Equal(t, ptrace.SpanKindServer.String(), kind)
assert.Equal(t, now.Add(-5*time.Millisecond).Unix(), int64(startTime))
assert.Equal(t, now.Unix(), int64(endTime))
assert.Equal(t, int(ptrace.StatusCodeOk), statusCode)
assert.Equal(t, ptrace.StatusCodeOk.String(), statusDescription)
assert.Equal(t, "{\"http.method\":\"GET\",\"http.status_code\":200}", attributes)
assert.Equal(t, 0, droppedAttributesCount)
assert.Equal(t, "{\"service.name\":\"test-service\"}", resourceAttributes)
assert.Equal(t, 0, resourceDroppedAttributesCount)
ok = rows.Next()
require.True(t, ok)
err = rows.Scan(
&rspanId,
&rtraceId,
&rparentSpanId,
&tracestate,
&serviceName,
&duration,
&name,
&kind,
&startTime,
&endTime,
&statusCode,
&statusDescription,
&attributes,
&droppedAttributesCount,
&resourceAttributes,
&resourceDroppedAttributesCount,
)
require.NoError(t, err)
assert.Equal(t, sql.RawBytes([]byte{0xee, 0xbc, 0x00, 0x00, 0x00, 0x00, 0xab, 0x02}), rspanId)
assert.Equal(t, sql.RawBytes([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}), rtraceId)
assert.Equal(t, sql.RawBytes([]byte{0xee, 0xbc, 0x00, 0x00, 0x00, 0x00, 0xab, 0x01}), rparentSpanId)
assert.Equal(t, "", tracestate)
assert.Equal(t, "test-service", serviceName)
assert.Equal(t, 3000, duration)
assert.Equal(t, "span2", name)
assert.Equal(t, ptrace.SpanKindInternal.String(), kind)
assert.Equal(t, now.Add(-4*time.Millisecond).Unix(), int64(startTime))
assert.Equal(t, now.Add(-1*time.Millisecond).Unix(), int64(endTime))
assert.Equal(t, int(ptrace.StatusCodeOk), statusCode)
assert.Equal(t, ptrace.StatusCodeOk.String(), statusDescription)
assert.Equal(t, "{\"custom.key\":\"custom-value\"}", attributes)
assert.Equal(t, 0, droppedAttributesCount)
assert.Equal(t, "{\"service.name\":\"test-service\"}", resourceAttributes)
assert.Equal(t, 0, resourceDroppedAttributesCount)
assert.False(t, rows.Next())
row = db.QueryRow("select count(1) from events;")
require.NoError(t, err)
err = row.Scan(&total)
require.NoError(t, err)
assert.Equal(t, 4, total)
row = db.QueryRow("select count(1) from links;")
require.NoError(t, err)
err = row.Scan(&total)
require.NoError(t, err)
assert.Equal(t, 1, total)
}
func Test_pcommonMapAsJSON(t *testing.T) {
tests := []struct {
name string
args pcommon.Map
want []byte
wantErr bool
}{
{
name: "empty",
args: pcommon.NewMap(),
want: []byte("{}"),
wantErr: false,
},
{
name: "simple",
args: func() pcommon.Map {
m := pcommon.NewMap()
m.PutStr("http.method", "GET")
m.PutInt("http.status_code", 200)
return m
}(),
want: []byte("{\"http.method\":\"GET\",\"http.status_code\":200}"),
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := pcommonMapAsJSON(tt.args)
if (err != nil) != tt.wantErr {
t.Errorf("pcommonMapAsJSON() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("pcommonMapAsJSON() = %v, want %v", string(got), string(tt.want))
}
})
}
}
Loading…
Cancel
Save