Copilot commented on code in PR #26: URL: https://github.com/apache/skywalking-mcp/pull/26#discussion_r2923984139
########## internal/prompts/trace.go: ########## @@ -0,0 +1,202 @@ +// Licensed to 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. Apache Software Foundation (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 prompts + +import ( + "context" + "fmt" + + "github.com/mark3labs/mcp-go/mcp" +) + +func traceInvestigationHandler(_ context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) { + args := request.Params.Arguments + serviceID := args["service_id"] + traceState := args["trace_state"] + duration := args["duration"] + + if duration == "" { + duration = defaultDuration + } + if traceState == "" { + traceState = "all" + } + + // Use the dynamic tool instructions + toolInstructions := generateToolInstructions("trace_investigation") + + prompt := fmt.Sprintf(`Investigate traces with filters: service_id="%s", trace_state="%s", duration="%s". + +%s + +**Analysis Steps:** + +**Find Problematic Traces** +- First use query_traces with view="summary" to get overview +- Look for patterns in error traces, slow traces, or anomalies +- Note trace IDs that need deeper investigation + +**Deep Dive on Specific Traces** +- Use query_traces with the identified trace_id Review Comment: This prompt instructs using query_traces with a "duration" filter, but query_traces now accepts start/end/step instead. Update the prompt to produce start/end (e.g. end="now" and start derived from duration) so it matches the actual tool parameters. ```suggestion prompt := fmt.Sprintf(`Investigate traces with filters: service_id="%s", trace_state="%s", time_range="%s". %s **Analysis Steps:** **Find Problematic Traces** - First use query_traces with end="now", start derived from the requested time_range (e.g., now minus the time_range), and view="summary" to get an overview - Look for patterns in error traces, slow traces, or anomalies - Note trace IDs that need deeper investigation **Deep Dive on Specific Traces** - Use query_traces with the identified trace_id and the same start/end time window ``` ########## internal/tools/log.go: ########## @@ -65,13 +68,26 @@ func buildLogQueryCondition(req *LogQueryRequest) *api.LogQueryCondition { paging := BuildPagination(req.PageNum, req.PageSize) + order := api.OrderDes + if req.QueryOrder == "ASC" { + order = api.OrderAsc + } + cond := &api.LogQueryCondition{ ServiceID: &req.ServiceID, ServiceInstanceID: &req.ServiceInstanceID, EndpointID: &req.EndpointID, - RelatedTrace: &api.TraceScopeCondition{TraceID: req.TraceID}, QueryDuration: &duration, Paging: paging, + QueryOrder: &order, + } + + if req.TraceID != "" || req.SegmentID != "" || req.SpanID != nil { + cond.RelatedTrace = &api.TraceScopeCondition{ + TraceID: req.TraceID, + SegmentID: &req.SegmentID, + SpanID: req.SpanID, + } Review Comment: RelatedTrace always sets SegmentID to &req.SegmentID when any trace scope filter is used. When only trace_id is provided (or only span_id), this passes an empty segment_id pointer, which can unintentionally filter out all logs. Only set SegmentID when req.SegmentID != "" (and similarly avoid setting span/segment pointers unless provided). ```suggestion traceScope := &api.TraceScopeCondition{} if req.TraceID != "" { traceScope.TraceID = req.TraceID } if req.SegmentID != "" { // Only set SegmentID when it is actually provided to avoid filtering by an empty segment. traceScope.SegmentID = &req.SegmentID } if req.SpanID != nil { traceScope.SpanID = req.SpanID } cond.RelatedTrace = traceScope ``` ########## internal/prompts/trace.go: ########## @@ -0,0 +1,202 @@ +// Licensed to 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. Apache Software Foundation (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 prompts + +import ( + "context" + "fmt" + + "github.com/mark3labs/mcp-go/mcp" +) + +func traceInvestigationHandler(_ context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) { + args := request.Params.Arguments + serviceID := args["service_id"] + traceState := args["trace_state"] + duration := args["duration"] + + if duration == "" { + duration = defaultDuration + } + if traceState == "" { + traceState = "all" + } + + // Use the dynamic tool instructions + toolInstructions := generateToolInstructions("trace_investigation") + + prompt := fmt.Sprintf(`Investigate traces with filters: service_id="%s", trace_state="%s", duration="%s". + +%s + +**Analysis Steps:** + +**Find Problematic Traces** +- First use query_traces with view="summary" to get overview +- Look for patterns in error traces, slow traces, or anomalies +- Note trace IDs that need deeper investigation + +**Deep Dive on Specific Traces** +- Use query_traces with the identified trace_id +- Start with view="summary" for quick insights +- Use view="full" for complete span analysis +- Use view="errors_only" if focusing on errors + +**Performance Analysis** +- Look for traces with high duration using min_trace_duration filter +- Identify bottlenecks in span timings +- Check for cascading delays + +**Error Pattern Analysis** +- Use query_traces with trace_state="error" +- Group errors by type and service +- Identify error propagation paths + +Provide specific findings and actionable recommendations.`, serviceID, traceState, duration, toolInstructions) + + return &mcp.GetPromptResult{ + Description: "Trace investigation using query tools", + Messages: []mcp.PromptMessage{ + { + Role: mcp.RoleUser, + Content: mcp.TextContent{ + Type: "text", + Text: prompt, + }, + }, + }, + }, nil +} + +func logAnalysisHandler(_ context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) { + args := request.Params.Arguments + serviceID := args["service_id"] + logLevel := args["log_level"] + duration := args["duration"] + + if duration == "" { + duration = defaultDuration + } + if logLevel == "" { + logLevel = "ERROR" + } + + prompt := fmt.Sprintf(`Analyze service logs using the query_logs tool: + +**Tool Configuration:** +- query_logs with following parameters: + - service_id: "%s" (if specified) + - tags: [{"key": "level", "value": "%s"}] for log level filtering + - duration: "%s" for time range Review Comment: This prompt tells users to call query_logs with a "duration" parameter, but query_logs only supports start/end/step. Please update the tool configuration section to use start/end (or call the generate_duration prompt first) so the instructions are actionable. ```suggestion - start and end: timestamps defining the time range (e.g., last %s) ``` ########## internal/prompts/trace.go: ########## @@ -0,0 +1,202 @@ +// Licensed to 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. Apache Software Foundation (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 prompts + +import ( + "context" + "fmt" + + "github.com/mark3labs/mcp-go/mcp" +) + +func traceInvestigationHandler(_ context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) { + args := request.Params.Arguments + serviceID := args["service_id"] + traceState := args["trace_state"] + duration := args["duration"] + + if duration == "" { + duration = defaultDuration + } + if traceState == "" { + traceState = "all" + } + + // Use the dynamic tool instructions + toolInstructions := generateToolInstructions("trace_investigation") + + prompt := fmt.Sprintf(`Investigate traces with filters: service_id="%s", trace_state="%s", duration="%s". + +%s + +**Analysis Steps:** + +**Find Problematic Traces** +- First use query_traces with view="summary" to get overview +- Look for patterns in error traces, slow traces, or anomalies +- Note trace IDs that need deeper investigation + +**Deep Dive on Specific Traces** +- Use query_traces with the identified trace_id +- Start with view="summary" for quick insights +- Use view="full" for complete span analysis +- Use view="errors_only" if focusing on errors + +**Performance Analysis** +- Look for traces with high duration using min_trace_duration filter +- Identify bottlenecks in span timings +- Check for cascading delays + +**Error Pattern Analysis** +- Use query_traces with trace_state="error" +- Group errors by type and service +- Identify error propagation paths + +Provide specific findings and actionable recommendations.`, serviceID, traceState, duration, toolInstructions) + + return &mcp.GetPromptResult{ + Description: "Trace investigation using query tools", + Messages: []mcp.PromptMessage{ + { + Role: mcp.RoleUser, + Content: mcp.TextContent{ + Type: "text", + Text: prompt, + }, + }, + }, + }, nil +} + +func logAnalysisHandler(_ context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) { + args := request.Params.Arguments + serviceID := args["service_id"] + logLevel := args["log_level"] + duration := args["duration"] + + if duration == "" { + duration = defaultDuration + } + if logLevel == "" { + logLevel = "ERROR" + } + + prompt := fmt.Sprintf(`Analyze service logs using the query_logs tool: + +**Tool Configuration:** +- query_logs with following parameters: + - service_id: "%s" (if specified) + - tags: [{"key": "level", "value": "%s"}] for log level filtering + - duration: "%s" for time range + - cold: true if historical data needed + +**Analysis Steps:** + +**Log Pattern Analysis** +- Use query_logs to get recent logs for the service +- Filter by log level (ERROR, WARN, INFO) +- Look for recurring error patterns +- Identify frequency of different log types + +**Error Investigation** +- Focus on ERROR level logs first +- Group similar error messages +- Check for correlation with trace IDs +- Look for timestamp patterns + +**Performance Correlation** +- Compare log timestamps with performance issues +- Look for resource exhaustion indicators +- Check for timeout or connection errors + +**Troubleshooting Workflow** +- Start with ERROR logs in the specified time range +- Use trace_id from logs to get detailed trace analysis +- Cross-reference with metrics for full picture + +Provide specific log analysis findings and recommendations.`, serviceID, logLevel, duration) + + return &mcp.GetPromptResult{ + Description: "Log analysis using query_logs tool", + Messages: []mcp.PromptMessage{ + { + Role: mcp.RoleUser, + Content: mcp.TextContent{ + Type: "text", + Text: prompt, + }, + }, + }, + }, nil +} + +func traceDeepDiveHandler(_ context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) { + args := request.Params.Arguments + traceID := args["trace_id"] + view := args["view"] + + if view == "" { + view = "summary" + } Review Comment: traceDeepDiveHandler ignores the prompt argument "check_cold_storage" (it isn't read from request.Params.Arguments). Either remove that argument from the prompt registration or implement the cold-storage fallback instructions in the generated prompt text. ########## internal/tools/log.go: ########## @@ -110,20 +127,35 @@ Workflow: Examples: - {"service_id": "Your_ApplicationName", "start": "2024-06-01 12:00:00", "end": "2024-06-01 13:00:00"}: Query logs for a service in a time range - {"trace_id": "abc123..."}: Query logs related to a specific trace +- {"trace_id": "abc123...", "segment_id": "seg456...", "span_id": 0}: Query logs for a specific span - {"tags": [{"key": "level", "value": "ERROR"}], "cold": true}: Query error logs from cold storage`, Review Comment: The query_logs docstring still references using a "duration" parameter to limit the time range, but the tool API only supports start/end/step. Please update the tool description/examples so callers don't try to pass an unsupported duration field. ########## README.md: ########## @@ -86,12 +86,9 @@ If using Docker: "run", "--rm", "-i", - "-e", - "SW_URL", - "skywalking-mcp:latest" - ], - "env": { - "SW_URL": "http://localhost:12800" + "skywalking-mcp:latest", + "--sw-url", + "http://localhost:12800" } Review Comment: The Docker + Cursor configuration JSON is malformed: the "args" array isn't closed (it's closed with a "}" instead of a "]"). As written, the snippet can't be pasted into a JSON config file. ```suggestion ] ``` ########## README.md: ########## @@ -102,17 +99,41 @@ If using Docker: SkyWalking MCP provides the following tools to query and analyze SkyWalking OAP data: -| Category | Tool Name | Description | Key Features | -|-------------|--------------------------|----------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **Trace** | `get_trace_details` | Get detailed trace information | Retrieve trace by ID; **Multiple views**: `full` (complete trace), `summary` (overview with metrics), `errors_only` (error spans only); Detailed span analysis | -| **Trace** | `get_cold_trace_details` | Get trace details from cold storage | Query historical traces from BanyanDB; **Multiple views**: `full`, `summary`, `errors_only`; Duration-based search; Historical incident investigation | -| **Trace** | `query_traces` | Query traces with intelligent analysis | Multi-condition filtering (service, endpoint, duration, state, tags); **Multiple views**: `full` (raw data), `summary` (intelligent analysis with performance insights), `errors_only` (error traces); Sort options; Slow trace detection; Performance metrics and statistics | -| **Metrics** | `query_single_metrics` | Query single metric values | Get specific metric values (CPM, response time, SLA, Apdex); Multiple entity scopes (Service, ServiceInstance, Endpoint, Process, Relations); Time range and cold storage support | -| **Metrics** | `query_top_n_metrics` | Query top N metric rankings | Rank entities by metric values; Configurable top N count; Ascending/descending order; Scope-based filtering; Performance analysis and issue identification | -| **Log** | `query_logs` | Query logs from SkyWalking OAP | Filter by service, instance, endpoint, trace ID, tags; Time range queries; Cold storage support; Pagination support | -| **MQE** | `execute_mqe_expression` | Execute MQE expressions for metrics | Execute complex MQE (Metrics Query Expression) queries; Support calculations, aggregations, comparisons, TopN, trend analysis; Multiple result types (single value, time series, sorted list); Entity filtering and relation metrics; Debug and tracing capabilities | -| **MQE** | `list_mqe_metrics` | List available metrics for MQE | Discover available metrics for MQE queries; Filter by regex patterns; Get metric metadata (type, catalog); Support service, instance, endpoint, relation, database, and infrastructure metrics | -| **MQE** | `get_mqe_metric_type` | Get metric type information | Get detailed type information for specific metrics; Understand metric structure (regular value, labeled value, sampled record); Help with correct MQE expression syntax | +| Category | Tool Name | Description | +|--------------|--------------------------------|---------------------------------------------------------------------------------------------------| +| **Trace** | `query_traces` | Query traces with multi-condition filtering (service, endpoint, duration, state, tags). Supports `full`, `summary`, and `errors_only` views with performance insights. | Review Comment: This description still mentions filtering traces by "duration", but the query_traces tool now uses start/end/step for time ranges. Update the README so it matches the current tool parameters. ```suggestion | **Trace** | `query_traces` | Query traces with multi-condition filtering (service, endpoint, state, tags, and time range via start/end/step). Supports `full`, `summary`, and `errors_only` views with performance insights. | ``` ########## internal/prompts/analysis.go: ########## @@ -0,0 +1,238 @@ +// Licensed to 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. Apache Software Foundation (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 prompts + +import ( + "context" + "fmt" + + "github.com/mark3labs/mcp-go/mcp" +) + +func performanceAnalysisHandler(_ context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) { + args := request.Params.Arguments + serviceName := args["service_name"] + duration := args["duration"] + + if duration == "" { + duration = defaultDuration + } + + // Use the dynamic tool instructions + toolInstructions := generateToolInstructions("performance_analysis") + + prompt := fmt.Sprintf(`Please analyze the performance of service '%s' over the last %s. + +%s + Review Comment: The analyze-performance prompt takes a "duration" argument, but the tools it references (execute_mqe_expression/query_traces) use start/end/step rather than duration. Consider converting duration into start/end inside the handler (or instruct to use generate_duration) so the prompt leads to valid tool calls. ########## internal/prompts/tools.go: ########## @@ -0,0 +1,91 @@ +// Licensed to 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. Apache Software Foundation (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 prompts + +import "fmt" + +// Tool capability mapping for different analysis types +var toolCapabilities = map[string][]string{ + "performance_analysis": { + "execute_mqe_expression", Review Comment: toolCapabilities for "performance_analysis" lists only execute_mqe_expression, but analysisChains for that analysis type recommends calling query_traces too. This makes generateToolInstructions internally inconsistent; add query_traces to toolCapabilities (or remove it from the chain). ```suggestion "execute_mqe_expression", "query_traces", ``` -- 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]
