roger pence

Potentially, each day is crucial in the total development

Search
Advanced Search
Folder to search:
Limit search to one of these properties:

    Using the Pino logger

    In page.server.ts

    // +page.server.ts
    import type { PageServerLoad } from './$types';
    
    export const load: PageServerLoad = async ({ locals, params }) => {
    	if (locals.logger?.db && locals.pool) {
    		await locals.logger.db(locals.pool, 'Payment processed', { slug: 'roger' });
    	}
    
    	return {
    		loggedAt: Date.now()
    	};
    };
    

    Logger usage

    The shared logger is implemented in src/lib/pino-logger.ts. The server hook in src/hooks.server.ts adds it to event.locals.logger for each request, and src/app.d.ts defines its TypeScript interface.

    Use the request-local logger when a SvelteKit server load function, action, endpoint, or remote function provides locals. Import the shared logger directly only in server-only code that has no request locals. Do not import the Pino logger into browser code.

    Standard log methods

    The logger provides debug, info, notice, warn, and error. Each method takes a message first and optional structured data second. These methods write to Pino's configured output; they do not write rows to the application log table.

    locals.logger.debug('Preparing account page', { userId });
    locals.logger.info('Account page loaded', { userId });
    locals.logger.notice('Account settings changed', { userId, setting: 'theme' });
    locals.logger.warn('Profile image was not found', { userId });
    locals.logger.error('Profile update failed', { userId, reason: 'database unavailable' });
    

    Prefer objects for the optional data argument so the information is logged as structured fields. Avoid logging passwords, tokens, or unnecessary personal information.

    From a server load function or action

    locals is supplied by SvelteKit to server-side handlers. For example, in +page.server.ts:

    import type { PageServerLoad } from './$types';
    
    export const load: PageServerLoad = async ({ locals, url }) => {
    	locals.logger.info('Loading page', { path: url.pathname });
    	return {};
    };
    

    The same methods are available in form actions and +server.ts request handlers through their event's locals.

    From other server-only code

    When the code does not receive a SvelteKit event (and therefore has no locals), import the shared logger directly:

    import logger from '#lib/pino-logger.js';
    
    logger.info('Background task started', { task: 'refresh-catalog' });
    

    Keep this import in server-only files, such as +page.server.ts, +server.ts, or server-only modules.

    Database logging

    locals.logger.db(pool, message, data?) writes an info log and also inserts a row into app_logs. It is asynchronous, so await it. The hook exposes the request's database pool as locals.pool.

    export const load = async ({ locals }) => {
    	await locals.logger.db(locals.pool, 'Product viewed', {
    		productId: 'product-123'
    	});
    
    	return {};
    };
    

    The equivalent outside a request handler uses the imported logger and a pool available to that server-only module:

    await logger.db(pool, 'Catalog refreshed', { itemCount: 42 });
    

    During a build, the hook supplies no-op implementations for db and download, so these calls do not write logs or database rows.

    Download logging

    locals.logger.download(pool, name, company, country, email_address, product, family) writes an info log and inserts a row into downloads_log. It is asynchronous:

    await locals.logger.download(
    	locals.pool,
    	'Alex Smith',
    	'Example Company',
    	'US',
    	'alex@example.com',
    	'DataGate 17.1',
    	'DataGate'
    );
    

    Use actual request data in application code, and only include personal information when required for the download record and permitted by the application's data-handling rules. Outside a request handler, call logger.download(...) with an available pool.

    Logging from a Svelte component in the browser

    Browser code cannot use locals or import the server Pino logger. To send a client event to the server, POST JSON to the existing src/routes/api/client-logs/+server.ts endpoint. That endpoint records accepted JSON as an info log under clientLog.

    <script lang="ts">
    	async function logClientEvent() {
    		try {
    			const response = await fetch('/api/client-logs', {
    				method: 'POST',
    				headers: { 'Content-Type': 'application/json' },
    				body: JSON.stringify({ event: 'save_clicked', component: 'ProfileForm' })
    			});
    
    			if (!response.ok) {
    				console.error('Client log request failed:', response.status);
    			}
    		} catch (error) {
    			console.error('Client log request failed:', error);
    		}
    	}
    </script>
    
    <button onclick={logClientEvent}>Save</button>
    

    The endpoint currently checks that the body is present and valid JSON, but does not validate its shape or accept a client-selected log level. Keep client payloads small and free of secrets; treat all client-supplied fields as untrusted. The global hook also requires the site_auth cookie for this endpoint, like other routes except /signon, so requests from unauthenticated visitors are redirected to sign-on.

    Log level configuration

    The logger uses debug as its minimum level in development and info in production. Development output is formatted with pino-pretty; the custom notice level is also available in both environments.

    Make a modern, animated version of the graphic shown in the 'example-static-widget artboard; (probably using HTML, JS, and Canvas) that shows the workflow moving from probe, to prove, to prepare, to propse, to perform, to publish. The result should be no wider than 1100px and should scale well on smaller viewports.

    Use colors adapted from the example artboard.

    The text should be provided in a configuration area of the code. Each chunk of text should be provided in this format:

    key: "english text|spanish text"

    where 'key' is the indentifer for a chunk of text, which is a single string, separated by the | pipe character where English is on the left and Spanish is on the right. The locale will be passed to this widget as either 'en' or 'es'. No other languages need to be considered.

    The result will ultimately rendered in a Svelte 5 component. Initially though, provide the example in pure HTML, JS, and CSS and that code will later be adapted to a Svelte component.

    The files should be written to this projects folder (monarch-workflow-widget).