Skip to content

Commit

Permalink
[feat][storage]: add write path for ClickHouse based on Jaeger V2
Browse files Browse the repository at this point in the history
Signed-off-by: zzzk1 <madzhou1@gmail.com>
  • Loading branch information
zzzk1 committed Mar 1, 2025
1 parent 300cc7c commit f050114
Show file tree
Hide file tree
Showing 42 changed files with 2,288 additions and 15 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci-e2e-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ jobs:
opensearch:
uses: ./.github/workflows/ci-e2e-opensearch.yml

clickhouse:
uses: ./.github/workflows/ci-e2e-clickhouse.yml
49 changes: 49 additions & 0 deletions .github/workflows/ci-e2e-clickhouse.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: CIT ClickHouse

on:
workflow_call:

concurrency:
group: cit-clickhouse-${{ github.workflow }}-${{ (github.event.pull_request && github.event.pull_request.number) || github.ref || github.run_id }}
cancel-in-progress: true

# See https://github.com/ossf/scorecard/blob/main/docs/checks.md#token-permissions
permissions: # added using https://github.com/step-security/secure-workflows
contents: read

jobs:
clickhouse:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
clickhouse-version: ["25.x"]
create-schema: [manual, auto]
name: clickhouse
steps:
- name: Harden Runner
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs

- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0

- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with:
go-version: 1.24.x

- name: Run clickhouse integration tests
id: test-execution
run: bash scripts/e2e/clickhouse.sh ${{ matrix.clickhouse-version }}-${{ matrix.create-schema }}
env:
SKIP_APPLY_SCHEMA: ${{ matrix.create-schema == 'auto' && true || false }}
- uses: ./.github/actions/verify-metrics-snapshot
with:
snapshot: metrics_snapshot_clickhouse
artifact_key: metrics_snapshot_clickhouse

- name: Upload coverage to codecov
uses: ./.github/actions/upload-codecov
with:
files: cover.out
flags: clickhouse-${{ matrix.clickhouse-version }}-${{ matrix.create-schema }}
7 changes: 7 additions & 0 deletions .mockery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,10 @@ packages:
github.com/jaegertracing/jaeger/internal/storage/v2/api/depstore:
config:
all: true
github.com/jaegertracing/jaeger/internal/storage/v2/clickhouse/client:
config:
all: true
interfaces:
Pool:
Conn:
Rows:
10 changes: 10 additions & 0 deletions docker-compose/clickhouse/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
services:
clickhouse:
container_name: clickhouse
image: bitnami/clickhouse:25.1.3
environment:
CLICKHOUSE_USER: "default"
CLICKHOUSE_PASSWORD: "default"
ports:
- 9000:9000
- 8123:8123
16 changes: 15 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ go 1.23.7
toolchain go1.24.0

