@magek/mcp-server 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +25 -0
- package/dist/prompts/cqrs-flow.d.ts +15 -0
- package/dist/prompts/cqrs-flow.js +252 -0
- package/dist/prompts/troubleshooting.d.ts +15 -0
- package/dist/prompts/troubleshooting.js +239 -0
- package/dist/resources/cli-reference.d.ts +13 -0
- package/dist/resources/cli-reference.js +193 -0
- package/dist/resources/documentation.d.ts +18 -0
- package/dist/resources/documentation.js +62 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.js +127 -0
- package/dist/utils/docs-loader.d.ts +19 -0
- package/dist/utils/docs-loader.js +111 -0
- package/docs/advanced/custom-templates.md +96 -0
- package/docs/advanced/data-migrations.md +181 -0
- package/docs/advanced/environment-configuration.md +74 -0
- package/docs/advanced/framework-packages.md +17 -0
- package/docs/advanced/health/sensor-health.md +389 -0
- package/docs/advanced/instrumentation.md +135 -0
- package/docs/advanced/register.md +119 -0
- package/docs/advanced/sensor.md +10 -0
- package/docs/advanced/testing.md +96 -0
- package/docs/advanced/touch-entities.md +45 -0
- package/docs/architecture/command.md +367 -0
- package/docs/architecture/entity.md +214 -0
- package/docs/architecture/event-driven.md +30 -0
- package/docs/architecture/event-handler.md +108 -0
- package/docs/architecture/event.md +145 -0
- package/docs/architecture/notifications.md +54 -0
- package/docs/architecture/queries.md +207 -0
- package/docs/architecture/read-model.md +507 -0
- package/docs/contributing.md +349 -0
- package/docs/docs-index.json +200 -0
- package/docs/features/error-handling.md +204 -0
- package/docs/features/event-stream.md +35 -0
- package/docs/features/logging.md +81 -0
- package/docs/features/schedule-actions.md +44 -0
- package/docs/getting-started/ai-coding-assistants.md +181 -0
- package/docs/getting-started/coding.md +543 -0
- package/docs/getting-started/installation.md +143 -0
- package/docs/graphql.md +1213 -0
- package/docs/index.md +62 -0
- package/docs/introduction.md +58 -0
- package/docs/magek-arch.png +0 -0
- package/docs/magek-cli.md +67 -0
- package/docs/magek-logo.svg +1 -0
- package/docs/security/authentication.md +189 -0
- package/docs/security/authorization.md +242 -0
- package/docs/security/security.md +16 -0
- package/package.json +46 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Data Migrations"
|
|
3
|
+
group: "Advanced"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Migrations
|
|
7
|
+
|
|
8
|
+
Migrations are a mechanism for updating or transforming the schemas of events and entities as your system evolves. This allows you to make changes to your data model without losing or corrupting existing data. There are two types of migration tools available in Magek: schema migrations and data migrations.
|
|
9
|
+
|
|
10
|
+
* **Schema migrations** are used to incrementally upgrade an event or entity from a past version to the next. They are applied lazily, meaning that they are performed on-the-fly whenever an event or entity is loaded. This allows you to make changes to your data model without having to manually update all existing artifacts, and makes it possible to apply changes without running lengthy migration processes.
|
|
11
|
+
|
|
12
|
+
* **Data migrations**, on the other hand, behave as background processes that can actively change the existing values in the database for existing entities and read models. They are particularly useful for data migrations that cannot be performed automatically with schema migrations, or for updating existing read models after a schema change.
|
|
13
|
+
|
|
14
|
+
Together, schema and data migrations provide a flexible and powerful toolset for managing the evolution of your data model over time.
|
|
15
|
+
|
|
16
|
+
## Schema migrations
|
|
17
|
+
|
|
18
|
+
Magek handles classes annotated with `@SchemaMigration` as **schema migrations**. The migration functions defined inside will update an existing artifact (either an event or an entity) from a previous version to a newer one whenever that artifact is visited. Schema migrations are applied to events and entities lazily, meaning that they are only applied when the event or entity is loaded. This ensures that the migration process is non-disruptive and does not affect the performance of your system. Schema migrations are also performed on-the-fly and the results are not written back to the database, as events are not revisited once the next snapshot is written in the database.
|
|
19
|
+
|
|
20
|
+
For example, to upgrade a `Product` entity from version 1 to version 2, you can write the following migration class:
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
@SchemaMigration(Product)
|
|
24
|
+
export class ProductMigration {
|
|
25
|
+
@toVersion(2, { fromSchema: ProductV1, toSchema: ProductV2 })
|
|
26
|
+
public async changeNameFieldToDisplayName(old: ProductV1): Promise<ProductV2> {
|
|
27
|
+
return new ProductV2(
|
|
28
|
+
old.id,
|
|
29
|
+
old.sku,
|
|
30
|
+
old.name,
|
|
31
|
+
old.description,
|
|
32
|
+
old.price,
|
|
33
|
+
old.pictures,
|
|
34
|
+
old.deleted
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Notice that we've used the `@toVersion` decorator in the above example. This decorator not only tells Magek what schema upgrade this migration performs, it also informs it about the existence of a version, which is always an integer number. Magek will always use the latest version known to tag newly created artifacts, defaulting to 1 when no migrations are defined. This ensures that the schema of newly created events and entities is up-to-date and that they can be migrated as needed in the future.
|
|
41
|
+
|
|
42
|
+
The `@toVersion` decorator takes two parameters in addition to the version: `fromSchema` and `toSchema`. The fromSchema parameter is set to `ProductV1`, while the `toSchema` parameter is set to `ProductV2`. This tells Magek that the migration is updating the `Product` object from version 1 (as defined by the `ProductV1` schema) to version 2 (as defined by the `ProductV2` schema).
|
|
43
|
+
|
|
44
|
+
As Magek can easily read the structure of your classes, the schemas are described as plain classes that you can maintain as part of your code. The `ProductV1` class represents the schema of the previous version of the `Product` object with the properties and structure of the `Product` object as it was defined in version 1. The `ProductV2` class is an alias for the latest version of the Product object. You can use the `Product` class here, there's no difference, but it's a good practice to create an alias for clarity.
|
|
45
|
+
|
|
46
|
+
It's a good practice to define the schema classes (`ProductV1` and `ProductV2`) as non-exported classes in the same migration file. This allows you to see the changes made between versions and helps to understand how the migration works:
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
class ProductV1 {
|
|
50
|
+
public constructor(
|
|
51
|
+
public id: UUID,
|
|
52
|
+
readonly sku: string,
|
|
53
|
+
readonly name: string,
|
|
54
|
+
readonly description: string,
|
|
55
|
+
readonly price: Money,
|
|
56
|
+
readonly pictures: Array<Picture>,
|
|
57
|
+
public deleted: boolean = false
|
|
58
|
+
) {}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
class ProductV2 extends Product {}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
When you want to upgrade your artifacts from V2 to V3, you can add a new function decorated with `@toVersion` to the same migrations class. You're free to structure the code the way you want, but we recommend keeping all migrations for the same artifact in the same migration class. For instance:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
@SchemaMigration(Product)
|
|
68
|
+
export class ProductMigration {
|
|
69
|
+
@toVersion(2, { fromSchema: ProductV1, toSchema: ProductV2 })
|
|
70
|
+
public async changeNameFieldToDisplayName(old: ProductV1): Promise<ProductV2> {
|
|
71
|
+
return new ProductV2(
|
|
72
|
+
old.id,
|
|
73
|
+
old.sku,
|
|
74
|
+
old.name, // It's now called `displayName`
|
|
75
|
+
old.description,
|
|
76
|
+
old.price,
|
|
77
|
+
old.pictures,
|
|
78
|
+
old.deleted
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@toVersion(3, { fromSchema: ProductV2, toSchema: ProductV3 })
|
|
83
|
+
public async addNewField(old: ProductV2): Promise<ProductV3> {
|
|
84
|
+
return new ProductV3(
|
|
85
|
+
old.id,
|
|
86
|
+
old.sku,
|
|
87
|
+
old.displayName,
|
|
88
|
+
old.description,
|
|
89
|
+
old.price,
|
|
90
|
+
old.pictures,
|
|
91
|
+
old.deleted,
|
|
92
|
+
42 // We set a default value to initialize this field
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
In this example, the `changeNameFieldToDisplayName` function updates the `Product` entity from version 1 to version 2 by renaming the `name` field to `displayName`. Then, `addNewField` function updates the `Product` entity from version 2 to version 3 by adding a new field called `newField` to the entity's schema. Notice that at this point, your database could have snapshots set as v1, v2, or v3, so while it might be tempting to redefine the original migration to keep a single 1-to-3 migration, it's usually a good idea to keep the intermediate steps. This way Magek will be able to handle any scenario.
|
|
99
|
+
|
|
100
|
+
## Data migrations
|
|
101
|
+
|
|
102
|
+
Data migrations can be seen as background processes that can actively update the values of existing entities and read models in the database. They can be useful to perform data migrations that cannot be handled with schema migrations, for example when you need to update the values exposed by the GraphQL API, or to initialize new read models that are projections of previously existing entities.
|
|
103
|
+
|
|
104
|
+
To create a data migration in Magek, you can use the `@DataMigration` decorator on a class that implements a `start` method. The `@DataMigration` decorator takes an object with a single parameter, `order`, which specifies the order in which the data migration should be run relative to other data migrations.
|
|
105
|
+
|
|
106
|
+
Data migrations are not run automatically, you need to invoke the `MagekDataMigrations.run()` method from an event handler or a command. This will emit a `MagekDataMigrationStarted` event, which will make Magek check for any pending migrations and run them in the specified order. A common pattern to be able to run migrations on demand is to add a special command, with access limited to an administrator role which calls this function.
|
|
107
|
+
|
|
108
|
+
It's advisable to design these functions in a way that allows re-running them in case of failures. In order to tell Magek that your migration has been applied successfully, at the end of each `DataMigration.start` method, you must emit a `MagekDataMigrationFinished` event manually.
|
|
109
|
+
|
|
110
|
+
Inside your `@DataMigration` classes, you can use the `MagekDataMigrations.migrateEntity` method to update the data for a specific entity. This method takes the old entity name, the old entity ID, and the new entity data as arguments. It will also generate an internal `MagekEntityMigrated` event before performing the migration.
|
|
111
|
+
|
|
112
|
+
Here is an example of how you might use the `@DataMigration` decorator and the `Magek.migrateEntity` method to update the quantity of the first item in a cart:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
@DataMigration({
|
|
116
|
+
order: 2,
|
|
117
|
+
})
|
|
118
|
+
export class CartIdDataMigrateV2 {
|
|
119
|
+
public constructor() {}
|
|
120
|
+
|
|
121
|
+
public static async start(register: Register): Promise<void> {
|
|
122
|
+
const entitiesIdsResult = await Magek.entitiesIDs('Cart', 500, undefined)
|
|
123
|
+
const paginatedEntityIdResults = entitiesIdsResult.items
|
|
124
|
+
|
|
125
|
+
const carts = await Promise.all(
|
|
126
|
+
paginatedEntityIdResults.map(async (entity) => await Magek.entity(Cart, entity.entityID))
|
|
127
|
+
)
|
|
128
|
+
return await Promise.all(
|
|
129
|
+
carts.map(async (cart) => {
|
|
130
|
+
cart.cartItems[0].quantity = 100
|
|
131
|
+
const newCart = new Cart(cart.id, cart.cartItems, cart.shippingAddress, cart.checks)
|
|
132
|
+
await MagekDataMigrations.migrateEntity('Cart', validCart.id, newCart)
|
|
133
|
+
return validCart.id
|
|
134
|
+
})
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
register.events(new MagekDataMigrationFinished('CartIdDataMigrateV2'))
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
# Migrate from Previous Magek Versions
|
|
143
|
+
|
|
144
|
+
* To migrate to new versions of Magek, check that you have the latest development dependencies required:
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
"devDependencies": {
|
|
148
|
+
"rimraf": "^5.0.0",
|
|
149
|
+
"@typescript-eslint/eslint-plugin": "4.22.1",
|
|
150
|
+
"@typescript-eslint/parser": "4.22.1",
|
|
151
|
+
"eslint": "7.26.0",
|
|
152
|
+
"eslint-config-prettier": "8.3.0",
|
|
153
|
+
"eslint-plugin-prettier": "3.4.0",
|
|
154
|
+
"mocha": "10.2.0",
|
|
155
|
+
"@types/mocha": "10.0.1",
|
|
156
|
+
"nyc": "15.1.0",
|
|
157
|
+
"prettier": "2.3.0",
|
|
158
|
+
"typescript": "4.5.4",
|
|
159
|
+
"ts-node": "9.1.1",
|
|
160
|
+
"@types/node": "15.0.2",
|
|
161
|
+
"ts-patch": "3.1.2",
|
|
162
|
+
"@magek/metadata": "0.30.2"
|
|
163
|
+
},
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Migrate to Magek version 1.19.0
|
|
167
|
+
|
|
168
|
+
Magek version 1.19.0 requires updating your index.ts file to export the `health` method. If you have an index.ts file created from a previous Magek version, update it accordingly. Example:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
export {
|
|
172
|
+
Magek,
|
|
173
|
+
eventDispatcher,
|
|
174
|
+
graphQLDispatcher,
|
|
175
|
+
health,
|
|
176
|
+
notifySubscribers,
|
|
177
|
+
triggerScheduledCommands,
|
|
178
|
+
} from '@magek/core'
|
|
179
|
+
|
|
180
|
+
Magek.start(__dirname)
|
|
181
|
+
```
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Environment Configuration"
|
|
3
|
+
group: "Advanced"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Environments
|
|
7
|
+
|
|
8
|
+
You can create multiple environments calling the `Magek.configure` function several times using different environment names as the first argument. You can create one file for each environment, but it is not required. In this example we set all environments in a single file:
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
// Here we use a single file called src/config.ts, but you can use separate files for each environment too.
|
|
12
|
+
|
|
13
|
+
Magek.configure('stage', (config: MagekConfig): void => {
|
|
14
|
+
config.appName = 'fruit-store-stage'
|
|
15
|
+
config.runtime = ServerRuntime
|
|
16
|
+
config.eventStoreAdapter = eventStore
|
|
17
|
+
config.readModelStoreAdapter = readModelStore
|
|
18
|
+
config.sessionStoreAdapter = sessionStore
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
Magek.configure('prod', (config: MagekConfig): void => {
|
|
22
|
+
config.appName = 'fruit-store-prod'
|
|
23
|
+
config.runtime = ServerRuntime
|
|
24
|
+
config.eventStoreAdapter = eventStore
|
|
25
|
+
config.readModelStoreAdapter = readModelStore
|
|
26
|
+
config.sessionStoreAdapter = sessionStore
|
|
27
|
+
})
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Pluggable Adapters
|
|
31
|
+
|
|
32
|
+
Magek uses a pluggable architecture for data storage, allowing you to choose the most appropriate storage solution for your needs. The framework provides several adapter types:
|
|
33
|
+
|
|
34
|
+
### Event Store Adapters
|
|
35
|
+
Event store adapters handle the storage and retrieval of events in your event-sourced system:
|
|
36
|
+
|
|
37
|
+
- `@magek/adapter-event-store-nedb` - A lightweight, file-based adapter perfect for development and testing
|
|
38
|
+
|
|
39
|
+
### Read Model Store Adapters
|
|
40
|
+
Read model store adapters manage the storage of read models (projections of your domain state):
|
|
41
|
+
|
|
42
|
+
- `@magek/adapter-read-model-store-nedb` - A lightweight, file-based adapter perfect for development and testing
|
|
43
|
+
|
|
44
|
+
### Session Store Adapters
|
|
45
|
+
Session store adapters handle WebSocket connections and subscription management:
|
|
46
|
+
|
|
47
|
+
- `@magek/adapter-session-store-nedb` - A lightweight, file-based adapter perfect for development and testing
|
|
48
|
+
|
|
49
|
+
This modular approach allows you to:
|
|
50
|
+
- Start development quickly with simple file-based stores
|
|
51
|
+
- Switch to production-grade databases without changing your application code
|
|
52
|
+
- Create custom adapters for specific requirements
|
|
53
|
+
- Test your application with different storage backends
|
|
54
|
+
|
|
55
|
+
To use adapters, simply import them and assign them to the corresponding configuration properties (`config.eventStoreAdapter`, `config.readModelStoreAdapter`, `config.sessionStoreAdapter`) in your environment configuration.
|
|
56
|
+
|
|
57
|
+
## Environment Files
|
|
58
|
+
|
|
59
|
+
It is also possible to place an environment configuration in a separated file. Let's say that a developer called "John" created its own configuration file `src/config/john.ts`. The content would be the following:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
|
|
63
|
+
Magek.configure('john', (config: MagekConfig): void => {
|
|
64
|
+
config.appName = 'john-fruit-store'
|
|
65
|
+
config.runtime = ServerRuntime
|
|
66
|
+
config.eventStoreAdapter = eventStore
|
|
67
|
+
config.readModelStoreAdapter = readModelStore
|
|
68
|
+
config.sessionStoreAdapter = sessionStore
|
|
69
|
+
})
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
This way, you can have different configurations depending on your needs.
|
|
73
|
+
|
|
74
|
+
Magek environments are extremely flexible. As shown in the first example, your 'fruit-store' app can have three team-wide environments: 'dev', 'stage', and 'prod', each of them with different app names or configurations. Developers, like "John" in the second example, can create their own private environments in separate config files to test their changes before committing them.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Framework Packages"
|
|
3
|
+
group: "Advanced"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Framework packages
|
|
7
|
+
The framework is already splitted into different packages:
|
|
8
|
+
|
|
9
|
+
## Framework Core
|
|
10
|
+
|
|
11
|
+
The `framework-core` package includes the most important components of the framework abstraction. It can be seen as skeleton or the main architecture of the framework.
|
|
12
|
+
|
|
13
|
+
The package defines the specification of how should a Magek application work without taking into account the specific providers that could be used. Every Magek provider package is based on the components that the framework core needs in order to work on the platform.
|
|
14
|
+
|
|
15
|
+
## Common
|
|
16
|
+
|
|
17
|
+
The `common` package includes the types that define the domain of the Magek framework. It defines domain concepts like an `Event`, a `Command` or a `Role`.
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Sensor Health"
|
|
3
|
+
group: "Advanced"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Health
|
|
7
|
+
|
|
8
|
+
The Health functionality allows users to easily monitor the health status of their applications. With this functionality, users can make GET requests to a specific endpoint and retrieve detailed information about the health and status of their application components.
|
|
9
|
+
|
|
10
|
+
### Enabling Health Functionality
|
|
11
|
+
|
|
12
|
+
To enable the Health functionality in your Magek application, follow these steps:
|
|
13
|
+
|
|
14
|
+
1. Install or update to the latest version of the Magek framework, ensuring compatibility with the Health functionality.
|
|
15
|
+
2. Enable the Magek Health endpoints in your application's configuration file. Example configuration in config.ts:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
|
|
19
|
+
Magek.configure('local', (config: MagekConfig): void => {
|
|
20
|
+
config.appName = 'my-store'
|
|
21
|
+
config.runtime = ServerRuntime
|
|
22
|
+
Object.values(config.sensorConfiguration.health.magek).forEach((indicator) => {
|
|
23
|
+
indicator.enabled = true
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or enable only the components you want:
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
Magek.configure('local', (config: MagekConfig): void => {
|
|
32
|
+
config.appName = 'my-store'
|
|
33
|
+
config.runtime = ServerRuntime
|
|
34
|
+
const sensors = config.sensorConfiguration.health.magek
|
|
35
|
+
sensors[HEALTH_INDICATORS_IDS.DATABASE].enabled = true
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
3. Optionally, implement health checks for your application components. Each component should provide a health method that performs the appropriate checks and returns a response indicating the health status. Example:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import {
|
|
43
|
+
MagekConfig,
|
|
44
|
+
HealthIndicatorResult,
|
|
45
|
+
HealthIndicatorMetadata,
|
|
46
|
+
HealthStatus,
|
|
47
|
+
} from '@magek/common'
|
|
48
|
+
|
|
49
|
+
@HealthSensor({
|
|
50
|
+
id: 'application',
|
|
51
|
+
name: 'my-application',
|
|
52
|
+
enabled: true,
|
|
53
|
+
details: true,
|
|
54
|
+
showChildren: true,
|
|
55
|
+
})
|
|
56
|
+
export class ApplicationHealthIndicator {
|
|
57
|
+
public async health(
|
|
58
|
+
config: MagekConfig,
|
|
59
|
+
healthIndicatorMetadata: HealthIndicatorMetadata
|
|
60
|
+
): Promise<HealthIndicatorResult> {
|
|
61
|
+
return {
|
|
62
|
+
status: HealthStatus.UP,
|
|
63
|
+
} as HealthIndicatorResult
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
4. A health check typically involves verifying the connectivity and status of the component, running any necessary tests, and returning an appropriate status code.
|
|
69
|
+
5. Start or restart your Magek application. The Health functionality will be available at the <https://your-application-url/sensor/health/> endpoint URL.
|
|
70
|
+
|
|
71
|
+
### Health Endpoint
|
|
72
|
+
|
|
73
|
+
The Health functionality provides a dedicated endpoint where users can make GET requests to retrieve the health status of their application. The endpoint URL is: <https://your-application-url/sensor/health/>
|
|
74
|
+
|
|
75
|
+
This endpoint will return all the enabled Magek and application components health status. To get specific component health status, add the component status to the url. For example, to get the events status use: <https://your-application-url/sensor/health/magek/database/events>
|
|
76
|
+
|
|
77
|
+
#### Available endpoints
|
|
78
|
+
|
|
79
|
+
Magek provides the following endpoints to retrieve the enabled components:
|
|
80
|
+
|
|
81
|
+
- <https://your-application-url/sensor/health/>: All the components status
|
|
82
|
+
- <https://your-application-url/sensor/health/magek>: Magek status
|
|
83
|
+
- <https://your-application-url/sensor/health/magek/database>: Database status
|
|
84
|
+
- <https://your-application-url/sensor/health/magek/database/events>: Events status
|
|
85
|
+
- <https://your-application-url/sensor/health/magek/database/readmodels>: ReadModels status
|
|
86
|
+
- <https://your-application-url/sensor/health/magek/function>: Functions status
|
|
87
|
+
- <https://your-application-url/sensor/health/your-component-id>: User defined status
|
|
88
|
+
- <https://your-application-url/sensor/health/your-component-id/your-component-child-id>: User child component status
|
|
89
|
+
|
|
90
|
+
Depending on the `showChildren` configuration, child components will be included or not.
|
|
91
|
+
|
|
92
|
+
### Health Status Response
|
|
93
|
+
|
|
94
|
+
Each component response will contain the following information:
|
|
95
|
+
|
|
96
|
+
- status: The component or subsystem status
|
|
97
|
+
- name: component description
|
|
98
|
+
- id: string. unique component identifier. You can request a component status using the id in the url
|
|
99
|
+
- details: optional object. If `details` is enabled, specific details about this component.
|
|
100
|
+
- components: optional object. If `showChildren` is enabled, child components health status.
|
|
101
|
+
|
|
102
|
+
Example:
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
[
|
|
106
|
+
{
|
|
107
|
+
"status": "UP",
|
|
108
|
+
"details": {
|
|
109
|
+
"urls": [
|
|
110
|
+
"dbs/my-store-app"
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
"name": "Magek Database",
|
|
114
|
+
"id": "magek/database",
|
|
115
|
+
"components": [
|
|
116
|
+
{
|
|
117
|
+
"status": "UP",
|
|
118
|
+
"details": {
|
|
119
|
+
"url": "dbs/my-store-app/colls/my-store-app-events-store",
|
|
120
|
+
"count": 6
|
|
121
|
+
},
|
|
122
|
+
"name": "Magek Database Events",
|
|
123
|
+
"id": "magek/database/events"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"status": "UP",
|
|
127
|
+
"details": [
|
|
128
|
+
{
|
|
129
|
+
"url": "dbs/my-store-app/colls/my-store-app-ProductReadModel",
|
|
130
|
+
"count": 1
|
|
131
|
+
}
|
|
132
|
+
],
|
|
133
|
+
"name": "Magek Database ReadModels",
|
|
134
|
+
"id": "magek/database/readmodels"
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### HTTP Status Codes
|
|
142
|
+
|
|
143
|
+
The health endpoint returns different HTTP status codes based on the overall health of the application:
|
|
144
|
+
|
|
145
|
+
- 200 OK: All components are healthy (UP)
|
|
146
|
+
- 503 Service Unavailable: One or more components are unhealthy (DOWN or PARTIALLY_UP)
|
|
147
|
+
|
|
148
|
+
### Get specific component health information
|
|
149
|
+
|
|
150
|
+
Use the `id` field to get specific component health information. Magek provides the following ids:
|
|
151
|
+
|
|
152
|
+
- magek
|
|
153
|
+
- magek/function
|
|
154
|
+
- magek/database
|
|
155
|
+
- magek/database/events
|
|
156
|
+
- magek/database/readmodels
|
|
157
|
+
|
|
158
|
+
You can provide new components:
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
@HealthSensor({
|
|
162
|
+
id: 'application',
|
|
163
|
+
})
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
@HealthSensor({
|
|
168
|
+
id: 'application/child',
|
|
169
|
+
})
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Add your own components to Magek:
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
@HealthSensor({
|
|
176
|
+
id: `${HEALTH_INDICATORS_IDS.DATABASE}/extra`,
|
|
177
|
+
})
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Or override Magek existing components with your own implementation:
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
@HealthSensor({
|
|
184
|
+
id: HEALTH_INDICATORS_IDS.DATABASE,
|
|
185
|
+
})
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Health configuration
|
|
189
|
+
|
|
190
|
+
Health components are fully configurable, allowing you to display the information you want at any moment.
|
|
191
|
+
|
|
192
|
+
Configuration options:
|
|
193
|
+
- enabled: If false, this indicator and the components of this indicator will be skipped
|
|
194
|
+
- details: If false, the indicator will not include the details
|
|
195
|
+
- showChildren: If false, this indicator will not include child components in the tree.
|
|
196
|
+
- Child components will be shown through child urls
|
|
197
|
+
- authorize: Authorize configuration. [See security documentation](https://docs.magek.ai/security/security)
|
|
198
|
+
|
|
199
|
+
#### Magek components default configuration
|
|
200
|
+
|
|
201
|
+
Magek sets the following default configuration for its own components:
|
|
202
|
+
|
|
203
|
+
- enabled: false
|
|
204
|
+
- details: true
|
|
205
|
+
- showChildren: true
|
|
206
|
+
|
|
207
|
+
Change this configuration using the `config.sensorConfiguration` object. This object provides:
|
|
208
|
+
|
|
209
|
+
- config.sensorConfiguration.health.globalAuthorizer: Allow to define authorization configuration
|
|
210
|
+
- config.sensorConfiguration.health.magek: Allow to override default Magek components configuration
|
|
211
|
+
- config.sensorConfiguration.health.magek[COMPONENT_ID].enabled
|
|
212
|
+
- config.sensorConfiguration.health.magek[COMPONENT_ID].details
|
|
213
|
+
- config.sensorConfiguration.health.magek[COMPONENT_ID].showChildren
|
|
214
|
+
|
|
215
|
+
#### User components configuration
|
|
216
|
+
|
|
217
|
+
Use `@HealthSensor` parameters to configure user components. Example:
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
@HealthSensor({
|
|
221
|
+
id: 'user',
|
|
222
|
+
name: 'my-application',
|
|
223
|
+
enabled: true,
|
|
224
|
+
details: true,
|
|
225
|
+
showChildren: true,
|
|
226
|
+
})
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Create your own health endpoint
|
|
230
|
+
|
|
231
|
+
Create your own health endpoint with a class annotated with `@HealthSensor` decorator. This class
|
|
232
|
+
should define a `health` method that returns a **HealthIndicatorResult**. Example:
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
import {
|
|
236
|
+
MagekConfig,
|
|
237
|
+
HealthIndicatorResult,
|
|
238
|
+
HealthIndicatorMetadata,
|
|
239
|
+
HealthStatus,
|
|
240
|
+
} from '@magek/common'
|
|
241
|
+
|
|
242
|
+
@HealthSensor({
|
|
243
|
+
id: 'application',
|
|
244
|
+
name: 'my-application',
|
|
245
|
+
enabled: true,
|
|
246
|
+
details: true,
|
|
247
|
+
showChildren: true,
|
|
248
|
+
})
|
|
249
|
+
export class ApplicationHealthIndicator {
|
|
250
|
+
public async health(
|
|
251
|
+
config: MagekConfig,
|
|
252
|
+
healthIndicatorMetadata: HealthIndicatorMetadata
|
|
253
|
+
): Promise<HealthIndicatorResult> {
|
|
254
|
+
return {
|
|
255
|
+
status: HealthStatus.UP,
|
|
256
|
+
} as HealthIndicatorResult
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Magek health endpoints
|
|
262
|
+
|
|
263
|
+
#### magek
|
|
264
|
+
|
|
265
|
+
- status: UP if and only if graphql function is UP and events are UP
|
|
266
|
+
- details:
|
|
267
|
+
- magekVersion: Magek version number
|
|
268
|
+
|
|
269
|
+
#### magek/function
|
|
270
|
+
|
|
271
|
+
- status: UP if and only if graphql function is UP
|
|
272
|
+
- details:
|
|
273
|
+
- graphQL_url: GraphQL function url
|
|
274
|
+
- cpus: Information about each logical CPU core.
|
|
275
|
+
- cpu:
|
|
276
|
+
- model: Cpu model. Example: AMD EPYC 7763 64-Core Processor
|
|
277
|
+
- speed: cpu speed in MHz
|
|
278
|
+
- times: The number of milliseconds the CPU/core spent in (see iostat)
|
|
279
|
+
- user: CPU utilization that occurred while executing at the user level (application)
|
|
280
|
+
- nice: CPU utilization that occurred while executing at the user level with nice priority.
|
|
281
|
+
- sys: CPU utilization that occurred while executing at the system level (kernel).
|
|
282
|
+
- idle: CPU or CPUs were idle and the system did not have an outstanding disk I/O request.
|
|
283
|
+
- irq: CPU load system
|
|
284
|
+
- timesPercentages: For each times value, the percentage over the total times
|
|
285
|
+
- memory:
|
|
286
|
+
- totalBytes: the total amount of system memory in bytes as an integer.
|
|
287
|
+
- freeBytes: the amount of free system memory in bytes as an integer.
|
|
288
|
+
|
|
289
|
+
#### magek/database
|
|
290
|
+
|
|
291
|
+
- status: UP if and only if events are UP and Read Models are UP
|
|
292
|
+
- details:
|
|
293
|
+
- urls: Database urls
|
|
294
|
+
|
|
295
|
+
#### magek/database/events
|
|
296
|
+
|
|
297
|
+
- status: UP if and only if events are UP
|
|
298
|
+
- details:
|
|
299
|
+
- file: event database file
|
|
300
|
+
- count: number of rows
|
|
301
|
+
|
|
302
|
+
#### magek/database/readmodels
|
|
303
|
+
|
|
304
|
+
- status: UP if and only if Read Models are UP
|
|
305
|
+
- details:
|
|
306
|
+
- file: Read Models database file
|
|
307
|
+
- count: number of total rows
|
|
308
|
+
|
|
309
|
+
> **Note:**
|
|
310
|
+
> Details will be included only if `details` is enabled
|
|
311
|
+
|
|
312
|
+
### Health status
|
|
313
|
+
|
|
314
|
+
Available status are
|
|
315
|
+
|
|
316
|
+
- UP: The component or subsystem is working as expected
|
|
317
|
+
- PARTIALLY_UP: The component is partially working or has reduced functionality
|
|
318
|
+
- DOWN: The component is not working
|
|
319
|
+
- OUT_OF_SERVICE: The component is out of service temporarily
|
|
320
|
+
- UNKNOWN: The component state is unknown
|
|
321
|
+
|
|
322
|
+
If a component throw an exception the status will be DOWN
|
|
323
|
+
|
|
324
|
+
### Securing health endpoints
|
|
325
|
+
|
|
326
|
+
To configure the health endpoints authorization use `config.sensorConfiguration.health.globalAuthorizer`.
|
|
327
|
+
|
|
328
|
+
Example:
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
config.sensorConfiguration.health.globalAuthorizer = {
|
|
332
|
+
authorize: 'all',
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
If the authorization process fails, the health endpoint will return a 401 error code
|
|
337
|
+
|
|
338
|
+
### Example
|
|
339
|
+
|
|
340
|
+
If all components are enable and showChildren is set to true:
|
|
341
|
+
|
|
342
|
+
- A Request to <https://your-application-url/sensor/health/> will return:
|
|
343
|
+
|
|
344
|
+
```text
|
|
345
|
+
├── magek
|
|
346
|
+
│ ├── database
|
|
347
|
+
│ ├── events
|
|
348
|
+
│ └── readmodels
|
|
349
|
+
└ └── function
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
If the database component is disabled, the same url will return:
|
|
353
|
+
|
|
354
|
+
```text
|
|
355
|
+
├── magek
|
|
356
|
+
└ └── function
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
If the request url is <https://your-application-url/sensor/health/database>, the component will not be returned
|
|
360
|
+
|
|
361
|
+
```text
|
|
362
|
+
[Empty]
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
And the child components will be disabled too using direct url <https://your-application-url/sensor/health/database/events>
|
|
366
|
+
|
|
367
|
+
```text
|
|
368
|
+
[Empty]
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
If database is enabled and showChildren is set to false and using <https://your-application-url/sensor/health/>
|
|
372
|
+
|
|
373
|
+
```text
|
|
374
|
+
├── magek
|
|
375
|
+
│ ├── database
|
|
376
|
+
│ └── function
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
using <https://your-application-url/sensor/health/database>, children will not be visible
|
|
380
|
+
|
|
381
|
+
```text
|
|
382
|
+
└── database
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
but you can access to them using the component url <https://your-application-url/sensor/health/database/events>
|
|
386
|
+
|
|
387
|
+
```text
|
|
388
|
+
└── events
|
|
389
|
+
```
|