forked from casdoor/casdoor
185 lines
4.8 KiB
Go
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
|
|
}
|