Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-28 Thread via GitHub


robocanic merged PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-28 Thread via GitHub


sonarqubecloud[bot] commented on PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#issuecomment-4825640723

   ## [![Quality Gate 
Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png
 'Quality Gate 
Passed')](https://sonarcloud.io/dashboard?id=apache_dubbo-admin&pullRequest=1483)
 **Quality Gate passed**  
   Issues  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0 New 
issues](https://sonarcloud.io/project/issues?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png
 '') [0 Accepted 
issues](https://sonarcloud.io/project/issues?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=ACCEPTED)
   
   Measures  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0 Security 
Hotspots](https://sonarcloud.io/project/security_hotspots?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0.0% Coverage on New 
Code](https://sonarcloud.io/component_measures?id=apache_dubbo-admin&pullRequest=1483&metric=new_coverage&view=list)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0.0% Duplication on New 
Code](https://sonarcloud.io/component_measures?id=apache_dubbo-admin&pullRequest=1483&metric=new_duplicated_lines_density&view=list)
  
 
   
   [See analysis details on SonarQube 
Cloud](https://sonarcloud.io/dashboard?id=apache_dubbo-admin&pullRequest=1483)
   
   


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-28 Thread via GitHub


robocanic commented on PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#issuecomment-4825636877

   LGTM.


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-13 Thread via GitHub


sonarqubecloud[bot] commented on PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#issuecomment-4698507368

   ## [![Quality Gate 
Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png
 'Quality Gate 
Passed')](https://sonarcloud.io/dashboard?id=apache_dubbo-admin&pullRequest=1483)
 **Quality Gate passed**  
   Issues  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0 New 
issues](https://sonarcloud.io/project/issues?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png
 '') [0 Accepted 
issues](https://sonarcloud.io/project/issues?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=ACCEPTED)
   
   Measures  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0 Security 
Hotspots](https://sonarcloud.io/project/security_hotspots?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0.0% Coverage on New 
Code](https://sonarcloud.io/component_measures?id=apache_dubbo-admin&pullRequest=1483&metric=new_coverage&view=list)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0.0% Duplication on New 
Code](https://sonarcloud.io/component_measures?id=apache_dubbo-admin&pullRequest=1483&metric=new_duplicated_lines_density&view=list)
  
 
   
   [See analysis details on SonarQube 
Cloud](https://sonarcloud.io/dashboard?id=apache_dubbo-admin&pullRequest=1483)
   
   


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-13 Thread via GitHub


Oxidaner commented on PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#issuecomment-4698507365

   @robocanic  done


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-13 Thread via GitHub


Oxidaner commented on code in PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#discussion_r3407944375


##
pkg/mcp/register.go:
##
@@ -310,4 +311,35 @@ func RegisterTools(server *Server) {
},
Handler: tools.GetApplicationServices,
})
+
+   logSearchProperties := logtools.LogSearchProperties()
+   server.RegisterTool(&common.ToolDef{
+   Name:"search_logs",
+   Description: "查询 Dubbo 服务日志,支持按应用、服务、实例、TraceID 和关键字过滤",
+   InputSchema: common.InputSchema{
+   Type:   "object",
+   Properties: logSearchProperties,
+   },
+   Handler: logtools.SearchLogs,
+   })
+
+   server.RegisterTool(&common.ToolDef{
+   Name:"analyze_error_logs",
+   Description: "分析错误日志并按错误模式聚合",
+   InputSchema: common.InputSchema{
+   Type:   "object",
+   Properties: logSearchProperties,
+   },
+   Handler: logtools.AnalyzeErrorLogs,
+   })
+
+   server.RegisterTool(&common.ToolDef{
+   Name:"get_log_capabilities",
+   Description: "获取日志查询能力,返回 Loki 当前可用 labels 以及查询参数到 labels 的映射",

Review Comment:
   done



-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-13 Thread via GitHub


Oxidaner commented on code in PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#discussion_r3407943709


##
pkg/config/observability/logs.go:
##
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 observability
+
+import (
+   "fmt"
+   "net/url"
+
+   "github.com/duke-git/lancet/v2/strutil"
+
+   "github.com/apache/dubbo-admin/pkg/common/bizerror"
+)
+
+type LogProviderType string
+
+const (
+   LogProviderLoki LogProviderType = "loki"
+)
+
+type LogsConfig struct {
+   DefaultProvider string  `json:"defaultProvider" 
yaml:"defaultProvider"`
+   Providers   []LogProviderConfig `json:"providers" yaml:"providers"`
+}
+
+type LogProviderConfig struct {
+   Name string  `json:"name" yaml:"name"`
+   Type LogProviderType `json:"type" yaml:"type"`
+   Endpoint string  `json:"endpoint" yaml:"endpoint"`
+   Tenant   string  `json:"tenant,omitempty" 
yaml:"tenant,omitempty"`
+}
+
+func (c *LogsConfig) Validate() error {
+   if c == nil || len(c.Providers) == 0 {
+   return nil
+   }
+   if strutil.IsBlank(c.DefaultProvider) {
+   return bizerror.New(bizerror.ConfigError, "default log provider 
is required")
+   }
+
+   foundDefault := false
+   for _, provider := range c.Providers {
+   if strutil.IsBlank(provider.Name) {
+   return bizerror.New(bizerror.ConfigError, "log provider 
name is required")
+   }
+   if provider.Name == c.DefaultProvider {
+   foundDefault = true
+   }
+   if provider.Type != LogProviderLoki {
+   return bizerror.New(bizerror.ConfigError, 
fmt.Sprintf("unsupported log provider type: %s", provider.Type))
+   }
+   if strutil.IsBlank(provider.Endpoint) {
+   return bizerror.New(bizerror.ConfigError, "log provider 
endpoint is required")
+   }
+   if _, err := url.Parse(provider.Endpoint); err != nil {
+   return bizerror.Wrap(err, bizerror.ConfigError, 
fmt.Sprintf("invalid log provider endpoint: %s", provider.Endpoint))
+   }

Review Comment:
   done



-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-13 Thread via GitHub


Oxidaner commented on code in PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#discussion_r3407940460


##
pkg/mcp/tools/log/loki.go:
##
@@ -0,0 +1,610 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 log
+
+import (
+   "context"
+   "encoding/json"
+   "fmt"
+   "io"
+   "net/http"
+   "net/url"
+   "regexp"
+   "sort"
+   "strconv"
+   "strings"
+   "sync"
+   "time"
+
+   "github.com/apache/dubbo-admin/pkg/common/bizerror"
+   observabilitycfg 
"github.com/apache/dubbo-admin/pkg/config/observability"
+)
+
+const (
+   defaultQueryWindow = time.Hour
+   labelCacheTTL  = 5 * time.Minute
+)
+
+var fallbackSelectorPriority = []string{
+   "namespace",
+   "job",
+   "app",
+   "appName",
+   "service_name",
+   "serviceName",
+   "service",
+   "pod",
+   "container",
+   "instance",
+   "instanceName",
+   "level",
+}
+
+var lokiLabelsCache = struct {
+   sync.Mutex
+   items map[string]cachedLokiLabels
+}{
+   items: map[string]cachedLokiLabels{},
+}
+
+type cachedLokiLabels struct {
+   labelsmap[string]struct{}
+   expiresAt time.Time
+}
+
+type lokiClient struct {
+   config observabilitycfg.LogProviderConfig
+   client *http.Client
+}
+
+type lokiQueryRangeResp struct {
+   Status string `json:"status"`
+   Data   struct {
+   Result []lokiStream `json:"result"`
+   } `json:"data"`
+   Error string `json:"error,omitempty"`
+}
+
+type lokiLabelsResp struct {
+   Status string   `json:"status"`
+   Data   []string `json:"data"`
+   Error  string   `json:"error,omitempty"`
+}
+
+type lokiStream struct {
+   Stream map[string]string `json:"stream"`
+   Values [][]string`json:"values"`
+}
+
+func newLokiClient(cfg observabilitycfg.LogProviderConfig) *lokiClient {
+   return &lokiClient{
+   config: cfg,
+   client: &http.Client{Timeout: 30 * time.Second},
+   }
+}
+
+func (c *lokiClient) search(ctx context.Context, req *SearchLogsReq) 
(*SearchLogsResp, error) {
+   if req.Limit <= 0 {
+   req.Limit = defaultLogLimit
+   }
+   start, end, err := resolveTimeRange(req.StartTime, req.EndTime)
+   if err != nil {
+   return nil, err
+   }
+
+   labelNames, _ := c.labelNames(ctx, start, end)
+   queries := buildLogQLQueriesWithLabels(req, labelNames)
+   merged := &SearchLogsResp{SourceEngine: "loki", Logs: make([]LogItem, 
0, req.Limit)}
+   seen := map[string]struct{}{}
+   for _, query := range queries {
+   logs, err := c.queryRange(ctx, query, start, end, req.Limit)
+   if err != nil {
+   return nil, err
+   }
+   // remove duplicates
+   for _, item := range logs {
+   key := dedupeKey(item)
+   if _, ok := seen[key]; ok {
+   continue
+   }
+   seen[key] = struct{}{}
+   merged.Logs = append(merged.Logs, item)
+   if len(merged.Logs) >= req.Limit {
+   break
+   }
+   }
+   if len(merged.Logs) >= req.Limit {
+   break
+   }
+   }
+
+   sort.SliceStable(merged.Logs, func(i, j int) bool {
+   return merged.Logs[i].Timestamp > merged.Logs[j].Timestamp
+   })
+   return merged, nil
+}
+
+func (c *lokiClient) capabilities(ctx context.Context, req 
*LogCapabilitiesReq) (*LogCapabilitiesResp, error) {
+   start, end, err := resolveTimeRange(req.StartTime, req.EndTime)
+   if err != nil {
+   return nil, err
+   }
+   labelNames, err := c.labelNames(ctx, start, end)
+   if err != nil {
+   return nil, err
+   }
+
+   return &LogCapabilitiesResp{
+   AvailableLabels: supportedLabels(labelNames),
+   SupportedFilters: []string{
+   "mesh",
+   "appName

Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-13 Thread via GitHub


Oxidaner commented on code in PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#discussion_r3407935291


##
pkg/mcp/tools/log/loki.go:
##
@@ -0,0 +1,610 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 log
+
+import (
+   "context"
+   "encoding/json"
+   "fmt"
+   "io"
+   "net/http"
+   "net/url"
+   "regexp"
+   "sort"
+   "strconv"
+   "strings"
+   "sync"
+   "time"
+
+   "github.com/apache/dubbo-admin/pkg/common/bizerror"
+   observabilitycfg 
"github.com/apache/dubbo-admin/pkg/config/observability"
+)
+
+const (
+   defaultQueryWindow = time.Hour
+   labelCacheTTL  = 5 * time.Minute
+)
+
+var fallbackSelectorPriority = []string{
+   "namespace",
+   "job",
+   "app",
+   "appName",
+   "service_name",
+   "serviceName",
+   "service",
+   "pod",
+   "container",
+   "instance",
+   "instanceName",
+   "level",
+}
+
+var lokiLabelsCache = struct {
+   sync.Mutex
+   items map[string]cachedLokiLabels
+}{
+   items: map[string]cachedLokiLabels{},
+}
+
+type cachedLokiLabels struct {
+   labelsmap[string]struct{}
+   expiresAt time.Time
+}
+
+type lokiClient struct {
+   config observabilitycfg.LogProviderConfig
+   client *http.Client
+}
+
+type lokiQueryRangeResp struct {
+   Status string `json:"status"`
+   Data   struct {
+   Result []lokiStream `json:"result"`
+   } `json:"data"`
+   Error string `json:"error,omitempty"`
+}
+
+type lokiLabelsResp struct {
+   Status string   `json:"status"`
+   Data   []string `json:"data"`
+   Error  string   `json:"error,omitempty"`
+}
+
+type lokiStream struct {
+   Stream map[string]string `json:"stream"`
+   Values [][]string`json:"values"`
+}
+
+func newLokiClient(cfg observabilitycfg.LogProviderConfig) *lokiClient {
+   return &lokiClient{
+   config: cfg,
+   client: &http.Client{Timeout: 30 * time.Second},
+   }
+}
+
+func (c *lokiClient) search(ctx context.Context, req *SearchLogsReq) 
(*SearchLogsResp, error) {
+   if req.Limit <= 0 {
+   req.Limit = defaultLogLimit
+   }
+   start, end, err := resolveTimeRange(req.StartTime, req.EndTime)
+   if err != nil {
+   return nil, err
+   }
+
+   labelNames, _ := c.labelNames(ctx, start, end)
+   queries := buildLogQLQueriesWithLabels(req, labelNames)
+   merged := &SearchLogsResp{SourceEngine: "loki", Logs: make([]LogItem, 
0, req.Limit)}
+   seen := map[string]struct{}{}
+   for _, query := range queries {
+   logs, err := c.queryRange(ctx, query, start, end, req.Limit)
+   if err != nil {
+   return nil, err
+   }
+   // remove duplicates
+   for _, item := range logs {
+   key := dedupeKey(item)
+   if _, ok := seen[key]; ok {
+   continue
+   }
+   seen[key] = struct{}{}
+   merged.Logs = append(merged.Logs, item)
+   if len(merged.Logs) >= req.Limit {
+   break
+   }
+   }
+   if len(merged.Logs) >= req.Limit {
+   break
+   }
+   }
+
+   sort.SliceStable(merged.Logs, func(i, j int) bool {
+   return merged.Logs[i].Timestamp > merged.Logs[j].Timestamp
+   })
+   return merged, nil
+}
+
+func (c *lokiClient) capabilities(ctx context.Context, req 
*LogCapabilitiesReq) (*LogCapabilitiesResp, error) {
+   start, end, err := resolveTimeRange(req.StartTime, req.EndTime)
+   if err != nil {
+   return nil, err
+   }
+   labelNames, err := c.labelNames(ctx, start, end)
+   if err != nil {
+   return nil, err
+   }
+
+   return &LogCapabilitiesResp{
+   AvailableLabels: supportedLabels(labelNames),
+   SupportedFilters: []string{
+   "mesh",
+   "appName

Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-13 Thread via GitHub


Oxidaner commented on code in PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#discussion_r3407923217


##
pkg/mcp/tools/log/loki.go:
##
@@ -0,0 +1,610 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 log
+
+import (
+   "context"
+   "encoding/json"
+   "fmt"
+   "io"
+   "net/http"
+   "net/url"
+   "regexp"
+   "sort"
+   "strconv"
+   "strings"
+   "sync"
+   "time"
+
+   "github.com/apache/dubbo-admin/pkg/common/bizerror"
+   observabilitycfg 
"github.com/apache/dubbo-admin/pkg/config/observability"
+)
+
+const (
+   defaultQueryWindow = time.Hour
+   labelCacheTTL  = 5 * time.Minute
+)
+
+var fallbackSelectorPriority = []string{
+   "namespace",
+   "job",
+   "app",
+   "appName",
+   "service_name",
+   "serviceName",
+   "service",
+   "pod",
+   "container",
+   "instance",
+   "instanceName",
+   "level",
+}
+
+var lokiLabelsCache = struct {
+   sync.Mutex
+   items map[string]cachedLokiLabels
+}{
+   items: map[string]cachedLokiLabels{},
+}
+
+type cachedLokiLabels struct {
+   labelsmap[string]struct{}
+   expiresAt time.Time
+}
+
+type lokiClient struct {
+   config observabilitycfg.LogProviderConfig
+   client *http.Client
+}
+
+type lokiQueryRangeResp struct {
+   Status string `json:"status"`
+   Data   struct {
+   Result []lokiStream `json:"result"`
+   } `json:"data"`
+   Error string `json:"error,omitempty"`
+}
+
+type lokiLabelsResp struct {
+   Status string   `json:"status"`
+   Data   []string `json:"data"`
+   Error  string   `json:"error,omitempty"`
+}
+
+type lokiStream struct {
+   Stream map[string]string `json:"stream"`
+   Values [][]string`json:"values"`
+}
+
+func newLokiClient(cfg observabilitycfg.LogProviderConfig) *lokiClient {
+   return &lokiClient{
+   config: cfg,
+   client: &http.Client{Timeout: 30 * time.Second},
+   }
+}
+
+func (c *lokiClient) search(ctx context.Context, req *SearchLogsReq) 
(*SearchLogsResp, error) {
+   if req.Limit <= 0 {
+   req.Limit = defaultLogLimit
+   }
+   start, end, err := resolveTimeRange(req.StartTime, req.EndTime)
+   if err != nil {
+   return nil, err
+   }
+
+   labelNames, _ := c.labelNames(ctx, start, end)
+   queries := buildLogQLQueriesWithLabels(req, labelNames)
+   merged := &SearchLogsResp{SourceEngine: "loki", Logs: make([]LogItem, 
0, req.Limit)}
+   seen := map[string]struct{}{}
+   for _, query := range queries {
+   logs, err := c.queryRange(ctx, query, start, end, req.Limit)
+   if err != nil {
+   return nil, err
+   }
+   // remove duplicates
+   for _, item := range logs {
+   key := dedupeKey(item)
+   if _, ok := seen[key]; ok {
+   continue
+   }
+   seen[key] = struct{}{}
+   merged.Logs = append(merged.Logs, item)
+   if len(merged.Logs) >= req.Limit {
+   break
+   }
+   }
+   if len(merged.Logs) >= req.Limit {
+   break
+   }
+   }
+
+   sort.SliceStable(merged.Logs, func(i, j int) bool {
+   return merged.Logs[i].Timestamp > merged.Logs[j].Timestamp
+   })
+   return merged, nil
+}
+
+func (c *lokiClient) capabilities(ctx context.Context, req 
*LogCapabilitiesReq) (*LogCapabilitiesResp, error) {
+   start, end, err := resolveTimeRange(req.StartTime, req.EndTime)
+   if err != nil {
+   return nil, err
+   }
+   labelNames, err := c.labelNames(ctx, start, end)
+   if err != nil {
+   return nil, err
+   }
+
+   return &LogCapabilitiesResp{
+   AvailableLabels: supportedLabels(labelNames),
+   SupportedFilters: []string{
+   "mesh",
+   "appName

Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-13 Thread via GitHub


Oxidaner commented on code in PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#discussion_r3407906419


##
pkg/mcp/tools/log/analyzer.go:
##
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 log
+
+import (
+   "fmt"
+   "regexp"
+   "sort"
+   "strings"
+)
+
+var volatileTokenPattern = regexp.MustCompile(`(?i)\b[0-9a-f]{8,}\b|\b\d+\b`)
+
+func analyzeErrors(logs []LogItem, sourceEngine string) *AnalyzeErrorLogsResp {
+   patternsByName := map[string]*ErrorPattern{}
+   for _, item := range logs {
+   if !isErrorLog(item) {
+   continue
+   }
+   patternName := normalizeMessagePattern(item.Message)
+   pattern := patternsByName[patternName]
+   if pattern == nil {
+   pattern = &ErrorPattern{
+   Pattern:   patternName,
+   Example:   item.Message,
+   FirstSeen: item.Timestamp,
+   LastSeen:  item.Timestamp,
+   }
+   patternsByName[patternName] = pattern
+   }
+   pattern.Count++
+   pattern.LastSeen = item.Timestamp
+   if len(pattern.Examples) < 3 {
+   pattern.Examples = append(pattern.Examples, item)
+   }

Review Comment:
   done



-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-13 Thread via GitHub


Copilot commented on code in PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#discussion_r3407671797


##
pkg/mcp/tools/log/analyzer.go:
##
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 log
+
+import (
+   "fmt"
+   "regexp"
+   "sort"
+   "strings"
+)
+
+var volatileTokenPattern = regexp.MustCompile(`(?i)\b[0-9a-f]{8,}\b|\b\d+\b`)
+
+func analyzeErrors(logs []LogItem, sourceEngine string) *AnalyzeErrorLogsResp {
+   patternsByName := map[string]*ErrorPattern{}
+   for _, item := range logs {
+   if !isErrorLog(item) {
+   continue
+   }
+   patternName := normalizeMessagePattern(item.Message)
+   pattern := patternsByName[patternName]
+   if pattern == nil {
+   pattern = &ErrorPattern{
+   Pattern:   patternName,
+   Example:   item.Message,
+   FirstSeen: item.Timestamp,
+   LastSeen:  item.Timestamp,
+   }
+   patternsByName[patternName] = pattern
+   }
+   pattern.Count++
+   pattern.LastSeen = item.Timestamp
+   if len(pattern.Examples) < 3 {
+   pattern.Examples = append(pattern.Examples, item)
+   }

Review Comment:
   `FirstSeen`/`LastSeen` are updated in a way that depends on input order. 
Since `SearchLogs` sorts logs descending, the current `pattern.LastSeen = 
item.Timestamp` ends up setting `LastSeen` to the oldest entry and never 
corrects `FirstSeen` when older entries are encountered. Update both fields 
using min/max comparisons instead of unconditional assignment.



##
pkg/mcp/tools/log/loki.go:
##
@@ -0,0 +1,610 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 log
+
+import (
+   "context"
+   "encoding/json"
+   "fmt"
+   "io"
+   "net/http"
+   "net/url"
+   "regexp"
+   "sort"
+   "strconv"
+   "strings"
+   "sync"
+   "time"
+
+   "github.com/apache/dubbo-admin/pkg/common/bizerror"
+   observabilitycfg 
"github.com/apache/dubbo-admin/pkg/config/observability"
+)
+
+const (
+   defaultQueryWindow = time.Hour
+   labelCacheTTL  = 5 * time.Minute
+)
+
+var fallbackSelectorPriority = []string{
+   "namespace",
+   "job",
+   "app",
+   "appName",
+   "service_name",
+   "serviceName",
+   "service",
+   "pod",
+   "container",
+   "instance",
+   "instanceName",
+   "level",
+}
+
+var lokiLabelsCache = struct {
+   sync.Mutex
+   items map[string]cachedLokiLabels
+}{
+   items: map[string]cachedLokiLabels{},
+}
+
+type cachedLokiLabels struct {
+   labelsmap[string]struct{}
+   expiresAt time.Time
+}
+
+type lokiClient struct {
+   config observabilitycfg.LogProviderConfig
+   client *http.Client
+}
+
+type lokiQueryRangeResp struct {
+   Status string `json:"status"`
+   Data   struct {
+   Result []lokiStream `json:"result"`
+   } `json:"data"`
+   Error string `json:"error,omitempty"`
+}
+
+type lokiLabelsResp struct {
+   Status string   `json:"status"`
+   Data   []string `json:"data"`
+   Error  string   `json:"error,omitempty"`
+}
+
+type lokiStr

Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-07 Thread via GitHub


sonarqubecloud[bot] commented on PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#issuecomment-4641935569

   ## [![Quality Gate 
Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png
 'Quality Gate 
Passed')](https://sonarcloud.io/dashboard?id=apache_dubbo-admin&pullRequest=1483)
 **Quality Gate passed**  
   Issues  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0 New 
issues](https://sonarcloud.io/project/issues?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png
 '') [0 Accepted 
issues](https://sonarcloud.io/project/issues?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=ACCEPTED)
   
   Measures  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0 Security 
Hotspots](https://sonarcloud.io/project/security_hotspots?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0.0% Coverage on New 
Code](https://sonarcloud.io/component_measures?id=apache_dubbo-admin&pullRequest=1483&metric=new_coverage&view=list)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0.0% Duplication on New 
Code](https://sonarcloud.io/component_measures?id=apache_dubbo-admin&pullRequest=1483&metric=new_duplicated_lines_density&view=list)
  
 
   
   [See analysis details on SonarQube 
Cloud](https://sonarcloud.io/dashboard?id=apache_dubbo-admin&pullRequest=1483)
   
   


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-07 Thread via GitHub


Oxidaner commented on PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#issuecomment-4641936749

   @robocanic done


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-06 Thread via GitHub


robocanic commented on PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#issuecomment-4639164406

   Please merge the branch and resolve the conflicts.


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-02 Thread via GitHub


sonarqubecloud[bot] commented on PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#issuecomment-4599847967

   ## [![Quality Gate 
Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png
 'Quality Gate 
Passed')](https://sonarcloud.io/dashboard?id=apache_dubbo-admin&pullRequest=1483)
 **Quality Gate passed**  
   Issues  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0 New 
issues](https://sonarcloud.io/project/issues?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png
 '') [0 Accepted 
issues](https://sonarcloud.io/project/issues?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=ACCEPTED)
   
   Measures  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0 Security 
Hotspots](https://sonarcloud.io/project/security_hotspots?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0.0% Coverage on New 
Code](https://sonarcloud.io/component_measures?id=apache_dubbo-admin&pullRequest=1483&metric=new_coverage&view=list)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0.0% Duplication on New 
Code](https://sonarcloud.io/component_measures?id=apache_dubbo-admin&pullRequest=1483&metric=new_duplicated_lines_density&view=list)
  
 
   
   [See analysis details on SonarQube 
Cloud](https://sonarcloud.io/dashboard?id=apache_dubbo-admin&pullRequest=1483)
   
   


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-02 Thread via GitHub


sonarqubecloud[bot] commented on PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#issuecomment-4599588943

   ## [![Quality Gate 
Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png
 'Quality Gate 
Passed')](https://sonarcloud.io/dashboard?id=apache_dubbo-admin&pullRequest=1483)
 **Quality Gate passed**  
   Issues  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0 New 
issues](https://sonarcloud.io/project/issues?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png
 '') [0 Accepted 
issues](https://sonarcloud.io/project/issues?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=ACCEPTED)
   
   Measures  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0 Security 
Hotspots](https://sonarcloud.io/project/security_hotspots?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0.0% Coverage on New 
Code](https://sonarcloud.io/component_measures?id=apache_dubbo-admin&pullRequest=1483&metric=new_coverage&view=list)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0.0% Duplication on New 
Code](https://sonarcloud.io/component_measures?id=apache_dubbo-admin&pullRequest=1483&metric=new_duplicated_lines_density&view=list)
  
 
   
   [See analysis details on SonarQube 
Cloud](https://sonarcloud.io/dashboard?id=apache_dubbo-admin&pullRequest=1483)
   
   


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] feat: mcp-log [dubbo-admin]

2026-06-01 Thread via GitHub


sonarqubecloud[bot] commented on PR #1483:
URL: https://github.com/apache/dubbo-admin/pull/1483#issuecomment-4593939375

   ## [![Quality Gate 
Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png
 'Quality Gate 
Passed')](https://sonarcloud.io/dashboard?id=apache_dubbo-admin&pullRequest=1483)
 **Quality Gate passed**  
   Issues  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0 New 
issues](https://sonarcloud.io/project/issues?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png
 '') [0 Accepted 
issues](https://sonarcloud.io/project/issues?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=ACCEPTED)
   
   Measures  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0 Security 
Hotspots](https://sonarcloud.io/project/security_hotspots?id=apache_dubbo-admin&pullRequest=1483&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0.0% Coverage on New 
Code](https://sonarcloud.io/component_measures?id=apache_dubbo-admin&pullRequest=1483&metric=new_coverage&view=list)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0.0% Duplication on New 
Code](https://sonarcloud.io/component_measures?id=apache_dubbo-admin&pullRequest=1483&metric=new_duplicated_lines_density&view=list)
  
 
   
   [See analysis details on SonarQube 
Cloud](https://sonarcloud.io/dashboard?id=apache_dubbo-admin&pullRequest=1483)
   
   


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]