-
-
Notifications
You must be signed in to change notification settings - Fork 494
Add Monitoring with Apitally recipe #3108
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
Conversation
|
Thanks for opening this pull request! 🎉 Please check out our contributing guidelines. |
WalkthroughA new REST API server written in Go using the Fiber framework has been introduced, featuring API key authentication and integrated request monitoring/logging with Apitally. Accompanying documentation in a README file provides setup instructions, usage guidance, and an overview of the monitoring features and endpoints. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant FiberServer
participant Apitally
Client->>FiberServer: HTTP Request with API Key
FiberServer->>FiberServer: Validate API Key
alt Valid Key
FiberServer->>Apitally: Log Request (with user info)
alt GET /v1/books
FiberServer-->>Client: Return list of books
else POST /v1/books
FiberServer->>FiberServer: Validate JSON body
alt Validation Error
FiberServer->>Apitally: Log Validation Error
FiberServer-->>Client: 400 Bad Request
else Success
FiberServer-->>Client: 201 Created
end
end
else Invalid Key
FiberServer-->>Client: 401 Unauthorized
end
Suggested reviewers
Poem
Tip ⚡️ Faster reviews with caching
Enjoy the performance boost—your workflow just got faster. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (9)
monitoring-with-apitally/README.md (4)
13-15: Prerequisites section could be more specific.While mentioning Golang installation is necessary, it would be helpful to specify a minimum required version of Go, especially if any newer language features are used in the code.
-Ensure you have Golang installed. +Ensure you have Golang installed (version 1.16 or later).
47-49: API key exposed in curl example.The API key is included in the curl example. While this is a sample key for demonstration purposes, it's good practice to avoid including API keys in documentation, even sample ones.
-curl -X GET -H "Authorization: Bearer d7e123f5a2b9c4e8d6a7b2c1f5e9d3a4" http://localhost:3000/v1/books +curl -X GET -H "Authorization: Bearer YOUR_API_KEY" http://localhost:3000/v1/books🧰 Tools
🪛 Gitleaks (8.21.2)
48-48:
(curl-auth-header)
51-56: Dashboard section could include more detail about Apitally features.The dashboard section briefly mentions the features but could be enhanced with more specifics about what metrics are available and how they can be used to improve API development and operations.
The Apitally dashboard will show the requests you've made to the API. -It provides detailed insights into the API's usage, errors, and performance. Individual requests can be inspected in the request log. You can also set up custom alerts. +It provides detailed insights into the API's usage, errors, and performance, including: + +- Request volumes and response times +- Error rates and status code distribution +- Endpoint popularity and usage patterns +- Detailed request/response inspection in the request log +- Custom alerts for error spikes or performance degradation
57-57: Consider adding alt text to the screenshot.For improved accessibility, consider adding more descriptive alt text to the screenshot image.
- +monitoring-with-apitally/main.go (5)
14-18: Consider using exported fields for apiKeyInfo struct.Since
apiKeyInfois used to populate theApitallyConsumerstruct (which has exported fields), consider making the fields inapiKeyInfoexported (capitalized) for consistency and to make the struct more reusable.type apiKeyInfo struct { - userID string - userName string - group string + UserID string + UserName string + Group string }
25-30: Hardcoded API keys in source code are a security risk.Storing API keys directly in the source code, even with a comment indicating they would be in a database in production, presents a security risk. Consider using environment variables or a configuration file that's not checked into version control, even for example code.
// API keys (in real life, these would be stored in a database) var apiKeys = map[string]apiKeyInfo{ - "d7e123f5a2b9c4e8d6a7b2c1f5e9d3a4": {userID: "user1", userName: "Alice", group: "admin"}, - "8f4e2d1c9b7a5f3e2d8c6b4a9f7e3d1c": {userID: "user2", userName: "Bob", group: "developer"}, - "3a9b8c7d6e5f4a2b1c9d8e7f6a5b4c3d": {userID: "user3", userName: "Charlie", group: "reader"}, + "example-key-1": {userID: "user1", userName: "Alice", group: "admin"}, + "example-key-2": {userID: "user2", userName: "Bob", group: "developer"}, + "example-key-3": {userID: "user3", userName: "Charlie", group: "reader"}, }For a more robust approach, you could load these from environment variables:
// LoadAPIKeys loads API keys from environment variables // Format: APIKEY_<key>=<userID>:<userName>:<group> func LoadAPIKeys() map[string]apiKeyInfo { keys := make(map[string]apiKeyInfo) for _, env := range os.Environ() { if strings.HasPrefix(env, "APIKEY_") { parts := strings.SplitN(env, "=", 2) if len(parts) != 2 { continue } key := strings.TrimPrefix(parts[0], "APIKEY_") values := strings.Split(parts[1], ":") if len(values) != 3 { continue } keys[key] = apiKeyInfo{ userID: values[0], userName: values[1], group: values[2], } } } return keys }
80-87: GET endpoint returns static data.The GET endpoint for books returns a static array rather than fetching from a database. This is appropriate for a simple example, but adding a comment to indicate this would help clarify that this is for demonstration purposes only.
// Routes app.Get("/v1/books", func(c *fiber.Ctx) error { + // Return static data for demonstration purposes books := []Book{ {Title: "The Go Programming Language", Author: "Alan A. A. Donovan"}, {Title: "Clean Code", Author: "Robert C. Martin"}, } return c.JSON(books) })
91-99: Request validation could be improved.The endpoint validates the structure but doesn't have specific validation rules. Consider adding validation tags to the Book struct to demonstrate more comprehensive validation.
type Book struct { - Title string `json:"title"` - Author string `json:"author"` + Title string `json:"title" validate:"required,min=1,max=100"` + Author string `json:"author" validate:"required,min=1,max=100"` }
106-108: Server startup lacks graceful shutdown.The server starts correctly but doesn't implement graceful shutdown, which would be important for a production application. Consider adding an example of graceful shutdown handling.
// Start server - log.Fatal(app.Listen(":3000")) + // Setup graceful shutdown + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) + + go func() { + <-c + fmt.Println("Gracefully shutting down...") + _ = app.Shutdown() + }() + + // Start server + if err := app.Listen(":3000"); err != nil && err != http.ErrServerClosed { + log.Fatal(err) + }This requires additional imports:
import ( // existing imports... "fmt" "net/http" "os" "os/signal" "syscall" )
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
monitoring-with-apitally/go.modis excluded by!**/*.modmonitoring-with-apitally/go.sumis excluded by!**/*.sum,!**/*.sum
📒 Files selected for processing (2)
monitoring-with-apitally/README.md(1 hunks)monitoring-with-apitally/main.go(1 hunks)
🧰 Additional context used
🪛 Gitleaks (8.21.2)
monitoring-with-apitally/README.md
48-48:
(curl-auth-header)
🔇 Additional comments (8)
monitoring-with-apitally/README.md (4)
1-5: Frontmatter looks good.The YAML frontmatter correctly defines the title, keywords, and description for the recipe, which will help with searchability and organization within the recipes collection.
7-11: Introduction and repository links are well-structured.The README properly introduces the recipe with badges linking to the GitHub repository and StackBlitz, making it easy for users to access the code. The concise description effectively communicates the purpose of the recipe.
30-37: API client ID setup instructions are clear.The instructions for obtaining and configuring the Apitally client ID are straightforward and include a code snippet showing where to place it. This helps users get started quickly.
59-62: References section is helpful.The references section provides useful links to both the Apitally and Fiber documentation, which is important for users who want to learn more about either technology.
monitoring-with-apitally/main.go (4)
3-12: Import organization is good.The imports are well-organized, grouping standard library imports first, followed by third-party packages. The explicit import of the Apitally package with an alias improves readability.
20-23: Book struct definition looks good.The
Bookstruct is properly defined with JSON tags, which will ensure correct serialization when returned in API responses.
32-50: Good secure implementation of API key validation.The API key validation function correctly uses crypto/sha256 for hashing and subtle.ConstantTimeCompare to prevent timing attacks. Setting consumer information for Apitally tracking is also well implemented.
73-78: API key authentication middleware is properly configured.The keyauth middleware is correctly set up with proper key lookup path and authentication scheme. The validateAPIKey function is appropriately referenced as the validator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
monitoring-with-apitally/main.go (1)
90-105:⚠️ Potential issueThe POST endpoint implementation is incomplete.
The POST endpoint contains a placeholder comment but doesn't implement any actual storage logic. This issue was flagged in previous reviews but hasn't been addressed.
Add in-memory storage functionality to demonstrate the full request flow:
+// In-memory storage for books (for demonstration purposes only) +var books = []Book{ + {Title: "The Go Programming Language", Author: "Alan A. A. Donovan"}, + {Title: "Clean Code", Author: "Robert C. Martin"}, +} app.Get("/v1/books", func(c *fiber.Ctx) error { - books := []Book{ - {Title: "The Go Programming Language", Author: "Alan A. A. Donovan"}, - {Title: "Clean Code", Author: "Robert C. Martin"}, - } return c.JSON(books) }) app.Post("/v1/books", func(c *fiber.Ctx) error { // Parse and validate the request body var req Book if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()}) } if err := validate.Struct(req); err != nil { // Capture validation errors in Apitally apitally.CaptureValidationError(c, err) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()}) } - // Logic to create a post goes here ... + // Add book to in-memory collection + books = append(books, req) - return c.Status(fiber.StatusCreated).Send(nil) + return c.Status(fiber.StatusCreated).JSON(req) })
🧹 Nitpick comments (2)
monitoring-with-apitally/README.md (1)
41-41: Consider using a clear placeholder format for the API key in the example.The curl example uses what appears to be a real API key format. Although this matches one of the test keys in your code, security scanners may flag this pattern, and users might mistakenly think this is a valid key.
Consider replacing it with a more obvious placeholder:
- curl -X GET -H "Authorization: Bearer d7e123f5a2b9c4e8d6a7b2c1f5e9d3a4" http://localhost:3000/v1/books + curl -X GET -H "Authorization: Bearer example-api-key-12345" http://localhost:3000/v1/books🧰 Tools
🪛 Gitleaks (8.21.2)
41-41:
(curl-auth-header)
monitoring-with-apitally/main.go (1)
26-31: Consider adding validation for API keysThe API keys are hardcoded and stored in a map with no validation of their format or strength. In a real application, these would need to be securely stored and validated.
For a more complete example, consider adding a comment emphasizing this is only for demonstration:
-// API keys (in real life, these would be stored in a database) +// API keys for demo purposes only +// WARNING: In production applications: +// 1. Never hardcode API keys in source code +// 2. Use a secure database or key management system +// 3. Implement key rotation and revocation capabilities
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
monitoring-with-apitally/README.md(1 hunks)monitoring-with-apitally/main.go(1 hunks)
🧰 Additional context used
🪛 Gitleaks (8.21.2)
monitoring-with-apitally/README.md
41-41:
(curl-auth-header)
🔇 Additional comments (2)
monitoring-with-apitally/main.go (2)
33-51: LGTM! Secure API key validation implementation.The API key validation uses cryptographically secure methods:
- Uses SHA-256 hashing
- Employs constant-time comparison to prevent timing attacks
- Sets consumer information for Apitally tracking
57-72: LGTM! Good Apitally configuration with environment variable.The Apitally middleware is properly configured using an environment variable for the client ID, addressing a previous review comment. The request logging configuration is comprehensive, capturing headers, bodies, and panic events.
There was a problem hiding this 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
🧹 Nitpick comments (5)
monitoring-with-apitally/README.md (5)
15-18: Specify minimum Go version.
It’s helpful to list the required Go version (e.g., Go 1.18+) under Prerequisites to prevent compatibility issues.
29-31: Usego mod tidyto install dependencies.
In a Go module, runninggo mod tidy(orgo mod download) is preferred overgo getto populatego.sumwithout unintentionally adding or upgrading dependencies. For example:- go get + go mod tidy
32-33: Clarify Apitally client ID vs. API key.
The instructions ask to “Obtain a client ID” for Apitally, yet the API uses a Bearer token. It may help to note that the Apitally client ID is only for monitoring, and that users should generate or use their own API key/token for authenticating requests if required.
42-44: Avoid hardcoded dummy token in example.
Example bearer tokens can be flagged by credential scanners. Replace with a placeholder like<YOUR_API_TOKEN>:- curl -X GET -H "Authorization: Bearer d7e123f5a2b9c4e8d6a7b2c1f5e9d3a4" http://localhost:3000/v1/books + curl -X GET -H "Authorization: Bearer <YOUR_API_TOKEN>" http://localhost:3000/v1/books🧰 Tools
🪛 Gitleaks (8.21.2)
43-43:
(curl-auth-header)
52-53: Enhance image accessibility.
Use a more descriptive alt text for the dashboard screenshot, for example:
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
monitoring-with-apitally/README.md(1 hunks)
🧰 Additional context used
🪛 Gitleaks (8.21.2)
monitoring-with-apitally/README.md
43-43:
(curl-auth-header)
🔇 Additional comments (5)
monitoring-with-apitally/README.md (5)
1-5: YAML front matter looks correct.
The title, keywords, and description are properly defined and follow the project’s conventions.
23-25: Setup instructions are accurate.
The clone andcdcommands correctly point to themonitoring-with-apitallydirectory.
36-39: Running instructions are clear.
ExportingAPITALLY_CLIENT_IDand executinggo run main.gowill start the server as expected.
56-57: References are relevant.
Linking to the official Apitally and Fiber documentation will guide users seeking more in-depth information.
9-10:✅ Verification successful
Verify the GitHub badge branch reference.
The badge URL usestree/master; if this repository’s default branch is nowmain, the link will break. Please confirm the default branch and update the URL accordingly:
🏁 Script executed:
gh api repos/gofiber/recipes --jq .default_branchLength of output: 58
Badge URL branch reference is correct
Verified that the repository’s default branch is
master, so the existing badge links usingtree/masterare accurate and do not require update.
|
THX for the example @itssimon pls follow the https://github.com/gofiber/recipes/blob/master/.github/CONTRIBUTING.md and execute the |
|
Thanks @ReneWerner87. That's done now and the table of contents is updated! |
|
Congrats on merging your first pull request! 🎉 We here at Fiber are proud of you! |
This PR adds a Monitoring with Apitally recipe that demonstrates how to easily add monitoring and request logging to any Go Fiber application with Apitally.
Apitally is a simple, lightweight API monitoring & analytics tool. It offers real-time insights into API usage, performance, and errors – without requiring complex setup or any extra infrastructure. The official Apitally middleware for Fiber can be integrated in just a few lines of code.
Summary by CodeRabbit
Summary by CodeRabbit
New Features
Documentation