From 601a99d194845659dd643f243bd03aadeef815ed Mon Sep 17 00:00:00 2001 From: Mingxi <71588583+joker-star-l@users.noreply.github.com> Date: Wed, 11 Sep 2024 23:09:28 +0800 Subject: [PATCH] [exporter/doris] Second PR of New component: Doris Exporter (#34980) **Description:** Second PR of New component: Doris Exporter. Implementation of traces. **Link to tracking Issue:** #33479 **Testing:** **Documentation:** --- .chloggen/doris-traces.yaml | 27 +++ exporter/dorisexporter/README.md | 9 +- exporter/dorisexporter/config.go | 52 ++++- exporter/dorisexporter/config_test.go | 8 +- exporter/dorisexporter/exporter_common.go | 117 ++++++++++ .../dorisexporter/exporter_common_test.go | 53 +++++ exporter/dorisexporter/exporter_traces.go | 215 ++++++++++++++++++ .../dorisexporter/exporter_traces_test.go | 97 ++++++++ exporter/dorisexporter/factory.go | 23 +- exporter/dorisexporter/go.mod | 37 ++- exporter/dorisexporter/go.sum | 36 ++- exporter/dorisexporter/sql/traces_ddl.sql | 42 ++++ 12 files changed, 693 insertions(+), 23 deletions(-) create mode 100644 .chloggen/doris-traces.yaml create mode 100644 exporter/dorisexporter/exporter_common.go create mode 100644 exporter/dorisexporter/exporter_common_test.go create mode 100644 exporter/dorisexporter/exporter_traces.go create mode 100644 exporter/dorisexporter/exporter_traces_test.go create mode 100644 exporter/dorisexporter/sql/traces_ddl.sql diff --git a/.chloggen/doris-traces.yaml b/.chloggen/doris-traces.yaml new file mode 100644 index 000000000000..86f6168b48c4 --- /dev/null +++ b/.chloggen/doris-traces.yaml @@ -0,0 +1,27 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: new_component + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: dorisexporter + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: traces implementation + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [33479] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: + +# If your change doesn't affect end users or the exported elements of any package, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [user] diff --git a/exporter/dorisexporter/README.md b/exporter/dorisexporter/README.md index f0ad02619a7c..28371b7118e4 100644 --- a/exporter/dorisexporter/README.md +++ b/exporter/dorisexporter/README.md @@ -24,13 +24,12 @@ The following configuration options are supported: * `logs` (default = otel_logs) The table name for logs. * `traces` (default = otel_traces) The table name for traces. * `metrics` (default = otel_metrics) The table name for metrics. -* `create_schema` (default = true) Whether databases and tables are created automatically. -* `mysql_endpoint` The mysql protocol address to create the schema; ignored if `create_schema` is false. +* `create_schema` (default = true) Whether databases and tables are created automatically in doris. +* `mysql_endpoint` The mysql protocol address of doris. Only use to create the schema; ignored if `create_schema` is false. * `history_days` (default = 0) Data older than these days will be deleted; ignored if `create_schema` is false. If set to 0, historical data will not be deleted. * `create_history_days` (default = 0) The number of days in the history partition that was created when the table was created; ignored if `create_schema` is false. If `history_days` is not 0, `create_history_days` needs to be less than or equal to `history_days`. * `replication_num` (default = 1) The number of replicas of the table; ignored if `create_schema` is false. * `timezone` (default is the time zone of the opentelemetry collector) The time zone of doris. -* `timeout` (default = 5s) Time to wait per individual attempt to send data to a backend. * `sending_queue` [details here](https://github.com/open-telemetry/opentelemetry-collector/tree/main/exporter/exporterhelper#configuration) * `enabled` (default = true) * `num_consumers` (default = 10) Number of consumers that dequeue batches; ignored if `enabled` is false. @@ -41,6 +40,10 @@ The following configuration options are supported: * `max_interval` (default = 30s) The upper bound on backoff; ignored if `enabled` is false. * `max_elapsed_time` (default = 300s) The maximum amount of time spent trying to send a batch; ignored if `enabled` is false. If set to 0, the retries are never stopped. +The Doris exporter supports common [HTTP Configuration Settings](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/confighttp/README.md#http-configuration-settings), except for compression (all requests are uncompressed). As a consequence of supporting [confighttp](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/confighttp/README.md#http-configuration-settings), the Doris exporter also supports common [TLS Configuration Settings](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/configtls/README.md#tls-configuration-settings). + +The Doris exporter sets `timeout` (HTTP request timeout) to 60s by default. All other defaults are as defined by [confighttp](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/confighttp/README.md#http-configuration-settings). + Example: ```yaml exporters: diff --git a/exporter/dorisexporter/config.go b/exporter/dorisexporter/config.go index db34a0f4d2f2..58ecaed09b4b 100644 --- a/exporter/dorisexporter/config.go +++ b/exporter/dorisexporter/config.go @@ -5,23 +5,24 @@ package dorisexporter // import "github.com/open-telemetry/opentelemetry-collect import ( "errors" + "fmt" "regexp" + "time" + "go.opentelemetry.io/collector/config/confighttp" "go.opentelemetry.io/collector/config/configopaque" "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/exporter/exporterhelper" ) type Config struct { - exporterhelper.TimeoutSettings `mapstructure:",squash"` - configretry.BackOffConfig `mapstructure:"retry_on_failure"` - exporterhelper.QueueSettings `mapstructure:"sending_queue"` + confighttp.ClientConfig `mapstructure:",squash"` + configretry.BackOffConfig `mapstructure:"retry_on_failure"` + exporterhelper.QueueSettings `mapstructure:"sending_queue"` // TableNames is the table name for logs, traces and metrics. Table `mapstructure:"table"` - // Endpoint is the http stream load address. - Endpoint string `mapstructure:"endpoint"` // Database is the database name. Database string `mapstructure:"database"` // Username is the authentication username. @@ -93,5 +94,46 @@ func (cfg *Config) Validate() (err error) { err = errors.Join(err, errors.New("metrics table name must be alphanumeric and underscore")) } + _, errT := cfg.timeZone() + if errT != nil { + err = errors.Join(err, errors.New("invalid timezone")) + } + return err } + +const ( + defaultStart = -2147483648 // IntMin +) + +func (cfg *Config) startHistoryDays() int32 { + if cfg.HistoryDays == 0 { + return defaultStart + } + return -cfg.HistoryDays +} + +func (cfg *Config) timeZone() (*time.Location, error) { + return time.LoadLocation(cfg.TimeZone) +} + +const ( + properties = ` +PROPERTIES ( +"replication_num" = "%d", +"enable_single_replica_compaction" = "true", +"compaction_policy" = "time_series", +"dynamic_partition.enable" = "true", +"dynamic_partition.create_history_partition" = "true", +"dynamic_partition.time_unit" = "DAY", +"dynamic_partition.start" = "%d", +"dynamic_partition.history_partition_num" = "%d", +"dynamic_partition.end" = "1", +"dynamic_partition.prefix" = "p" +) +` +) + +func (cfg *Config) propertiesStr() string { + return fmt.Sprintf(properties, cfg.ReplicationNum, cfg.startHistoryDays(), cfg.CreateHistoryDays) +} diff --git a/exporter/dorisexporter/config_test.go b/exporter/dorisexporter/config_test.go index 8311476a5242..223384626c9c 100644 --- a/exporter/dorisexporter/config_test.go +++ b/exporter/dorisexporter/config_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/confighttp" "go.opentelemetry.io/collector/config/configopaque" "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/confmap/confmaptest" @@ -30,6 +31,10 @@ func TestLoadConfig(t *testing.T) { defaultCfg.(*Config).Endpoint = "http://localhost:8030" defaultCfg.(*Config).MySQLEndpoint = "localhost:9030" + httpClientConfig := confighttp.NewDefaultClientConfig() + httpClientConfig.Timeout = 5 * time.Second + httpClientConfig.Endpoint = "http://localhost:8030" + tests := []struct { id component.ID expected component.Config @@ -41,7 +46,7 @@ func TestLoadConfig(t *testing.T) { { id: component.NewIDWithName(metadata.Type, "full"), expected: &Config{ - TimeoutSettings: exporterhelper.TimeoutSettings{Timeout: 5 * time.Second}, + ClientConfig: httpClientConfig, BackOffConfig: configretry.BackOffConfig{ Enabled: true, InitialInterval: 5 * time.Second, @@ -60,7 +65,6 @@ func TestLoadConfig(t *testing.T) { Traces: "otel_traces", Metrics: "otel_metrics", }, - Endpoint: "http://localhost:8030", Database: "otel", Username: "admin", Password: configopaque.String("admin"), diff --git a/exporter/dorisexporter/exporter_common.go b/exporter/dorisexporter/exporter_common.go new file mode 100644 index 000000000000..1c00bb10c78c --- /dev/null +++ b/exporter/dorisexporter/exporter_common.go @@ -0,0 +1,117 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package dorisexporter // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/dorisexporter" + +import ( + "bytes" + "context" + "database/sql" + "fmt" + "net/http" + "time" + + _ "github.com/go-sql-driver/mysql" // for register database driver + "go.opentelemetry.io/collector/component" + "go.uber.org/zap" +) + +const timeFormat = "2006-01-02 15:04:05.999999" + +type commonExporter struct { + component.TelemetrySettings + + client *http.Client + + logger *zap.Logger + cfg *Config + timeZone *time.Location +} + +func newExporter(logger *zap.Logger, cfg *Config, set component.TelemetrySettings) *commonExporter { + // There won't be an error because it's already been validated in the Config.Validate method. + timeZone, _ := cfg.timeZone() + + return &commonExporter{ + TelemetrySettings: set, + logger: logger, + cfg: cfg, + timeZone: timeZone, + } +} + +func (e *commonExporter) formatTime(t time.Time) string { + return t.In(e.timeZone).Format(timeFormat) +} + +type streamLoadResponse struct { + TxnID int64 + Label string + Status string + ExistingJobStatus string + Message string + NumberTotalRows int64 + NumberLoadedRows int64 + NumberFilteredRows int64 + NumberUnselectedRows int64 + LoadBytes int64 + LoadTimeMs int64 + BeginTxnTimeMs int64 + StreamLoadPutTimeMs int64 + ReadDataTimeMs int64 + WriteDataTimeMs int64 + CommitAndPublishTimeMs int64 + ErrorURL string +} + +func (r *streamLoadResponse) success() bool { + return r.Status == "Success" || r.Status == "Publish Timeout" +} + +func streamLoadURL(address string, db string, table string) string { + return address + "/api/" + db + "/" + table + "/_stream_load" +} + +func streamLoadRequest(ctx context.Context, cfg *Config, table string, data []byte) (*http.Request, error) { + url := streamLoadURL(cfg.Endpoint, cfg.Database, table) + req, err := http.NewRequestWithContext(ctx, http.MethodPut, url, bytes.NewBuffer(data)) + if err != nil { + return nil, err + } + + req.Header.Set("format", "json") + req.Header.Set("Expect", "100-continue") + req.Header.Set("strip_outer_array", "true") + req.SetBasicAuth(cfg.Username, string(cfg.Password)) + + return req, nil +} + +func createDorisHTTPClient(ctx context.Context, cfg *Config, host component.Host, settings component.TelemetrySettings) (*http.Client, error) { + client, err := cfg.ClientConfig.ToClient(ctx, host, settings) + if err != nil { + return nil, err + } + + client.CheckRedirect = func(req *http.Request, _ []*http.Request) error { + req.SetBasicAuth(cfg.Username, string(cfg.Password)) + return nil + } + + return client, nil +} + +func createDorisMySQLClient(cfg *Config) (*sql.DB, error) { + dsn := fmt.Sprintf("%s:%s@tcp(%s)/mysql", cfg.Username, string(cfg.Password), cfg.MySQLEndpoint) + conn, err := sql.Open("mysql", dsn) + return conn, err +} + +func createAndUseDatabase(ctx context.Context, conn *sql.DB, cfg *Config) error { + _, err := conn.ExecContext(ctx, "CREATE DATABASE IF NOT EXISTS "+cfg.Database) + if err != nil { + return err + } + _, err = conn.ExecContext(ctx, "USE "+cfg.Database) + return err +} diff --git a/exporter/dorisexporter/exporter_common_test.go b/exporter/dorisexporter/exporter_common_test.go new file mode 100644 index 000000000000..aa0a93c695eb --- /dev/null +++ b/exporter/dorisexporter/exporter_common_test.go @@ -0,0 +1,53 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package dorisexporter // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/dorisexporter" + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/configtelemetry" + "go.opentelemetry.io/otel/metric" +) + +var testTelemetrySettings = component.TelemetrySettings{ + LeveledMeterProvider: func(_ configtelemetry.Level) metric.MeterProvider { + return nil + }, +} + +func TestNewCommonExporter(t *testing.T) { + cfg := createDefaultConfig().(*Config) + exporter := newExporter(nil, cfg, testTelemetrySettings) + require.NotNil(t, exporter) +} + +func TestCommonExporter_FormatTime(t *testing.T) { + cfg := createDefaultConfig().(*Config) + exporter := newExporter(nil, cfg, testTelemetrySettings) + require.NotNil(t, exporter) + + now := time.Date(2024, 1, 1, 0, 0, 0, 1000, time.Local) + require.Equal(t, "2024-01-01 00:00:00.000001", exporter.formatTime(now)) +} + +func TestStreamLoadResponse_Success(t *testing.T) { + resp := &streamLoadResponse{ + Status: "Success", + } + require.True(t, resp.success()) + + resp.Status = "Publish Timeout" + require.True(t, resp.success()) + + resp.Status = "Fail" + require.False(t, resp.success()) +} + +func TestStreamLoadUrl(t *testing.T) { + url := streamLoadURL("http://doris:8030", "otel", "otel_logs") + require.Equal(t, "http://doris:8030/api/otel/otel_logs/_stream_load", url) +} diff --git a/exporter/dorisexporter/exporter_traces.go b/exporter/dorisexporter/exporter_traces.go new file mode 100644 index 000000000000..40793c613605 --- /dev/null +++ b/exporter/dorisexporter/exporter_traces.go @@ -0,0 +1,215 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package dorisexporter // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/dorisexporter" + +import ( + "context" + _ "embed" // for SQL file embedding + "encoding/json" + "fmt" + "io" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/pdata/ptrace" + semconv "go.opentelemetry.io/collector/semconv/v1.25.0" + "go.uber.org/zap" + + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/traceutil" +) + +//go:embed sql/traces_ddl.sql +var tracesDDL string + +// dTrace Trace to Doris +type dTrace struct { + ServiceName string `json:"service_name"` + Timestamp string `json:"timestamp"` + TraceID string `json:"trace_id"` + SpanID string `json:"span_id"` + TraceState string `json:"trace_state"` + ParentSpanID string `json:"parent_span_id"` + SpanName string `json:"span_name"` + SpanKind string `json:"span_kind"` + EndTime string `json:"end_time"` + Duration int64 `json:"duration"` + SpanAttributes map[string]any `json:"span_attributes"` + Events []*dEvent `json:"events"` + Links []*dLink `json:"links"` + StatusMessage string `json:"status_message"` + StatusCode string `json:"status_code"` + ResourceAttributes map[string]any `json:"resource_attributes"` + ScopeName string `json:"scope_name"` + ScopeVersion string `json:"scope_version"` +} + +// dEvent Event to Doris +type dEvent struct { + Timestamp string `json:"timestamp"` + Name string `json:"name"` + Attributes map[string]any `json:"attributes"` +} + +// dLink Link to Doris +type dLink struct { + TraceID string `json:"trace_id"` + SpanID string `json:"span_id"` + TraceState string `json:"trace_state"` + Attributes map[string]any `json:"attributes"` +} + +type tracesExporter struct { + *commonExporter +} + +func newTracesExporter(logger *zap.Logger, cfg *Config, set component.TelemetrySettings) *tracesExporter { + return &tracesExporter{ + commonExporter: newExporter(logger, cfg, set), + } +} + +func (e *tracesExporter) start(ctx context.Context, host component.Host) error { + client, err := createDorisHTTPClient(ctx, e.cfg, host, e.TelemetrySettings) + if err != nil { + return err + } + e.client = client + + if !e.cfg.CreateSchema { + return nil + } + + conn, err := createDorisMySQLClient(e.cfg) + if err != nil { + return err + } + defer conn.Close() + + err = createAndUseDatabase(ctx, conn, e.cfg) + if err != nil { + return err + } + + ddl := fmt.Sprintf(tracesDDL, e.cfg.Table.Traces, e.cfg.propertiesStr()) + _, err = conn.ExecContext(ctx, ddl) + return err +} + +func (e *tracesExporter) shutdown(_ context.Context) error { + if e.client != nil { + e.client.CloseIdleConnections() + } + return nil +} + +func (e *tracesExporter) pushTraceData(ctx context.Context, td ptrace.Traces) error { + traces := make([]*dTrace, 0, td.SpanCount()) + + for i := 0; i < td.ResourceSpans().Len(); i++ { + resourceSpan := td.ResourceSpans().At(i) + resource := resourceSpan.Resource() + resourceAttributes := resource.Attributes() + serviceName := "" + v, ok := resourceAttributes.Get(semconv.AttributeServiceName) + if ok { + serviceName = v.AsString() + } + + for j := 0; j < resourceSpan.ScopeSpans().Len(); j++ { + scopeSpan := resourceSpan.ScopeSpans().At(j) + + for k := 0; k < scopeSpan.Spans().Len(); k++ { + span := scopeSpan.Spans().At(k) + + events := span.Events() + newEvents := make([]*dEvent, 0, events.Len()) + for l := 0; l < events.Len(); l++ { + event := events.At(l) + + newEvent := &dEvent{ + Timestamp: e.formatTime(event.Timestamp().AsTime()), + Name: event.Name(), + Attributes: event.Attributes().AsRaw(), + } + + newEvents = append(newEvents, newEvent) + } + + links := span.Links() + newLinks := make([]*dLink, 0, links.Len()) + for l := 0; l < links.Len(); l++ { + link := links.At(l) + + newLink := &dLink{ + TraceID: traceutil.TraceIDToHexOrEmptyString(link.TraceID()), + SpanID: traceutil.SpanIDToHexOrEmptyString(link.SpanID()), + TraceState: link.TraceState().AsRaw(), + Attributes: link.Attributes().AsRaw(), + } + + newLinks = append(newLinks, newLink) + } + + trace := &dTrace{ + ServiceName: serviceName, + Timestamp: e.formatTime(span.StartTimestamp().AsTime()), + TraceID: traceutil.TraceIDToHexOrEmptyString(span.TraceID()), + SpanID: traceutil.SpanIDToHexOrEmptyString(span.SpanID()), + TraceState: span.TraceState().AsRaw(), + ParentSpanID: traceutil.SpanIDToHexOrEmptyString(span.ParentSpanID()), + SpanName: span.Name(), + SpanKind: traceutil.SpanKindStr(span.Kind()), + EndTime: e.formatTime(span.EndTimestamp().AsTime()), + Duration: span.EndTimestamp().AsTime().Sub(span.StartTimestamp().AsTime()).Microseconds(), + SpanAttributes: span.Attributes().AsRaw(), + Events: newEvents, + Links: newLinks, + StatusMessage: span.Status().Message(), + StatusCode: traceutil.StatusCodeStr(span.Status().Code()), + ResourceAttributes: resourceAttributes.AsRaw(), + ScopeName: scopeSpan.Scope().Name(), + ScopeVersion: scopeSpan.Scope().Version(), + } + + traces = append(traces, trace) + } + } + } + + return e.pushTraceDataInternal(ctx, traces) +} + +func (e *tracesExporter) pushTraceDataInternal(ctx context.Context, traces []*dTrace) error { + marshal, err := json.Marshal(traces) + if err != nil { + return err + } + + req, err := streamLoadRequest(ctx, e.cfg, e.cfg.Table.Traces, marshal) + if err != nil { + return err + } + + res, err := e.client.Do(req) + if err != nil { + return err + } + defer res.Body.Close() + + body, err := io.ReadAll(res.Body) + if err != nil { + return err + } + + response := streamLoadResponse{} + err = json.Unmarshal(body, &response) + if err != nil { + return err + } + + if !response.success() { + return fmt.Errorf("failed to push trace data: %s", response.Message) + } + + return nil +} diff --git a/exporter/dorisexporter/exporter_traces_test.go b/exporter/dorisexporter/exporter_traces_test.go new file mode 100644 index 000000000000..efc1f1bdca5d --- /dev/null +++ b/exporter/dorisexporter/exporter_traces_test.go @@ -0,0 +1,97 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package dorisexporter // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/dorisexporter" + +import ( + "context" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/ptrace" + semconv "go.opentelemetry.io/collector/semconv/v1.25.0" +) + +func TestPushTraceData(t *testing.T) { + config := createDefaultConfig().(*Config) + config.Endpoint = "http://127.0.0.1:18030" + config.CreateSchema = false + + err := config.Validate() + require.NoError(t, err) + + exporter := newTracesExporter(nil, config, testTelemetrySettings) + + ctx := context.Background() + + client, err := createDorisHTTPClient(ctx, config, nil, testTelemetrySettings) + require.NoError(t, err) + require.NotNil(t, client) + + exporter.client = client + + defer func() { + _ = exporter.shutdown(ctx) + }() + + server := &http.Server{ + ReadTimeout: 5 * time.Second, + } + go func() { + http.HandleFunc("/api/otel/otel_traces/_stream_load", func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"Status":"Success"}`)) + }) + server.Addr = ":18030" + _ = server.ListenAndServe() + }() + + time.Sleep(1 * time.Second) + + err = exporter.pushTraceData(ctx, simpleTraces(10)) + require.NoError(t, err) + + _ = server.Shutdown(ctx) +} + +func simpleTraces(count int) ptrace.Traces { + traces := ptrace.NewTraces() + rs := traces.ResourceSpans().AppendEmpty() + rs.SetSchemaUrl("https://opentelemetry.io/schemas/1.4.0") + rs.Resource().SetDroppedAttributesCount(10) + rs.Resource().Attributes().PutStr("service.name", "test-service") + ss := rs.ScopeSpans().AppendEmpty() + ss.Scope().SetName("io.opentelemetry.contrib.doris") + ss.Scope().SetVersion("1.0.0") + ss.SetSchemaUrl("https://opentelemetry.io/schemas/1.7.0") + ss.Scope().SetDroppedAttributesCount(20) + ss.Scope().Attributes().PutStr("lib", "doris") + timestamp := time.Now() + for i := 0; i < count; i++ { + s := ss.Spans().AppendEmpty() + s.SetTraceID([16]byte{1, 2, 3, byte(i)}) + s.SetSpanID([8]byte{1, 2, 3, byte(i)}) + s.TraceState().FromRaw("trace state") + s.SetParentSpanID([8]byte{1, 2, 4, byte(i)}) + s.SetName("call db") + s.SetKind(ptrace.SpanKindInternal) + s.SetStartTimestamp(pcommon.NewTimestampFromTime(timestamp)) + s.SetEndTimestamp(pcommon.NewTimestampFromTime(timestamp.Add(time.Minute))) + s.Attributes().PutStr(semconv.AttributeServiceName, "v") + s.Status().SetMessage("error") + s.Status().SetCode(ptrace.StatusCodeError) + event := s.Events().AppendEmpty() + event.SetName("event1") + event.SetTimestamp(pcommon.NewTimestampFromTime(timestamp)) + event.Attributes().PutStr("level", "info") + link := s.Links().AppendEmpty() + link.SetTraceID([16]byte{1, 2, 5, byte(i)}) + link.SetSpanID([8]byte{1, 2, 5, byte(i)}) + link.TraceState().FromRaw("error") + link.Attributes().PutStr("k", "v") + } + return traces +} diff --git a/exporter/dorisexporter/factory.go b/exporter/dorisexporter/factory.go index e0ef823200e8..a527e5650c5e 100644 --- a/exporter/dorisexporter/factory.go +++ b/exporter/dorisexporter/factory.go @@ -8,12 +8,12 @@ import ( "time" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/confighttp" "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exporterhelper" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/pmetric" - "go.opentelemetry.io/collector/pdata/ptrace" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/dorisexporter/internal/metadata" ) @@ -29,10 +29,13 @@ func NewFactory() exporter.Factory { } func createDefaultConfig() component.Config { + httpClientConfig := confighttp.NewDefaultClientConfig() + httpClientConfig.Timeout = 60 * time.Second + return &Config{ - TimeoutSettings: exporterhelper.NewDefaultTimeoutSettings(), - QueueSettings: exporterhelper.NewDefaultQueueSettings(), - BackOffConfig: configretry.NewDefaultBackOffConfig(), + ClientConfig: httpClientConfig, + QueueSettings: exporterhelper.NewDefaultQueueSettings(), + BackOffConfig: configretry.NewDefaultBackOffConfig(), Table: Table{ Logs: "otel_logs", Traces: "otel_traces", @@ -59,13 +62,19 @@ func createLogsExporter(ctx context.Context, set exporter.Settings, cfg componen } func createTracesExporter(ctx context.Context, set exporter.Settings, cfg component.Config) (exporter.Traces, error) { + c := cfg.(*Config) + exporter := newTracesExporter(set.Logger, c, set.TelemetrySettings) return exporterhelper.NewTracesExporter( ctx, set, cfg, - func(_ context.Context, _ ptrace.Traces) error { - return nil - }, + exporter.pushTraceData, + exporterhelper.WithStart(exporter.start), + exporterhelper.WithShutdown(exporter.shutdown), + // we config the timeout option in http client, so we don't need to set timeout here + exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: 0}), + exporterhelper.WithQueue(c.QueueSettings), + exporterhelper.WithRetry(c.BackOffConfig), ) } diff --git a/exporter/dorisexporter/go.mod b/exporter/dorisexporter/go.mod index c384dd6ac907..ddb4826f13aa 100644 --- a/exporter/dorisexporter/go.mod +++ b/exporter/dorisexporter/go.mod @@ -6,6 +6,9 @@ toolchain go1.22.7 require ( github.com/cenkalti/backoff/v4 v4.3.0 + // cannot use higher version: https://github.com/go-sql-driver/mysql/issues/1602 + github.com/go-sql-driver/mysql v1.7.1 + github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.108.0 github.com/stretchr/testify v1.9.0 go.opentelemetry.io/collector/component v0.109.0 go.opentelemetry.io/collector/config/configopaque v1.15.0 @@ -14,18 +17,29 @@ require ( go.opentelemetry.io/collector/exporter v0.109.0 go.opentelemetry.io/collector/pdata v1.15.0 go.uber.org/goleak v1.3.0 - go.uber.org/zap v1.27.0 // indirect + go.uber.org/zap v1.27.0 +) + +require ( + go.opentelemetry.io/collector/config/confighttp v0.109.0 + go.opentelemetry.io/collector/config/configtelemetry v0.109.0 + go.opentelemetry.io/collector/semconv v0.109.0 + go.opentelemetry.io/otel/metric v1.29.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect @@ -42,29 +56,44 @@ require ( github.com/prometheus/common v0.57.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/rs/cors v1.11.1 // indirect go.opentelemetry.io/collector v0.109.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.109.0 // indirect + go.opentelemetry.io/collector/client v1.15.0 // indirect + go.opentelemetry.io/collector/config/configauth v0.109.0 // indirect + go.opentelemetry.io/collector/config/configcompression v1.15.0 // indirect + go.opentelemetry.io/collector/config/configtls v1.15.0 // indirect + go.opentelemetry.io/collector/config/internal v0.109.0 // indirect go.opentelemetry.io/collector/consumer v0.109.0 // indirect go.opentelemetry.io/collector/consumer/consumerprofiles v0.109.0 // indirect go.opentelemetry.io/collector/consumer/consumertest v0.109.0 // indirect go.opentelemetry.io/collector/exporter/exporterprofiles v0.109.0 // indirect go.opentelemetry.io/collector/extension v0.109.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.109.0 // indirect go.opentelemetry.io/collector/extension/experimental/storage v0.109.0 // indirect + go.opentelemetry.io/collector/featuregate v1.15.0 // indirect go.opentelemetry.io/collector/pdata/pprofile v0.109.0 // indirect go.opentelemetry.io/collector/receiver v0.109.0 // indirect go.opentelemetry.io/collector/receiver/receiverprofiles v0.109.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect go.opentelemetry.io/otel v1.29.0 // indirect go.opentelemetry.io/otel/exporters/prometheus v0.51.0 // indirect - go.opentelemetry.io/otel/metric v1.29.0 // indirect go.opentelemetry.io/otel/sdk v1.29.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect go.opentelemetry.io/otel/trace v1.29.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.28.0 // indirect golang.org/x/sys v0.24.0 // indirect - golang.org/x/text v0.17.0 // indirect + golang.org/x/text v0.18.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect google.golang.org/grpc v1.66.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal => ../../internal/coreinternal + +replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil => ../../pkg/pdatautil + +replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest => ../../pkg/pdatatest + +replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden => ../../pkg/golden diff --git a/exporter/dorisexporter/go.sum b/exporter/dorisexporter/go.sum index ddf620decb45..653dd58fecab 100644 --- a/exporter/dorisexporter/go.sum +++ b/exporter/dorisexporter/go.sum @@ -8,20 +8,30 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w= github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.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= @@ -64,6 +74,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= 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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= @@ -72,14 +84,26 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/collector v0.109.0 h1:ULnMWuwcy4ix1oP5RFFRcmpEbaU5YabW6nWcLMQQRo0= go.opentelemetry.io/collector v0.109.0/go.mod h1:gheyquSOc5E9Y+xsPmpA+PBrpPc+msVsIalY76/ZvnQ= +go.opentelemetry.io/collector/client v1.15.0 h1:SMUKTntljRmFvB8nCVf6KjbEQ/qm63wi+huDx+Bc/po= +go.opentelemetry.io/collector/client v1.15.0/go.mod h1:m0MdKbzRIVgyGu70qbJ6TwBmKtblk7cmPqspM45a5yY= go.opentelemetry.io/collector/component v0.109.0 h1:AU6eubP1htO8Fvm86uWn66Kw0DMSFhgcRM2cZZTYfII= go.opentelemetry.io/collector/component v0.109.0/go.mod h1:jRVFY86GY6JZ61SXvUN69n7CZoTjDTqWyNC+wJJvzOw= +go.opentelemetry.io/collector/config/configauth v0.109.0 h1:6I2g1dcXD7KCmzXWHaL09I6RSmiCER4b+UARYkmMw3U= +go.opentelemetry.io/collector/config/configauth v0.109.0/go.mod h1:i36T9K3m7pLSlqMFdy+npY7JxfxSg3wQc8bHNpykLLE= +go.opentelemetry.io/collector/config/configcompression v1.15.0 h1:HHzus/ahJW2dA6h4S4vs1MwlbOck27Ivk/L3o0V94UA= +go.opentelemetry.io/collector/config/configcompression v1.15.0/go.mod h1:pnxkFCLUZLKWzYJvfSwZnPrnm0twX14CYj2ADth5xiU= +go.opentelemetry.io/collector/config/confighttp v0.109.0 h1:6R2+zI1LqFarEnCL4k+1DCsFi+aVeUTbfFOQBk0JBh0= +go.opentelemetry.io/collector/config/confighttp v0.109.0/go.mod h1:fzvAO2nCnP9XRUiaCBh1AZ2whUf99iQTkEVFCyH+URk= go.opentelemetry.io/collector/config/configopaque v1.15.0 h1:J1rmPR1WGro7BNCgni3o+VDoyB7ZqH2/SG1YK+6ujCw= go.opentelemetry.io/collector/config/configopaque v1.15.0/go.mod h1:6zlLIyOoRpJJ+0bEKrlZOZon3rOp5Jrz9fMdR4twOS4= go.opentelemetry.io/collector/config/configretry v1.15.0 h1:4ZUPrWWh4wiwdlGnss2lZDhvf1xkt8uwHEqmuqovMEs= go.opentelemetry.io/collector/config/configretry v1.15.0/go.mod h1:KvQF5cfphq1rQm1dKR4eLDNQYw6iI2fY72NMZVa+0N0= go.opentelemetry.io/collector/config/configtelemetry v0.109.0 h1:ItbYw3tgFMU+TqGcDVEOqJLKbbOpfQg3AHD8b22ygl8= go.opentelemetry.io/collector/config/configtelemetry v0.109.0/go.mod h1:R0MBUxjSMVMIhljuDHWIygzzJWQyZHXXWIgQNxcFwhc= +go.opentelemetry.io/collector/config/configtls v1.15.0 h1:imUIYDu6lo7juxxgpJhoMQ+LJRxqQzKvjOcWTo4u0IY= +go.opentelemetry.io/collector/config/configtls v1.15.0/go.mod h1:T3pOF5UemLzmYgY7QpiZuDRrihJ8lyXB0cDe6j1F1Ek= +go.opentelemetry.io/collector/config/internal v0.109.0 h1:uAlmO9Gu4Ff5wXXWWn+7XRZKEBjwGE8YdkdJxOlodns= +go.opentelemetry.io/collector/config/internal v0.109.0/go.mod h1:JJJGJTz1hILaaT+01FxbCFcDvPf2otXqMcWk/s2KvlA= go.opentelemetry.io/collector/confmap v1.15.0 h1:KaNVG6fBJXNqEI+/MgZasH0+aShAU1yAkSYunk6xC4E= go.opentelemetry.io/collector/confmap v1.15.0/go.mod h1:GrIZ12P/9DPOuTpe2PIS51a0P/ZM6iKtByVee1Uf3+k= go.opentelemetry.io/collector/consumer v0.109.0 h1:fdXlJi5Rat/poHPiznM2mLiXjcv1gPy3fyqqeirri58= @@ -94,8 +118,12 @@ go.opentelemetry.io/collector/exporter/exporterprofiles v0.109.0 h1:px+iViqF0JB6 go.opentelemetry.io/collector/exporter/exporterprofiles v0.109.0/go.mod h1:Zs5z/fdsRN3v9mChU2aYNGzUAJgY+2D+T7ZRGiZ3lmY= go.opentelemetry.io/collector/extension v0.109.0 h1:r/WkSCYGF1B/IpUgbrKTyJHcfn7+A5+mYfp5W7+B4U0= go.opentelemetry.io/collector/extension v0.109.0/go.mod h1:WDE4fhiZnt2haxqSgF/2cqrr5H+QjgslN5tEnTBZuXc= +go.opentelemetry.io/collector/extension/auth v0.109.0 h1:yKUMCUG3IkjuOnHriNj0nqFU2DRdZn3Tvn9eqCI0eTg= +go.opentelemetry.io/collector/extension/auth v0.109.0/go.mod h1:wOIv49JhXIfol8CRmQvLve05ft3nZQUnTfcnuZKxdbo= go.opentelemetry.io/collector/extension/experimental/storage v0.109.0 h1:kIJiOXHHBgMCvuDNA602dS39PJKB+ryiclLE3V5DIvM= go.opentelemetry.io/collector/extension/experimental/storage v0.109.0/go.mod h1:6cGr7MxnF72lAiA7nbkSC8wnfIk+L9CtMzJWaaII9vs= +go.opentelemetry.io/collector/featuregate v1.15.0 h1:8KRWaZaE9hLlyMXnMTvnWtUJnzrBuTI0aLIvxqe8QP0= +go.opentelemetry.io/collector/featuregate v1.15.0/go.mod h1:47xrISO71vJ83LSMm8+yIDsUbKktUp48Ovt7RR6VbRs= go.opentelemetry.io/collector/pdata v1.15.0 h1:q/T1sFpRKJnjDrUsHdJ6mq4uSqViR/f92yvGwDby/gY= go.opentelemetry.io/collector/pdata v1.15.0/go.mod h1:2wcsTIiLAJSbqBq/XUUYbi+cP+N87d0jEJzmb9nT19U= go.opentelemetry.io/collector/pdata/pprofile v0.109.0 h1:5lobQKeHk8p4WC7KYbzL6ZqqX3eSizsdmp5vM8pQFBs= @@ -106,6 +134,10 @@ go.opentelemetry.io/collector/receiver v0.109.0 h1:DTOM7xaDl7FUGQIjvjmWZn03JUE+a go.opentelemetry.io/collector/receiver v0.109.0/go.mod h1:jeiCHaf3PE6aXoZfHF5Uexg7aztu+Vkn9LVw0YDKm6g= go.opentelemetry.io/collector/receiver/receiverprofiles v0.109.0 h1:KKzdIixE/XJWvqdCcNWAOtsEhNKu4waLKJjawjhnPLw= go.opentelemetry.io/collector/receiver/receiverprofiles v0.109.0/go.mod h1:FKU+RFkSLWWB3tUUB6vifapZdFp1FoqVYVQ22jpHc8w= +go.opentelemetry.io/collector/semconv v0.109.0 h1:6CStOFOVhdrzlHg51kXpcPHRKPh5RtV7z/wz+c1TG1g= +go.opentelemetry.io/collector/semconv v0.109.0/go.mod h1:zCJ5njhWpejR+A40kiEoeFm1xq1uzyZwMnRNX6/D82A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= go.opentelemetry.io/otel/exporters/prometheus v0.51.0 h1:G7uexXb/K3T+T9fNLCCKncweEtNEBMTO+46hKX5EdKw= @@ -145,8 +177,8 @@ golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= golang.org/x/sys v0.24.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.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= diff --git a/exporter/dorisexporter/sql/traces_ddl.sql b/exporter/dorisexporter/sql/traces_ddl.sql new file mode 100644 index 000000000000..42d48d82de65 --- /dev/null +++ b/exporter/dorisexporter/sql/traces_ddl.sql @@ -0,0 +1,42 @@ +CREATE TABLE IF NOT EXISTS %s +( + service_name VARCHAR(200), + timestamp DATETIME(6), + trace_id VARCHAR(200), + span_id STRING, + trace_state STRING, + parent_span_id STRING, + span_name STRING, + span_kind STRING, + end_time DATETIME(6), + duration BIGINT, + span_attributes VARIANT, + events ARRAY>>, + links ARRAY>>, + status_message STRING, + status_code STRING, + resource_attributes VARIANT, + scope_name STRING, + scope_version STRING, + INDEX idx_service_name(service_name) USING INVERTED, + INDEX idx_timestamp(timestamp) USING INVERTED, + INDEX idx_trace_id(trace_id) USING INVERTED, + INDEX idx_span_id(span_id) USING INVERTED, + INDEX idx_trace_state(trace_state) USING INVERTED, + INDEX idx_parent_span_id(parent_span_id) USING INVERTED, + INDEX idx_span_name(span_name) USING INVERTED, + INDEX idx_span_kind(span_kind) USING INVERTED, + INDEX idx_end_time(end_time) USING INVERTED, + INDEX idx_duration(duration) USING INVERTED, + INDEX idx_span_attributes(span_attributes) USING INVERTED, + INDEX idx_status_message(status_message) USING INVERTED, + INDEX idx_status_code(status_code) USING INVERTED, + INDEX idx_resource_attributes(resource_attributes) USING INVERTED, + INDEX idx_scope_name(scope_name) USING INVERTED, + INDEX idx_scope_version(scope_version) USING INVERTED +) +ENGINE = OLAP +DUPLICATE KEY(service_name, timestamp) +PARTITION BY RANGE(timestamp) () +DISTRIBUTED BY HASH(trace_id) BUCKETS AUTO +%s;