برنامه نویسی

بدون گلوبال به آثار otel بروید

بنابراین من در حال انجام برخی از کارهایی هستم که به یک سرویس GO اضافه می کنم و یادداشت هایی دارم. سرویس مورد نظر درخواست هایی را با عنوان های ردیابی دریافت می کند ، اما همچنین به خدمات دیگر تماس می گیرد و بنابراین باید عنوان ها را به درخواست های بعدی نیز تزریق کند.

در مرحله اول ، Otel SDK بسیار گسترده است و مدتی طول می کشد تا سرتان را دور خود بکشید. همچنین ، فکر نکنید که فقط می توانید یک افزونه را برای روتر HTTP خود اضافه کنید و انجام شود- متاسفانه چنین شانسی نیست. مثالهای SDK از متغیرهای جهانی در مکان های مختلف که من واقعاً دوست ندارم استفاده می کند. در واقع از چند سال پیش مانند کتابخانه پرومتئوس احساس می شود. به هر حال ، این راهنما با هدف جلوگیری از همه متغیرهای جهانی و انجام صحیح کارها است.

راه اندازی

اول چیزها اول- شما به یک دسته از مواردی که فوری می کنید نیاز دارید و سپس برنامه خود را منتقل می کنید. فهمیدم که 3 موردی که برای عبور از آن نیاز داشتم این بود trace.Tracerبا trace.TracerProvider و propagation.TextMapPropagatorبشر

تنظیم واقعی هر یک از این موارد مانند این به نظر می رسد:

...
otel.SetTracerProvider(noop.NewTracerProvider())
exporter, err := otlptracehttp.New(ctx)
r := resource.NewWithAttributes(
        semconv.SchemaURL,
        semconv.ServiceName("myService"),
        semconv.ServiceVersionKey.String("myVersion"),
    )
traceProvider := sdktrace.NewTracerProvider(
            sdktrace.WithBatcher(exporter),
            sdktrace.WithResource(r),
        )
tracer = traceProvider.Tracer(serviceName, trace.WithInstrumentationVersion(version))
textMapPropagator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})
...
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

کاری که من به پایان رساندم ، ایجاد ساختاری با این چیزها در آن است ، به علاوه برخی موارد مشاهده دیگر که همه در اطراف برنامه با هم منتقل می شوند و این باعث می شود چیز بسیار تمیزتر شود

...
type O11y struct {
    Logger            *zerolog.Logger
    Metrics           *PromMetrics
    Tracer            trace.Tracer
    TraceProvider     trace.TracerProvider
    TextMapPropagator propagation.TextMapPropagator
}
...
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

در این تنظیم از برخی متغیرهای محیط استفاده می شود تا در واقع جزئیات نقطه انتهایی OTEL را بدست آورید. جزئیات بیشتر در مورد این موارد را می توان در مشخصات متغیر محیط یافت. من این الگوی را دوست دارم زیرا تغییر نقطه پایانی بدون تغییر کد واقعی می تواند رخ دهد.

اکنون ما آماده استفاده از این موارد در جایی هستیم.

سرور HTTP

بیایید فرض کنیم که از نوعی بسته روتر استفاده می کنید- من به شدت توصیه می کنم که از افزونه OTEL برای آن بسته استفاده کنید. می توانید این افزونه ها را در رجیستری OTEL پیدا کنید. در این حالت ما از Julien Schmidt Httprouter استفاده می کنیم و این افزونه از Splunk است (هیچ ارتباطی با ورود به سیستم Splunk شما نیست)- Splunkhttprouter.

مسیر واردات برای این کمی مسخره است ، اما من دوست دارم آن را نامعقول کنم تا بدانم که ما با نسخه ردیابی کار می کنیم:

import (
...  
tracerouter "github.com/signalfx/splunk-otel-go/instrumentation/github.com/julienschmidt/httprouter/splunkhttprouter"
...
)
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

اکنون واقعاً باید روتر درست کنید و آن را به ساختار سرور اضافه کنید:

type Server struct {
    router *tracerouter.Router
    O11y
}

func New(o o11y.O11y) (*Server, error){
  ...
  s := &Server{
    router: tracerouter.New(
        otelhttp.WithTracerProvider(o.TraceProvider),
        otelhttp.WithPropagators(o.TextMapPropagator),
    ),
  }
  ...
  return s, nil
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

یک یادداشت کوچک در اینجا- ممکن است بخواهید برخی از مسیرها را از داشتن هرگونه ردیابی روی آنها محروم کنید. این به شرح زیر انجام می شود:

func OtelReqFilter(req *http.Request) bool {
    return req.URL.Path != "/healthcheck" &&
        req.URL.Path != "/metrics"
}

حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

سپس این را به عنوان گزینه دیگری در tracerouter.New()، یعنی

...
router: tracerouter.New(
            otelhttp.WithFilter(tracer.OtelReqFilter),
...
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

اکنون سرانجام به جایی می رسیم و می توانیم برخی از دهانه ها را اضافه کنیم.

func (s *Server) myRouteHandler(w http.ResponseWriter, r *http.Request) {    
    span := trace.SpanFromContext(r.Context())
        defer span.End()
    ....
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

یک چیز دیگر- رسیدگی به خطای یک عمل دو مرحله ای است:

span.RecordError(err)
span.SetStatus(codes.Error, "some error")
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

خلاف واقع در اولین عملیات در واقع وضعیت دهانه را تعیین نمی کند.

مشتری HTTP

اکنون مشتری بسیار ساده تر است ، با این حال ، زیرا ما از مقادیر جهانی در OTEL SDK استفاده نمی کنیم ، ما هنوز هم باید در بعضی موارد عبور کنیم تا هدرهای کمیاب در درخواست های خروجی تزریق شوند.

برای هر مشتری که آن را ایجاد می کنید باید چیزی شبیه به آن باشد:

client := &http.Client{Transport: otelhttp.NewTransport(
http.DefaultTransport,
        otelhttp.WithTracerProvider(o.TraceProvider),
       otelhttp.WithPropagators(o.TextMapPropagator),
)}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

پایان

  • از متغیرهای جهانی استفاده نکنید
  • چیزهایی را که نیاز خود را به آن منتقل کنید- بیش از آنچه برای OTEL فکر می کنید وجود دارد.
  • برای تنظیم پارامترهای OTEL مانند درصد نمونه برداری از متغیرهای محیط استفاده کنید. این بدان معنی است که برای به روزرسانی آنها به تغییر کد احتیاج ندارید.
  • درخواست های خود را فیلتر کنید /metrics وت /healthchecksبشر

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا