Skip to content

Commit a1edda1

Browse files
committed
[feat][storage]: add write path for ClickHouse based on Jaeger V2
Signed-off-by: zzzk1 <[email protected]>
1 parent 1b64454 commit a1edda1

40 files changed

+2274
-9
lines changed

.github/workflows/ci-e2e-all.yml

+2
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,5 @@ jobs:
3737
opensearch:
3838
uses: ./.github/workflows/ci-e2e-opensearch.yml
3939

40+
clickhouse:
41+
uses: ./.github/workflows/ci-e2e-clickhouse.yml
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: CIT ClickHouse
2+
3+
on:
4+
workflow_call:
5+
6+
concurrency:
7+
group: cit-clickhouse-${{ github.workflow }}-${{ (github.event.pull_request && github.event.pull_request.number) || github.ref || github.run_id }}
8+
cancel-in-progress: true
9+
10+
# See https://github.com/ossf/scorecard/blob/main/docs/checks.md#token-permissions
11+
permissions: # added using https://github.com/step-security/secure-workflows
12+
contents: read
13+
14+
jobs:
15+
clickhouse:
16+
runs-on: ubuntu-latest
17+
strategy:
18+
fail-fast: false
19+
matrix:
20+
clickhouse-version: ["25.x"]
21+
create-schema: [auto]
22+
name: clickhouse
23+
steps:
24+
- name: Harden Runner
25+
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
26+
with:
27+
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
28+
29+
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
30+
31+
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
32+
with:
33+
go-version: 1.24.x
34+
35+
- name: Run clickhouse integration tests
36+
id: test-execution
37+
run: bash scripts/e2e/clickhouse.sh
38+
- uses: ./.github/actions/verify-metrics-snapshot
39+
with:
40+
snapshot: metrics_snapshot_clickhouse
41+
artifact_key: metrics_snapshot_clickhouse
42+
43+
- name: Upload coverage to codecov
44+
uses: ./.github/actions/upload-codecov
45+
with:
46+
files: cover.out
47+
flags: clickhouse-${{ matrix.clickhouse-version }}-${{ matrix.create-schema }}

.mockery.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,10 @@ packages:
7979
github.com/jaegertracing/jaeger/internal/storage/v2/api/depstore:
8080
config:
8181
all: true
82+
github.com/jaegertracing/jaeger/internal/storage/v2/clickhouse/client:
83+
config:
84+
all: true
85+
interfaces:
86+
Pool:
87+
Conn:
88+
Rows:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
services:
2+
clickhouse:
3+
container_name: clickhouse
4+
image: bitnami/clickhouse:25.1.3
5+
environment:
6+
CLICKHOUSE_USER: "default"
7+
CLICKHOUSE_PASSWORD: "default"
8+
ports:
9+
- 9000:9000
10+
- 8123:8123

go.mod

+15-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ go 1.23.7
55
toolchain go1.24.1
66

