Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update BrowseDetails data structure #132

Merged
merged 2 commits into from
Feb 24, 2025
Merged

Update BrowseDetails data structure #132

merged 2 commits into from
Feb 24, 2025

Conversation

kanapuli
Copy link
Collaborator

@kanapuli kanapuli commented Feb 24, 2025

Refactors the browse functionality to use a new BrowseDetails structure. This change improves the information passed through channels during browsing operations, including task and worker counts. The new structure enhances logging and provides more detailed progress information during node browsing.

Summary by CodeRabbit

  • New Features

    • Enhanced node browsing now displays enriched details including additional context such as task and worker counts for improved operational insight.
    • Added a method to calculate the average response time of requests processed, enhancing server metrics functionality.
  • Refactor

    • Streamlined data handling and messaging across browsing operations ensure consistent, comprehensive status reporting throughout the system.

Refactors the browse functionality to use a new BrowseDetails 
structure. This change improves the information passed through 
channels during browsing operations, including task and worker 
counts. The new structure enhances logging and provides more 
detailed progress information during node browsing.
@kanapuli kanapuli self-assigned this Feb 24, 2025
Copy link
Contributor

coderabbitai bot commented Feb 24, 2025

Walkthrough

The changes refactor the OPC UA browsing functionality by updating the channel type from NodeDef to a new, more detailed BrowseDetails type. The modifications span several files, with function signatures, variable declarations, and test routines updated accordingly. Additionally, a new type BrowseDetails is introduced in the frontend code to encapsulate extra information such as task and worker counts, and the logging of browse operations is adjusted.

Changes

Files Change Summary
opcua_plugin/browse.go, opcua_plugin/opcua_opc-plc_test.go, opcua_plugin/opcua_unittest_test.go, opcua_plugin/server_info.go Updated function signatures, variable declarations, and channel initializations: changed opcuaBrowserChan from chan NodeDef to chan BrowseDetails.
opcua_plugin/browse_frontend.go Introduced the new type BrowseDetails; updated the collectNodes function to receive BrowseDetails instead of NodeDef and removed the logBrowseStatus function for logging.
opcua_plugin/browse_workers.go Added a new method AverageResponseTime to the ServerMetrics struct to calculate average response times.

Possibly related PRs

Suggested reviewers

  • JeremyTheocharis
  • Scarjit
  • led0nk

Poem

I hopped through the code with a curious glance,
Swapping old channels for new data’s dance.
BrowseDetails now sing with TaskCount and WorkerCount,
Guiding each byte like a well-worn account.
With every hop, my code garden blooms bright—
A rabbit’s delight in each line of byte! 🐰

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@kanapuli
Copy link
Collaborator Author

@CodeRabbit show your magic by reviewing this PR. Be more strict and get all nitpicks

Copy link
Contributor

coderabbitai bot commented Feb 24, 2025

🧩 Analysis chain

@kanapuli: I'll perform a thorough review of the changes with extra attention to detail and code quality standards.


🏁 Script executed:

#!/bin/bash
# Get the PR diff
gh pr diff 132

# List files changed in the PR
gh pr view 132 --json files --jq '.files[].path'

Length of output: 9588


@kanapuli: I've reviewed the changes and found several areas for improvement:

  1. Documentation:
// BrowseDetails represents the details of a browse operation.
type BrowseDetails struct {
    NodeDef     NodeDef
    TaskCount   int64
    WorkerCount int64
}

The struct documentation should be more descriptive. Consider:

// BrowseDetails encapsulates information about a node browsing operation,
// including the node definition and current operation statistics.
// TaskCount represents the number of pending browse tasks.
// WorkerCount represents the number of active browse operations.
type BrowseDetails struct {
    NodeDef     NodeDef // The node being browsed
    TaskCount   int64   // Number of pending browse tasks
    WorkerCount int64   // Number of active browse operations
}
  1. Magic Numbers:
    In multiple files, channel buffer sizes are hardcoded:
opcuaBrowserChan := make(chan BrowseDetails, 100)  // in test files
opcuaBrowserChan := make(chan BrowseDetails, 3)    // in server_info.go

Consider defining these as named constants with clear documentation about their purpose.

  1. Error Handling:
    In collectNodes, the context cancellation could be more explicit:
func collectNodes(ctx context.Context, nodeBrowserChan chan BrowseDetails, nodeIDMap map[string]*NodeDef, nodes *[]NodeDef, msgChan chan<- string) {
    for browseRecord := range nodeBrowserChan {
        select {
        case <-ctx.Done():
            return
        default:
            // ... existing code
        }
    }
}

Consider handling the context cancellation error:

