Skip to content

Commit 6e7adc3

Browse files
authored
Revert "chore: move part of docs to enterprise repository (#7385)" (#7386)
This reverts commit a72218b.
1 parent a72218b commit 6e7adc3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+18289
-7
lines changed

docs/content/3.middleware/1.index.md

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
title: Overview
3+
---
4+
# Middleware
5+
6+
Alokai's **Server Middleware** is an Express.js application that provides a single place for you to connect to the multiple services that you need to run your storefront.
7+
8+
It acts as a layer between your frontend application and the various services that you need to connect to, such as a commerce backend, CMS, or payment gateway.
9+
10+
Our different [integrations](/integrations) add onto the middleware to provide additional API Clients specific for a certain integration that you can interact with using the [SDK](/sdk).
11+
12+
## Features
13+
14+
::list{type="success"}
15+
- Connect multiple services using different technologies and libraries
16+
- Create and [extend](/middleware/guides/extensions) integrations to add new capabilities or modify their behavior
17+
- Control of the requests sent to the integration platform and responses sent back to the Nuxt.js application
18+
- Securely store credentials on the server without exposing them to the end-users of your application
19+
- Improve site performance by moving logic to the server abd shipping less code to the browser
20+
::
21+
22+
## Getting Started
23+
24+
If you're using our storefront, the middleware is set up for you. Our storefronts come with a middleware and frontend app already configured, so you can get started right away.
25+
26+
But if you're building your Alokai application from scratch, you'll need to set up the middleware to connect to your backend services.
27+
28+
::grid{:columns="2"}
29+
#section-1
30+
:card{to="/middleware/guides/extensions" title="See Available Storefronts" description="Get started with one of our ready-to-customize storefronts." icon="material-symbols:storefront"}
31+
#section-2
32+
:card{to="/middleware/guides/extensions" title="Start From Scratch" description="Set up your server middleware, configure it, and more." icon="gridicons:customize"}
33+
::
34+
35+
## Architecture
36+
37+
The easiest way to explain the Server Middleware architecture is to base the explanation on the Alokai Integration context.
38+
39+
In the container, the server application uses the integration that can communicate with the external service provider (e.g. commerce backend). The integration can be extended by the integration extensions. Middleware config is provided for both integration and its extensions.
40+
41+
<img alt="Middleware Data Flow" src="./img/overview/architecture.svg" class="mx-auto" />
42+
43+
44+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
# Logger
2+
3+
The middleware application provides a logger instance that automatically attaches metadata related to the scope of each call. By adding this contextual data, the logger makes it significantly easier to trace the origin of logs or errors, simplifying the debugging and monitoring process across the application.
4+
5+
:::info
6+
The logger has been available since version 5.1.0. Please refer to the [middleware changelog](https://docs.alokai.com/middleware/reference/change-log#_510) for more details.
7+
:::
8+
9+
## Using logger
10+
11+
The middleware application provides access to the logger in various parts of the system, such as in extensions and integrations. This flexibility allows you to log important events, errors, and other data throughout the lifecycle of your application.
12+
13+
In this section, we will explore how to access and use the logger in different parts of the application.
14+
15+
The examples below demonstrate how to use the application logger to ensure that correct metadata is conveyed in the logs. To achieve that, we will use the `getLogger` function to extract the logger instance from the passed argument.
16+
17+
:::tip
18+
The logger is integrated into the middleware to provide additional metadata about the scope of call with every log out of the box. In case of error, it also provides an error boundary.
19+
:::
20+
21+
### Basic Logger usage
22+
23+
To use the logger, you need to import the `getLogger` function from the middleware package. Depending on the context, you can obtain the logger from different sources, such as the `alokai` object, `context` object, or `params` object. All such cases are covered in the following examples. For this example, we will use the `context` object.
24+
25+
```ts
26+
import { getLogger } from "@vue-storefront/middleware";
27+
28+
// Assume that `context` is available in the current scope
29+
const logger = getLogger(context);
30+
logger.info("Middleware is running!");
31+
```
32+
33+
Prints:
34+
35+
```json
36+
{
37+
"message": "Middleware is running!",
38+
"timestamp": "2024-10-22T19:04:18.791Z",
39+
"severity": "INFO",
40+
"alokai": {
41+
"context": "middleware",
42+
"scope": {
43+
// ...
44+
}
45+
}
46+
}
47+
```
48+
49+
The provided logger has a second optional argument that allows you to include custom metadata to be attached to the JSON output.
50+
For example:
51+
52+
```ts
53+
logger.info("I've just fetched a user!", {
54+
userId: "123",
55+
});
56+
```
57+
58+
Prints:
59+
60+
```json
61+
{
62+
"message": "I've just fetched a user!",
63+
"timestamp": "2024-10-22T19:04:18.791Z",
64+
"severity": "INFO",
65+
"alokai": {
66+
"context": "middleware",
67+
"scope": {
68+
// ...
69+
}
70+
},
71+
"userId": "123"
72+
}
73+
```
74+
75+
:::warning
76+
It's forbidden to overwrite **alokai** key within provided metadata. Any attempt will be ineffective. If you need to provide additional metadata, use a different key. **alokai** key is reserved for internal use only.
77+
:::
78+
79+
### `extendApp`
80+
81+
```ts
82+
import { getLogger } from "@vue-storefront/middleware";
83+
84+
const someExtension = {
85+
name: "some-extension",
86+
extendApp(params) {
87+
const logger = getLogger(params);
88+
89+
logger.info(
90+
"You can call a logger inside extendApp hook, called on bootstrap of the application"
91+
);
92+
},
93+
};
94+
```
95+
96+
### Hooks
97+
98+
Logger is available in hooks factory:
99+
100+
```ts
101+
import { getLogger } from "@vue-storefront/middleware";
102+
103+
const paypalExtension = {
104+
name: "sapcc-paypal-extension",
105+
hooks(req, res, alokai) {
106+
const logger = getLogger(alokai);
107+
logger.info(
108+
"You can call a logger every time a hooks factory gets invoked"
109+
);
110+
return {
111+
// ...
112+
};
113+
},
114+
};
115+
```
116+
117+
In order, to use logger in certain hooks like `beforeCall`, `beforeCreate`, `afterCall`, `afterCreate` obtain it from it's params:
118+
119+
```ts
120+
import { getLogger } from "@vue-storefront/middleware";
121+
122+
const paypalExtension = {
123+
name: "sapcc-paypal-extension",
124+
hooks(req, res, alokai) {
125+
return {
126+
beforeCall(params) {
127+
const logger = getLogger(params);
128+
logger.info("You can log every time a beforeCall hook gets invoked");
129+
return params.args;
130+
},
131+
beforeCreate(params) {
132+
const logger = getLogger(params);
133+
logger.info("You can log every time a beforeCreate hook gets invoked");
134+
return params.configuration;
135+
},
136+
afterCall(params) {
137+
const logger = getLogger(params);
138+
logger.info("You can log every time a afterCall hook gets invoked");
139+
return params.response;
140+
},
141+
afterCreate(params) {
142+
const logger = getLogger(params);
143+
logger.info("You can log every time a afterCreate hook gets invoked");
144+
return params.configuration;
145+
},
146+
};
147+
},
148+
};
149+
```
150+
151+
#### Caveat: Accessing logger via closure
152+
153+
Consider the following snippet:
154+
155+
```ts
156+
import { getLogger } from "@vue-storefront/middleware";
157+
158+
const someExtension = {
159+
name: "some-extension",
160+
hooks(req, res, alokai) {
161+
const hooksLogger = getLogger(alokai);
162+
hooksLogger.info(
163+
"You can call a logger every time a hooks factory gets invoked"
164+
);
165+
return {
166+
beforeCall(params) {
167+
// Never access via closure a logger belonging to the hooks factory:
168+
hooksLogger.info("Don't do that!");
169+
// Instead use own logger of every hook function:
170+
const logger = getLogger(params);
171+
logger.info("Do that!");
172+
return params.args;
173+
},
174+
};
175+
},
176+
};
177+
```
178+
179+
:::warning
180+
Attempt of using `hooksLogger` inside `beforeCall` or other hooks via closure corrupts information about scope of call of the log. Always use logger provided in params to the hook.
181+
:::
182+
183+
### extendApiMethods
184+
185+
Inside extended api methods, obtain logger from `context` using `getLogger` function.
186+
187+
```ts
188+
import { getLogger } from "@vue-storefront/middleware";
189+
190+
const testingExtension = {
191+
name: "some-extension",
192+
extendApiMethods: {
193+
addedCustomEndpoint(context) {
194+
const logger = getLogger(context);
195+
logger.info("You can log inside newly created handler!");
196+
return {
197+
// ...
198+
};
199+
},
200+
},
201+
};
202+
```
203+
204+
:::tip
205+
You can derive logger from context the same way if you are creating an integration.
206+
:::
207+
208+
### onCreate
209+
210+
The hook got a new parameter from which you can derive the logger with help of `getLogger` function.
211+
212+
```ts
213+
import { type AlokaiContainer, getLogger } from "@vue-storefront/middleware";
214+
215+
const onCreate = async (
216+
config: Record<string, unknown> = {},
217+
alokai: AlokaiContainer
218+
) => {
219+
const logger = getLogger(alokai);
220+
logger.info("You can log inside onCreate when creating a new integration");
221+
222+
return {
223+
// ...
224+
};
225+
};
226+
```
227+
228+
## Configuration
229+
230+
The middleware logger offers flexible configuration options to control logging behavior across the application. These options allow you to manage the verbosity and level of detail in logs based on the needs of different environments, such as development or production.
231+
232+
### Available Configuration Options
233+
234+
```ts
235+
/**
236+
* Options for the logger.
237+
*/
238+
export interface LoggerOptions {
239+
/**
240+
* The log level aligned with RFC5424.
241+
*/
242+
verbosity?: LogVerbosity; // (def. "info")
243+
244+
/**
245+
* Whether to include the stack trace in the log message.
246+
*/
247+
includeStackTrace?: boolean; // (def. true)
248+
}
249+
```
250+
251+
#### 1. Verbosity
252+
253+
This option sets the log verbosity level based on the [RFC 5424](https://datatracker.ietf.org/doc/html/rfc5424) syslog standard. It defines the severity of log messages that should be recorded. Available log levels are:
254+
255+
- **emergency**: The highest severity level, indicating a system-wide emergency.
256+
- **alert**: Indicates an urgent condition that requires immediate attention.
257+
- **critical**: Highlights critical issues that need immediate action.
258+
- **error**: Used to log error messages that could affect functionality.
259+
- **warning**: Logs warnings about potential issues that should be monitored.
260+
- **notice**: Records significant but non-critical events.
261+
- **info**: Logs general informational messages indicating normal operation.
262+
- **debug**: The most detailed log level, useful for tracing and debugging the application.
263+
264+
**Example:**
265+
Setting the log verbosity level to `error` ensures only error messages and above (i.e., critical, alert, emergency) will be captured:
266+
267+
```json
268+
{
269+
"logger": {
270+
"verbosity": "error"
271+
}
272+
}
273+
```
274+
275+
For a development environment, you might prefer a more verbose log level like `debug`:
276+
277+
```json
278+
{
279+
"logger": {
280+
"verbosity": "debug"
281+
}
282+
}
283+
```
284+
285+
#### 2. includeStackTrace
286+
287+
This option specifies whether the stack trace should be included in the log messages. If set to `true`, stack traces will be included in error messages, which can be helpful during debugging. If set to `false`, logs will be more concise.
288+
289+
```json
290+
{
291+
"logger": {
292+
"includeStackTrace": true
293+
}
294+
}
295+
```
296+
297+
### Global configuration
298+
299+
To configure the logger globally, add a `logger` object to the top-level configuration of the middleware. This configuration will apply to all integrations and parts of the application unless specifically overridden. Here’s an example of a global configuration where the stack trace is included in the logs, and the log level is set to `debug`:
300+
301+
```js[middleware.config.js]
302+
export const config = {
303+
"logger": {
304+
"includeStackTrace": true,
305+
"verbosity": "debug"
306+
},
307+
// The rest of the middleware configuration
308+
"integrations": {
309+
// ...
310+
}
311+
}
312+
```
313+
314+
This global logger configuration ensures that all logs, regardless of the integration or scope, will follow these settings.
315+
316+
### Per integration configuration
317+
318+
If you need different logging settings for specific integrations, you can configure the logger separately within each integration. The logger configuration should be added at the same level as `location` and `configuration` keys within the integration’s object.
319+
320+
For example, here is how you would configure the logger for an integration with the key `commerce`:
321+
322+
```js[middleware.config.js]
323+
export const config = {
324+
"integrations": {
325+
"commerce": {
326+
"location": "@vsf-enterprise/sapcc-api/server",
327+
328+
"configuration": {
329+
// Configuration of integration itself
330+
}
331+
332+
// Configuration of the logger only for "commerce" integration
333+
"logger": {
334+
"includeStackTrace": true,
335+
"verbosity": "debug"
336+
},
337+
}
338+
}
339+
}
340+
```
341+
342+
In this case, the logging configuration applies only to the `commerce` integration, overriding the global settings if they exist. The logger configuration can vary for each integration, allowing you to customize the level of logging detail based on the needs of specific integrations.
343+
344+
This approach provides the flexibility to define global logging behavior while also giving control to fine-tune logging per integration, ensuring you capture the necessary details for debugging and monitoring in the most relevant areas.

0 commit comments

Comments
 (0)