fix: add client IP and UA to entry

This commit is contained in:
Yang Luo
2026-04-05 02:07:41 +08:00
parent fffb26deb9
commit 9030a06792
6 changed files with 68 additions and 28 deletions

View File

@@ -20,6 +20,8 @@ import (
coltracepb "go.opentelemetry.io/proto/otlp/collector/trace/v1"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"github.com/casdoor/casdoor/util"
)
// @Title AddOtlpTrace
@@ -49,7 +51,9 @@ func (c *ApiController) AddOtlpTrace() {
return
}
if err := provider.AddTrace(message); err != nil {
clientIp := util.GetClientIpFromRequest(c.Ctx.Request)
userAgent := c.Ctx.Request.Header.Get("User-Agent")
if err := provider.AddTrace(message, clientIp, userAgent); err != nil {
responseOtlpError(c.Ctx, 500, "save trace failed: %v", err)
return
}
@@ -87,7 +91,9 @@ func (c *ApiController) AddOtlpMetrics() {
return
}
if err := provider.AddMetrics(message); err != nil {
clientIp := util.GetClientIpFromRequest(c.Ctx.Request)
userAgent := c.Ctx.Request.Header.Get("User-Agent")
if err := provider.AddMetrics(message, clientIp, userAgent); err != nil {
responseOtlpError(c.Ctx, 500, "save metrics failed: %v", err)
return
}
@@ -125,7 +131,9 @@ func (c *ApiController) AddOtlpLogs() {
return
}
if err := provider.AddLogs(message); err != nil {
clientIp := util.GetClientIpFromRequest(c.Ctx.Request)
userAgent := c.Ctx.Request.Header.Get("User-Agent")
if err := provider.AddLogs(message, clientIp, userAgent); err != nil {
responseOtlpError(c.Ctx, 500, "save logs failed: %v", err)
return
}

View File

@@ -17,9 +17,10 @@ package log
import "fmt"
// OtlpAdder persists a single OTLP record into the backing store.
// Parameters: entryType ("trace"/"metrics"/"log") and message (JSON payload).
// Parameters: entryType ("trace"/"metrics"/"log"), message (JSON payload),
// clientIp and userAgent from the originating HTTP request.
// The unique entry name is generated by the implementation.
type OtlpAdder func(entryType, message string) error
type OtlpAdder func(entryType, message, clientIp, userAgent string) error
// OpenClawProvider receives OpenTelemetry data pushed by an OpenClaw agent over
// HTTP and persists each record as an Entry row via the OtlpAdder supplied at
@@ -47,16 +48,16 @@ func (p *OpenClawProvider) Start(_ EntryAdder, _ func(error)) error { return nil
func (p *OpenClawProvider) Stop() error { return nil }
// AddTrace persists an OTLP trace payload (already serialised to JSON).
func (p *OpenClawProvider) AddTrace(message []byte) error {
return p.addOtlpEntry("trace", string(message))
func (p *OpenClawProvider) AddTrace(message []byte, clientIp, userAgent string) error {
return p.addOtlpEntry("trace", string(message), clientIp, userAgent)
}
// AddMetrics persists an OTLP metrics payload (already serialised to JSON).
func (p *OpenClawProvider) AddMetrics(message []byte) error {
return p.addOtlpEntry("metrics", string(message))
func (p *OpenClawProvider) AddMetrics(message []byte, clientIp, userAgent string) error {
return p.addOtlpEntry("metrics", string(message), clientIp, userAgent)
}
// AddLogs persists an OTLP logs payload (already serialised to JSON).
func (p *OpenClawProvider) AddLogs(message []byte) error {
return p.addOtlpEntry("log", string(message))
func (p *OpenClawProvider) AddLogs(message []byte, clientIp, userAgent string) error {
return p.addOtlpEntry("log", string(message), clientIp, userAgent)
}

View File

@@ -31,8 +31,10 @@ type Entry struct {
Provider string `xorm:"varchar(100)" json:"provider"`
Application string `xorm:"varchar(100)" json:"application"`
Type string `xorm:"varchar(100)" json:"type"`
Message string `xorm:"mediumtext" json:"message"`
Type string `xorm:"varchar(100)" json:"type"`
ClientIp string `xorm:"varchar(100)" json:"clientIp"`
UserAgent string `xorm:"varchar(500)" json:"userAgent"`
Message string `xorm:"mediumtext" json:"message"`
}

View File

@@ -637,7 +637,7 @@ func GetLogProviderFromProvider(provider *Provider) (log.LogProvider, error) {
if provider.Type == "Agent" && provider.SubType == "OpenClaw" {
providerName := provider.Name
return log.NewOpenClawProvider(providerName, func(entryType, message string) error {
return log.NewOpenClawProvider(providerName, func(entryType, message, clientIp, userAgent string) error {
name := log.GenerateEntryName()
currentTime := util.GetCurrentTime()
entry := &Entry{
@@ -648,6 +648,8 @@ func GetLogProviderFromProvider(provider *Provider) (log.LogProvider, error) {
DisplayName: name,
Provider: providerName,
Type: entryType,
ClientIp: clientIp,
UserAgent: userAgent,
Message: message,
}
_, err := AddEntry(entry)

View File

@@ -191,6 +191,22 @@ class EntryEditPage extends React.Component {
<Input disabled value={this.state.entry.type ?? ""} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{i18next.t("general:Client IP")}:
</Col>
<Col span={22} >
<Input disabled value={this.state.entry.clientIp ?? ""} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{i18next.t("general:User agent")}:
</Col>
<Col span={22} >
<Input disabled value={this.state.entry.userAgent ?? ""} />
</Col>
</Row>
<EntryMessageViewer entry={this.state.entry} labelSpan={(Setting.isMobile()) ? 22 : 2} contentSpan={22} />
</Card>
);

View File

@@ -35,6 +35,8 @@ class EntryListPage extends BaseListPage {
provider: "",
application: "",
type: "",
clientIp: "",
userAgent: "",
message: "",
};
}
@@ -163,22 +165,31 @@ class EntryListPage extends BaseListPage {
},
},
{
title: i18next.t("general:Application"),
dataIndex: "application",
key: "application",
title: i18next.t("general:Type"),
dataIndex: "type",
key: "type",
width: "140px",
sorter: true,
...this.getColumnSearchProps("application"),
render: (text, record) => {
if (!text) {
return null;
}
return (
<Link to={`/applications/${record.owner}/${text}`}>
{text}
</Link>
);
},
...this.getColumnSearchProps("type"),
},
{
title: i18next.t("general:Client IP"),
dataIndex: "clientIp",
key: "clientIp",
width: "140px",
sorter: true,
...this.getColumnSearchProps("clientIp", (row, highlightContent) => (
<a target="_blank" rel="noreferrer" href={`https://db-ip.com/${row.text}`}>
{highlightContent}
</a>
)),
},
{
title: i18next.t("general:User agent"),
dataIndex: "userAgent",
key: "userAgent",
sorter: true,
...this.getColumnSearchProps("userAgent"),
},
{
title: i18next.t("payment:Message"),