require (
github.com/ClickHouse/ch-go v0.65.1
github.com/ClickHouse/clickhouse-go/v2 v2.32.2
github.com/HdrHistogram/hdrhistogram-go v1.1.2
github.com/Shopify/sarama v1.37.2
github.com/apache/thrift v0.21.0
Expand Down Expand Up @@ -104,8 +106,20 @@ require (
)

require (
github.com/andybalholm/brotli v1.1.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect
github.com/dmarkham/enumer v1.5.10 // indirect
github.com/go-faster/city v1.0.1 // indirect
github.com/go-faster/errors v0.7.1 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/pascaldekloe/name v1.0.1 // indirect
github.com/paulmach/orb v0.11.1 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
go.opentelemetry.io/collector/extension/extensiontest v0.120.0 // indirect
golang.org/x/mod v0.23.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/tools v0.30.0 // indirect
)

require (
Expand Down Expand Up @@ -266,7 +280,7 @@ require (
go.opentelemetry.io/collector/processor/xprocessor v0.120.0 // indirect
go.opentelemetry.io/collector/receiver/receivertest v0.120.0 // indirect
go.opentelemetry.io/collector/receiver/xreceiver v0.120.0 // indirect
go.opentelemetry.io/collector/semconv v0.120.0 // indirect
go.opentelemetry.io/collector/semconv v0.120.0
go.opentelemetry.io/collector/service v0.120.0 // indirect
go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 // indirect
go.opentelemetry.io/contrib/config v0.14.0 // indirect
Expand Down
50 changes: 44 additions & 6 deletions go.sum

Large diffs are not rendered by default.

61 changes: 61 additions & 0 deletions internal/storage/integration/clickhouse_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) 2025 The Jaeger Authors.
// SPDX-License-Identifier: Apache-2.0

package integration

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zaptest"

"github.com/jaegertracing/jaeger/internal/storage/v2/clickhouse"
"github.com/jaegertracing/jaeger/internal/storage/v2/clickhouse/config"
"github.com/jaegertracing/jaeger/pkg/testutils"
)

type ClickhouseIntegrationTestSuite struct {
StorageIntegration
factory *clickhouse.Factory
}

func (s *ClickhouseIntegrationTestSuite) cleanUp(t *testing.T) {
require.NoError(t, s.factory.Purge(context.Background()))
}

func (s *ClickhouseIntegrationTestSuite) initialize(t *testing.T) {
logger := zaptest.NewLogger(t, zaptest.WrapOptions(zap.AddCaller()))

cfg := config.DefaultConfiguration()
cfg.ConnConfig.Database = "jaeger"
cfg.PoolConfig.ClientConfig.Database = "jaeger"
f, err := clickhouse.NewFactory(&cfg, logger)
require.NoError(t, err)

t.Cleanup(func() {
assert.NoError(t, f.Close())
})

traceWriter, err := f.CreateTraceWriter()
require.NoError(t, err)
traceReader, err := f.CreateTracReader()
require.NoError(t, err)

s.TraceWriter = traceWriter
s.TraceReader = traceReader
s.factory = f
s.CleanUp = s.cleanUp
}

func TestClickHouseStorage(t *testing.T) {
SkipUnlessEnv(t, "clickhouse")
t.Cleanup(func() {
testutils.VerifyGoLeaksOnceForClickhouse(t)
})
s := &ClickhouseIntegrationTestSuite{}
s.initialize(t)
s.testGetTrace(t)
}
7 changes: 5 additions & 2 deletions internal/storage/integration/package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ import (
)

func TestMain(m *testing.M) {
if os.Getenv("STORAGE") == "elasticsearch" || os.Getenv("STORAGE") == "opensearch" {
switch os.Getenv("STORAGE") {
case "elasticsearch":
testutils.VerifyGoLeaksForES(m)
} else {
case "opensearch":
testutils.VerifyGoLeaksForES(m)
default:
testutils.VerifyGoLeaks(m)
}
}
8 changes: 8 additions & 0 deletions internal/storage/v2/clickhouse/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright (c) 2025 The Jaeger Authors.
# SPDX-License-Identifier: Apache-2.0

FROM docker.io/bitnami/clickhouse:25

COPY schema/* /clickhouse-schema/

ENTRYPOINT ["sh","/clickhouse-schema/docker.sh"]
35 changes: 35 additions & 0 deletions internal/storage/v2/clickhouse/client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) 2025 The Jaeger Authors.
// SPDX-License-Identifier: Apache-2.0

package client

import (
"context"

"go.opentelemetry.io/collector/pdata/ptrace"
)

type Pool interface {
Do(ctx context.Context, query string, td ...ptrace.Traces) error
Close() error
}

type Conn interface {
QueryRow(ctx context.Context, query string, arg string) Row
Query(ctx context.Context, query string, arg string) (Rows, error)
Exec(ctx context.Context, query string) error
Close() error
}

type Rows interface {
Next() bool
Scan(dest ...any) error
ScanStruct(dest any) error
Err() error
}

type Row interface {
Err() error
Scan(dest ...any) error
ScanStruct(dest any) error
}
42 changes: 42 additions & 0 deletions internal/storage/v2/clickhouse/client/conn/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) 2025 The Jaeger Authors.
// SPDX-License-Identifier: Apache-2.0

package conn

import (
client "github.com/ClickHouse/clickhouse-go/v2"
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
)

type Configuration struct {
Address []string `mapstructure:"address"`
Database string `mapstructure:"database"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
}

func DefaultConfig() Configuration {
return Configuration{
Address: []string{"127.0.0.1:9000"},
Database: "default",
Username: "default",
Password: "default",
}
}

func NewConn(config Configuration) (driver.Conn, error) {
option := client.Options{
Addr: config.Address,
Auth: client.Auth{
Database: config.Database,
Username: config.Username,
Password: config.Password,
},
}

conn, err := client.Open(&option)
if err != nil {
return nil, err
}
return conn, nil

Check warning on line 41 in internal/storage/v2/clickhouse/client/conn/config.go

View check run for this annotation

Codecov / codecov/patch

internal/storage/v2/clickhouse/client/conn/config.go#L27-L41

Added lines #L27 - L41 were not covered by tests
}
28 changes: 28 additions & 0 deletions internal/storage/v2/clickhouse/client/conn/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) 2025 The Jaeger Authors.
// SPDX-License-Identifier: Apache-2.0

package conn

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/jaegertracing/jaeger/pkg/testutils"
)

func TestDefaultConfig(t *testing.T) {
excepted := Configuration{
Address: []string{"127.0.0.1:9000"},
Database: "default",
Username: "default",
Password: "default",
}
actual := DefaultConfig()
assert.NotNil(t, actual)
assert.Equal(t, excepted, actual)
}

func TestMain(m *testing.M) {
testutils.VerifyGoLeaks(m)
}
Loading

0 comments on commit f050114

Please sign in to comment.