Files
casdoor/object/log_provider.go
2026-04-08 09:52:45 +08:00

185 lines
4.8 KiB
Go

// Copyright 2026 The Casdoor Authors. All Rights Reserved.
//
// 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 object
import (
"fmt"
"sync"
"github.com/casdoor/casdoor/log"
)
var (
runningCollectors = map[string]log.LogProvider{} // providerGetId() -> LogProvider
runningCollectorsMu sync.Mutex
)
// InitLogProviders scans all globally-configured Log providers and starts
// background collection for pull-based providers (e.g. System Log, SELinux Log)
// and registers passive providers (e.g. OpenClaw).
// It is called once from main() after the database is ready.
func InitLogProviders() {
providers, err := GetGlobalProviders()
if err != nil {
return
}
for _, p := range providers {
if p.Category != "Log" {
continue
}
if p.State == "Disabled" {
continue
}
switch p.Type {
case "System Log", "SELinux Log":
startLogCollector(p)
case "Agent":
if p.SubType == "OpenClaw" {
startOpenClawProvider(p)
startOpenClawTranscriptSync(p)
}
}
}
}
func stopCollector(id string) {
runningCollectorsMu.Lock()
defer runningCollectorsMu.Unlock()
if existing, ok := runningCollectors[id]; ok {
_ = existing.Stop()
delete(runningCollectors, id)
}
}
// startLogCollector starts a pull-based log collector (System Log / SELinux Log)
// for the given provider. If a collector for the same provider is already
// running it is stopped first.
func startLogCollector(provider *Provider) {
id := provider.GetId()
stopCollector(id)
lp, err := log.GetLogProvider(provider.Type, provider.Host, provider.Port, provider.Title)
if err != nil {
return
}
providerName := provider.Name
addEntry := func(owner, createdTime, _ string, message string) error {
name := log.GenerateEntryName()
entry := &Entry{
Owner: owner,
Name: name,
CreatedTime: createdTime,
UpdatedTime: createdTime,
DisplayName: name,
Provider: providerName,
Message: message,
}
_, err := AddEntry(entry)
return err
}
onError := func(err error) {
fmt.Printf("InitLogProviders: collector for provider %s stopped with error: %v\n", providerName, err)
}
if err := lp.Start(addEntry, onError); err != nil {
fmt.Printf("InitLogProviders: failed to start collector for provider %s: %v\n", providerName, err)
return
}
runningCollectorsMu.Lock()
defer runningCollectorsMu.Unlock()
runningCollectors[id] = lp
}
// startOpenClawProvider registers an OpenClaw provider in runningCollectors so
// that incoming OTLP requests can be routed to it by IP.
func startOpenClawProvider(provider *Provider) {
id := provider.GetId()
stopCollector(id)
lp, err := GetLogProviderFromProvider(provider)
if err != nil {
fmt.Printf("InitLogProviders: failed to create OpenClaw provider %s: %v\n", provider.Name, err)
return
}
runningCollectorsMu.Lock()
defer runningCollectorsMu.Unlock()
runningCollectors[id] = lp
}
func refreshLogProviderRuntime(oldID string, provider *Provider) {
if provider == nil {
if oldID != "" {
stopLogProviderRuntime(oldID)
}
return
}
if oldID != "" {
stopLogProviderRuntime(oldID)
}
if provider.Category != "Log" {
return
}
if provider.State == "Disabled" {
return
}
switch provider.Type {
case "System Log", "SELinux Log":
startLogCollector(provider)
case "Agent":
if provider.SubType == "OpenClaw" {
startOpenClawProvider(provider)
startOpenClawTranscriptSync(provider)
}
}
}
func stopLogProviderRuntime(providerID string) {
if providerID == "" {
return
}
stopCollector(providerID)
stopOpenClawTranscriptSync(providerID)
}
// GetOpenClawProviderByIP returns the running OpenClawProvider whose Host field
// matches clientIP, or whose Host is empty (meaning any IP is allowed).
// Returns nil if no matching provider is registered.
func GetOpenClawProviderByIP(clientIP string) (*log.OpenClawProvider, error) {
providers := []*Provider{}
err := ormer.Engine.Where("category = ? AND type = ? AND sub_type = ? AND (state = ? OR state = ?)", "Log", "Agent", "OpenClaw", "Enabled", "").Find(&providers)
if err != nil {
return nil, err
}
runningCollectorsMu.Lock()
defer runningCollectorsMu.Unlock()
for _, p := range providers {
if p.Host == "" || p.Host == clientIP {
if lp, ok := runningCollectors[p.GetId()]; ok {
if ocp, ok := lp.(*log.OpenClawProvider); ok {
return ocp, nil
}
}
}
}
return nil, nil
}