func collectNodes(ctx context.Context, nodeBrowserChan chan BrowseDetails, nodeIDMap map[string]*NodeDef, nodes *[]NodeDef, msgChan chan<- string) error {
    for browseRecord := range nodeBrowserChan {
        select {
        case <-ctx.Done():
            return ctx.Err()
        default:
            // ... existing code
        }
    }
    return nil
}
  1. Code Duplication:
    There's repeated channel creation code in multiple places:
nodeHeartbeatChan := make(chan NodeDef, 1)
errChanHeartbeat := make(chan error, 1)
opcuaBrowserChanHeartbeat := make(chan BrowseDetails, 1)

Consider creating a helper function to create these channel sets with appropriate buffer sizes.

  1. Progress Message Format:
    The progress message format could be more consistent:
msgChan <- fmt.Sprintf("found node '%s' (%d pending tasks, %d active browse operations)",
    browseRecord.NodeDef.BrowseName,
    browseRecord.TaskCount,
    browseRecord.WorkerCount)

Consider using structured logging or a more parseable format for better monitoring integration.

  1. Type Safety:
    In Browse function, consider adding validation for the new BrowseDetails channel:
if opcuaBrowserChan == nil {
    return fmt.Errorf("opcuaBrowserChan cannot be nil")
}
  1. Test Coverage:
    Add specific test cases for the new BrowseDetails structure and its handling in channels.

These changes will improve code quality, maintainability, and reliability. Let me know if you'd like me to elaborate on any of these points.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (1)
opcua_plugin/browse.go (1)

386-386: ⚠️ Potential issue

Update error messages to reflect the correct timeout duration.

The error messages mention "5 minutes" but the context timeout is set to 1 hour (line 362). This inconsistency could confuse users.

-				g.Log.Warn("browse function received timeout signal after 5 minutes. Please select less nodes.")
+				g.Log.Warn("browse function received timeout signal after 1 hour. Please select less nodes.")

Also applies to: 410-410

🧹 Nitpick comments (4)
opcua_plugin/browse.go (4)

64-66: Update function documentation to reflect the new parameter type.

The function documentation should be updated to describe the new BrowseDetails channel parameter and its purpose.

 // Browse is a public wrapper function for the browse function
 // Avoid using this function directly, use it only for testing
+// opcuaBrowserChan receives BrowseDetails containing node information along with task and worker counts

249-254: Avoid redundant path assignment.

The path is being set twice:

  1. In NodeDef creation (line 235)
  2. In BrowseDetails creation (line 254)

This is redundant and could lead to confusion.

 browserDetails := BrowseDetails{
   NodeDef:     def,
   TaskCount:   taskWg.Count(),
   WorkerCount: workerWg.Count(),
 }
-browserDetails.NodeDef.Path = join(task.path, def.BrowseName)

540-541: Enhance error message with actionable information.

The current error message doesn't provide enough context about compatibility requirements or how to resolve the issue.

-		g.Log.Errorf("Did not subscribe to any nodes. This can happen if the nodes that are selected are incompatible with this benthos version. Aborting...")
+		g.Log.Errorf("Did not subscribe to any nodes. This can happen if the selected nodes are incompatible with this benthos version (requires nodes with AttributeIDValue). Please verify node compatibility and refer to documentation for supported node types. Aborting...")

609-628: Optimize path collision resolution.