77
require (
8+
github.com/ClickHouse/ch-go v0.65.1
9+
github.com/ClickHouse/clickhouse-go/v2 v2.32.2
810
github.com/HdrHistogram/hdrhistogram-go v1.1.2
911
github.com/Shopify/sarama v1.37.2
1012
github.com/apache/thrift v0.21.0
@@ -104,8 +106,20 @@ require (
104106
)
105107

106108
require (
109+
github.com/andybalholm/brotli v1.1.1 // indirect
107110
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect
111+
github.com/dmarkham/enumer v1.5.10 // indirect
112+
github.com/go-faster/city v1.0.1 // indirect
113+
github.com/go-faster/errors v0.7.1 // indirect
114+
github.com/jackc/puddle/v2 v2.2.2 // indirect
115+
github.com/pascaldekloe/name v1.0.1 // indirect
116+
github.com/paulmach/orb v0.11.1 // indirect
117+
github.com/segmentio/asm v1.2.0 // indirect
118+
github.com/shopspring/decimal v1.4.0 // indirect
108119
go.opentelemetry.io/collector/extension/extensiontest v0.120.0 // indirect
120+
golang.org/x/mod v0.23.0 // indirect
121+
golang.org/x/sync v0.11.0 // indirect
122+
golang.org/x/tools v0.30.0 // indirect
109123
)
110124

111125
require (
@@ -265,7 +279,7 @@ require (
265279
go.opentelemetry.io/collector/processor/xprocessor v0.120.0 // indirect
266280
go.opentelemetry.io/collector/receiver/receivertest v0.120.0 // indirect
267281
go.opentelemetry.io/collector/receiver/xreceiver v0.120.0 // indirect
268-
go.opentelemetry.io/collector/semconv v0.120.0 // indirect
282+
go.opentelemetry.io/collector/semconv v0.120.0
269283
go.opentelemetry.io/collector/service v0.120.0 // indirect
270284
go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 // indirect
271285
go.opentelemetry.io/contrib/config v0.14.0 // indirect

go.sum

+44-6
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) 2025 The Jaeger Authors.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package integration
5+
6+
import (
7+
"context"
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
"go.uber.org/zap"
13+
"go.uber.org/zap/zaptest"
14+
15+
"github.com/jaegertracing/jaeger/internal/storage/v2/clickhouse"
16+
"github.com/jaegertracing/jaeger/internal/storage/v2/clickhouse/config"
17+
"github.com/jaegertracing/jaeger/pkg/testutils"
18+
)
19+
20+
type ClickhouseIntegrationTestSuite struct {
21+
StorageIntegration
22+
factory *clickhouse.Factory
23+
}
24+
25+
func (s *ClickhouseIntegrationTestSuite) cleanUp(t *testing.T) {
26+
require.NoError(t, s.factory.Purge(context.Background()))
27+
}
28+
29+
func (s *ClickhouseIntegrationTestSuite) initialize(t *testing.T) {
30+
logger := zaptest.NewLogger(t, zaptest.WrapOptions(zap.AddCaller()))
31+
32+
cfg := config.DefaultConfiguration()
33+
cfg.ConnConfig.Database = "jaeger"
34+
cfg.PoolConfig.ClientConfig.Database = "jaeger"
35+
f, err := clickhouse.NewFactory(&cfg, logger)
36+
require.NoError(t, err)
37+
38+
t.Cleanup(func() {
39+
assert.NoError(t, f.Close())
40+
})
41+
42+
traceWriter, err := f.CreateTraceWriter()
43+
require.NoError(t, err)
44+
traceReader, err := f.CreateTracReader()
45+
require.NoError(t, err)
46+
47+
s.TraceWriter = traceWriter
48+
s.TraceReader = traceReader
49+
s.factory = f
50+
s.CleanUp = s.cleanUp
51+
}
52+
53+
func TestClickHouseStorage(t *testing.T) {
54+
SkipUnlessEnv(t, "clickhouse")
55+
t.Cleanup(func() {
56+
testutils.VerifyGoLeaksOnceForClickhouse(t)
57+
})
58+
s := &ClickhouseIntegrationTestSuite{}
59+
s.initialize(t)
60+
s.testGetTrace(t)
61+
}

internal/storage/integration/elasticsearch_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,15 @@ func testElasticsearchStorage(t *testing.T, allTagsAsFields bool) {
193193
}
194194

195195
func TestElasticsearchStorage(t *testing.T) {
196+
SkipUnlessEnv(t, "elasticsearch", "opensearch")
196197
t.Cleanup(func() {
197198
testutils.VerifyGoLeaksOnceForES(t)
198199
})
199200
testElasticsearchStorage(t, false)
200201
}
201202

202203
func TestElasticsearchStorage_AllTagsAsObjectFields(t *testing.T) {
204+
SkipUnlessEnv(t, "elasticsearch", "opensearch")
203205
t.Cleanup(func() {
204206
testutils.VerifyGoLeaksOnceForES(t)
205207
})

internal/storage/integration/package_test.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ import (
1111
)
1212

1313
func TestMain(m *testing.M) {
14-
if os.Getenv("STORAGE") == "elasticsearch" || os.Getenv("STORAGE") == "opensearch" {
14+
switch os.Getenv("STORAGE") {
15+
case "elasticsearch":
16+
case "opensearch":
1517
testutils.VerifyGoLeaksForES(m)
16-
} else {
18+
case "clickhouse":
19+
testutils.VerifyGoLeaksForClickhouse(m)
20+
default:
1721
testutils.VerifyGoLeaks(m)
1822
}
1923
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright (c) 2025 The Jaeger Authors.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
FROM docker.io/bitnami/clickhouse:25
5+
6+
COPY schema/* /clickhouse-schema/
7+
8+
ENTRYPOINT ["sh","/clickhouse-schema/docker.sh"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) 2025 The Jaeger Authors.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package client
5+
6+
import (
7+
"context"
8+
9+
"go.opentelemetry.io/collector/pdata/ptrace"
10+
)
11+
12+
type Pool interface {
13+
Do(ctx context.Context, query string, td ...ptrace.Traces) error
14+
Close() error
15+
}
16+
17+
type Conn interface {
18+
// TODO arg should support the dyment parameter.
19+
Query(ctx context.Context, query string, arg string) (Rows, error)
20+
Exec(ctx context.Context, query string) error
21+
Close() error
22+
}
23+
24+
type Rows interface {
25+
Next() bool
26+
Scan(dest ...any) error
27+
ScanStruct(dest any) error
28+
Err() error
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) 2025 The Jaeger Authors.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package conn
5+
6+
// Configuration clickhouse-go client connection configuration for read trace.
7+
// more detail see:https://clickhouse.com/docs/integrations/go#connection-settings
8+
type Configuration struct {
9+
Address []string `mapstructure:"address"`
10+
Database string `mapstructure:"database"`
11+
Username string `mapstructure:"username"`
12+
Password string `mapstructure:"password"`
13+
}
14+
15+
func DefaultConfig() Configuration {
16+
return Configuration{
17+
Address: []string{"127.0.0.1:9000"},
18+
Database: "default",
19+
Username: "default",
20+
Password: "default",
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) 2025 The Jaeger Authors.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package conn
5+
6+
import (
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
11+
"github.com/jaegertracing/jaeger/pkg/testutils"
12+
)
13+
14+
func TestDefaultConfig(t *testing.T) {
15+
expected := Configuration{
16+
Address: []string{"127.0.0.1:9000"},
17+
Database: "default",
18+
Username: "default",
19+
Password: "default",
20+
}
21+
actual := DefaultConfig()
22+
assert.NotNil(t, actual)
23+
assert.Equal(t, expected, actual)
24+
}
25+
26+
func TestMain(m *testing.M) {
27+
testutils.VerifyGoLeaks(m)
28+
}

0 commit comments

Comments
 (0)