This is an automated email from the ASF dual-hosted git repository.

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git


The following commit(s) were added to refs/heads/main by this push:
     new a727830d57 fix(go/adbc/driver): corrects 'none' trace exporter 
handling (#4822)
a727830d57 is described below

commit a727830d5722262fc7c3e24b6f8edb982c7b9b29
Author: Bruce Irschick <[email protected]>
AuthorDate: Wed Sep 30 17:24:00 2026 -0700

    fix(go/adbc/driver): corrects 'none' trace exporter handling (#4822)
    
    This pull request enhances the tracing functionality and its test
    coverage for the FlightSQL ADBC driver. The main changes include
    refactoring the tracing test logic for better reusability, adding
    comprehensive tests for tracing exporter configuration (including
    default and override folder handling), and ensuring that explicitly
    disabling tracing uses the global tracer provider.
    
    **Tracing test improvements:**
    
    * Refactored tracing test logic by extracting common functionality into
    helper functions: `executeFlightSQLTraceQuery`, `traceFiles`, and
    `setDefaultTracingFolder` in `flightsql_adbc_test.go`. This improves
    test readability and maintainability.
    
[[1]](diffhunk://#diff-1147cdf8ab7a5dcb1d84bcb2b7a2185cf2fc3802b7eb3718bffadfe990ecdf56L320-L336)
    
[[2]](diffhunk://#diff-1147cdf8ab7a5dcb1d84bcb2b7a2185cf2fc3802b7eb3718bffadfe990ecdf56L357-R396)
    * Added new tests to verify tracing exporter behavior:
    - Test that enabling and disabling the ADBC file exporter produces or
    omits trace files as expected.
    - Test that the default tracing folder is used when no folder is
    specified.
    - Test that specifying a tracing folder option overrides the default
    folder and prevents traces from being written to the default location.
    
    **Tracing exporter configuration:**
    
    * Updated the tracing initialization logic in `DatabaseImplBase` so that
    both an empty exporter name and an explicit `TelemetryExporterNone`
    value result in using the global tracer provider, ensuring tracing is
    effectively disabled in these cases.
    * Added a unit test to verify that setting the exporter to
    `TelemetryExporterNone` uses the global tracer provider, ensuring
    correct behavior when tracing is disabled.
    
    **Test infrastructure:**
    
    * Imported the OpenTelemetry package in `driver_test.go` to support the
    new tracer provider assertions.
    
    Developed with assistance from GitHub Copilot (Copilot SDK in VS Code).
    
    Co-authored-by: Bruce Irschick (Bit Quill Technologies Inc) 
<[email protected]>
---
 go/adbc/driver/flightsql/flightsql_adbc_test.go   | 137 ++++++++++++++++------
 go/adbc/driver/internal/driverbase/database.go    |   4 +-
 go/adbc/driver/internal/driverbase/driver_test.go |  14 +++
 3 files changed, 120 insertions(+), 35 deletions(-)

diff --git a/go/adbc/driver/flightsql/flightsql_adbc_test.go 
b/go/adbc/driver/flightsql/flightsql_adbc_test.go
index d7dc28c3f4..0a73eabcc7 100644
--- a/go/adbc/driver/flightsql/flightsql_adbc_test.go
+++ b/go/adbc/driver/flightsql/flightsql_adbc_test.go
@@ -340,10 +340,12 @@ func TestADBCFlightSQL(t *testing.T) {
        suite.Run(t, &DomainSocketTests{db: db})
 }
 
-func TestFlightSQLTracingProducesTraceFiles(t *testing.T) {
+func executeFlightSQLTraceQuery(t *testing.T, tracingOpts map[string]string) {
+       t.Helper()
+
        // TODO: Reuse example.CreateDB() here after apache/arrow-go#916 
isolates
        // the shared in-memory SQLite database per call.
-       db, err := sql.Open("sqlite", 
fmt.Sprintf("file:%s-%d?mode=memory&cache=private", strings.ToLower(t.Name()), 
time.Now().UnixNano()))
+       db, err := sql.Open("sqlite", 
fmt.Sprintf("file:trace-%d?mode=memory&cache=private", time.Now().UnixNano()))
        require.NoError(t, err)
        defer validation.CheckedClose(t, db)
 
@@ -351,49 +353,118 @@ func TestFlightSQLTracingProducesTraceFiles(t 
*testing.T) {
        drv := q.SetupDriver(t)
        defer q.TearDownDriver(t, drv)
 
-       traceDir := t.TempDir()
        opts := q.DatabaseOptions()
-       opts[adbc.OptionKeyTelemetryTracesExporter] = 
string(adbc.TelemetryExporterAdbcFile)
-       opts[adbc.OptionKeyTelemetryTracesFolderPath] = traceDir
+       for key, value := range tracingOpts {
+               opts[key] = value
+       }
 
-       func() {
-               adbcDB, err := drv.NewDatabase(opts)
-               require.NoError(t, err)
-               defer validation.CheckedClose(t, adbcDB)
+       adbcDB, err := drv.NewDatabase(opts)
+       require.NoError(t, err)
+       defer validation.CheckedClose(t, adbcDB)
 
-               cnxn, err := adbcDB.Open(context.Background())
-               require.NoError(t, err)
-               defer validation.CheckedClose(t, cnxn)
+       cnxn, err := adbcDB.Open(context.Background())
+       require.NoError(t, err)
+       defer validation.CheckedClose(t, cnxn)
 
-               stmt, err := cnxn.NewStatement()
-               require.NoError(t, err)
-               defer validation.CheckedClose(t, stmt)
+       stmt, err := cnxn.NewStatement()
+       require.NoError(t, err)
+       defer validation.CheckedClose(t, stmt)
 
-               require.NoError(t, stmt.SetSqlQuery("SELECT 1"))
-               reader, _, err := stmt.ExecuteQuery(context.Background())
-               require.NoError(t, err)
-               defer reader.Release()
+       require.NoError(t, stmt.SetSqlQuery("SELECT 1"))
+       reader, _, err := stmt.ExecuteQuery(context.Background())
+       require.NoError(t, err)
+       defer reader.Release()
 
-               for reader.Next() {
-               }
-               require.NoError(t, reader.Err())
-       }()
+       for reader.Next() {
+       }
+       require.NoError(t, reader.Err())
+}
+
+func traceFiles(t *testing.T, traceDir string) []string {
+       t.Helper()
 
        files, err := filepath.Glob(filepath.Join(traceDir, "*.jsonl"))
        require.NoError(t, err)
-       require.NotEmpty(t, files)
+       return files
+}
 
-       var traceOutput strings.Builder
-       for _, file := range files {
-               data, err := os.ReadFile(file)
-               require.NoError(t, err)
-               traceOutput.Write(data)
+func setDefaultTracingFolder(t *testing.T) string {
+       t.Helper()
+
+       tempDir := t.TempDir()
+       switch runtime.GOOS {
+       case "windows":
+               localAppDataDir := filepath.Join(tempDir, "AppData", "Local")
+               t.Setenv("LocalAppData", localAppDataDir)
+               return filepath.Join(localAppDataDir, "ADBC", "Traces")
+       case "darwin":
+               t.Setenv("HOME", tempDir)
+               return filepath.Join(tempDir, "Library", "Application Support", 
"ADBC", "Traces")
+       default:
+               stateDir := filepath.Join(tempDir, ".local", "state")
+               t.Setenv("XDG_STATE_HOME", stateDir)
+               t.Setenv("HOME", tempDir)
+               return filepath.Join(stateDir, "adbc", "traces")
        }
+}
+
+func TestFlightSQLTracingAdbcFileExporterCanBeEnabledAndDisabled(t *testing.T) 
{
+       t.Run("enabled", func(t *testing.T) {
+               traceDir := t.TempDir()
+               executeFlightSQLTraceQuery(t, map[string]string{
+                       adbc.OptionKeyTelemetryTracesExporter:   
string(adbc.TelemetryExporterAdbcFile),
+                       adbc.OptionKeyTelemetryTracesFolderPath: traceDir,
+               })
+
+               files := traceFiles(t, traceDir)
+               require.NotEmpty(t, files)
+
+               var traceOutput strings.Builder
+               for _, file := range files {
+                       data, err := os.ReadFile(file)
+                       require.NoError(t, err)
+                       traceOutput.Write(data)
+               }
+
+               output := traceOutput.String()
+               require.Contains(t, output, "FlightSQL.Database.Open")
+               require.Contains(t, output, "FlightSQL.Database.Close")
+               require.Contains(t, output, "FlightSQL.Statement.ExecuteQuery")
+       })
+
+       t.Run("disabled", func(t *testing.T) {
+               traceDir := t.TempDir()
+               executeFlightSQLTraceQuery(t, map[string]string{
+                       adbc.OptionKeyTelemetryTracesExporter:   
string(adbc.TelemetryExporterNone),
+                       adbc.OptionKeyTelemetryTracesFolderPath: traceDir,
+               })
+
+               require.Empty(t, traceFiles(t, traceDir))
+       })
+}
+
+func TestFlightSQLTracingAdbcFileExporterUsesDefaultFolder(t *testing.T) {
+       defaultTraceDir := setDefaultTracingFolder(t)
+
+       executeFlightSQLTraceQuery(t, map[string]string{
+               adbc.OptionKeyTelemetryTracesExporter: 
string(adbc.TelemetryExporterAdbcFile),
+       })
+
+       require.NotEmpty(t, traceFiles(t, defaultTraceDir))
+}
+
+func TestFlightSQLTracingFolderOptionOverridesDefaultFolder(t *testing.T) {
+       defaultTraceDir := setDefaultTracingFolder(t)
+       overrideTraceDir := t.TempDir()
+
+       executeFlightSQLTraceQuery(t, map[string]string{
+               adbc.OptionKeyTelemetryTracesExporter:   
string(adbc.TelemetryExporterAdbcFile),
+               adbc.OptionKeyTelemetryTracesFolderPath: overrideTraceDir,
+       })
 
-       output := traceOutput.String()
-       require.Contains(t, output, "FlightSQL.Database.Open")
-       require.Contains(t, output, "FlightSQL.Database.Close")
-       require.Contains(t, output, "FlightSQL.Statement.ExecuteQuery")
+       require.NotEmpty(t, traceFiles(t, overrideTraceDir))
+       _, err := os.Stat(defaultTraceDir)
+       require.ErrorIs(t, err, os.ErrNotExist)
 }
 
 // TestFlightSQLTracingCleansUpAfterConstructionFailure verifies that failures
diff --git a/go/adbc/driver/internal/driverbase/database.go 
b/go/adbc/driver/internal/driverbase/database.go
index fb664f7199..50693a66bd 100644
--- a/go/adbc/driver/internal/driverbase/database.go
+++ b/go/adbc/driver/internal/driverbase/database.go
@@ -277,8 +277,8 @@ func (base *DatabaseImplBase) InitTracing(
                exporterName = getExporterName()
        }
 
-       // Empty exporter
-       if exporterName == "" {
+       // Empty or explicitly disabled exporter
+       if exporterName == "" || exporterName == 
string(adbc.TelemetryExporterNone) {
                base.tracerProvider = otel.GetTracerProvider()
                base.Tracer = otel.Tracer(fullyQualifiedDriverName)
                return
diff --git a/go/adbc/driver/internal/driverbase/driver_test.go 
b/go/adbc/driver/internal/driverbase/driver_test.go
index 2084cd140c..808f581e31 100644
--- a/go/adbc/driver/internal/driverbase/driver_test.go
+++ b/go/adbc/driver/internal/driverbase/driver_test.go
@@ -36,6 +36,7 @@ import (
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/mock"
        "github.com/stretchr/testify/require"
+       "go.opentelemetry.io/otel"
 )
 
 const (
@@ -460,6 +461,19 @@ func TestCustomizedDriver(t *testing.T) {
        }
 }
 
+func TestTracingExporterNoneUsesGlobalTracerProvider(t *testing.T) {
+       info := driverbase.DefaultDriverInfo("MockDriver")
+       drv := driverbase.NewDriverImplBase(info, memory.DefaultAllocator)
+
+       dbBase, err := driverbase.NewDatabaseImplBase(context.Background(), 
&drv, driverbase.TracingOptions{
+               ExporterName: string(adbc.TelemetryExporterNone),
+       })
+       require.NoError(t, err)
+       require.Same(t, otel.GetTracerProvider(), dbBase.GetTracerProvider())
+       require.NoError(t, dbBase.ForceFlushTracing(context.Background()))
+       require.NoError(t, dbBase.Close())
+}
+
 type driverImpl struct {
        driverbase.DriverImplBase
 

Reply via email to