1# go-baseapp [](http://godoc.org/github.com/palantir/go-baseapp)
2
3A minimal, not-quite-a-framework for building web applications on top of the
4standard library. It provides:
5
6- A selection of dependencies for logging, metrics, and routing that fit well
7 with the standard library
8- A standard configuration type
9- A basic configurable server type
10- A default (but optional) middleware stack
11
12This doesn't take the place of frameworks like [echo][], [gin][], or others,
13but if you prefer to stay close to the standard library for simple
14applications, `go-baseapp` will save you time when starting new projects.
15
16[echo]: https://echo.labstack.com/
17[gin]: https://gin-gonic.github.io/gin/
18
19## Usage
20
21Create a `baseapp.Server` object, register your handlers, and start the server:
22
23
24```go
25func main() {
26 config := baseapp.HTTPConfig{
27 Address: "127.0.0.1",
28 Port: "8000",
29 }
30 loggingConfig := baseapp.LoggingConfig{
31 Pretty: true,
32 Level: "debug",
33 }
34
35 logger := baseapp.NewLogger(loggingConfig)
36
37 // create a server with default options and no metrics prefix
38 server, err := baseapp.NewServer(config, baseapp.DefaultParams(logger, "")...)
39 if err != nil {
40 panic(err)
41 }
42
43 // register handlers
44 server.Mux().Handle(pat.Get("/hello"), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
45 baseapp.WriteJSON(w, http.StatusOK, map[string]string{
46 "message": fmt.Sprintf("Hello, %s!", r.FormValue("name")),
47 })
48 }))
49
50 // start the server (blocking)
51 server.Start()
52}
53```
54
55### Example
56
57The [example package](example/main.go) provides a full server that responds to
58`GET /api/message` requests with a static message from the configuration.
59
60You can start the server using:
61
62 ./godelw dep
63 ./godelw run example
64
65Navigate to `http://localhost:8000/api/message` to see the output.
66
67## Features and Opinions
68
69`go-baseapp` was designed and is maintained by Palantir's developer tools team.
70When developing this project, we had the following in mind:
71
721. Minimize code and knowledge beyond the standard library. Because we support
73 many applications that have many contributors, we want to minimize the time
74 people spend learning frameworks before being able to add new features or
75 develop new services. To this end, we've used the standard library where we
76 can and picked small dependencies with obvious APIs when we need more
77 features.
78
793. Allow easy extension. Our opinions in this library form a starting point,
80 but it should be possible to ignore any of them and add your solutions if
81 you disagree with something or it doesn't work in a specific situation.
82
834. Provide ops-friendly defaults. Our default configuration enables things like
84 request IDs, request and runtime metrics, nice error formatting, and panic
85 recovery. These are all easy to implement, but are also easy to forget when
86 setting up a new project.
87
88Notably, performance is not a major concern. While we try to avoid decisions
89that are obviously not performant, our request scale is usually low and it
90makes more sense to optimize on the factors above.
91
92### Dependencies
93
94Our selected dependencies are ultimately somewhat arbitrary, but have worked
95well for us and do not include transitive dependencies of their own:
96
97- [rs/zerolog](https://github.com/rs/zerolog) for logging. We like that it has
98 an easy-to-use API, built-in support for `context.Context`, and helpful
99 `net/http` integration via the `hlog` package.
100- [rcrowley/go-metrics](https://github.com/rcrowley/go-metrics) for metrics. We
101 like that it supports many metrics types, isn't coupled to a specific publish
102 method, and has existing integrations with many monitoring and aggregation
103 tools.
104- [goji.io](http://goji.io/) for routing. We like that it provides a minimal
105 API, supports middleware, and integrates nicely with `context.Context`.
106- [bluekeyes/hatpear](https://github.com/bluekeyes/hatpear) for error
107 aggregation. We like that it allows returning errors from HTTP handlers in a
108 way that integrates well with `net/http`.
109
110### Server Options
111
112The default server configuration (`baseapp.DefaultParams`) does the following:
113
114- Sets a logger
115- Creates a metrics registry with an optional prefix
116- Adds the default middleware to all routes (see below)
117- Configures log timestamps to use UTC and nanosecond precision
118- Improves the formatting of logged errors
119- Enables Go runtime metrics collection
120
121If you only want some of these options, provide your own set of parameters with
122only the parts you want; all of the components are exported parts of this
123library or dependencies.
124
125### Graceful Shutdown
126
127`go-baseapp` can be optionally configured to gracefully stop the running server by handling SIGINT and SIGTERM.
128
129The parameter `ShutdownWaitTime` on the `baseapp.HTTPConfig` struct enables graceful shutdown, and
130also informs the server how long to wait during the shutdown process before terminating.
131
132### Middleware
133
134The default middleware stack (`baseapp.DefaultMiddleware`) does the following:
135
136- Adds a logger to the request context
137- Adds a metrics registry to the request context
138- Generates an ID for all requests and sets the `X-Request-ID` header
139- Logs and emits metrics for all requests
140- Handles errors returned by individual route handlers
141- Recovers from panics in individual route handlers
142
143If you only want some of these features, create your own middleware stack
144selecting the parts you want; all of the components are exported parts of this
145library or dependencies.
146
147### Metrics
148
149If enabled, the server emits the following metrics:
150
151| metric name | type | definition |
152| ----------- | ---- | ---------- |
153| `server.requests` | `counter` | the count of requests handled by the server |
154| `server.requests.2xx` | `counter` | like `server.requests`, but only counting 2XX status codes |
155| `server.requests.3xx` | `counter` | like `server.requests`, but only counting 3XX status codes |
156| `server.requests.4xx` | `counter` | like `server.requests`, but only counting 4XX status codes |
157| `server.requests.5xx` | `counter` | like `server.requests`, but only counting 5XX status codes |
158| `server.goroutines` | `gauge` | the number of active goroutines |
159| `server.mem.used` | `gauge` | the amount of memory used by the process |
160
161The `baseapp/datadog` package provides an easy way to publish metrics to
162Datadog. Other aggregators can be configured with custom code in a similar way.
163
164## Contributing
165
166Contributions and issues are welcome. For new features or large contributions,
167we prefer discussing the proposed change on a GitHub issue prior to a PR.
168
169New functionality should avoid adding new dependencies if possible and should
170be broadly useful. Feature requests that are specific to certain uses will
171likely be declined unless they can be redesigned to be generic or optional.
172
173Before submitting a pull request, please run tests and style checks:
174
175```
176./godelw verify
177```
178
179## License
180
181This library is made available under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0).
View as plain text