Topik ini menjelaskan cara menggunakan kit pengembangan perangkat lunak (SDK) OpenTelemetry untuk Golang guna mengingest data jejak dari aplikasi Golang ke Simple Log Service.
Simple Log Service menyediakan probe komersial berpemilik untuk bahasa Go. Probe ini menawarkan instrumentasi non-intrusif, fitur tambahan, dan stabilitas yang lebih baik. Untuk informasi selengkapnya, lihat Mulai memantau aplikasi Go.
Prasyarat
Lingkungan pengembangan Golang versi 1.13 atau yang lebih baru telah diinstal.
Alur ingest
Inisialisasi penyedia OpenTelemetry.
Tentukan apakah kondisi untuk ingest semi-otomatis terpenuhi.
Jika kondisi terpenuhi, gunakan metode semi-otomatis untuk mengingest data jejak.
Untuk skenario yang tidak didukung oleh metode semi-otomatis, gunakan metode manual.
Jika kondisi tidak terpenuhi, gunakan metode manual untuk mengingest data jejak.
Langkah 1: Inisialisasi penyedia OpenTelemetry
Untuk menyederhanakan penggunaan penyedia OpenTelemetry, Simple Log Service menyediakan SLS Provider, yang membantu Anda membangun dependensi yang diperlukan dan mengunggahnya ke Simple Log Service dengan cepat.
Inisialisasi penyedia OpenTelemetry sebelum membuat jejak atau mendaftarkan metrik.
Anda dapat menginisialisasi penyedia OpenTelemetry dengan menjalankan kode atau mengonfigurasi variabel lingkungan:
Inisialisasi dengan menjalankan kode.
Tambahkan dependensi.
module opentelemetry-golang-sample go 1.13 require ( github.com/aliyun-sls/opentelemetry-go-provider-sls v0.10.0 go.opentelemetry.io/otel v1.16.0 go.opentelemetry.io/otel/metric v1.16.0 go.opentelemetry.io/otel/trace v1.16.0 )Konfigurasikan kode inisialisasi.
Ganti variabel dalam kode berikut sesuai kebutuhan Anda. Untuk deskripsi variabel, lihat Deskripsi variabel.
package main import ( "github.com/aliyun-sls/opentelemetry-go-provider-sls/provider" ) func main() { slsConfig, err := provider.NewConfig(provider.WithServiceName("${service}"), provider.WithServiceNamespace("${service.namespace}"), provider.WithServiceVersion("${version}"), provider.WithTraceExporterEndpoint("${endpoint}"), provider.WithMetricExporterEndpoint("${endpoint}"), provider.WithSLSConfig("${project}", "${instance}", "${access-key-id}", "${access-key-secret}")) // Gunakan panic() untuk keluar dari program jika inisialisasi gagal. Anda juga dapat menggunakan metode penanganan error lainnya. if err != nil { panic(err) } if err := provider.Start(slsConfig); err != nil { panic(err) } defer provider.Shutdown(slsConfig) // Tambahkan kode logika bisnis Anda. ... }Tabel 1. Deskripsi variabel
Variabel
Deskripsi
Contoh
${service}
Nama layanan. Atur parameter ini berdasarkan skenario Anda.
payment
${service.namespace}
Namespace tempat layanan tersebut berada.
order
${version}
Nomor versi layanan. Gunakan format va.b.c.
v0.1.2
${endpoint}
Titik akhir proyek Simple Log Service. Formatnya adalah ${project}.${region-endpoint}:Port. Parameter dijelaskan sebagai berikut:
${project}: Nama proyek Simple Log Service.
${region-endpoint}: Titik akhir wilayah tempat proyek Simple Log Service berada. Titik akhir jaringan publik, jaringan klasik, dan VPC didukung. Untuk informasi selengkapnya, lihat Endpoints.
Port: Port jaringan. Nilainya tetap 10010.
CatatanJika Anda mengatur parameter ini ke stdout, misalnya, provider.WithTraceExporterEndpoint("stdout"), data akan dicetak ke output standar.
Jika Anda membiarkan parameter ini kosong, data jejak tidak diunggah ke Simple Log Service.
test-project.cn-hangzhou.log.aliyuncs.com:10010
${project}
Nama proyek Simple Log Service.
test-project
${instance}
ID instans Trace. Untuk informasi selengkapnya, lihat Buat instans Trace.
test-traces
${access-key-id}
ID AccessKey Akun Alibaba Cloud Anda.
Gunakan pasangan Kunci Akses (ID AccessKey dan Rahasia AccessKey) dari Pengguna Resource Access Management (RAM) yang hanya memiliki izin menulis pada proyek Simple Log Service. Untuk informasi selengkapnya tentang cara memberikan izin kepada Pengguna RAM untuk menulis data ke proyek tertentu, lihat Otorisasi. Untuk informasi selengkapnya tentang cara mendapatkan pasangan Kunci Akses, lihat Pasangan Kunci Akses.
None
${access-key-secret}
Rahasia AccessKey Akun Alibaba Cloud Anda.
Gunakan pasangan Kunci Akses dari Pengguna RAM yang hanya memiliki izin menulis pada proyek Simple Log Service.
None
Inisialisasi dengan mengonfigurasi variabel lingkungan.
Metode konfigurasi
Variabel lingkungan
Wajib
Deskripsi
Nilai default
WithServiceName
SLS_OTEL_SERVICE_NAME
Ya
Nama layanan. Atur parameter ini berdasarkan skenario Anda.
None
WithServiceNamespace
SLS_OTEL_SERVICE-NAMESPACE
Tidak
Namespace tempat layanan tersebut berada.
order
WithServiceVersion
SLS_OTEL_SERVICE_VERSION
Ya
Nomor versi layanan. Gunakan format va.b.c.
v0.1.0
WithSLSConfig
SLS_OTEL_PROJECT, SLS_OTEL_INSTANCE_ID, SLS_OTEL_ACCESS_KEY_ID, SLS_OTEL_ACCESS_KEY_SECRET
Tidak
Informasi resource Simple Log Service, termasuk nama proyek, nama instans Trace, serta ID AccessKey dan Rahasia AccessKey pengguna yang hanya memiliki izin menulis pada proyek tersebut. Untuk informasi selengkapnya tentang cara memberikan izin kepada Pengguna RAM untuk menulis data ke proyek tertentu, lihat Otorisasi. Untuk informasi selengkapnya tentang cara mendapatkan pasangan Kunci Akses, lihat Pasangan Kunci Akses.
None
WithTraceExporterEndpoint
SLS_OTEL_TRACE_ENDPOINT
Tidak
Titik akhir proyek Simple Log Service. Formatnya adalah ${project}.${region-endpoint}:Port. Parameter dijelaskan sebagai berikut:
${project}: Nama proyek Simple Log Service.
${region-endpoint}: Titik akhir wilayah tempat proyek Simple Log Service berada. Akses jaringan internal dan publik didukung. Untuk informasi selengkapnya, lihat Endpoints.
Port: Port jaringan. Nilainya tetap 10010.
CatatanJika Anda mengatur parameter ini ke stdout, data akan dicetak ke output standar.
Jika Anda membiarkan parameter ini kosong, data jejak tidak diunggah ke Simple Log Service.
stdout
WithTraceExporterInsecure
SLS_OTEL_TRACE_INSECURE
Tidak
Menentukan apakah akan menggunakan metode transmisi yang tidak aman.
true: Gunakan metode transmisi yang tidak aman.
false: Gunakan metode transmisi yang aman.
CatatanJika mengirim data langsung ke Simple Log Service, atur parameter ini ke false.
false
WithMetricExporterEndpoint
SLS_OTEL_METRIC_ENDPOINT
Tidak
Titik akhir proyek Simple Log Service. Formatnya adalah ${project}.${region-endpoint}:Port. Parameter dijelaskan sebagai berikut:
${project}: Nama proyek Simple Log Service.
${region-endpoint}: Titik akhir wilayah tempat proyek Simple Log Service berada. Akses jaringan internal dan publik didukung. Untuk informasi selengkapnya, lihat Endpoints.
Port: Port jaringan. Nilainya tetap 10010.
CatatanJika Anda mengatur parameter ini ke stdout, data akan dicetak ke output standar.
Jika Anda membiarkan parameter ini kosong, data metrik tidak diunggah ke Simple Log Service.
stdout
WithMetricExporterInsecure
SLS_OTEL_METRIC_INSECURE
Tidak
Menentukan apakah akan menggunakan metode transmisi yang tidak aman.
true: Gunakan metode transmisi yang tidak aman.
false: Gunakan metode transmisi yang aman.
CatatanJika mengirim data langsung ke Simple Log Service, atur parameter ini ke false.
false
WithResourceAttributes
None
Tidak
Konfigurasikan tag tambahan, seperti environment dan zona.
None
WithResource
OTEL_RESOURCE_ATTRIBUTES
Tidak
Konfigurasikan tag tambahan, seperti environment dan zona. Formatnya adalah key1=value1,key2=value2.
None
WithMetricReportingPeriod
SLS_OTEL_METRIC_EXPORT_PERIOD
Tidak
Interval ekspor metrik. Atur nilai antara 15s hingga 60s.
30s
WithErrorHandler
None
Tidak
Fungsi penanganan error. Fungsi ini dipanggil ketika terjadi error internal di SDK. Efeknya sama dengan WithErrorHandlerFunc.
None
WithErrorHandlerFunc
None
Tidak
Fungsi penanganan error.
None
None
SLS_OTEL_ATTRIBUTES_ENV_KEYS
Tidak
Konfigurasikan tag tambahan, seperti environment dan zona. Ini mirip dengan OTEL_RESOURCE_ATTRIBUTES. Perbedaannya adalah untuk kunci atribut yang didefinisikan oleh SLS_OTEL_ATTRIBUTES_ENV_KEYS, nilai aktualnya dibaca dari variabel lingkungan yang sesuai.
Ini sering digunakan dalam skenario Kubernetes untuk mengisi nilai templat ke variabel lingkungan tertentu. Formatnya adalah env-key-1|env-key-2|env-key-3.
None
Langkah 2: Memasukkan data
(Direkomendasikan) Ingest semi-otomatis
OpenTelemetry menyediakan instrumentasi otomatis untuk banyak library umum. Jika aplikasi Anda menggunakan library tersebut, Anda dapat menggunakan solusi instrumentasi otomatis yang sesuai untuk mengingest data. Untuk daftar library yang didukung, lihat Solusi instrumentasi otomatis Golang.
Ingest net/http
Contoh berikut didasarkan pada go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.37.0. Untuk informasi selengkapnya, lihat otel-http-example.
Ganti variabel dalam kode berikut sesuai kebutuhan Anda. Untuk deskripsi variabel, lihat Deskripsi variabel.
package main import ( "fmt" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric/global" "io" "net/http" "time" "github.com/aliyun-sls/opentelemetry-go-provider-sls/provider" "go.opentelemetry.io/otel/trace" ) func main() { slsConfig, err := provider.NewConfig(provider.WithServiceName("${service}"), provider.WithServiceNamespace("${service.namespace}"), provider.WithServiceVersion("${version}"), provider.WithTraceExporterEndpoint("${endpoint}"), provider.WithMetricExporterEndpoint("${endpoint}"), provider.WithSLSConfig("${project}", "${instance}", "${access-key-id}", "${access-key-secret}")) // Gunakan panic() untuk keluar dari program jika inisialisasi gagal. Anda juga dapat menggunakan metode penanganan error lainnya. if err != nil { panic(err) } if err := provider.Start(slsConfig); err != nil { panic(err) } defer provider.Shutdown(slsConfig) // Untuk menganalisis data metrik di aplikasi Anda, Anda dapat mendaftarkan metrik yang relevan. labels := []attribute.KeyValue{ attribute.String("label1", "value1"), } meter := global.Meter("aliyun.sls") sayDavidCount, _ := meter.Int64Counter("say_david_count") helloHandler := func(w http.ResponseWriter, req *http.Request) { if time.Now().Unix()%10 == 0 { _, _ = io.WriteString(w, "Hello, world!\n") } else { // Untuk mencatat event, Anda dapat mengambil Span dari Context dan menambahkan Event. ctx := req.Context() span := trace.SpanFromContext(ctx) span.AddEvent("say : Hello, I am david", trace.WithAttributes(attribute.KeyValue{ Key: "label-key-1", Value: attribute.StringValue("label-value-1"), })) _, _ = io.WriteString(w, "Hello, I am david!\n") sayDavidCount.Add(req.Context(), 1, labels...) } } // Untuk menggunakan injeksi otomatis otel net/http, cukup bungkus http.Handler dengan otelhttp.NewHandler. otelHandler := otelhttp.NewHandler(http.HandlerFunc(helloHandler), "Hello") http.Handle("/hello", otelHandler) fmt.Println("Now listen port 8080, you can visit 127.0.0.1:8080/hello .") err = http.ListenAndServe(":8080", nil) if err != nil { panic(err) } }Ingest mux
Contoh berikut didasarkan pada go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.37.0. API dapat berubah di versi yang lebih baru. Untuk contoh terbaru, lihat otel-mux-example.
Ganti variabel dalam kode berikut sesuai kebutuhan Anda. Untuk deskripsi variabel, lihat Deskripsi variabel.
package main import ( "context" "fmt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric/global" "net/http" "github.com/aliyun-sls/opentelemetry-go-provider-sls/provider" "github.com/gorilla/mux" "go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux" "go.opentelemetry.io/otel/trace" ) func main() { slsConfig, err := provider.NewConfig(provider.WithServiceName("${service}"), provider.WithServiceNamespace("${service.namespace}"), provider.WithServiceVersion("${version}"), provider.WithTraceExporterEndpoint("${endpoint}"), provider.WithMetricExporterEndpoint("${endpoint}"), provider.WithSLSConfig("${project}", "${instance}", "${access-key-id}", "${access-key-secret}")) // Gunakan panic() untuk keluar dari program jika inisialisasi gagal. Anda juga dapat menggunakan metode penanganan error lainnya. if err != nil { panic(err) } if err := provider.Start(slsConfig); err != nil { panic(err) } defer provider.Shutdown(slsConfig) // Untuk menganalisis data metrik di aplikasi Anda, Anda dapat mendaftarkan metrik yang relevan. labels := []attribute.KeyValue{ attribute.String("label1", "value1"), } meter := global.Meter("aliyun.sls") callUsersCount, _ := meter.Int64Counter("call_users_count") r := mux.NewRouter() r.Use(otelmux.Middleware("my-server")) r.HandleFunc("/users/{id:[0-9]+}", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) id := vars["id"] callUsersCount.Add(r.Context(), 1, labels...) name := getUser(r.Context(), id) reply := fmt.Sprintf("user %s (id %s)\n", name, id) _, _ = w.Write(([]byte)(reply)) })) http.Handle("/", r) fmt.Println("Now listen port 8080, you can visit 127.0.0.1:8080/users/xxx .") _ = http.ListenAndServe(":8080", nil) } func getUser(ctx context.Context, id string) string { if id == "123" { return "otelmux tester" } // Untuk mencatat event, Anda dapat mengambil Span dari Context dan menambahkan Event. span := trace.SpanFromContext(ctx) span.AddEvent("unknown user id : "+id, trace.WithAttributes(attribute.KeyValue{ Key: "label-key-1", Value: attribute.StringValue("label-value-1"), })) return "unknown" }
Pemasukan Manual
Ganti variabel dalam kode berikut sesuai kebutuhan Anda. Untuk deskripsi variabel, lihat Deskripsi variabel.
// Copyright The AliyunSLS Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "context" "errors" "fmt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric/global" "go.opentelemetry.io/otel/metric/instrument" "math/rand" "time" "github.com/aliyun-sls/opentelemetry-go-provider-sls/provider" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/trace" ) func main() { slsConfig, err := provider.NewConfig(provider.WithServiceName("payment"), provider.WithServiceVersion("v0.1.0"), provider.WithTraceExporterEndpoint("stdout"), provider.WithMetricExporterEndpoint("stdout"), provider.WithSLSConfig("test-project", "test-otel", "access-key-id", "access-key-secret")) // Gunakan panic() untuk keluar dari program jika inisialisasi gagal. Anda juga dapat menggunakan metode penanganan error lainnya. if err != nil { panic(err) } if err := provider.Start(slsConfig); err != nil { panic(err) } defer provider.Shutdown(slsConfig) mockTrace() mockMetrics() } func mockMetrics() { // Tambahkan informasi tag. labels := []attribute.KeyValue{ attribute.String("label1", "value1"), } meter := global.Meter("ex.com/basic") meter.Float64ObservableCounter("randval", instrument.WithFloat64Callback(func(ctx context.Context, observer instrument.Float64Observer) error { observer.Observe(rand.Float64(), labels...) return nil })) temperature, _ := meter.Float64Counter("temperature") interrupts, _ := meter.Int64Counter("interrupts") ctx := context.Background() for { temperature.Add(ctx, 100+10*rand.NormFloat64(), labels...) interrupts.Add(ctx, int64(rand.Intn(100)), labels...) time.Sleep(time.Second * time.Duration(rand.Intn(10))) } } func mockTrace() { tracer := otel.Tracer("ex.com/basic") ctx0 := context.Background() ctx1, finish1 := tracer.Start(ctx0, "foo") defer finish1.End() ctx2, finish2 := tracer.Start(ctx1, "bar") defer finish2.End() ctx3, finish3 := tracer.Start(ctx2, "baz") defer finish3.End() ctx := ctx3 getSpan(ctx) addAttribute(ctx) addEvent(ctx) recordException(ctx) createChild(ctx, tracer) } // contoh mendapatkan span saat ini // Dapatkan Span saat ini. func getSpan(ctx context.Context) { span := trace.SpanFromContext(ctx) fmt.Printf("current span: %v\n", span) } // contoh menambahkan atribut ke span // Tambahkan atribut ke Span. func addAttribute(ctx context.Context) { span := trace.SpanFromContext(ctx) span.SetAttributes(attribute.KeyValue{ Key: "label-key-1", Value: attribute.StringValue("label-value-1")}) } // contoh menambahkan event ke span // Tambahkan event ke Span. func addEvent(ctx context.Context) { span := trace.SpanFromContext(ctx) span.AddEvent("event1", trace.WithAttributes( attribute.String("event-attr1", "event-string1"), attribute.Int64("event-attr2", 10))) } // contoh mencatat exception // Catat hasil Span dan pesan error. func recordException(ctx context.Context) { span := trace.SpanFromContext(ctx) span.RecordError(errors.New("exception has occurred")) span.SetStatus(codes.Error, "internal error") } // contoh membuat child span // Buat Span anak. func createChild(ctx context.Context, tracer trace.Tracer) { // span := trace.SpanFromContext(ctx) _, childSpan := tracer.Start(ctx, "child") defer childSpan.End() fmt.Printf("child span: %v\n", childSpan) }