Files
Byron.wang ca3d00229e Feat/Implement structured logging and Trace ID propagation (#552)
* use slog instead of log package and format to new log schema

* update the environment name to LOG_OUTPUT_FORMAT

* add the env to .env.example

* fix log reference error

* change the order of milldlewares

* delete unused code

* fix the concurrently session potential race condition

* fix the log format in tests

* update the duplicate code

* refactor: convert log functions to slog structured format

- Change log.Error/Info/Warn/Debug/Panic to accept msg + key-value pairs
- Remove printf-style formatting from log functions
- Update log calls in internal/cluster, internal/db, internal/core/session_manager
- Remove unused 'initialized' variable from log package
- Remaining files will be updated in follow-up commits

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: update all log call sites to use slog structured format

Convert all log.Error, log.Info, log.Warn, log.Debug, and log.Panic
calls from printf-style formatting to slog key-value pairs.

Before: log.Error("failed to do something: %s", err.Error())
After:  log.Error("failed to do something", "error", err)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: update cmd/ log calls to use slog structured format

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: implement GnetLogger for structured logging in gnet

* refactor: remove deprecated log visibility functions and related calls

* feat: enhance session management with trace and identity context propagation

* feat: implement serverless transaction handler and writer for plugin runtime

* refactor: rename context field to traceCtx in RealBackwardsInvocation

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Yeuoly <admin@srmxy.cn>
2025-12-30 11:00:48 +08:00

114 lines
2.7 KiB
Go

package http_requests
import (
"bytes"
"context"
"encoding/json"
"io"
"mime/multipart"
"net/http"
"strings"
"github.com/langgenius/dify-plugin-daemon/pkg/utils/log"
)
func buildHttpRequest(method string, url string, options ...HttpOptions) (*http.Request, error) {
req, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
for _, option := range options {
switch option.Type {
case HttpOptionTypeContext:
if ctx, ok := option.Value.(context.Context); ok {
ctx = log.EnsureTrace(ctx)
traceparent := log.GetTraceparentHeader(ctx)
if traceparent != "" {
req.Header.Set("traceparent", traceparent)
}
}
case "header":
for k, v := range option.Value.(map[string]string) {
req.Header.Set(k, v)
}
case "params":
q := req.URL.Query()
for k, v := range option.Value.(map[string]string) {
q.Add(k, v)
}
req.URL.RawQuery = q.Encode()
case "payload":
q := req.URL.Query()
for k, v := range option.Value.(map[string]string) {
q.Add(k, v)
}
req.Body = io.NopCloser(strings.NewReader(q.Encode()))
case "payloadMultipart":
buffer := new(bytes.Buffer)
writer := multipart.NewWriter(buffer)
files := option.Value.(map[string]any)["files"].(map[string]HttpPayloadMultipartFile)
for filename, file := range files {
part, err := writer.CreateFormFile(filename, file.Filename)
if err != nil {
writer.Close()
return nil, err
}
_, err = io.Copy(part, file.Reader)
if err != nil {
writer.Close()
return nil, err
}
}
payload := option.Value.(map[string]any)["payload"].(map[string]string)
for k, v := range payload {
if err := writer.WriteField(k, v); err != nil {
writer.Close()
return nil, err
}
}
if err := writer.Close(); err != nil {
return nil, err
}
req.Body = io.NopCloser(buffer)
req.Header.Set("Content-Type", writer.FormDataContentType())
case "payloadText":
req.Body = io.NopCloser(strings.NewReader(option.Value.(string)))
req.Header.Set("Content-Type", "text/plain")
case "payloadReader":
req.Body = option.Value.(io.ReadCloser)
case "payloadJson":
jsonStr, err := json.Marshal(option.Value)
if err != nil {
return nil, err
}
req.Body = io.NopCloser(bytes.NewBuffer(jsonStr))
// set application/json content type
req.Header.Set("Content-Type", "application/json")
case "directReferer":
req.Header.Set("Referer", url)
}
}
return req, nil
}
func Request(client *http.Client, url string, method string, options ...HttpOptions) (*http.Response, error) {
req, err := buildHttpRequest(method, url, options...)
if err != nil {
return nil, err
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
return resp, nil
}