1 | # Ignition
|
2 |
|
3 | ![Build Status](https://github.com/TryGhost/Ignition/workflows/Test/badge.svg?branch=master)
|
4 |
|
5 | Basic configuration and tooling shared across applications
|
6 |
|
7 | # Install
|
8 |
|
9 | `npm install ghost-ignition --save`
|
10 |
|
11 | or
|
12 |
|
13 | `yarn add ghost-ignition`
|
14 |
|
15 | # Usage
|
16 |
|
17 | Ignition offers the following features:
|
18 |
|
19 | - Logging
|
20 | - Errors
|
21 | - Config using nconf
|
22 | - HTTP Server
|
23 | - Debug
|
24 |
|
25 | ## Logging
|
26 |
|
27 | ### Configuration
|
28 |
|
29 | |Property|Type|Required|Default|Description|
|
30 | |---|---|---|---|---|
|
31 | |domain|String|No|'localhost'| The domain of your service. The domain is used to generate the log filenames.|
|
32 | |env|String|No|'development'| The environment is used for to generate the log filenames.
|
33 | |mode|String|No|'short'| A specific option for stdout/stderr logging. You can configure if the logger should log with "long" (many information) or "short" (less information) output.
|
34 | |level|String|No|'info'| Configure the default log level. The log level ("info", "warn", "error") defines which logs should be piped into stdout and log files.
|
35 | |transports|Array|No|['stdout']| A comma separated list of transports. Available transports are: file, stdout, stderr, loggly, gelf
|
36 | |rotation|Object|No|{enabled: true, period: '1w', count: 100}| If file transport is enabled, you can configure if you would like to enable log rotation.
|
37 | |path|String|No|process.cwd()| If file transport is enabled, the path config can be used to define the target log folder.
|
38 | |loggly|Object|No|null| If loggly transport is enabled, you can send your logs to loggly.
|
39 | |gelf|Object|No|null| If GELF transport is enabled, you can send your logs to GELF collector.
|
40 |
|
41 | Example:
|
42 |
|
43 | ```js
|
44 | const ignition = require('ghost-ignition');
|
45 |
|
46 | const logging = ignition.logging({
|
47 | domain: 'example.com',
|
48 | env: 'production',
|
49 | mode: 'long',
|
50 | level: 'info',
|
51 | transports: ['file'],
|
52 | rotation: {enabled: true, period: '1d', count: 10},
|
53 | path: '/var/log'
|
54 | });
|
55 | ```
|
56 |
|
57 | ### Examples
|
58 |
|
59 | ```js
|
60 | logging.info({req: req, res: res});
|
61 | logging.info({req: req, res: res, err: err});
|
62 | logging.info('Info');
|
63 | logging.error(new Error());
|
64 | logging.warn('this', 'is', 'a', 'warning');
|
65 | logging.debug('this is a debug mode');
|
66 | logging.warn(err, 'Caught an error from service X.');
|
67 | logging.warn('A friendly message.', err);
|
68 | logging.warn('A friendly message.', {err: err});
|
69 | ```
|
70 |
|
71 | ### Transports
|
72 |
|
73 | #### File
|
74 |
|
75 | Ignition creates two log files by default:
|
76 |
|
77 | - An errors log file, which only contains logs from `logging.error`
|
78 | - A general log file, which contains all logs from `logging.info`, `logging.warn` and `logging.error`
|
79 |
|
80 | If you would like to open a log file on disk, we highly recommend to install bunyan with NPM (`npm i -g bunyan`).
|
81 | You can then open your log file with `bunyan your.log` in the shell, which makes it possible to read the content.
|
82 |
|
83 | #### Loggly
|
84 |
|
85 | The loggly transport makes it possible to send your logs to loggly.
|
86 | The stream will only send errors to loggly at the moment.
|
87 |
|
88 | Example:
|
89 |
|
90 | ```js
|
91 | const ignition = require('ghost-ignition');
|
92 |
|
93 | const logging = ignition.logging({
|
94 | transports: ['file', 'loggly'],
|
95 | loggly: {
|
96 | token: 'token',
|
97 | subdomain: 'subdomain',
|
98 | // The "match" property is helpful if you only want to send specific errors to loggly. It's a regex string.
|
99 | match: 'level:critical' // or 'statusCode:500|statusCode:403'
|
100 | },
|
101 | ...
|
102 | });
|
103 | ```
|
104 |
|
105 | #### GELF
|
106 |
|
107 | The transport makes it possible to send logs to the GELF UDP collector.
|
108 |
|
109 | Example:
|
110 |
|
111 | ```
|
112 | const ignition = require('ghost-ignition');
|
113 |
|
114 | const logging = ignition.logging({
|
115 | transports: ['gelf'],
|
116 | gelf: {
|
117 | host: 'gelf.example.com', // Default: '127.0.0.1'
|
118 | post: 12345 // Default: 12201
|
119 | },
|
120 | ...
|
121 | });
|
122 | ```
|
123 |
|
124 | ### Shell
|
125 |
|
126 | #### ENV Variables
|
127 |
|
128 | Ignition accepts some env variables to modify the log output.
|
129 |
|
130 | `LEVEL=error` - Only print errors.
|
131 | `MODE=long` - Show full & long log output.
|
132 | `LOIN=true` - Set's the level to "info" and the mode to "long".
|
133 |
|
134 | ## Errors
|
135 |
|
136 | Ignition errors contains a set of useful & common error classes.
|
137 | Each Ignition error inherits from [Node's native error](https://nodejs.org/api/errors.html#errors_class_error) and keeps the structure!
|
138 |
|
139 | ### Extra properties
|
140 |
|
141 | On top of the native error properties (message, code, stack), Ignition errors support the following properties:
|
142 |
|
143 | |Property|Description
|
144 | |---|---|
|
145 | |id|A unique error ID, which every error get's attached.
|
146 | |statusCode|The HTTP status code.
|
147 | |level|Indicates if an error is "critical" or "normal".
|
148 | |errorType|Name/type of the error.
|
149 | |context|Context the error is in e.g. user was logged in
|
150 | |help|This property is useful to e.g. show a link to docs.
|
151 | |errorDetails|Extra detailed information you can pass in.
|
152 |
|
153 | ### List of errors
|
154 |
|
155 | |Error|Status Code|Level|Description
|
156 | |---|---|---|---|
|
157 | |InternalServerError|500|critical|Common error for internal errors.
|
158 | |IncorrectUsageError|400|critical|Mis-usage inside the code base.
|
159 | |NotFoundError|404|normal|Common error if a resource/page cannot be found.
|
160 | |BadRequestError|400|normal|Common error if the request structure is wrong.
|
161 | |UnauthorizedError|401|normal|Common error if authentication failed.
|
162 | |NoPermissionError|403|normal|Common error if the request has no permissions.
|
163 | |ValidationError|422|normal|Common error if the request input/content is invalid.
|
164 | |UnsupportedMediaTypeError|415|normal|Common error if the media inside a request is unsupported.
|
165 | |TooManyRequestsError|429|normal|Common error for handling brute forcing.
|
166 | |MaintenanceError|503|normal|Helpful error if your application is in maintenance mode.
|
167 | |MethodNotAllowedError|405|normal|Helpful error if e.g. the request method is unsupported.
|
168 | |RequestEntityTooLargeError|413|normal|Helpful error if file upload is too big.
|
169 |
|
170 | ### Examples
|
171 |
|
172 | ```js
|
173 | new logging.errors.InternalServerError({
|
174 | message: 'Something went very wrong',
|
175 | context: {
|
176 | user: 1
|
177 | }
|
178 | })
|
179 |
|
180 | // Ignition supports nested errors. It will try to inherit properties and extend the stack trace.
|
181 | // This is super useful if you receive an error from a calling unit, but you would like to wrap it into a custom error.
|
182 | new logging.errors.InternalServerError({
|
183 | err: err
|
184 | })
|
185 | ```
|
186 |
|
187 | ### Error utils
|
188 |
|
189 | ```js
|
190 | const ignition = require('ghost-ignition');
|
191 |
|
192 | // you can pass any error and ignition will tell you if this is a custom ignition error
|
193 | ignition.errors.utils.isIgnitionError(err);
|
194 |
|
195 | // serialize an error to a specific format
|
196 | ignition.errors.utils.serialize(err, {format: 'jsonapi|oauth'});
|
197 |
|
198 | // deserialize specific format to error instance
|
199 | ignition.errors.utils.deserialize(err);
|
200 | ```
|
201 |
|
202 | ## Config
|
203 |
|
204 | Ignition config uses nconf to create a configuration object based on your environment.
|
205 |
|
206 | ### Requirements
|
207 |
|
208 | - Create config files based on your available environments.
|
209 | - Instantiate Ignition config.
|
210 | - Read [nconf documentation](https://github.com/indexzero/nconf#readme) to understand how to use the config object.
|
211 |
|
212 | ### Examples
|
213 |
|
214 | config.example.json (defaults)
|
215 | ```json
|
216 | {
|
217 | "port": 9999
|
218 | }
|
219 | ```
|
220 |
|
221 | config.production.json
|
222 | ```json
|
223 | {
|
224 | "host": "blog.com"
|
225 | }
|
226 | ```
|
227 |
|
228 | config.development.json
|
229 | ```json
|
230 | {
|
231 | "host": "localhost"
|
232 | }
|
233 | ```
|
234 |
|
235 | ```js
|
236 | // As soon as you call the config object, Ignition will read your config files from disk and returns a config object.
|
237 | // The config object is then cached. You can operate on the config object using `set` and `get` (see [nconf](https://github.com/indexzero/nconf#readme))
|
238 | const config = require('ghost-ignition').config();
|
239 |
|
240 | // -> {port: 9999, host: localhost}
|
241 | ```
|
242 |
|
243 | ## Debug
|
244 |
|
245 | Ignition debug offers an easy way to add debugging to your application.
|
246 | It wraps the [debug](https://github.com/visionmedia/debug#readme) NPM module to simplify how to add debug information to your files.
|
247 | Ignition debug will try to read your package.json to get the name/alias of your application.
|
248 | You can enable the debug log by passing the "DEBUG" environment variable.
|
249 |
|
250 | ### Requirements
|
251 |
|
252 | - Read [debug documentation](https://github.com/visionmedia/debug#readme).
|
253 |
|
254 |
|
255 | ### Examples
|
256 |
|
257 | package.json
|
258 | ```json
|
259 | "name": "myproject",
|
260 | "alias": "proj"
|
261 | ```
|
262 |
|
263 | ```js
|
264 | const debug = require('ghost-ignition').debug('api-controller');
|
265 |
|
266 | debug('Calling the model layer.');
|
267 |
|
268 | // DEBUG=proj:api-controller yarn start
|
269 | ```
|
270 |
|
271 | ## Server
|
272 |
|
273 | The HTTP server bundles common logic in one place.
|
274 |
|
275 | - error handling for the HTTP server
|
276 | - port normalisation
|
277 |
|
278 | ### Requirements
|
279 |
|
280 | - Express
|
281 | - Ignition config
|
282 |
|
283 | ### Examples
|
284 |
|
285 | ```js
|
286 | const ignition = require('ghost-ignition');
|
287 | ignition.server.start(app);
|
288 | ignition.server.stop(app);
|
289 | ```
|
290 |
|
291 | # Test
|
292 |
|
293 | - `yarn lint` run just eslint
|
294 | - `yarn test` run eslint && then tests
|
295 |
|
296 | # Publish
|
297 |
|
298 | - `yarn ship`
|
299 |
|
300 | # Copyright & License
|
301 |
|
302 | Copyright (c) 2013-2021 Ghost Foundation - Released under the [MIT license](LICENSE).
|