Ecostack commented on code in PR #650: URL: https://github.com/apache/skywalking-website/pull/650#discussion_r1377194704
########## content/blog/2023-10-18-skywalking-toolkit-trace/index.md: ########## @@ -0,0 +1,285 @@ +--- +title: "Detailed explanation of SkyWalking Go Toolkit Trace" +date: 2023-10-18 +author: "Alipebt" +description: "This article shows the introduction and usage of toolkit trace provided by Skywalking Go to users." + +--- + +## Background + +SkyWalking Go is an open-source, non-intrusive Golang agent used for monitoring, tracing, and data collection within distributed systems. It enables users to observe the flow and latency of requests within the system, collect performance data from various system components for performance monitoring, and troubleshoot issues by tracing the complete path of requests. + +In version v0.3.0, Skywalking Go introduced the toolkit trace tool. Trace APIs allow users to include critical operations, functions, or services in the tracing scope in situations where plugins do not support them. This inclusion enables tracking and monitoring of these operations and can be used for fault analysis, diagnosis, and performance monitoring. + +Before diving into this, you can learn how to use the Skywalking Go agent by referring to the [SkyWalking Go Agent Quick Start Guide](https://skywalking.apache.org/zh/2023-06-01-quick-start-with-skywalking-go-agent/). + +The following sections will explain how to use these interfaces in specific scenarios. + +## Introducing the Trace Toolkit + +Execute the following command in the project's root directory: + +```shell +go get github.com/apache/skywalking-go/toolkit +``` + +To use the toolkit trace interface, you need to import the package into your project: + +```go +"github.com/apache/skywalking-go/toolkit/trace" +``` + +## Manual Tracing + +A Span is the fundamental unit of an operation in Tracing. It represents an operation within a specific timeframe, such as a request, a function call, or a specific action. It records essential information about a particular operation, including start and end times, the operation's name, tags (key-value pairs), and relationships between operations. Multiple Spans can form a hierarchical structure. + +In situations where Skywalking-go doesn't support a particular framework, users can manually create Spans to obtain tracing information. + +(Here, I have removed the supported frameworks for the sake of the example. These are only examples. You should reference this when using the APIs in private and/or unsupported frameworks) + +For example, when you need to trace an HTTP response, you can create a span using trace.CreateEntrySpan() within the method handling the request, and end the span using trace.StopSpan() after processing. +When sending an HTTP request, use trace.CreateExitSpan() to create a span, and end the span after the request returns. + +Here are two HTTP services named `consumer` and `provider`. When a user accesses the `consumer` service, it receives the user's request internally and then accesses the provider to obtain resources. + +```go +// consumer.go +package main + +import ( + "io" + "net/http" + + _ "github.com/apache/skywalking-go" + "github.com/apache/skywalking-go/toolkit/trace" +) + +func getProvider() (*http.Response, error) { + // Create an HTTP request + req, err := http.NewRequest("GET", "http://localhost:9998/provider", http.NoBody) + // Create an ExitSpan before sending the HTTP request. + trace.CreateExitSpan("GET:/provider", "localhost:9999", + func(headerKey, headerValue string) error { + // Injector adds specific header information to the request. + req.Header.Add(headerKey, headerValue) + return nil + }) + // Finish the ExitSpan and ensure it executes when the function returns using defer. + defer trace.StopSpan() + + // Send the request. + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return nil, err + } + return resp, nil +} + +func consumerHandler(w http.ResponseWriter, r *http.Request) { + // Create an EntrySpan to trace the execution of the consumerHandler method. + trace.CreateEntrySpan(r.Method+"/consumer", func(headerKey string) (string, error) { + // Extractor retrieves the header information added to the request. + return r.Header.Get(headerKey), nil + }) + // Finish the EntrySpan. + defer trace.StopSpan() + + // Prepare to send an HTTP request. + resp, err := getProvider() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return + } + _, _ = w.Write(body) +} + +func main() { + http.HandleFunc("/consumer", consumerHandler) + + _ = http.ListenAndServe(":9999", nil) +} +``` + +```go +// provider.go +package main + +import ( + "net/http" + + _ "github.com/apache/skywalking-go" + "github.com/apache/skywalking-go/toolkit/trace" +) + +func providerHandler(w http.ResponseWriter, r *http.Request) { + //Create an EntrySpan to trace the execution of the providerHandler method. + trace.CreateEntrySpan("GET:/provider", func(headerKey string) (string, error) { + return r.Header.Get(headerKey), nil + }) + // Finish the EntrySpan. + defer trace.StopSpan() + + _, _ = w.Write([]byte("success from provider")) +} + +func main() { + http.HandleFunc("/provider", providerHandler) + + _ = http.ListenAndServe(":9998", nil) +} + +``` + + + +Then, in the terminal, execute: + +```shell +go build -toolexec="/path/to/go-agent" -a -o consumer ./consumer.go +./consumer +``` + +```shell +go build -toolexec="/path/to/go-agent" -a -o provider ./provider.go +./provider +``` + +```shell +curl 127.0.0.1:9999/consumer +``` + +At this point, the UI will display the span information you created. + + + +If you need to trace methods that are executed only locally, you can use trace.CreateLocalSpan(). If you don't need to monitor information or states from the other end, you can change ExitSpan and EntrySpan to LocalSpan. + +The usage examples provided are for illustration purposes, and users can decide the tracing granularity and where in the program they need tracing. + +Please note that if a program ends too quickly, it may cause tracing data to be unable to be asynchronously sent to the SkyWalking backend. Review Comment: I am not sure if it is possible but can a manual sync be forced for short running programs? -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: notifications-unsubscr...@skywalking.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org