Skip to content

Commit 7a4776e

Browse files
committed
feat: Add Opentelemetry integration design in client_design.md
Signed-off-by: chenhuan <xiangyuyu_2024@qq.com>
1 parent 7ca72bd commit 7a4776e

File tree

3 files changed

+345
-0
lines changed

3 files changed

+345
-0
lines changed

openGemini.github.io

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 7ca72bd65544f93de353c494d1abdbbb79f6b31e

src/guide/develop/client_design.md

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,179 @@ classDiagram
245245
SeriesResult "1" *-- "0..*" Series: contains
246246
```
247247

248+
# OpenTelemetry integration design
249+
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.
250+
251+
## Interceptor design
252+
The interceptor pattern defines a standardized interface to hook into client operations (query/write) and inject telemetry logic.
253+
254+
255+
```mermaid
256+
Interceptor interface {
257+
Query(ctx context.Context, query *InterceptorQuery) InterceptorClosure
258+
Write(ctx context.Context, write *InterceptorWrite) InterceptorClosure
259+
}
260+
```
261+
262+
## Define the base client class,associated with the Interceptor interface
263+
The base  Client  class manages a collection of interceptors, allowing dynamic registration and execution of interceptor logic during client operations.
264+
265+
```mermaid
266+
class Client {
267+
- []Interceptor interceptors
268+
}
269+
```
270+
271+
## Define the interceptor implementation class integrating OpenTelemetry,implementing the Interceptor interface
272+
The OtelClient class implements the Interceptor interface, embedding OpenTelemetry logic to capture traces, metrics, and logs for client operations.
273+
274+
```mermaid
275+
class OtelClient {
276+
Interceptor
277+
}
278+
```
279+
280+
## Tracing system core module
281+
282+
```mermaid
283+
class TraceContext {
284+
+ traceId: String
285+
+ parentTraceId: String
286+
+ operationName: String
287+
+ timestamp: Long
288+
+ attributes: Map~String, Object~
289+
+ createChildContext() : TraceContext
290+
+ addAttribute(key, value) : void
291+
+ getAttribute(key) : Object
292+
}
293+
294+
class ContextManager {
295+
+ getCurrentContext() : TraceContext
296+
+ bindContext(context, task) : void
297+
+ unbindContext() : TraceContext
298+
}
299+
300+
class OperationInterceptor {
301+
<<Interface>>
302+
+ preProcess(operationContext) : void
303+
+ postProcess(operationContext, result) : void
304+
+ errorProcess(operationContext, exception) : void
305+
}
306+
307+
class QueryInterceptor {
308+
+ preProcess(operationContext) : void
309+
+ postProcess(operationContext, queryResult) : void
310+
+ errorProcess(operationContext, exception) : void
311+
}
312+
313+
class WriteInterceptor {
314+
+ preProcess(operationContext) : void
315+
+ postProcess(operationContext, writeResult) : void
316+
+ errorProcess(operationContext, exception) : void
317+
}
318+
319+
class InterceptorChain {
320+
+ interceptors: List~OperationInterceptor~
321+
+ addInterceptor(interceptor) : void
322+
+ executePreFlow(operationContext) : void
323+
+ executePostFlow(operationContext, result) : void
324+
+ executeErrorFlow(operationContext, exception) : void
325+
}
326+
327+
class OperationContext {
328+
+ traceContext: TraceContext
329+
+ operationType: Enum~Query/Write~
330+
+ operationParams: Map~String, Object~
331+
+ getTraceContext() : TraceContext
332+
+ setOperationResult(result) : void
333+
}
334+
335+
class SDKConfigurator {
336+
+ configureExporter(exporter) : SDKConfigurator
337+
+ configurePropagator(propagator) : SDKConfigurator
338+
+ configureTracerProvider(provider) : SDKConfigurator
339+
+ initialize() : OpenTelemetrySDK
340+
}
341+
342+
class TraceExporter {
343+
<<Interface>>
344+
+ exportTraceData(traceDataList) : void
345+
}
346+
347+
class ContextPropagator {
348+
<<Interface>>
349+
+ inject(traceContext, carrier) : void
350+
+ extract(carrier) : TraceContext
351+
}
352+
353+
class TracerProvider {
354+
+ getTracer(name) : Tracer
355+
}
356+
357+
class Tracer {
358+
+ createTraceContext(operationName) : TraceContext
359+
+ endTraceContext(traceContext) : void
360+
}
361+
362+
class OpenTelemetrySDK {
363+
+ getTracerProvider() : TracerProvider
364+
+ getContextPropagator() : ContextPropagator
365+
+ getTraceExporter() : TraceExporter
366+
}
367+
368+
QueryInterceptor ..|> OperationInterceptor
369+
WriteInterceptor ..|> OperationInterceptor
370+
InterceptorChain o-- OperationInterceptor : contains
371+
OperationContext o-- TraceContext : holds
372+
ContextManager o-- TraceContext : manages
373+
374+
SDKConfigurator ..> TraceExporter : configures
375+
SDKConfigurator ..> ContextPropagator : configures
376+
SDKConfigurator ..> TracerProvider : configures
377+
SDKConfigurator ..> OpenTelemetrySDK : initializes
378+
OpenTelemetrySDK o-- TracerProvider : contains
379+
OpenTelemetrySDK o-- ContextPropagator : contains
380+
OpenTelemetrySDK o-- TraceExporter : contains
381+
TracerProvider o-- Tracer : provides
382+
Tracer ..> TraceContext : creates/ends
383+
384+
InterceptorChain ..> OperationContext : processes
385+
Tracer ..> ContextManager : binds context
386+
```
387+
388+
## Usage Example(Go language examples)
389+
390+
```mermaid
391+
func main() {
392+
var ctx = context.Background()
393+
shutdown, err := setupOtelSDK(ctx)
394+
if err != nil {
395+
return
396+
}
397+
defer func() {
398+
err = errors.Join(err, shutdown(ctx))
399+
}()
400+
401+
config := &opengemini.Config{
402+
Addresses: []opengemini.Address{{
403+
Host: "127.0.0.1",
404+
Port: 8086,
405+
}},
406+
}
407+
client, err := opengemini.NewClient(config)
408+
if err != nil {
409+
fmt.Println(err)
410+
return
411+
}
412+
413+
client.Interceptors(opengemini.NewOtelInterceptor())
414+
415+
err = client.CreateDatabase("db0")
416+
if err != nil {
417+
}
418+
}
419+
```
420+
248421
# QueryBuilder design
249422

250423
```mermaid