The current implementation updates paths for both nodes when a collision is found, which could lead to unnecessary updates and potential cascading collisions. Consider updating only the second node's path.

 if node.Path == otherNode.Path {
-  // update only the last element of the path, after the last dot
-  nodePathSplit := strings.Split(node.Path, ".")
-  nodePath := strings.Join(nodePathSplit[:len(nodePathSplit)-1], ".")
-  nodePath = nodePath + "." + sanitize(node.NodeID.String())
-  nodes[i].Path = nodePath
-
   otherNodePathSplit := strings.Split(otherNode.Path, ".")
   otherNodePath := strings.Join(otherNodePathSplit[:len(otherNodePathSplit)-1], ".")
   otherNodePath = otherNodePath + "." + sanitize(otherNode.NodeID.String())
   nodes[j].Path = otherNodePath
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eaabc70 and dac8ad5.

📒 Files selected for processing (5)
  • opcua_plugin/browse.go (6 hunks)
  • opcua_plugin/browse_frontend.go (3 hunks)
  • opcua_plugin/opcua_opc-plc_test.go (1 hunks)
  • opcua_plugin/opcua_unittest_test.go (3 hunks)
  • opcua_plugin/server_info.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
`**/*`: When reviewing an error message, ensure it meets the...

**/*: When reviewing an error message, ensure it meets these guidelines. If a message is lacking (e.g., missing clear next steps or context), provide an example of the correct format to help improve clarity and usability.

Quick Guidelines for Writing Effective Error Messages

  1. Structure Your Message with Three Key Parts
    • Context:
    Explain what the system was doing.
    Example: “Couldn’t parse config file: /etc/sample-config.properties.”
    • Error Description:
    Clearly state what failed without generic wording.
    Example: “Invalid snapshot mode ‘nevr’ provided.”
    • Mitigation/Next Steps:
    Tell the user what to do next. For complex issues, include an error code or documentation link.
    Example: “Please update the mode; refer to our docs for valid options.”
  2. Clarity & Conciseness
    • Use plain, simple language and avoid unnecessary jargon (unless targeting technical users).
    • Aim for short sentences (ideally 8–14 words) for better understanding.
  3. Consistent Tone & Style
    • Uniformity: Use the same voice, terminology, and punctuation across all messages.
    • Empathy: Maintain a neutral, supportive tone; avoid blaming the user.
    • Avoid overly casual language (skip “oops”/“whoops” and excessive exclamation points).
  4. Visibility & Placement (User-Facing Messages)
    • Proximity: Place error messages close to the related UI element to reduce cognitive load.
    • Design: Use high-contrast text, icons, or subtle animations; follow accessibility guidelines (don’t rely solely on color).
  5. Actionability & Efficiency
    • Clearly indicate the next steps (e.g., “Retry later”, “Log in again”, “Check your input”).
    • Preserve user input when possible to minimize frustration.
    • Where relevant, provide error codes or links for further troubleshooting.
  6. Security & Privacy Considerations
    • User-Facing: Avoid exposing internal details or sensitive data.
    • Developer/Logging: Include detailed context (like file paths or exception chains) for debugging, but be cautious about sensitive information.
  7. Logging & Exception Best Practices (for Developer/Operations Messages)
    • Log the full context—including exception chains—to aid troubleshooting.
    • Use structured logging (e.g., JSON) for filtering and analysis.
    • Choose a consistent method: either raise an exception or log an error (not both) to avoid redundancy.
    • Don’t make error messages an API contract; expose machine-readable error codes or types instead.
  8. Additional Best Practices
    • Fail Early: Report errors as soon as possible (e.g., during input validation or startup).
    • One Concept, One Term: Use consistent terminology across messages and documentation.
    • Localization: For internal logs, use English; if localizing for users, follow a vetted process.
  • opcua_plugin/server_info.go
  • opcua_plugin/browse_frontend.go
  • opcua_plugin/opcua_unittest_test.go
  • opcua_plugin/opcua_opc-plc_test.go
  • opcua_plugin/browse.go
`**/*`: Whenever in a new PR a new function or code is intro...

**/*: Whenever in a new PR a new function or code is introduced, ensure that there is at least somewhere as a code comment, in the README or wherer ever explained the "why" behind the decision. So e.g., why something was preferred over other options, or why a certain loop needs to be executed.

  • opcua_plugin/server_info.go
  • opcua_plugin/browse_frontend.go
  • opcua_plugin/opcua_unittest_test.go
  • opcua_plugin/opcua_opc-plc_test.go
  • opcua_plugin/browse.go
🔇 Additional comments (6)
opcua_plugin/browse_frontend.go (2)

14-19: LGTM! Well-structured type definition.

The new BrowseDetails type effectively encapsulates both the node information and browsing metrics, providing a clear and maintainable way to track browsing progress.


85-101: LGTM! Enhanced node collection with progress tracking.

The updated collectNodes function now provides better visibility into the browsing process by logging both pending tasks and active browse operations.

opcua_plugin/server_info.go (1)

36-36: LGTM! Consistent type usage.

The channel type update maintains consistency with the new BrowseDetails structure, though the data is not used in this function as noted in the comments.

opcua_plugin/opcua_unittest_test.go (2)

69-69: LGTM! Updated test variable declaration.

The test setup correctly uses the new BrowseDetails type for the browser channel.


692-712: LGTM! Well-structured test helper function.

The startBrowsing helper function maintains its clear structure while adapting to the new BrowseDetails type.

opcua_plugin/opcua_opc-plc_test.go (1)

426-426: LGTM! Updated test channel type.

The test case correctly uses the new BrowseDetails type for the browser channel.

Implements AverageResponseTime method for ServerMetrics to provide
insights into server performance. Updates BrowseDetails struct and
frontend to include this metric, enhancing monitoring capabilities.
Improves user feedback during browsing operations.
@kanapuli kanapuli requested a review from led0nk February 24, 2025 08:55
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🔭 Outside diff range comments (1)
opcua_plugin/browse_frontend.go (1)

62-65: ⚠️ Potential issue

Replace sleep-based synchronization with proper channel coordination.

Using time.Sleep as a synchronization mechanism is unreliable and could lead to race conditions or missing nodes.

Consider using a done channel or wait group to properly coordinate node collection:

-	// TODO: Temporary workaround - Adding a timeout ensures all child nodes are properly
-	// collected in the nodes[] array. Without this timeout, the last children nodes
-	// may be missing from the results.
-	time.Sleep(3 * time.Second)
+	// Create a done channel to signal completion of node collection
+	done := make(chan struct{})
+	go func() {
+		// Wait for all goroutines to finish
+		wg.Wait()
+		// Close channels
+		close(nodeChan)
+		close(errChan)
+		close(opcuaBrowserChan)
+		// Signal completion
+		close(done)
+	}()
+
+	// Wait for completion or context cancellation
+	select {
+	case <-done:
+		// Node collection completed successfully
+	case <-ctx.Done():
+		return rootNode, ctx.Err()
+	}
🧹 Nitpick comments (4)
opcua_plugin/browse_workers.go (2)

56-66: Consider maintaining a running average for better performance.

The method recalculates the average each time by iterating through all response times. For better performance, consider maintaining a running average and total count.

Here's a suggested implementation:

 type ServerMetrics struct {
 	mu             sync.Mutex
-	responseTimes  []time.Duration
+	responseTimes   []time.Duration
+	runningTotal    time.Duration
 	currentWorkers int
 	targetLatency  time.Duration
 	workerControls map[uuid.UUID]chan struct{}
 }

 func (sm *ServerMetrics) recordResponseTime(duration time.Duration) {
 	sm.mu.Lock()
 	defer sm.mu.Unlock()
+	sm.runningTotal += duration
 	if len(sm.responseTimes) >= SampleSize {
+		sm.runningTotal -= sm.responseTimes[0]
 		sm.responseTimes = sm.responseTimes[1:]
 	}
 	sm.responseTimes = append(sm.responseTimes, duration)
 }

 func (sm *ServerMetrics) AverageResponseTime() time.Duration {
 	sm.mu.Lock()
 	defer sm.mu.Unlock()
 	if len(sm.responseTimes) == 0 {
 		return 0
 	}
-	var totalTime time.Duration
-	for _, t := range sm.responseTimes {
-		totalTime += t
-	}
-	return totalTime / time.Duration(len(sm.responseTimes))
+	return sm.runningTotal / time.Duration(len(sm.responseTimes))
 }

56-66: Reduce code duplication in average calculation.

The average calculation logic is duplicated between AverageResponseTime and adjustWorkers. Consider extracting this into a private helper method.

Here's a suggested implementation:

+func (sm *ServerMetrics) calculateAverage() time.Duration {
+	if len(sm.responseTimes) == 0 {
+		return 0
+	}
+	return sm.runningTotal / time.Duration(len(sm.responseTimes))
+}

 func (sm *ServerMetrics) AverageResponseTime() time.Duration {
 	sm.mu.Lock()
 	defer sm.mu.Unlock()
-	if len(sm.responseTimes) == 0 {
-		return 0
-	}
-	var totalTime time.Duration
-	for _, t := range sm.responseTimes {
-		totalTime += t
-	}
-	return totalTime / time.Duration(len(sm.responseTimes))
+	return sm.calculateAverage()
 }

 func (sm *ServerMetrics) adjustWorkers(logger Logger) (toAdd, toRemove int) {
 	sm.mu.Lock()
 	defer sm.mu.Unlock()

 	if len(sm.responseTimes) < SampleSize {
 		return 0, 0
 	}

-	var totalTime time.Duration
-	for _, t := range sm.responseTimes {
-		totalTime += t
-	}
-	avgResponse := totalTime / time.Duration(len(sm.responseTimes))
+	avgResponse := sm.calculateAverage()
 	oldWorkerCount := sm.currentWorkers

Also applies to: 68-102

opcua_plugin/browse_frontend.go (2)

14-20: Enhance struct documentation with field descriptions.

The struct documentation should explain the purpose of each field to improve code maintainability.

Apply this diff to improve documentation:

-// BrowseDetails represents the details of a browse operation.
+// BrowseDetails represents the details of a browse operation, including metrics and node information.
+//
+// Fields:
+// - NodeDef: The node definition containing the node's attributes and relationships
+// - TaskCount: Number of pending browse tasks in the queue
+// - WorkerCount: Number of active worker goroutines performing browse operations
+// - AvgServerResponseTime: Average time taken by the server to respond to browse requests
 type BrowseDetails struct {
 	NodeDef               NodeDef
 	TaskCount             int64
 	WorkerCount           int64
 	AvgServerResponseTime time.Duration
 }

43-45: Define channel buffer sizes as constants.

The channel buffer sizes are hardcoded. Consider defining them as named constants for better maintainability.

Apply this diff:

+const (
+	// ChannelBufferSize defines the buffer size for browse operation channels
+	ChannelBufferSize = MaxTagsToBrowse
+)

-	nodeChan := make(chan NodeDef, MaxTagsToBrowse)
-	errChan := make(chan error, MaxTagsToBrowse)
-	opcuaBrowserChan := make(chan BrowseDetails, MaxTagsToBrowse)
+	nodeChan := make(chan NodeDef, ChannelBufferSize)
+	errChan := make(chan error, ChannelBufferSize)
+	opcuaBrowserChan := make(chan BrowseDetails, ChannelBufferSize)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dac8ad5 and bac2410.

📒 Files selected for processing (3)
  • opcua_plugin/browse.go (6 hunks)
  • opcua_plugin/browse_frontend.go (3 hunks)
  • opcua_plugin/browse_workers.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • opcua_plugin/browse.go
🧰 Additional context used
📓 Path-based instructions (2)
`**/*`: When reviewing an error message, ensure it meets the...

**/*: When reviewing an error message, ensure it meets these guidelines. If a message is lacking (e.g., missing clear next steps or context), provide an example of the correct format to help improve clarity and usability.

Quick Guidelines for Writing Effective Error Messages

  1. Structure Your Message with Three Key Parts
    • Context:
    Explain what the system was doing.
    Example: “Couldn’t parse config file: /etc/sample-config.properties.”
    • Error Description:
    Clearly state what failed without generic wording.
    Example: “Invalid snapshot mode ‘nevr’ provided.”
    • Mitigation/Next Steps:
    Tell the user what to do next. For complex issues, include an error code or documentation link.
    Example: “Please update the mode; refer to our docs for valid options.”
  2. Clarity & Conciseness
    • Use plain, simple language and avoid unnecessary jargon (unless targeting technical users).
    • Aim for short sentences (ideally 8–14 words) for better understanding.
  3. Consistent Tone & Style
    • Uniformity: Use the same voice, terminology, and punctuation across all messages.
    • Empathy: Maintain a neutral, supportive tone; avoid blaming the user.
    • Avoid overly casual language (skip “oops”/“whoops” and excessive exclamation points).
  4. Visibility & Placement (User-Facing Messages)
    • Proximity: Place error messages close to the related UI element to reduce cognitive load.
    • Design: Use high-contrast text, icons, or subtle animations; follow accessibility guidelines (don’t rely solely on color).
  5. Actionability & Efficiency
    • Clearly indicate the next steps (e.g., “Retry later”, “Log in again”, “Check your input”).
    • Preserve user input when possible to minimize frustration.
    • Where relevant, provide error codes or links for further troubleshooting.
  6. Security & Privacy Considerations
    • User-Facing: Avoid exposing internal details or sensitive data.
    • Developer/Logging: Include detailed context (like file paths or exception chains) for debugging, but be cautious about sensitive information.
  7. Logging & Exception Best Practices (for Developer/Operations Messages)
    • Log the full context—including exception chains—to aid troubleshooting.
    • Use structured logging (e.g., JSON) for filtering and analysis.
    • Choose a consistent method: either raise an exception or log an error (not both) to avoid redundancy.
    • Don’t make error messages an API contract; expose machine-readable error codes or types instead.
  8. Additional Best Practices
    • Fail Early: Report errors as soon as possible (e.g., during input validation or startup).
    • One Concept, One Term: Use consistent terminology across messages and documentation.
    • Localization: For internal logs, use English; if localizing for users, follow a vetted process.
  • opcua_plugin/browse_workers.go
  • opcua_plugin/browse_frontend.go
`**/*`: Whenever in a new PR a new function or code is intro...

**/*: Whenever in a new PR a new function or code is introduced, ensure that there is at least somewhere as a code comment, in the README or wherer ever explained the "why" behind the decision. So e.g., why something was preferred over other options, or why a certain loop needs to be executed.

  • opcua_plugin/browse_workers.go
  • opcua_plugin/browse_frontend.go
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: create-manifests
  • GitHub Check: go-test-opcua-plc

@kanapuli kanapuli merged commit 34d8c06 into master Feb 24, 2025
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants