Client Design
Background
Due to the InfluxDB 1.X client largely being in maintenance mode, and openGemini continuously evolving, the community has decided to develop its own client SDK for openGemini to better support it. This includes functionalities like supporting multiple server addresses and the Apache Arrow Flight protocol.
Client SDK Planned Features
- Support for connecting to multiple server addresses
- Support for the Apache Arrow Flight protocol
- Capabilities for SQL queries, structured queries, writing, and batch writing are detailed in the UML diagram below
- Default timeouts, with a connection timeout of 10 seconds and read/write timeout of 30 seconds
The methods described in this document assume that the programming language does not support overloading. If overloading is supported by the programming language, some optimizations and adjustments can be made to the method names.
Client constructor params design
Database & RetentionPolicy management design
Write point design
Execute interface design
The Execute interface provides a unified SQL execution interface that automatically routes different types of statements to appropriate underlying methods. This design supports SQL-like statements including INSERT, SELECT, CREATE, DROP, and other database operations with parameter support and type safety.
Statement routing logic
Parameter support
The Execute interface supports parameterized statements with automatic type conversion:
Usage examples
Basic usage
result, err := client.Execute(opengemini.Statement{
Database: "mydb",
Command: "SELECT * FROM weather LIMIT 10",
})
Parameterized query
result, err := client.Execute(opengemini.Statement{
Database: "mydb",
Command: "SELECT * FROM weather WHERE location=$loc AND temp>$temp",
Params: map[string]any{
"loc": "beijing",
"temp": 25.0,
},
})
Parameterized insert
result, err := client.Execute(opengemini.Statement{
Database: "mydb",
Command: "INSERT weather,location=$location temperature=$temp,humidity=$hum",
Params: map[string]any{
"location": "shanghai",
"temp": 30.2,
"hum": 70,
},
})
Query design
OpenTelemetry integration design
To enhance the observability of the OpenGemini client and facilitate tracking of performance metrics, errors, and other information related to query and write operations, this solution adopts the interceptor pattern to integrate OpenTelemetry, enabling full-link tracing. The design supports non-intrusive extensions, allowing coexistence with other interceptors (such as logging and authentication interceptors) while minimizing modifications to the original client.
Interceptor design
The interceptor pattern defines a standardized interface to hook into client operations (query/write) and inject telemetry logic.
Define the base client class,associated with the Interceptor interface
The base Client class manages a collection of interceptors, allowing dynamic registration and execution of interceptor logic during client operations.
Define the interceptor implementation class integrating OpenTelemetry,implementing the Interceptor interface
The OtelClient class implements the Interceptor interface, embedding OpenTelemetry logic to capture traces, metrics, and logs for client operations.
Tracing system core module
Usage Example(Go language examples)
func main() {
var ctx = context.Background()
shutdown, err := setupOtelSDK(ctx)
if err != nil {
return
}
defer func() {
err = errors.Join(err, shutdown(ctx))
}()
config := &opengemini.Config{
Addresses: []opengemini.Address{{
Host: "127.0.0.1",
Port: 8086,
}},
}
client, err := opengemini.NewClient(config)
if err != nil {
fmt.Println(err)
return
}
client.Interceptors(opengemini.NewOtelInterceptor())
err = client.CreateDatabase("db0")
if err != nil {
}
}
QueryBuilder design
Ping design
Inner Http client design
Using a design similar to InnerHttpClient, encapsulate authentication, load balancing, retry logic, and more within the internal structure, providing a simple interface to the client. This enhances modularity and code clarity.
Error handling
Error message
Scene1 http request failed
$operation request failed, error: $error_details
Scene2 http response code is not 200~300
$operation error resp, code: $code, body: $body
Scene3 other error
$operation failed, error: $error_details
# example:
writePoint failed, unmarshall response body error: json: cannot unmarshal number ...