src/zh/guide/develop/client_design.md

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,177 @@ classDiagram
230230
SeriesResult "1" *-- "0..*" Series: contains
231231
```
232232

233+
# OpenTelemetry 集成设计
234+
为增强 OpenGemini 客户端的可观测性,便于追踪与查询、写入操作相关的性能指标、错误及其他信息,本方案采用拦截器模式集成 OpenTelemetry,实现全链路追踪。该设计支持非侵入式扩展,允许与其他拦截器(如日志、认证拦截器)共存,同时最大限度减少对原有客户端的修改。
235+
## 拦截器设计
236+
拦截器模式定义了标准化接口,用于挂钩客户端操作(查询/写入)并注入遥测逻辑。
237+
238+
```mermaid
239+
Interceptor interface {
240+
Query(ctx context.Context, query *InterceptorQuery) InterceptorClosure
241+
Write(ctx context.Context, write *InterceptorWrite) InterceptorClosure
242+
}
243+
```
244+
245+
## 定义基础客户端类,关联拦截器接口
246+
基础 Client 类管理一组拦截器,允许在客户端操作期间动态注册和执行拦截器逻辑。
247+
248+
```mermaid
249+
class Client {
250+
- []Interceptor interceptors
251+
}
252+
```
253+
254+
## 定义集成 OpenTelemetry 的拦截器实现类,实现 Interceptor 接口
255+
OtelClient 类实现 Interceptor 接口,嵌入 OpenTelemetry 逻辑以捕获客户端操作的跟踪、指标和日志。
256+
257+
```mermaid
258+
class OtelClient {
259+
Interceptor
260+
}
261+
```
262+
263+
## 追踪系统核心模块
264+
265+
```mermaid
266+
class TraceContext {
267+
+ traceId: String
268+
+ parentTraceId: String
269+
+ operationName: String
270+
+ timestamp: Long
271+
+ attributes: Map~String, Object~
272+
+ createChildContext() : TraceContext
273+
+ addAttribute(key, value) : void
274+
+ getAttribute(key) : Object
275+
}
276+
277+
class ContextManager {
278+
+ getCurrentContext() : TraceContext
279+
+ bindContext(context, task) : void
280+
+ unbindContext() : TraceContext
281+
}
282+
283+
class OperationInterceptor {
284+
<<Interface>>
285+
+ preProcess(operationContext) : void
286+
+ postProcess(operationContext, result) : void
287+
+ errorProcess(operationContext, exception) : void
288+
}
289+
290+
class QueryInterceptor {
291+
+ preProcess(operationContext) : void
292+
+ postProcess(operationContext, queryResult) : void
293+
+ errorProcess(operationContext, exception) : void
294+
}
295+
296+
class WriteInterceptor {
297+
+ preProcess(operationContext) : void
298+
+ postProcess(operationContext, writeResult) : void
299+
+ errorProcess(operationContext, exception) : void
300+
}
301+
302+
class InterceptorChain {
303+
+ interceptors: List~OperationInterceptor~
304+
+ addInterceptor(interceptor) : void
305+
+ executePreFlow(operationContext) : void
306+
+ executePostFlow(operationContext, result) : void
307+
+ executeErrorFlow(operationContext, exception) : void
308+
}
309+
310+
class OperationContext {
311+
+ traceContext: TraceContext
312+
+ operationType: Enum~Query/Write~
313+
+ operationParams: Map~String, Object~
314+
+ getTraceContext() : TraceContext
315+
+ setOperationResult(result) : void
316+
}
317+
318+
class SDKConfigurator {
319+
+ configureExporter(exporter) : SDKConfigurator
320+
+ configurePropagator(propagator) : SDKConfigurator
321+
+ configureTracerProvider(provider) : SDKConfigurator
322+
+ initialize() : OpenTelemetrySDK
323+
}
324+
325+
class TraceExporter {
326+
<<Interface>>
327+
+ exportTraceData(traceDataList) : void
328+
}
329+
330+
class ContextPropagator {
331+
<<Interface>>
332+
+ inject(traceContext, carrier) : void
333+
+ extract(carrier) : TraceContext
334+
}
335+
336+
class TracerProvider {
337+
+ getTracer(name) : Tracer
338+
}
339+
340+
class Tracer {
341+
+ createTraceContext(operationName) : TraceContext
342+
+ endTraceContext(traceContext) : void
343+
}
344+
345+
class OpenTelemetrySDK {
346+
+ getTracerProvider() : TracerProvider
347+
+ getContextPropagator() : ContextPropagator
348+
+ getTraceExporter() : TraceExporter
349+
}
350+
351+
QueryInterceptor ..|> OperationInterceptor
352+
WriteInterceptor ..|> OperationInterceptor
353+
InterceptorChain o-- OperationInterceptor : contains
354+
OperationContext o-- TraceContext : holds
355+
ContextManager o-- TraceContext : manages
356+
357+
SDKConfigurator ..> TraceExporter : configures
358+
SDKConfigurator ..> ContextPropagator : configures
359+
SDKConfigurator ..> TracerProvider : configures
360+
SDKConfigurator ..> OpenTelemetrySDK : initializes
361+
OpenTelemetrySDK o-- TracerProvider : contains
362+
OpenTelemetrySDK o-- ContextPropagator : contains
363+
OpenTelemetrySDK o-- TraceExporter : contains
364+
TracerProvider o-- Tracer : provides
365+
Tracer ..> TraceContext : creates/ends
366+
367+
InterceptorChain ..> OperationContext : processes
368+
Tracer ..> ContextManager : binds context
369+
```
370+
371+
## 使用示例(Go language examples)
372+
373+
```mermaid
374+
func main() {
375+
var ctx = context.Background()
376+
shutdown, err := setupOtelSDK(ctx)
377+
if err != nil {
378+
return
379+
}
380+
defer func() {
381+
err = errors.Join(err, shutdown(ctx))
382+
}()
383+
384+
config := &opengemini.Config{
385+
Addresses: []opengemini.Address{{
386+
Host: "127.0.0.1",
387+
Port: 8086,
388+
}},
389+
}
390+
client, err := opengemini.NewClient(config)
391+
if err != nil {
392+
fmt.Println(err)
393+
return
394+
}
395+
396+
client.Interceptors(opengemini.NewOtelInterceptor())
397+
398+
err = client.CreateDatabase("db0")
399+
if err != nil {
400+
}
401+
}
402+
```
403+
233404
# 查询构造器设计
234405

235406
```mermaid

0 commit comments

Comments
 (0)