Skip to content

Commit f492017

Browse files
Merge pull request #44 from opencomponents/docs-local-mode-and-component-logging
Document local mode correctly and component logging via plugins
2 parents 18e4f3f + 3f89841 commit f492017

2 files changed

Lines changed: 125 additions & 12 deletions

File tree

website/docs/reference/faq.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,14 @@ oc preview http://localhost:3030/your-component
156156
3. **CORS issues** - Verify cross-origin settings
157157
4. **SSL/HTTPS** - Ensure proper SSL configuration
158158

159+
### Why don't I see `console.log` from my component outside `oc dev`?
160+
161+
In local development (`oc dev`), the registry runs with `local: true` and forwards component `console.*` calls to the process console. On a normal (non-local) registry — including staging and production with remote storage — those calls are discarded.
162+
163+
This is by design. `local` is **not** a "use filesystem storage" flag you can flip in lower environments to get logs back. Setting `local: true` on a deployed registry also disables publishing and changes other production behaviour.
164+
165+
For intentional logging in any environment, register a logging plugin and call it from `server.js`. See [Logging from components](../registry/registry-configuration#logging-from-components).
166+
159167
### Template compilation errors
160168

161169
**For ES6 templates (default):**

website/docs/registry/registry-configuration.md

Lines changed: 117 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,9 @@ For unsuscribing to all [events](#registry-events).
129129
| ------------------------- | ----------------- | --------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
130130
| <sub>discovery</sub> | boolean | no | `true` | Enables the HTML discovery page and `/components` endpoint |
131131
| <sub>discoveryFunc</sub> | function | no | - | Function to decide whether discovery should be enabled for the current request. Function signature: `(opts: { host?: string; secure: boolean }) => boolean` |
132-
| <sub>local</sub> | boolean | no | - | Indicates whether the registry serves components from the local file system (`true`) or from remote storage (`false`) |
133-
| <sub>path</sub> | string | no | - | Absolute path where local components are stored (used when `local` is `true`) |
134-
| <sub>hotReloading</sub> | boolean | no | `!!local` | Enables hot-reloading of component code. Always `true` when `local` is `true` |
132+
| <sub>local</sub> | boolean | no | - | Enables **local development mode** (what `oc dev` sets). Not a storage selector — see [Local development mode](#local-development-mode) |
133+
| <sub>path</sub> | string | no | - | Absolute path where local components are stored (required when `local` is `true`) |
134+
| <sub>hotReloading</sub> | boolean | no | `!!local` | Enables hot-reloading of component code. Defaults to `true` when `local` is `true` |
135135
| <sub>liveReloadPort</sub> | number | no | - | TCP port of the LiveReload server used by the preview page |
136136
| <sub>compileClient</sub> | boolean or object | no | `true` | Set options for the oc-client-browser compilation. Set to `false` to disable client compilation, or provide options object for custom compilation settings |
137137

@@ -255,6 +255,8 @@ registry.start();
255255

256256
### Local Development Configuration
257257

258+
Prefer `oc dev` over hand-rolling this. The CLI starts a registry with `local: true` and the right defaults for day-to-day component work.
259+
258260
```js
259261
var oc = require("oc");
260262

@@ -274,6 +276,22 @@ var registry = new oc.Registry(configuration);
274276
registry.start();
275277
```
276278

279+
#### Local development mode
280+
281+
`local: true` turns on **local development mode**. It is **not** a toggle between "filesystem storage" and "remote storage" that you would flip in staging or production.
282+
283+
When `local` is `true`, the registry:
284+
285+
- Serves components from a local directory (`path`) instead of a storage adapter
286+
- **Disables publishing** — components cannot be published to a local registry
287+
- Enables hot-reloading of component code (unless you override `hotReloading`)
288+
- Forwards component `console.*` calls to the process console (so `console.log` in `server.js` is visible while developing)
289+
- Sets `NODE_ENV` to `development` inside the component sandbox
290+
- Surfaces richer server-side error details (including processed stack frames) in responses and logs
291+
- Skips storage/metadata validation that production registries require
292+
293+
Do **not** set `local: true` on a deployed registry to get component logs or filesystem-like behaviour. You will lose publishing and change other production semantics. For intentional logging outside `oc dev`, use a [logging plugin](#logging-from-components).
294+
277295
### Custom Storage Adapter Configuration
278296

279297
```js
@@ -462,14 +480,11 @@ module.exports.execute = function (context) {
462480
return connection.get(featureName);
463481
};
464482
};
465-
466-
// Enable context awareness
467-
module.exports.context = true;
468483
```
469484

470485
### Plugin Registration
471486

472-
This is how to register plugins in a registry:
487+
This is how to register plugins in a registry. Context awareness is enabled with `context: true` on the **registration** object (not on the plugin module):
473488

474489
```js
475490
// ./registry/init.js
@@ -488,6 +503,7 @@ registry.register({
488503
// Register a context-aware plugin
489504
registry.register({
490505
name: "getSecureFeature",
506+
context: true,
491507
register: require("./oc-plugins/feature-flags"),
492508
options: {
493509
connectionString: connectionString,
@@ -512,6 +528,78 @@ module.exports.data = function (context, callback) {
512528
};
513529
```
514530

531+
### Logging from components
532+
533+
Outside `oc dev`, component `console.log` / `console.error` / etc. are discarded. That is intentional: the registry sandbox does not ship every component's unstructured console output into production process logs.
534+
535+
`local: true` is not a production logging switch (see [Local development mode](#local-development-mode)). For logging in staging or production, register a plugin and call it from `server.js`.
536+
537+
A minimal context-aware logger:
538+
539+
```js
540+
// ./registry/oc-plugins/log.js
541+
var logger;
542+
543+
module.exports.register = function (options, dependencies, next) {
544+
// options.logger is your real logger (pino, winston, Datadog client, ...)
545+
logger = options.logger;
546+
next();
547+
};
548+
549+
// With context: true on registry.register(...), execute receives component
550+
// context and returns the function exposed as context.plugins.log(...)
551+
module.exports.execute = function (context) {
552+
return function (level, message, meta) {
553+
logger[level]({
554+
component: context.name,
555+
version: context.version,
556+
message: message,
557+
...(meta || {}),
558+
});
559+
};
560+
};
561+
```
562+
563+
Register it on the registry (note `context: true` on the registration object):
564+
565+
```js
566+
registry.register({
567+
name: "log",
568+
context: true,
569+
register: require("./oc-plugins/log"),
570+
options: {
571+
logger: myLogger, // your structured logger
572+
},
573+
});
574+
```
575+
576+
Declare and use it from the component:
577+
578+
```js
579+
// package.json (component)
580+
// "oc": { "plugins": ["log"] }
581+
582+
// server.js
583+
module.exports.data = function (context, callback) {
584+
context.plugins.log("info", "fetching user", { id: context.params.userId });
585+
586+
// ...
587+
588+
callback(null, {
589+
/* view model */
590+
});
591+
};
592+
```
593+
594+
Why a plugin instead of turning on `console` in production:
595+
596+
- **Opt-in** — only components that call the plugin pay the cost
597+
- **Structured** — level, message, and metadata can go to your monitoring stack
598+
- **Scoped** — with `context: true`, every line can include component name and version
599+
- **Controlled** — the registry owns sampling, redaction, and destinations
600+
601+
`verbosity` only controls the registry's own access/process logging. It does not enable component sandbox `console` output.
602+
515603
### When to Use Context Awareness
516604

517605
Context awareness is useful when you need to:
@@ -574,8 +662,16 @@ module.exports.execute = function (context) {
574662
}
575663
};
576664
};
665+
```
666+
667+
Register with `context: true`:
577668

578-
module.exports.context = true;
669+
```js
670+
registry.register({
671+
name: "advancedFeatureManager",
672+
context: true,
673+
register: require("./oc-plugins/advanced-feature-manager"),
674+
});
579675
```
580676

581677
### Plugin Dependencies
@@ -593,7 +689,7 @@ module.exports.register = function (options, dependencies, next) {
593689
// This register function is only called after all dependencies are registered
594690
client.connect(options.connectionString, function (err, conn) {
595691
connection = conn;
596-
dependencies.log("secure logger client initialized");
692+
dependencies.log.handler("secure logger client initialized");
597693
next();
598694
});
599695
};
@@ -612,8 +708,17 @@ module.exports.execute = function (context) {
612708
return connection.log(enrichedMessage);
613709
};
614710
};
711+
```
615712

616-
module.exports.context = true;
713+
```js
714+
registry.register({
715+
name: "secureLogger",
716+
context: true,
717+
register: require("./oc-plugins/secure-logger"),
718+
options: {
719+
connectionString: connectionString,
720+
},
721+
});
617722
```
618723

619724
### Plugin Configuration Options
@@ -623,11 +728,11 @@ module.exports.context = true;
623728
| `name` | string | yes | - | Unique identifier for the plugin |
624729
| `register` | object | yes | - | Plugin module with register and execute functions |
625730
| `options` | object | no | `{}` | Configuration options passed to the plugin |
626-
| `context` | boolean | no | `false` | Enable component context awareness |
731+
| `context` | boolean | no | `false` | Enable component context awareness on `registry.register(...)` |
627732

628733
### Context Object Structure
629734

630-
When `context: true` is set, the context object passed to the execute function contains:
735+
When `context: true` is set on `registry.register(...)`, the context object passed to the execute function contains:
631736

632737
```js
633738
{

0 commit comments

Comments
 (0)