├── .husky ├── .gitignore ├── pre-commit └── commit-msg ├── integration ├── .gitkeep ├── src │ ├── gql │ │ ├── logger.filter.ts │ │ ├── simple-object.model.ts │ │ ├── exception.filter.ts │ │ └── gql.resolver.ts │ ├── simple-object.model.ts │ ├── app.service.ts │ ├── shared │ │ ├── fail.guard.ts │ │ ├── exception.filter.ts │ │ └── server-exception.filter.ts │ ├── grpc │ │ ├── client │ │ │ ├── hello-service.interface.ts │ │ │ ├── grpc-client.module.ts │ │ │ └── grpc-client.controller.ts │ │ ├── server │ │ │ ├── grpc-server.module.ts │ │ │ └── grpc-server.controller.ts │ │ └── hello │ │ │ └── hello.proto │ ├── http │ │ ├── http-server.module.ts │ │ ├── error-logging.filter.ts │ │ └── http.controller.ts │ ├── rpc │ │ ├── server │ │ │ ├── rpc-server.module.ts │ │ │ └── rpc-server.controller.ts │ │ └── client │ │ │ ├── rpc-client.module.ts │ │ │ └── rpc-client.controller.ts │ ├── kafka │ │ ├── server │ │ │ ├── kafka-server.module.ts │ │ │ └── kafka-server.controller.ts │ │ └── client │ │ │ ├── kafka-client.module.ts │ │ │ └── kafka-client.controller.ts │ ├── nested-module │ │ ├── app.controller.ts │ │ ├── logger.module.ts │ │ ├── app.service.ts │ │ └── app.module.ts │ ├── for-feats │ │ ├── app.service.ts │ │ ├── app.controller.ts │ │ └── app.module.ts │ └── ws │ │ ├── ws.module.ts │ │ ├── ws.filter.ts │ │ └── ws.gateway.ts ├── .c8rc └── test │ ├── utils │ ├── index.ts │ ├── createModule.ts │ └── ws-promise.ts │ ├── nested-module.spec.ts │ └── for-feats.spec.ts ├── .nxignore ├── apps └── docs │ ├── public │ ├── CNAME │ ├── favicon.ico │ └── make-scrollable-code-focusable.js │ ├── src │ ├── env.d.ts │ ├── components │ │ ├── Header │ │ │ ├── OgmaLogo.astro │ │ │ ├── SkipToContent.astro │ │ │ ├── LanguageSelect.css │ │ │ └── SidebarToggle.tsx │ │ ├── Footer │ │ │ └── Footer.astro │ │ ├── RightSidebar │ │ │ ├── RightSidebar.astro │ │ │ └── ThemeToggleButton.css │ │ ├── PageContent │ │ │ └── PageContent.astro │ │ └── HeadCommon.astro │ ├── pages │ │ ├── index.astro │ │ └── en │ │ │ ├── nestjs │ │ │ ├── ws │ │ │ │ ├── overview.md │ │ │ │ ├── ws.md │ │ │ │ └── socket.io.md │ │ │ ├── http │ │ │ │ ├── overview.md │ │ │ │ ├── platform-express.md │ │ │ │ └── platform-fastify.md │ │ │ ├── rpc │ │ │ │ ├── tcp.md │ │ │ │ ├── grpc.md │ │ │ │ ├── mqtt.md │ │ │ │ ├── nats.md │ │ │ │ ├── kafka.md │ │ │ │ ├── redis.md │ │ │ │ ├── rabbitmq.md │ │ │ │ └── overview.md │ │ │ ├── graphql │ │ │ │ ├── overview.md │ │ │ │ ├── platform-graphql.md │ │ │ │ └── platform-graphql-fastify.md │ │ │ └── filter.md │ │ │ └── cli.md │ └── languages.ts │ └── project.json ├── renovate.json ├── packages ├── logger │ ├── src │ │ ├── logger │ │ │ └── index.ts │ │ ├── utils │ │ │ ├── index.ts │ │ │ ├── is-nil.ts │ │ │ └── colorize.ts │ │ ├── index.ts │ │ └── interfaces │ │ │ ├── index.ts │ │ │ ├── print-message-options.ts │ │ │ └── ogma-print-options.ts │ ├── tsconfig.build.json │ ├── .c8rc │ ├── test │ │ └── index.spec.ts │ ├── project.json │ └── package.json ├── instrumentation │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ └── types.ts │ ├── tsconfig.build.json │ ├── CHANGELOG.md │ ├── .c8rc │ ├── package.json │ └── project.json ├── platform-grpc │ ├── src │ │ ├── index.ts │ │ └── grpc-interceptor.service.ts │ ├── tsconfig.build.json │ ├── .c8rc │ ├── project.json │ ├── package.json │ └── README.md ├── platform-mqtt │ ├── src │ │ ├── index.ts │ │ └── mqtt-interceptor.service.ts │ ├── tsconfig.build.json │ ├── .c8rc │ ├── project.json │ ├── package.json │ └── README.md ├── platform-nats │ ├── src │ │ ├── index.ts │ │ └── nats-interceptor.service.ts │ ├── tsconfig.build.json │ ├── .c8rc │ ├── project.json │ ├── README.md │ └── package.json ├── platform-tcp │ ├── src │ │ ├── index.ts │ │ └── tcp-interceptor.service.ts │ ├── tsconfig.build.json │ ├── .c8rc │ ├── README.md │ ├── project.json │ └── package.json ├── platform-ws │ ├── src │ │ ├── index.ts │ │ └── ws-interceptor.service.ts │ ├── tsconfig.build.json │ ├── .c8rc │ ├── project.json │ ├── package.json │ └── README.md ├── platform-kafka │ ├── src │ │ ├── index.ts │ │ └── kafka-interceptor.service.ts │ ├── tsconfig.build.json │ ├── .c8rc │ ├── project.json │ ├── package.json │ └── README.md ├── platform-redis │ ├── src │ │ ├── index.ts │ │ └── redis-interceptor.service.ts │ ├── tsconfig.build.json │ ├── .c8rc │ ├── project.json │ ├── README.md │ └── package.json ├── platform-express │ ├── src │ │ ├── index.ts │ │ └── express-interceptor.service.ts │ ├── tsconfig.build.json │ ├── .c8rc │ ├── README.md │ ├── project.json │ └── package.json ├── platform-fastify │ ├── src │ │ ├── index.ts │ │ └── fastify-interceptor.service.ts │ ├── tsconfig.build.json │ ├── .c8rc │ ├── README.md │ ├── project.json │ └── package.json ├── platform-graphql │ ├── src │ │ ├── index.ts │ │ └── graphql-interceptor.service.ts │ ├── tsconfig.build.json │ ├── .c8rc │ ├── project.json │ ├── package.json │ └── README.md ├── platform-rabbitmq │ ├── src │ │ ├── index.ts │ │ └── rabbitmq-interceptor.service.ts │ ├── tsconfig.build.json │ ├── .c8rc │ ├── project.json │ ├── README.md │ └── package.json ├── platform-socket.io │ ├── src │ │ ├── index.ts │ │ └── socket-io-interceptor.service.ts │ ├── tsconfig.build.json │ ├── .c8rc │ ├── project.json │ ├── package.json │ └── README.md ├── common │ ├── src │ │ ├── simple.type.ts │ │ ├── color.enum.ts │ │ ├── index.ts │ │ ├── level.enum.ts │ │ ├── log.interface.ts │ │ └── stream.interface.ts │ ├── tsconfig.build.json │ ├── package.json │ └── project.json ├── platform-graphql-fastify │ ├── src │ │ ├── index.ts │ │ └── graphql-fastify-interceptor.service.ts │ ├── tsconfig.build.json │ ├── .c8rc │ ├── project.json │ ├── package.json │ └── README.md ├── cli │ ├── tsconfig.build.json │ ├── .c8rc │ ├── src │ │ ├── messages.ts │ │ ├── main.ts │ │ ├── file.service.ts │ │ ├── app.module.ts │ │ └── stream.service.ts │ ├── project.json │ └── package.json ├── styler │ ├── tsconfig.build.json │ ├── .c8rc │ ├── package.json │ ├── src │ │ ├── style.enum.ts │ │ └── index.ts │ └── project.json └── nestjs-module │ ├── tsconfig.build.json │ ├── src │ ├── interfaces │ │ ├── index.ts │ │ ├── ogma-provider-options.interface.ts │ │ ├── request-context.interface.ts │ │ ├── ogma-service-meta.interface.ts │ │ └── ogma-options.interface.ts │ ├── decorators │ │ ├── index.ts │ │ ├── skip.decorator.ts │ │ └── ogma-context.decorator.ts │ ├── interceptor │ │ ├── providers │ │ │ ├── index.ts │ │ │ ├── noop-interceptor.service.ts │ │ │ ├── websocket-interceptor.service.ts │ │ │ ├── gql-interceptor.service.ts │ │ │ └── rpc-interceptor.service.ts │ │ └── interfaces │ │ │ └── interceptor-service.interface.ts │ ├── index.ts │ ├── ogma-core.module-definition.ts │ ├── ogma.constants.ts │ ├── ogma-filter.service.ts │ └── ogma-core.module.ts │ ├── .c8rc │ ├── test │ ├── app.service.ts │ ├── app.module.ts │ ├── ogma-logger.decorator.spec.ts │ ├── ogma-module.spec.ts │ ├── ogma-context.decorator.spec.ts │ ├── skip.decorator.spec.ts │ ├── noop-interceptor.service.spec.ts │ └── app.service.spec.ts │ ├── project.json │ └── package.json ├── tsconfig.json ├── .prettierignore ├── mosquitto └── config │ └── mosquitto.conf ├── .czrc ├── benchmarks ├── interceptor │ ├── tsconfig.build.json │ ├── tsconfig.json │ ├── src │ │ ├── app.service.ts │ │ ├── app.module.ts │ │ └── app.controller.ts │ ├── package.json │ ├── project.json │ └── README.md ├── bench │ ├── tsconfig.json │ ├── README.md │ ├── package.json │ └── src │ │ └── bench.ts └── logger │ ├── tsconfig.json │ ├── src │ ├── pino.logger.ts │ ├── ogma.logger.ts │ ├── bunyan.logger.ts │ ├── ogma-json.logger.ts │ ├── omga-with-masks.logger.ts │ └── winston.logger.ts │ ├── package.json │ ├── project.json │ └── README.md ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ └── Parser_Request.yml ├── dependabot.yml └── FUNDING.yml ├── .c8rc ├── pnpm-workspace.yaml ├── .npmrc ├── tsconfig.spec.json ├── .lintstagedrc ├── tools ├── tsconfig.json └── remove-main-from-package.ts ├── .changeset ├── config.json └── README.md ├── .swcrc ├── .prettierrc ├── tsconfig.base.json ├── .gitignore ├── .eslintrc.json ├── LICENSE ├── commitlint.config.js ├── .eslintrc.js ├── docker-compose.yml └── nx.json /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /integration/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.nxignore: -------------------------------------------------------------------------------- 1 | pnpm-lock.yaml 2 | -------------------------------------------------------------------------------- /integration/src/gql/logger.filter.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/docs/public/CNAME: -------------------------------------------------------------------------------- 1 | ogma.jaymcdoniel.dev 2 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/logger/src/logger/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ogma'; 2 | -------------------------------------------------------------------------------- /apps/docs/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json" 3 | } 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | pnpm-lock.yaml 2 | 3 | /.nx/cache 4 | /.nx/workspace-data -------------------------------------------------------------------------------- /mosquitto/config/mosquitto.conf: -------------------------------------------------------------------------------- 1 | listener 1883 2 | allow_anonymous true -------------------------------------------------------------------------------- /.czrc: -------------------------------------------------------------------------------- 1 | { 2 | "path": "./node_modules/cz-conventional-changelog" 3 | } 4 | 5 | -------------------------------------------------------------------------------- /packages/instrumentation/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/instrumentation'; 2 | -------------------------------------------------------------------------------- /packages/platform-grpc/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc-interceptor.service'; 2 | -------------------------------------------------------------------------------- /packages/platform-mqtt/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './mqtt-interceptor.service'; 2 | -------------------------------------------------------------------------------- /packages/platform-nats/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './nats-interceptor.service'; 2 | -------------------------------------------------------------------------------- /packages/platform-tcp/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './tcp-interceptor.service'; 2 | -------------------------------------------------------------------------------- /packages/platform-ws/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ws-interceptor.service'; 2 | -------------------------------------------------------------------------------- /benchmarks/interceptor/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json" 3 | } -------------------------------------------------------------------------------- /packages/platform-kafka/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kafka-interceptor.service'; 2 | -------------------------------------------------------------------------------- /packages/platform-redis/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './redis-interceptor.service'; 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | ## Do allow blank issues 2 | blank_issues_enabled: true 3 | -------------------------------------------------------------------------------- /packages/platform-express/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './express-interceptor.service'; 2 | -------------------------------------------------------------------------------- /packages/platform-fastify/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './fastify-interceptor.service'; 2 | -------------------------------------------------------------------------------- /packages/platform-graphql/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './graphql-interceptor.service'; 2 | -------------------------------------------------------------------------------- /packages/platform-rabbitmq/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './rabbitmq-interceptor.service'; 2 | -------------------------------------------------------------------------------- /packages/platform-socket.io/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './socket-io-interceptor.service'; 2 | -------------------------------------------------------------------------------- /integration/src/simple-object.model.ts: -------------------------------------------------------------------------------- 1 | export class SimpleObject { 2 | hello: string; 3 | } 4 | -------------------------------------------------------------------------------- /packages/common/src/simple.type.ts: -------------------------------------------------------------------------------- 1 | export type OgmaSimpleType = string | number | boolean; 2 | -------------------------------------------------------------------------------- /packages/logger/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './colorize'; 2 | export * from './is-nil'; 3 | -------------------------------------------------------------------------------- /.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": ["integration", "**/test/*"], 3 | "reporter": ["lcov", "text"] 4 | } 5 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/**' 3 | - 'integration/**' 4 | - 'benchmarks/**' -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | ./node_modules/.bin/lint-staged 5 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | tag-version-prefix="" 2 | message="chore(release): %s :tada:" 3 | enable-pre-post-scripts=true 4 | -------------------------------------------------------------------------------- /apps/docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmcdo29/ogma/HEAD/apps/docs/public/favicon.ico -------------------------------------------------------------------------------- /packages/platform-graphql-fastify/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './graphql-fastify-interceptor.service'; 2 | -------------------------------------------------------------------------------- /packages/cli/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/logger/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/styler/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/instrumentation/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/nestjs-module/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/platform-grpc/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/platform-kafka/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/platform-mqtt/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/platform-nats/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/platform-redis/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/platform-tcp/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/platform-ws/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/platform-express/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/platform-fastify/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/platform-graphql/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/platform-rabbitmq/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/platform-socket.io/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "sourceMap": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/platform-graphql-fastify/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /.lintstagedrc: -------------------------------------------------------------------------------- 1 | { 2 | "*.ts": ["prettier --write", "eslint --ext ts"], 3 | "*.{md,html,json,js}": ["prettier --write"] 4 | } 5 | 6 | -------------------------------------------------------------------------------- /packages/logger/src/index.ts: -------------------------------------------------------------------------------- 1 | export { OgmaDefaults, OgmaOptions, OgmaPrintOptions } from './interfaces'; 2 | export * from './logger'; 3 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | [ -n "$CI" ] && exit 0 5 | ./node_modules/.bin/commitlint --edit $1 6 | -------------------------------------------------------------------------------- /packages/common/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../../tsconfig.json", 3 | "compilerOptions": {}, 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/interfaces/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ogma-options.interface'; 2 | export * from './ogma-service-meta.interface'; 3 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/interfaces/ogma-provider-options.interface.ts: -------------------------------------------------------------------------------- 1 | export interface OgmaProviderOptions { 2 | addRequestId: boolean; 3 | } 4 | -------------------------------------------------------------------------------- /packages/logger/src/utils/is-nil.ts: -------------------------------------------------------------------------------- 1 | export function isNil(val: unknown): boolean { 2 | return val === undefined || val === null || val === ''; 3 | } 4 | -------------------------------------------------------------------------------- /packages/logger/src/interfaces/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ogma-options'; 2 | export * from './ogma-print-options'; 3 | export * from './print-message-options'; 4 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/interfaces/request-context.interface.ts: -------------------------------------------------------------------------------- 1 | export interface RequestContext { 2 | getContext?: () => any; 3 | requestId: string; 4 | } 5 | -------------------------------------------------------------------------------- /benchmarks/bench/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist" 5 | }, 6 | "include": ["src"] 7 | } 8 | -------------------------------------------------------------------------------- /benchmarks/logger/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist" 5 | }, 6 | "include": ["src"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/instrumentation/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @ogma/instrumentation 2 | 3 | ## 0.1.0 4 | 5 | ### Minor Changes 6 | 7 | - 03a37fe: Initial release of @ogma/instrumentation 8 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ogma-context.decorator'; 2 | export * from './ogma-logger.decorator'; 3 | export * from './skip.decorator'; 4 | -------------------------------------------------------------------------------- /apps/docs/public/make-scrollable-code-focusable.js: -------------------------------------------------------------------------------- 1 | Array.from(document.getElementsByTagName('pre')).forEach((element) => { 2 | element.setAttribute('tabindex', '0'); 3 | }); 4 | -------------------------------------------------------------------------------- /packages/common/src/color.enum.ts: -------------------------------------------------------------------------------- 1 | export enum Color { 2 | BLACK = 0, 3 | RED, 4 | GREEN, 5 | YELLOW, 6 | BLUE, 7 | MAGENTA, 8 | CYAN, 9 | WHITE, 10 | } 11 | -------------------------------------------------------------------------------- /tools/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./", 5 | "baseUrl": "./", 6 | "declaration": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /integration/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": [ 3 | "integration" 4 | ], 5 | "reporter": [ 6 | "text", 7 | "lcov" 8 | ], 9 | "reportDir": "integration/coverage" 10 | } 11 | -------------------------------------------------------------------------------- /integration/src/gql/simple-object.model.ts: -------------------------------------------------------------------------------- 1 | import { Field, ObjectType } from '@nestjs/graphql'; 2 | 3 | @ObjectType() 4 | export class SimpleObject { 5 | @Field() 6 | hello: string; 7 | } 8 | -------------------------------------------------------------------------------- /integration/src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class AppService { 5 | getHello() { 6 | return { hello: 'world' }; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /benchmarks/interceptor/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "../.." 6 | }, 7 | "include": ["src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/common/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './color.enum'; 2 | export * from './level.enum'; 3 | export * from './log.interface'; 4 | export * from './simple.type'; 5 | export * from './stream.interface'; 6 | -------------------------------------------------------------------------------- /benchmarks/interceptor/src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class AppService { 5 | getHello() { 6 | return { hello: 'world' }; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/cli/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/cli/src", 3 | "include": [ 4 | "packages/cli/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/cli/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /packages/cli/src/messages.ts: -------------------------------------------------------------------------------- 1 | export const generalError = 'There was an error reading the file.\n'; 2 | export const badFormat = 3 | 'The log file provided is not in Ogma format. Please try another log file.\n'; 4 | -------------------------------------------------------------------------------- /packages/logger/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/logger/src", 3 | "include": [ 4 | "packages/logger/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/logger/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /packages/styler/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/styler/src", 3 | "include": [ 4 | "packages/styler/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/styler/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /apps/docs/src/components/Header/OgmaLogo.astro: -------------------------------------------------------------------------------- 1 | --- 2 | type Props = { 3 | size: number; 4 | }; 5 | const { size } = Astro.props as Props; 6 | --- 7 | 8 | Ogma Logo 9 | -------------------------------------------------------------------------------- /integration/src/shared/fail.guard.ts: -------------------------------------------------------------------------------- 1 | import { CanActivate, Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class FailGuard implements CanActivate { 5 | canActivate() { 6 | return false; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/common", 3 | "version": "1.2.0", 4 | "description": "A package for the @ogma packages to have centralized typings.", 5 | "publishConfig": { 6 | "access": "public" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/instrumentation/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/instrumentation/src", 3 | "include": ["packages/instrumentation/src/**/*.ts"], 4 | "reporter": ["text", "lcov"], 5 | "reportDir": "./packages/instrumentation/coverage" 6 | } 7 | -------------------------------------------------------------------------------- /packages/platform-ws/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/platform-ws/src", 3 | "include": [ 4 | "packages/platform-ws/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/platform-ws/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/interfaces/ogma-service-meta.interface.ts: -------------------------------------------------------------------------------- 1 | export interface OgmaServiceMeta { 2 | application?: string; 3 | context?: string; 4 | correlationId?: string; 5 | each?: boolean; 6 | [key: string]: unknown; 7 | } 8 | -------------------------------------------------------------------------------- /packages/platform-tcp/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/platform-tcp/src", 3 | "include": [ 4 | "packages/platform-tcp/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/platform-tcp/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /packages/nestjs-module/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/nestjs-module/src", 3 | "include": [ 4 | "packages/nestjs-module/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/nestjs-module/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /packages/platform-grpc/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/platform-grpc/src", 3 | "include": [ 4 | "packages/platform-grpc/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/platform-grpc/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /packages/platform-kafka/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/platform-kafka/src", 3 | "include": [ 4 | "packages/platform-kafka/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/platform-kafka/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /packages/platform-mqtt/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/platform-mqtt/src", 3 | "include": [ 4 | "packages/platform-mqtt/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/platform-mqtt/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /packages/platform-nats/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/platform-nats/src", 3 | "include": [ 4 | "packages/platform-nats/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/platform-nats/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /packages/platform-redis/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/platform-redis/src", 3 | "include": [ 4 | "packages/platform-redis/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/platform-redis/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /packages/logger/test/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { test } from 'uvu'; 2 | import { ok } from 'uvu/assert'; 3 | 4 | import { Ogma } from '../src'; 5 | 6 | test('should have the main export be defined', () => { 7 | ok(Ogma); 8 | }); 9 | test.run(); 10 | -------------------------------------------------------------------------------- /apps/docs/src/pages/index.astro: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /packages/platform-express/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/platform-express/src", 3 | "include": [ 4 | "packages/platform-express/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/platform-express/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /packages/platform-fastify/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/platform-fastify/src", 3 | "include": [ 4 | "packages/platform-fastify/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/platform-fastify/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /packages/platform-graphql/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/platform-graphql/src", 3 | "include": [ 4 | "packages/platform-graphql/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/platform-graphql/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /packages/platform-rabbitmq/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/platform-rabbitmq/src", 3 | "include": [ 4 | "packages/platform-rabbitmq/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/platform-rabbitmq/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /integration/src/grpc/client/hello-service.interface.ts: -------------------------------------------------------------------------------- 1 | export interface HelloService { 2 | sayHello(data: { ip?: string }): { hello: string }; 3 | sayError(data: { ip?: string }): { hello: string }; 4 | saySkip(data: { ip?: string }): { hello: string }; 5 | } 6 | -------------------------------------------------------------------------------- /packages/platform-socket.io/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/platform-socket.io/src", 3 | "include": [ 4 | "packages/platform-socket.io/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/platform-socket.io/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /packages/cli/src/main.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { CommandFactory } from 'nest-commander'; 4 | 5 | import { AppModule } from './app.module'; 6 | 7 | async function bootstrap() { 8 | await CommandFactory.run(AppModule); 9 | } 10 | 11 | bootstrap(); 12 | -------------------------------------------------------------------------------- /packages/platform-graphql-fastify/.c8rc: -------------------------------------------------------------------------------- 1 | { 2 | "src": "./packages/platform-graphql-fastify/src", 3 | "include": [ 4 | "packages/platform-graphql-fastify/src/**/*.ts" 5 | ], 6 | "reporter": ["text", "lcov"], 7 | "reportDir": "./packages/platform-graphql-fastify/coverage" 8 | } 9 | -------------------------------------------------------------------------------- /benchmarks/logger/src/pino.logger.ts: -------------------------------------------------------------------------------- 1 | import { WriteStream } from 'fs'; 2 | import { pino } from 'pino'; 3 | export function createPinoLogger(stream: WriteStream) { 4 | return pino( 5 | { 6 | level: 'info', 7 | name: 'Pino Bench', 8 | }, 9 | stream, 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /packages/cli/src/file.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { promises } from 'fs'; 3 | 4 | @Injectable() 5 | export class FileService { 6 | async read(fileName: string): Promise { 7 | return (await promises.readFile(fileName)).toString(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /benchmarks/logger/src/ogma.logger.ts: -------------------------------------------------------------------------------- 1 | import { OgmaStream } from '@ogma/common'; 2 | import { Ogma } from '@ogma/logger'; 3 | 4 | export function createOgmaLogger(stream: OgmaStream) { 5 | return new Ogma({ 6 | application: 'Ogma Bench', 7 | stream, 8 | logLevel: 'INFO', 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /benchmarks/logger/src/bunyan.logger.ts: -------------------------------------------------------------------------------- 1 | import { createLogger as BunyanLogger } from 'bunyan'; 2 | import { WriteStream } from 'fs'; 3 | 4 | export function createBunyanLogger(stream: WriteStream) { 5 | return BunyanLogger({ 6 | name: 'Bunyan Bench', 7 | stream, 8 | level: 'info', 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /packages/logger/src/interfaces/print-message-options.ts: -------------------------------------------------------------------------------- 1 | import { LogLevel } from '@ogma/common'; 2 | 3 | export interface PrintMessageOptions { 4 | level: LogLevel; 5 | formattedLevel: string; 6 | application?: string; 7 | context?: string; 8 | correlationId?: string; 9 | [key: string]: unknown; 10 | } 11 | -------------------------------------------------------------------------------- /integration/src/http/http-server.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | 3 | import { AppService } from '../app.service'; 4 | import { HttpController } from './http.controller'; 5 | 6 | @Module({ 7 | controllers: [HttpController], 8 | providers: [AppService], 9 | }) 10 | export class HttpServerModule {} 11 | -------------------------------------------------------------------------------- /benchmarks/logger/src/ogma-json.logger.ts: -------------------------------------------------------------------------------- 1 | import { OgmaStream } from '@ogma/common'; 2 | import { Ogma } from '@ogma/logger'; 3 | 4 | export function createOgmaJsonLogger(stream: OgmaStream) { 5 | return new Ogma({ 6 | application: 'Ogma Bench', 7 | stream, 8 | logLevel: 'INFO', 9 | json: true, 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /packages/styler/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/styler", 3 | "version": "1.1.0", 4 | "description": "A package for the @ogma packages to deal with adding color and string styling to terminal logs", 5 | "publishConfig": { 6 | "access": "public" 7 | }, 8 | "dependencies": { 9 | "@ogma/common": "^1.1.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /integration/src/rpc/server/rpc-server.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | 3 | import { AppService } from '../../app.service'; 4 | import { RpcServerController } from './rpc-server.controller'; 5 | 6 | @Module({ 7 | controllers: [RpcServerController], 8 | providers: [AppService], 9 | }) 10 | export class RpcServerModule {} 11 | -------------------------------------------------------------------------------- /integration/src/grpc/server/grpc-server.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | 3 | import { AppService } from '../../app.service'; 4 | import { GrpcServerController } from './grpc-server.controller'; 5 | 6 | @Module({ 7 | controllers: [GrpcServerController], 8 | providers: [AppService], 9 | }) 10 | export class GrpcServerModule {} 11 | -------------------------------------------------------------------------------- /benchmarks/logger/src/omga-with-masks.logger.ts: -------------------------------------------------------------------------------- 1 | import { OgmaStream } from '@ogma/common'; 2 | import { Ogma } from '@ogma/logger'; 3 | 4 | export function createOgmaWithMasksLogger(stream: OgmaStream) { 5 | return new Ogma({ 6 | application: 'Ogma Mask Bench', 7 | stream, 8 | logLevel: 'INFO', 9 | masks: ['d', 'hello'], 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /integration/src/kafka/server/kafka-server.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | 3 | import { AppService } from '../../app.service'; 4 | import { KafkaServerController } from './kafka-server.controller'; 5 | 6 | @Module({ 7 | controllers: [KafkaServerController], 8 | providers: [AppService], 9 | }) 10 | export class KafkaServerModule {} 11 | -------------------------------------------------------------------------------- /packages/common/src/level.enum.ts: -------------------------------------------------------------------------------- 1 | export enum LogLevel { 2 | ALL, 3 | VERBOSE, 4 | DEBUG, 5 | LOG, 6 | WARN, 7 | ERROR, 8 | FATAL, 9 | OFF, 10 | INFO = LogLevel.LOG, 11 | FINE = LogLevel.VERBOSE, 12 | SILLY = LogLevel.ALL, 13 | } 14 | 15 | export type OgmaWritableLevel = Exclude; 16 | -------------------------------------------------------------------------------- /benchmarks/logger/src/winston.logger.ts: -------------------------------------------------------------------------------- 1 | import { WriteStream } from 'fs'; 2 | import { createLogger as WinstonLogger, transports as WinstonTransports } from 'winston'; 3 | 4 | export function createWinstonLogger(stream: WriteStream) { 5 | return WinstonLogger({ 6 | level: 'info', 7 | transports: [new WinstonTransports.Stream({ stream })], 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /integration/src/nested-module/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get } from '@nestjs/common'; 2 | 3 | import { AppService } from './app.service'; 4 | 5 | @Controller() 6 | export class AppController { 7 | constructor(private readonly appService: AppService) {} 8 | 9 | @Get() 10 | sayHello() { 11 | return this.appService.getHello(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/common/src/log.interface.ts: -------------------------------------------------------------------------------- 1 | import { OgmaWritableLevel } from './level.enum'; 2 | 3 | export interface OgmaLog { 4 | time: string | number; 5 | hostname?: string; 6 | application?: string; 7 | context?: string; 8 | message?: string; 9 | level: string; 10 | pid?: string | number; 11 | ool: OgmaWritableLevel; 12 | [key: string]: any; 13 | } 14 | -------------------------------------------------------------------------------- /benchmarks/bench/README.md: -------------------------------------------------------------------------------- 1 | NestJS Logger x 7,799 ops/sec ±1.47% (85 runs sampled)
Ogma x 695,349 ops/sec ±4.70% (82 runs sampled)
OgmaJson x 277,887 ops/sec ±0.81% (96 runs sampled)
Pino x 779,229 ops/sec ±22.44% (68 runs sampled)
console.log x 147,514 ops/sec ±2.71% (85 runs sampled)
process.stdout x 413,788 ops/sec ±2.05% (79 runs sampled)

Fastest is Ogma 2 | -------------------------------------------------------------------------------- /integration/src/nested-module/logger.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { OgmaModule } from '@ogma/nestjs-module'; 3 | 4 | @Module({ 5 | imports: [ 6 | OgmaModule.forRoot({ 7 | service: { 8 | application: 'NestedModule', 9 | }, 10 | interceptor: false, 11 | }), 12 | ], 13 | }) 14 | export class LoggerModule {} 15 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/interceptor/providers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './abstract-interceptor.service'; 2 | export * from './delegator.service'; 3 | export * from './gql-interceptor.service'; 4 | export * from './http-interceptor.service'; 5 | export * from './noop-interceptor.service'; 6 | export * from './rpc-interceptor.service'; 7 | export * from './websocket-interceptor.service'; 8 | -------------------------------------------------------------------------------- /integration/src/grpc/hello/hello.proto: -------------------------------------------------------------------------------- 1 | syntax="proto3"; 2 | 3 | package hello; 4 | 5 | service HelloService { 6 | rpc SayHello (Ip) returns (Greeting) {} 7 | 8 | rpc SayError (Ip) returns (Greeting) {} 9 | 10 | rpc SaySkip (Ip) returns (Greeting) {} 11 | } 12 | 13 | message Greeting { 14 | string hello = 1; 15 | } 16 | 17 | message Ip { 18 | optional string ip = 1; 19 | } -------------------------------------------------------------------------------- /packages/nestjs-module/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './decorators'; 2 | export * from './interceptor/ogma.interceptor'; 3 | export * from './interceptor/providers'; 4 | export * from './interfaces/ogma-options.interface'; 5 | export * from './ogma.module'; 6 | export { createProviderToken } from './ogma.provider'; 7 | export * from './ogma.service'; 8 | export * from './ogma-filter.service'; 9 | -------------------------------------------------------------------------------- /integration/src/for-feats/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { OgmaLogger, OgmaService } from '@ogma/nestjs-module'; 3 | 4 | @Injectable() 5 | export class AppService { 6 | constructor(@OgmaLogger('AppService') private readonly logger: OgmaService) {} 7 | 8 | hello() { 9 | this.logger.log('Hello'); 10 | return { hello: 'world' }; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/nestjs-module/test/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | import { OgmaLogger, OgmaService } from '../src'; 4 | 5 | @Injectable() 6 | export class AppService { 7 | constructor(@OgmaLogger('AppService') private readonly logger: OgmaService) {} 8 | 9 | getHello() { 10 | this.logger.log('Say Hello'); 11 | return { hello: 'world' }; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/nestjs-module/test/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | 3 | import { OgmaModule } from '../src'; 4 | import { AppService } from './app.service'; 5 | 6 | @Module({ 7 | imports: [ 8 | OgmaModule.forRoot({ 9 | interceptor: false, 10 | }), 11 | OgmaModule.forFeature(AppService), 12 | ], 13 | providers: [AppService], 14 | }) 15 | export class AppModule {} 16 | -------------------------------------------------------------------------------- /apps/docs/src/components/Footer/Footer.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import AvatarList from './AvatarList.astro'; 3 | type Props = { 4 | path: string; 5 | }; 6 | const { path } = Astro.props as Props; 7 | --- 8 | 9 |
10 | 11 |
12 | 13 | 20 | -------------------------------------------------------------------------------- /integration/src/nested-module/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { OgmaLogger, OgmaService } from '@ogma/nestjs-module'; 3 | 4 | @Injectable() 5 | export class AppService { 6 | constructor(@OgmaLogger('AppService') private readonly logger: OgmaService) {} 7 | 8 | getHello() { 9 | this.logger.log('Hello NestedModule'); 10 | return { hello: 'World' }; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /benchmarks/bench/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "benchmark-bench", 3 | "private": true, 4 | "_moduleAliases": { 5 | "@ogma/common": "dist/packages/common/src", 6 | "@ogma/logger": "dist/packages/logger/src", 7 | "@ogma/nestjs-module": "dist/packages/nestjs-module/src", 8 | "@ogma/platform-express": "dist/packages/platform-express/src", 9 | "@ogma/styler": "dist/packages/styler/src" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /benchmarks/logger/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "benchmark-logger", 3 | "private": true, 4 | "_moduleAliases": { 5 | "@ogma/common": "dist/packages/common/src", 6 | "@ogma/logger": "dist/packages/logger/src", 7 | "@ogma/nestjs-module": "dist/packages/nestjs-module/src", 8 | "@ogma/platform-express": "dist/packages/platform-express/src", 9 | "@ogma/styler": "dist/packages/styler/src" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /integration/src/shared/exception.filter.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ArgumentsHost, 3 | Catch, 4 | ExceptionFilter as NestExceptionFilter, 5 | HttpException, 6 | } from '@nestjs/common'; 7 | 8 | @Catch() 9 | export class ExceptionFilter implements NestExceptionFilter { 10 | catch(exception: HttpException, host: ArgumentsHost) { 11 | const res = host.switchToHttp().getResponse(); 12 | res.send(exception); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /benchmarks/interceptor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "benchmark-interceptor", 3 | "private": true, 4 | "_moduleAliases": { 5 | "@ogma/common": "dist/packages/common/src", 6 | "@ogma/logger": "dist/packages/logger/src", 7 | "@ogma/nestjs-module": "dist/packages/nestjs-module/src", 8 | "@ogma/platform-express": "dist/packages/platform-express/src", 9 | "@ogma/styler": "dist/packages/styler/src" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/cli/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | 3 | import { FileService } from './file.service'; 4 | import { OgmaCommand } from './ogma.command'; 5 | import { OgmaGetterService } from './ogma-getters.service'; 6 | import { StreamService } from './stream.service'; 7 | 8 | @Module({ 9 | providers: [OgmaCommand, FileService, OgmaGetterService, StreamService], 10 | }) 11 | export class AppModule {} 12 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/ogma-core.module-definition.ts: -------------------------------------------------------------------------------- 1 | import { ConfigurableModuleBuilder } from '@nestjs/common'; 2 | 3 | import { OgmaModuleOptions } from './interfaces'; 4 | 5 | export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN, ASYNC_OPTIONS_TYPE } = 6 | new ConfigurableModuleBuilder() 7 | .setClassMethodName('forRoot') 8 | .setFactoryMethodName('createModuleConfig') 9 | .build(); 10 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.4.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "linked": [], 6 | "access": "public", 7 | "baseBranch": "main", 8 | "updateInternalDependencies": "patch", 9 | "ignore": [], 10 | "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { 11 | "onlyUpdatePeerDependentsWhenOutOfRange": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/instrumentation/src/lib/types.ts: -------------------------------------------------------------------------------- 1 | import { Span } from '@opentelemetry/api'; 2 | import { InstrumentationConfig } from '@opentelemetry/instrumentation'; 3 | 4 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 5 | export type LogHookFunction = (span: Span, record: Record, level?: string) => void; 6 | 7 | export interface OgmaInstrumentationConfig extends InstrumentationConfig { 8 | logHook?: LogHookFunction; 9 | } 10 | -------------------------------------------------------------------------------- /apps/docs/src/languages.ts: -------------------------------------------------------------------------------- 1 | import { KNOWN_LANGUAGE_CODES, KNOWN_LANGUAGES } from './config'; 2 | export { KNOWN_LANGUAGE_CODES, KNOWN_LANGUAGES }; 3 | 4 | export const langPathRegex = /\/([a-z]{2}-?[A-Z]{0,2})\//; 5 | 6 | export function getLanguageFromURL(pathname: string) { 7 | const langCodeMatch = pathname.match(langPathRegex); 8 | const langCode = langCodeMatch ? langCodeMatch[1] : 'en'; 9 | return langCode as typeof KNOWN_LANGUAGE_CODES[number]; 10 | } 11 | -------------------------------------------------------------------------------- /.swcrc: -------------------------------------------------------------------------------- 1 | { 2 | "jsc": { 3 | "parser": { 4 | "syntax": "typescript", 5 | "decorators": true 6 | }, 7 | "transform": { 8 | "legacyDecorator": true, 9 | "decoratorMetadata": true 10 | }, 11 | "target": "es2017", 12 | "keepClassNames": true, 13 | "baseUrl": ".", 14 | "paths": { 15 | "@ogma/*": ["packages/*/src/"] 16 | } 17 | }, 18 | "module": { 19 | "type": "commonjs", 20 | "strictMode": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /integration/src/nested-module/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { OgmaModule } from '@ogma/nestjs-module'; 3 | 4 | import { AppController } from './app.controller'; 5 | import { AppService } from './app.service'; 6 | import { LoggerModule } from './logger.module'; 7 | 8 | @Module({ 9 | imports: [LoggerModule, OgmaModule.forFeature(AppService)], 10 | controllers: [AppController], 11 | providers: [AppService], 12 | }) 13 | export class NestedModule {} 14 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "always", 4 | "trailingComma": "all", 5 | "printWidth": 100, 6 | "overrides": [ 7 | { 8 | "files": "*.md", 9 | "options": { 10 | "printWidth": 70, 11 | "useTabs": false, 12 | "trailingComma": "none", 13 | "proseWrap": "never" 14 | } 15 | }, 16 | { 17 | "files": ".*rc", 18 | "options": { 19 | "parser": "json" 20 | } 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/decorators/skip.decorator.ts: -------------------------------------------------------------------------------- 1 | import { OGMA_INTERCEPTOR_SKIP } from '../ogma.constants'; 2 | 3 | export function OgmaSkip() { 4 | return (target: any, key?: string | symbol, descriptor?: TypedPropertyDescriptor) => { 5 | if (descriptor) { 6 | Reflect.defineMetadata(OGMA_INTERCEPTOR_SKIP, true, descriptor.value); 7 | return descriptor; 8 | } 9 | Reflect.defineMetadata(OGMA_INTERCEPTOR_SKIP, true, target); 10 | return target; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works with multi-package repos, or single-package repos to help you version and publish your code. You can find the full documentation for it [in our repository](https://github.com/changesets/changesets) 4 | 5 | We have a quick list of common questions to get you started engaging with this project in [our documentation](https://github.com/changesets/changesets/blob/master/docs/common-questions.md) 6 | -------------------------------------------------------------------------------- /integration/src/gql/exception.filter.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ArgumentsHost, 3 | Catch, 4 | ExceptionFilter as NestExceptionFilter, 5 | HttpException, 6 | } from '@nestjs/common'; 7 | import { OgmaFilterService } from '@ogma/nestjs-module'; 8 | 9 | @Catch() 10 | export class ExceptionFilter implements NestExceptionFilter { 11 | constructor(private readonly service: OgmaFilterService) {} 12 | catch(exception: HttpException, host: ArgumentsHost) { 13 | this.service.log(exception, host); 14 | return exception; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /integration/src/ws/ws.module.ts: -------------------------------------------------------------------------------- 1 | import { DynamicModule, Module } from '@nestjs/common'; 2 | import { OgmaModule, OgmaModuleOptions } from '@ogma/nestjs-module'; 3 | 4 | import { AppService } from '../app.service'; 5 | import { WsGateway } from './ws.gateway'; 6 | 7 | @Module({}) 8 | export class WsModule { 9 | static register(options: OgmaModuleOptions): DynamicModule { 10 | return { 11 | module: WsModule, 12 | imports: [OgmaModule.forRoot(options)], 13 | providers: [WsGateway, AppService], 14 | }; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/platform-ws/src/ws-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | import { Parser, WebsocketInterceptorService } from '@ogma/nestjs-module'; 3 | 4 | @Parser('ws') 5 | export class WsParser extends WebsocketInterceptorService { 6 | getCallerIp(context: ExecutionContext): string { 7 | return (this.getClient(context) as any)._socket.remoteAddress; 8 | } 9 | 10 | getProtocol(): string { 11 | return 'WS'; 12 | } 13 | 14 | getMethod(): string { 15 | return 'websocket'; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /integration/src/for-feats/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get } from '@nestjs/common'; 2 | import { OgmaLogger, OgmaService } from '@ogma/nestjs-module'; 3 | 4 | import { AppService } from './app.service'; 5 | 6 | @Controller() 7 | export class AppController { 8 | constructor( 9 | private readonly service: AppService, 10 | @OgmaLogger('AppController') private readonly logger: OgmaService, 11 | ) {} 12 | 13 | @Get() 14 | sayHello() { 15 | this.logger.log('Hello'); 16 | return this.service.hello(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /integration/src/http/error-logging.filter.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentsHost, Catch } from '@nestjs/common'; 2 | import { BaseExceptionFilter } from '@nestjs/core'; 3 | import { OgmaFilterService } from '@ogma/nestjs-module'; 4 | 5 | @Catch() 6 | export class ErrorLoggingFilter extends BaseExceptionFilter { 7 | constructor(private readonly logger: OgmaFilterService) { 8 | super(); 9 | } 10 | 11 | catch(exception: Error, host: ArgumentsHost) { 12 | this.logger.log(exception, host); 13 | return super.catch(exception, host); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/decorators/ogma-context.decorator.ts: -------------------------------------------------------------------------------- 1 | import { Inject } from '@nestjs/common'; 2 | 3 | import { 4 | OGMA_CONTEXT, 5 | OGMA_INSTANCE, 6 | OGMA_INTERCEPTOR_OPTIONS, 7 | OGMA_TRACE_METHOD_OPTION, 8 | } from '../ogma.constants'; 9 | 10 | export const InjectOgma = () => Inject(OGMA_INSTANCE); 11 | export const InjectOgmaContext = () => Inject(OGMA_CONTEXT); 12 | export const InjectTraceMethod = () => Inject(OGMA_TRACE_METHOD_OPTION); 13 | export const InjectOgmaInterceptorOptions = () => Inject(OGMA_INTERCEPTOR_OPTIONS); 14 | -------------------------------------------------------------------------------- /packages/nestjs-module/test/ogma-logger.decorator.spec.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu'; 2 | import { instance } from 'uvu/assert'; 3 | 4 | import { OgmaLogger } from '../src'; 5 | 6 | class TestClass {} 7 | 8 | const OgmaLoggerDecoratorSuite = suite('Ogma Logger Decorators'); 9 | OgmaLoggerDecoratorSuite('Should work with a string', () => { 10 | instance(OgmaLogger('TestContext'), Function); 11 | }); 12 | OgmaLoggerDecoratorSuite('Should work with a class', () => { 13 | instance(OgmaLogger(TestClass), Function); 14 | }); 15 | OgmaLoggerDecoratorSuite.run(); 16 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": false, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "target": "es2017", 9 | "sourceMap": false, 10 | "outDir": "./lib", 11 | "baseUrl": "./", 12 | "strict": false, 13 | "noUnusedLocals": false, 14 | "lib": ["ES7"], 15 | "esModuleInterop": true, 16 | "paths": { 17 | "@ogma/*": ["packages/*/src/"] 18 | } 19 | }, 20 | "exclude": ["node_modules", "lib"] 21 | } 22 | -------------------------------------------------------------------------------- /integration/src/rpc/client/rpc-client.module.ts: -------------------------------------------------------------------------------- 1 | import { DynamicModule, Module } from '@nestjs/common'; 2 | import { ClientOptions, ClientsModule } from '@nestjs/microservices'; 3 | 4 | import { RpcClientController } from './rpc-client.controller'; 5 | 6 | @Module({}) 7 | export class RpcClientModule { 8 | static register(options: ClientOptions): DynamicModule { 9 | return { 10 | module: RpcClientModule, 11 | imports: [ClientsModule.register([{ name: 'RPC-SERVICE', ...options }])], 12 | controllers: [RpcClientController], 13 | }; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /benchmarks/interceptor/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { DynamicModule, Module } from '@nestjs/common'; 2 | import { OgmaModule, OgmaModuleOptions } from '@ogma/nestjs-module'; 3 | 4 | import { AppController } from './app.controller'; 5 | import { AppService } from './app.service'; 6 | 7 | @Module({ 8 | controllers: [AppController], 9 | providers: [AppService], 10 | }) 11 | export class AppModule { 12 | static forRoot(options: OgmaModuleOptions): DynamicModule { 13 | return { 14 | module: AppModule, 15 | imports: [OgmaModule.forRoot(options)], 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/instrumentation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/instrumentation", 3 | "version": "0.1.0", 4 | "dependencies": { 5 | "@opentelemetry/context-async-hooks": "^1.25.0", 6 | "@opentelemetry/instrumentation": "^0.44.0", 7 | "@opentelemetry/sdk-trace-base": "^1.25.0", 8 | "@opentelemetry/sdk-trace-node": "^1.25.0", 9 | "tslib": "^2.3.0" 10 | }, 11 | "peerDependencies": { 12 | "@ogma/logger": "^3.2.0", 13 | "@opentelemetry/api": "^1.3.0" 14 | }, 15 | "type": "commonjs", 16 | "main": "./src/index.js", 17 | "typings": "./src/index.d.ts" 18 | } 19 | -------------------------------------------------------------------------------- /apps/docs/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "application", 5 | "sourceRoot": "apps/docs/src", 6 | "targets": { 7 | "build": { 8 | "executor": "nx:run-commands", 9 | "options": { 10 | "command": "pnpm astro build --root apps/docs" 11 | } 12 | }, 13 | "serve": { 14 | "executor": "nx:run-commands", 15 | "options": { 16 | "command": "pnpm astro dev --port 3333 --root apps/docs --verbose" 17 | } 18 | } 19 | }, 20 | "tags": [] 21 | } 22 | -------------------------------------------------------------------------------- /integration/src/for-feats/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { OgmaModule } from '@ogma/nestjs-module'; 3 | 4 | import { AppController } from './app.controller'; 5 | import { AppService } from './app.service'; 6 | 7 | @Module({ 8 | imports: [ 9 | OgmaModule.forFeatures([AppService, AppController]), 10 | OgmaModule.forRoot({ 11 | service: { 12 | application: 'forFeatures', 13 | }, 14 | interceptor: false, 15 | }), 16 | ], 17 | providers: [AppService], 18 | controllers: [AppController], 19 | }) 20 | export class ForFeatsModule {} 21 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/ws/overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: overview 3 | title: Websocket Overview 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | And lastly, Ogma comes with two parsers for Websockets, one for [ws](https://github.com/websockets/ws) and one for [socket.io](https://socket.io). All that's needed is to make use of either [`@ogma/platform-socket.io`](/en/nestjs/ws/socket.io) or[`@ogma/platform-ws`](/en/nestjs/ws/ws). 8 | 9 | ``` 10 | [2021-09-06T18:50:22.947Z] [INFO] [jay-pop] [Socket.io] [138632] [1630954222944958] [WsGateway#getMessage] ::1 - socket.io message WS 200 2ms - 17 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/interfaces/ogma-options.interface.ts: -------------------------------------------------------------------------------- 1 | import { OgmaWritableLevel } from '@ogma/common'; 2 | import { OgmaOptions } from '@ogma/logger'; 3 | 4 | export type OgmaModuleOptions = Partial & { 5 | traceMethod?: Lowercase; 6 | /** 7 | * determine if extra metadata in the interceptor should be added to the logged line 8 | */ 9 | inlineMeta?: boolean; 10 | }; 11 | 12 | export type Type = new (...args: any[]) => T; 13 | 14 | export interface OgmaInterceptorServiceOptions { 15 | json: boolean; 16 | color: boolean; 17 | inlineMeta?: boolean; 18 | } 19 | -------------------------------------------------------------------------------- /benchmarks/logger/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "benchmark-logger", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "benchmarks/logger/src", 5 | "type": "library", 6 | "targets": { 7 | "bench": { 8 | "executor": "nx:run-commands", 9 | "options": { 10 | "cwd": "benchmarks/logger", 11 | "commands": [ 12 | "../../node_modules/.bin/tsc -p tsconfig.json", 13 | "node -r module-alias/register dist/benchmarks/logger/src/index" 14 | ], 15 | "parallel": false 16 | } 17 | } 18 | }, 19 | "implicitDependencies": [] 20 | } 21 | -------------------------------------------------------------------------------- /packages/cli/src/stream.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { fromEvent, Observable } from 'rxjs'; 3 | import { filter, map } from 'rxjs/operators'; 4 | import { Readable } from 'stream'; 5 | 6 | @Injectable() 7 | export class StreamService { 8 | readFromStream(stream: Readable): { log: Observable; done: Observable } { 9 | return { 10 | log: fromEvent(stream, 'data').pipe( 11 | filter((val) => Buffer.isBuffer(val)), 12 | map((val: Buffer) => val.toString('utf-8')), 13 | ), 14 | done: fromEvent(stream, 'end').pipe(map(() => true)), 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/platform-grpc/src/grpc-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | import { Parser, RpcInterceptorService } from '@ogma/nestjs-module'; 3 | 4 | @Parser('rpc') 5 | export class GrpcParser extends RpcInterceptorService { 6 | getCallPoint(context: ExecutionContext) { 7 | return super.getCallPoint(context).rpc; 8 | } 9 | 10 | getCallerIp(context: ExecutionContext) { 11 | const data = this.getData<{ ip?: string }>(context); 12 | return data?.ip || ''; 13 | } 14 | 15 | getProtocol() { 16 | return 'grpc'; 17 | } 18 | 19 | getMethod() { 20 | return 'gRPC'; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | dist/ 3 | tmp/ 4 | node_modules/ 5 | *.tsbuildinfo 6 | tools/*.js 7 | 8 | # Logs 9 | logs 10 | *.log 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | lerna-debug.log* 15 | 16 | # OS 17 | .DS_Store 18 | 19 | # Tests 20 | coverage/ 21 | coverage-tmp/ 22 | /.nyc_output 23 | 24 | # IDEs and editors 25 | /.idea 26 | .project 27 | .classpath 28 | .c9/ 29 | *.launch 30 | .settings/ 31 | *.sublime-workspace 32 | tags 33 | 34 | # IDE - VSCode 35 | .vscode/* 36 | 37 | *.tgz 38 | 39 | *.txt 40 | *.gql 41 | 42 | # Generated Docusaurus files 43 | .docusaurus/ 44 | .cache-loader/ 45 | 46 | .nx/cache 47 | .nx/workspace-data -------------------------------------------------------------------------------- /apps/docs/src/components/Header/SkipToContent.astro: -------------------------------------------------------------------------------- 1 | --- 2 | type Props = {}; 3 | --- 4 | 5 | 6 | 7 | 27 | -------------------------------------------------------------------------------- /benchmarks/interceptor/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "benchmark-interceptor", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "benchmarks/interceptor/src", 6 | "targets": { 7 | "bench": { 8 | "executor": "nx:run-commands", 9 | "options": { 10 | "cwd": "benchmarks/interceptor", 11 | "commands": [ 12 | "../../node_modules/.bin/tsc -p tsconfig.build.json", 13 | "node -r module-alias/register dist/benchmarks/interceptor/src/main" 14 | ], 15 | "parallel": false 16 | } 17 | } 18 | }, 19 | "implicitDependencies": [] 20 | } 21 | -------------------------------------------------------------------------------- /integration/src/shared/server-exception.filter.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentsHost, Catch, HttpException, Optional } from '@nestjs/common'; 2 | import { BaseRpcExceptionFilter } from '@nestjs/microservices'; 3 | import { OgmaFilterService } from '@ogma/nestjs-module'; 4 | import { Observable, throwError } from 'rxjs'; 5 | 6 | @Catch() 7 | export class ExceptionFilter extends BaseRpcExceptionFilter { 8 | constructor(@Optional() private readonly service?: OgmaFilterService) { 9 | super(); 10 | } 11 | catch(exception: HttpException, host: ArgumentsHost): Observable { 12 | this.service?.log(exception, host); 13 | return throwError(() => exception); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /integration/src/grpc/client/grpc-client.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { ClientsModule, Transport } from '@nestjs/microservices'; 3 | import { join } from 'path'; 4 | 5 | import { GrpcClientController } from './grpc-client.controller'; 6 | 7 | @Module({ 8 | imports: [ 9 | ClientsModule.register([ 10 | { 11 | transport: Transport.GRPC, 12 | name: 'GRPC_SERVICE', 13 | options: { 14 | package: 'hello', 15 | protoPath: join(__dirname, '..', 'hello/hello.proto'), 16 | }, 17 | }, 18 | ]), 19 | ], 20 | controllers: [GrpcClientController], 21 | }) 22 | export class GrpcClientModule {} 23 | -------------------------------------------------------------------------------- /packages/nestjs-module/test/ogma-module.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test } from '@nestjs/testing'; 2 | import { suite } from 'uvu'; 3 | import { ok } from 'uvu/assert'; 4 | 5 | import { OgmaModule, OgmaModuleOptions } from '../src'; 6 | 7 | const noIntOptions = {}; 8 | 9 | const allOptions: OgmaModuleOptions = {}; 10 | const OgmaModuleSuite = suite('Ogma Module'); 11 | for (const options of [noIntOptions, undefined, allOptions]) { 12 | OgmaModuleSuite(`It should make the module for ${options}`, async () => { 13 | const mod = await Test.createTestingModule({ 14 | imports: [OgmaModule.forRoot(options)], 15 | }).compile(); 16 | ok(mod); 17 | }); 18 | } 19 | OgmaModuleSuite.run(); 20 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | commit-message: 13 | prefix: "chore(deps): " 14 | ignore: 15 | - dependency-name: "nx" 16 | - dependency-name: "@nx/*" 17 | -------------------------------------------------------------------------------- /packages/common/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "common", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/common/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/common", 11 | "main": "packages/common/src/index.ts", 12 | "tsConfig": "packages/common/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/common/package.json", 15 | "assets": ["packages/common/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": true 17 | } 18 | } 19 | }, 20 | "implicitDependencies": [] 21 | } 22 | -------------------------------------------------------------------------------- /packages/nestjs-module/test/ogma-context.decorator.spec.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu'; 2 | import { instance } from 'uvu/assert'; 3 | 4 | import { InjectOgma, InjectOgmaContext, InjectOgmaInterceptorOptions } from '../src'; 5 | 6 | const OgmaDecoratorsSuite = suite('Ogma Decorators'); 7 | OgmaDecoratorsSuite('should return Inject(Ogma_Instance)', () => { 8 | instance(InjectOgma(), Function); 9 | }); 10 | OgmaDecoratorsSuite('Should return Inject(OGMA_CONTEXT)', () => { 11 | instance(InjectOgmaContext(), Function); 12 | }); 13 | OgmaDecoratorsSuite('Should return Inject(OGMA_INTERCEPTOR_OPTIONS)', () => { 14 | instance(InjectOgmaInterceptorOptions(), Function); 15 | }); 16 | 17 | OgmaDecoratorsSuite.run(); 18 | -------------------------------------------------------------------------------- /integration/src/ws/ws.filter.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ArgumentsHost, 3 | Catch, 4 | ExceptionFilter as NestExceptionFilter, 5 | HttpException, 6 | } from '@nestjs/common'; 7 | import { OgmaFilterService } from '@ogma/nestjs-module'; 8 | 9 | @Catch() 10 | export class ExceptionFilter implements NestExceptionFilter { 11 | constructor(private readonly service: OgmaFilterService) {} 12 | catch(exception: HttpException, host: ArgumentsHost) { 13 | this.service.log(exception, host); 14 | const client = host.switchToWs().getClient(); 15 | if (client._isServer) { 16 | return client.send('exception'); 17 | } else { 18 | return client.emit('exception', exception.message); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/common/src/stream.interface.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A simple type to allow for easy use of the `ogma` library on front and backend 3 | * abstracted away from the NodeJS `WritableStream`, though inspiration was drawn from it 4 | */ 5 | export interface OgmaStream { 6 | /** 7 | * The method for actually writing the log. This is made to be as open ended as possible for great extensibility. 8 | */ 9 | write: (message: unknown) => unknown; 10 | /** 11 | * A utility method to determine if color can be used. This should usually return a 1, 4, 8, or 24. 12 | * @see https://nodejs.org/dist/latest-v14.x/docs/api/tty.html#tty_writestream_getcolordepth_env 13 | */ 14 | getColorDepth?: () => number; 15 | } 16 | -------------------------------------------------------------------------------- /packages/platform-rabbitmq/src/rabbitmq-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | import { RmqContext } from '@nestjs/microservices'; 3 | import { Parser, RpcInterceptorService } from '@ogma/nestjs-module'; 4 | 5 | @Parser('rpc') 6 | export class RabbitMqParser extends RpcInterceptorService { 7 | getCallPoint(context: ExecutionContext) { 8 | return this.getClient(context).getPattern(); 9 | } 10 | 11 | getCallerIp(context: ExecutionContext) { 12 | const data = this.getData<{ ip: string }>(context); 13 | return data.ip || ''; 14 | } 15 | 16 | getMethod() { 17 | return 'RabbitMQ'; 18 | } 19 | 20 | getProtocol() { 21 | return 'amqp'; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/platform-kafka/src/kafka-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | import { KafkaContext } from '@nestjs/microservices'; 3 | import { Parser, RpcInterceptorService } from '@ogma/nestjs-module'; 4 | 5 | @Parser('rpc') 6 | export class KafkaParser extends RpcInterceptorService { 7 | getCallPoint(context: ExecutionContext) { 8 | return this.getClient(context).getTopic(); 9 | } 10 | 11 | getCallerIp(context: ExecutionContext) { 12 | const data = this.getData<{ value?: { ip?: string } }>(context); 13 | return data?.value?.ip || ''; 14 | } 15 | 16 | getMethod() { 17 | return 'Kafka'; 18 | } 19 | 20 | getProtocol() { 21 | return 'kafka'; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/platform-nats/src/nats-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | import { NatsContext } from '@nestjs/microservices'; 3 | import { Parser, RpcInterceptorService } from '@ogma/nestjs-module'; 4 | 5 | @Parser('rpc') 6 | export class NatsParser extends RpcInterceptorService { 7 | getCallPoint(context: ExecutionContext) { 8 | const client = this.getClient(context); 9 | return client.getSubject(); 10 | } 11 | 12 | getCallerIp(context: ExecutionContext) { 13 | const data = this.getData<{ ip: string }>(context); 14 | return data.ip || ''; 15 | } 16 | 17 | getMethod() { 18 | return 'NATS'; 19 | } 20 | 21 | getProtocol() { 22 | return 'nats'; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/logger/src/utils/colorize.ts: -------------------------------------------------------------------------------- 1 | import { Color, OgmaSimpleType } from '@ogma/common'; 2 | import { style as styler, Styler } from '@ogma/styler'; 3 | 4 | const colorizeMap: Record = { 5 | [Color.BLACK]: 'black', 6 | [Color.RED]: 'red', 7 | [Color.GREEN]: 'green', 8 | [Color.YELLOW]: 'yellow', 9 | [Color.BLUE]: 'blue', 10 | [Color.MAGENTA]: 'magenta', 11 | [Color.CYAN]: 'cyan', 12 | [Color.WHITE]: 'white', 13 | }; 14 | 15 | export function colorize( 16 | value: OgmaSimpleType, 17 | color: Color = Color.WHITE, 18 | style: Styler = styler, 19 | useColor = true, 20 | ): string { 21 | if (useColor) { 22 | return style[colorizeMap[color]].apply(value); 23 | } 24 | 25 | return value.toString(); 26 | } 27 | -------------------------------------------------------------------------------- /packages/platform-redis/src/redis-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | import { RedisContext } from '@nestjs/microservices'; 3 | import { Parser, RpcInterceptorService } from '@ogma/nestjs-module'; 4 | 5 | @Parser('rpc') 6 | export class RedisParser extends RpcInterceptorService { 7 | getCallPoint(context: ExecutionContext): string { 8 | return this.getClient(context).getChannel(); 9 | } 10 | 11 | getCallerIp(context: ExecutionContext): any { 12 | const data = this.getData<{ ip: string }>(context); 13 | return data?.ip || ''; 14 | } 15 | 16 | getProtocol(): string { 17 | return 'redis'; 18 | } 19 | 20 | getMethod(): string { 21 | return 'REDIS'; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /benchmarks/interceptor/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Delete, Get, Patch, Post, Put } from '@nestjs/common'; 2 | 3 | import { AppService } from './app.service'; 4 | 5 | @Controller() 6 | export class AppController { 7 | constructor(private readonly appService: AppService) {} 8 | 9 | @Post() 10 | postHello() { 11 | return this.appService.getHello(); 12 | } 13 | 14 | @Patch() 15 | patchHello() { 16 | return this.appService.getHello(); 17 | } 18 | 19 | @Put() 20 | putHello() { 21 | return this.appService.getHello(); 22 | } 23 | 24 | @Delete() 25 | deleteHello() { 26 | return this.appService.getHello(); 27 | } 28 | 29 | @Get() 30 | getHello() { 31 | return this.appService.getHello(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /integration/src/kafka/client/kafka-client.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { ClientsModule, Transport } from '@nestjs/microservices'; 3 | 4 | import { KafkaClientController } from './kafka-client.controller'; 5 | 6 | @Module({ 7 | imports: [ 8 | ClientsModule.register([ 9 | { 10 | name: 'KAFKA_SERVICE', 11 | transport: Transport.KAFKA, 12 | options: { 13 | client: { 14 | clientId: 'client', 15 | brokers: ['localhost:9092'], 16 | }, 17 | consumer: { 18 | groupId: 'client-consumer', 19 | }, 20 | }, 21 | }, 22 | ]), 23 | ], 24 | controllers: [KafkaClientController], 25 | }) 26 | export class KafkaClientModule {} 27 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [jmcdo29]# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /integration/test/utils/index.ts: -------------------------------------------------------------------------------- 1 | import { OgmaFilterService, OgmaInterceptor, OgmaService } from '@ogma/nestjs-module'; 2 | 3 | process.stdout.getColorDepth = () => 8; 4 | export * from './createModule'; 5 | export * from './matcher'; 6 | export * from './ws-promise'; 7 | export const hello = { hello: 'world' }; 8 | 9 | export const reportValues = ( 10 | ogma: OgmaService, 11 | logs: Parameters[], 12 | ) => { 13 | if (process.env.CI) { 14 | return; 15 | } 16 | console.log('\n'); 17 | for (const log of logs) { 18 | ogma.info(log[0], { 19 | context: log[1] 20 | ? `${log[1]?.getClass().name}#${log[1]?.getHandler().name}` 21 | : 'ExceptionFilter', 22 | correlationId: log[2] ?? '', 23 | }); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/interceptor/providers/noop-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | import { AbstractInterceptorService } from './abstract-interceptor.service'; 4 | 5 | @Injectable() 6 | export class NoopInterceptorService extends AbstractInterceptorService { 7 | getCallerIp(): string[] | string { 8 | return 'caller ip'; 9 | } 10 | 11 | getCallPoint(): string { 12 | return 'call point'; 13 | } 14 | 15 | getStatus(): string { 16 | return 'status'; 17 | } 18 | 19 | getMethod(): string { 20 | return 'method'; 21 | } 22 | 23 | getProtocol(): string { 24 | return 'protocol'; 25 | } 26 | 27 | setRequestId(): void { 28 | return; 29 | } 30 | 31 | getRequestId() { 32 | return 'correlationId'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/platform-socket.io/src/socket-io-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | import { MESSAGE_METADATA } from '@nestjs/websockets/constants'; 3 | import { Parser, WebsocketInterceptorService } from '@ogma/nestjs-module'; 4 | 5 | @Parser('ws') 6 | export class SocketIOParser extends WebsocketInterceptorService { 7 | getCallPoint(context: ExecutionContext): string { 8 | return this.reflector.get(MESSAGE_METADATA, context.getHandler()); 9 | } 10 | 11 | getCallerIp(context: ExecutionContext): string[] | string { 12 | const client = this.getClient(context); 13 | return client.handshake.address; 14 | } 15 | 16 | getProtocol(): string { 17 | return 'WS'; 18 | } 19 | 20 | getMethod(): string { 21 | return 'socket.io'; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/platform-tcp/README.md: -------------------------------------------------------------------------------- 1 | # `@ogma/platform-tcp` 2 | 3 | The `TcpParser` parser for the `OgmaInterceptor`. This plugin class parses TCP request and response object to be able to successfully log the data about the request. For more information, check out [the @ogma/nestjs-module](../nestjs-module/README.md) documentation. 4 | 5 | ## Installation 6 | 7 | Nothing special, standard `npm i @ogma/platform-tcp` or `yarn add @ogma/platform-tcp` 8 | 9 | ## Usage 10 | 11 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 12 | 13 | ```ts 14 | @Module( 15 | OgmaModule.forRoot({ 16 | interceptor: { 17 | rpc: TcpParser 18 | } 19 | }) 20 | ) 21 | export class AppModule {} 22 | ``` 23 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/http/overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: overview 3 | title: HTTP Overview 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | Ogma has two primary parsers for HTTP request logging, depending on the underlying HTTP adapter you're using, [`@ogma/platform-express`](/en/nestjs/http/platform-express) and [`@ogma/platform-fastify`](/en/nestjs/http/platform-fastify). These packages are almost identical, with the only differences being some of the underlying types, to have stronger typing to match with the adapter. Either of these, or a [custom adapter](/en/nestjs/custom) are available to pass to the `providers` array for Ogma to find. 8 | 9 | ``` 10 | [2021-09-06T18:50:22.767Z] [INFO] [jay-pop] [Express] [138639] [1630954222762841] [HttpController#getHello] ::1 - GET / HTTP/1.1 200 3ms - 17 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/logger/src/interfaces/ogma-print-options.ts: -------------------------------------------------------------------------------- 1 | export interface OgmaPrintOptions { 2 | /** 3 | * Extra context you can add to the log e.g. the calling method 4 | * @default '' 5 | */ 6 | context?: string; 7 | /** 8 | * Extra information you can add to the log. Not sure why you'd want to override the application, but you can. 9 | * @default '' 10 | */ 11 | application?: string; 12 | /** 13 | * A field you can add to allow for log tracing 14 | * @default '' 15 | */ 16 | correlationId?: string; 17 | /** 18 | * set this option to `true` to enable ogma to log multiple items each on a new line, just like 19 | * `console.log('Hello', 'how', 'are', 'you?')`. This will only effect the logs if the first parameter 20 | * is an array 21 | */ 22 | each?: boolean; 23 | [key: string]: unknown; 24 | } 25 | -------------------------------------------------------------------------------- /packages/platform-express/README.md: -------------------------------------------------------------------------------- 1 | # `@ogma/platform-express` 2 | 3 | The `ExpressInterceptorParser` parser for the `OgmaInterceptor`. This plugin class parses Express request and response object to be able to successfully log the data about the request. For more information, check out [the @ogma/nestjs-module](../nestjs-module/README.md) documentation. 4 | 5 | ## Installation 6 | 7 | Nothing special, standard `npm i @ogma/platform-express` or `yarn add @ogma/platform-express` 8 | 9 | ## Usage 10 | 11 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 12 | 13 | ```ts 14 | @Module( 15 | OgmaModule.forRoot({ 16 | interceptor: { 17 | http: ExpressParser 18 | } 19 | }) 20 | ) 21 | export class AppModule {} 22 | ``` 23 | -------------------------------------------------------------------------------- /packages/platform-fastify/README.md: -------------------------------------------------------------------------------- 1 | # `@ogma/platform-fastify` 2 | 3 | The `FastifyInterceptorParser` parser for the `OgmaInterceptor`. This plugin class parses Fastify request and response object to be able to successfully log the data about the request. For more information, check out [the @ogma/nestjs-module](../nestjs-module/README.md) documentation. 4 | 5 | ## Installation 6 | 7 | Nothing special, standard `npm i @ogma/platform-fastify` or `yarn add @ogma/platform-fastify` 8 | 9 | ## Usage 10 | 11 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 12 | 13 | ```ts 14 | @Module( 15 | OgmaModule.forRoot({ 16 | interceptor: { 17 | http: FastifyParser 18 | } 19 | }) 20 | ) 21 | export class AppModule {} 22 | ``` 23 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/rpc/tcp.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: tcp 3 | title: Platform TCP 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | The `TcpParser` parser for the `OgmaInterceptor`. This plugin class parses TCP request and response object to be able to successfully log the data about the request. For more information, check out the [@ogma/nestjs-module](/en/nestjs/module) documentation. 8 | 9 | ## Installation 10 | 11 | Nothing special, standard `npm i @ogma/platform-tcp` or `yarn add @ogma/platform-tcp` 12 | 13 | ## Usage 14 | 15 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 16 | 17 | ```ts 18 | @Module({ 19 | imports: [OgmaModule.forRoot({})], 20 | providers: [TcpParser] 21 | }) 22 | export class AppModule {} 23 | ``` 24 | -------------------------------------------------------------------------------- /packages/platform-mqtt/src/mqtt-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | import { MqttContext } from '@nestjs/microservices'; 3 | import { Parser, RpcInterceptorService } from '@ogma/nestjs-module'; 4 | 5 | @Parser('rpc') 6 | export class MqttParser extends RpcInterceptorService { 7 | getCallPoint(context: ExecutionContext): string { 8 | return this.getClient(context).getTopic(); 9 | } 10 | 11 | getCallerIp(context: ExecutionContext): string { 12 | const client = this.getClient(context); 13 | const packet = client.getPacket(); 14 | const payload = JSON.parse(packet.payload.toString()); 15 | return payload.data?.ip || ''; 16 | } 17 | 18 | getMethod(): string { 19 | return 'MQTT'; 20 | } 21 | 22 | getProtocol(): string { 23 | return 'mqtt'; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/rpc/grpc.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: grpc 3 | title: Platform gRPC 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | The `GrpcParser` parser for the `OgmaInterceptor`. This plugin class parses gRPC request and response object to be able to successfully log the data about the request. For more information, check out the [@ogma/nestjs-module](/en/nestjs/module) documentation. 8 | 9 | ## Installation 10 | 11 | Nothing special, standard `npm i @ogma/platform-grpc` or `yarn add @ogma/platform-grpc` 12 | 13 | ## Usage 14 | 15 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 16 | 17 | ```ts 18 | @Module({ 19 | imports: [OgmaModule.forRoot({})], 20 | providers: [GrpcParser] 21 | }) 22 | export class AppModule {} 23 | ``` 24 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/rpc/mqtt.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: mqtt 3 | title: Platform MQTT 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | The `MqttParser` parser for the `OgmaInterceptor`. This plugin class parses MQTT request and response object to be able to successfully log the data about the request. For more information, check out the [@ogma/nestjs-module](/en/nestjs/module) documentation. 8 | 9 | ## Installation 10 | 11 | Nothing special, standard `npm i @ogma/platform-mqtt` or `yarn add @ogma/platform-mqtt` 12 | 13 | ## Usage 14 | 15 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 16 | 17 | ```ts 18 | @Module({ 19 | imports: [OgmaModule.forRoot({})], 20 | providers: [MqttParser] 21 | }) 22 | export class AppModule {} 23 | ``` 24 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/rpc/nats.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: nats 3 | title: Platform Nats 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | The `NatsParser` parser for the `OgmaInterceptor`. This plugin class parses NATS request and response object to be able to successfully log the data about the request. For more information, check out the [@ogma/nestjs-module](/en/nestjs/module) documentation. 8 | 9 | ## Installation 10 | 11 | Nothing special, standard `npm i @ogma/platform-nats` or `yarn add @ogma/platform-nats` 12 | 13 | ## Usage 14 | 15 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 16 | 17 | ```ts 18 | @Module({ 19 | imports: [OgmaModule.forRoot({})], 20 | providers: [NatsParser] 21 | }) 22 | export class AppModule {} 23 | ``` 24 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/rpc/kafka.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: kafka 3 | title: Platform Kafka 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | The `KafkaParser` parser for the `OgmaInterceptor`. This plugin class parses Kafka request and response object to be able to successfully log the data about the request. For more information, check out the [@ogma/nestjs-module](/en/nestjs/module) documentation. 8 | 9 | ## Installation 10 | 11 | Nothing special, standard `npm i @ogma/platform-kafka` or `yarn add @ogma/platform-kafka` 12 | 13 | ## Usage 14 | 15 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 16 | 17 | ```ts 18 | @Module({ 19 | imports: [OgmaModule.forRoot({})], 20 | providers: [KafkaParser] 21 | }) 22 | export class AppModule {} 23 | ``` 24 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/rpc/redis.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: redis 3 | title: Platform Redis 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | The `RedisParser` parser for the `OgmaInterceptor`. This plugin class parses Redis request and response object to be able to successfully log the data about the request. For more information, check out the [@ogma/nestjs-module](/en/nestjs/module) documentation. 8 | 9 | ## Installation 10 | 11 | Nothing special, standard `npm i @ogma/platform-redis` or `yarn add @ogma/platform-redis` 12 | 13 | ## Usage 14 | 15 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 16 | 17 | ```ts 18 | @Module({ 19 | imports: [OgmaModule.forRoot({})], 20 | providers: [RedisParser] 21 | }) 22 | export class AppModule {} 23 | ``` 24 | -------------------------------------------------------------------------------- /packages/nestjs-module/test/skip.decorator.spec.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu'; 2 | import { not, ok } from 'uvu/assert'; 3 | 4 | import { OgmaSkip } from '../src'; 5 | import { OGMA_INTERCEPTOR_SKIP } from '../src/ogma.constants'; 6 | 7 | const OgmaSkipSuite = suite('OgmaSkip'); 8 | OgmaSkipSuite('It should work on an entire class', () => { 9 | @OgmaSkip() 10 | class TestClass {} 11 | ok(Reflect.getMetadata(OGMA_INTERCEPTOR_SKIP, TestClass)); 12 | }); 13 | OgmaSkipSuite('It should work on a single method', () => { 14 | class TestClass { 15 | @OgmaSkip() 16 | shouldSkip(): void { 17 | console.log('do nothing'); 18 | } 19 | } 20 | const testClass = new TestClass(); 21 | ok(Reflect.getMetadata(OGMA_INTERCEPTOR_SKIP, testClass.shouldSkip)); 22 | not.ok(Reflect.getMetadata(OGMA_INTERCEPTOR_SKIP, TestClass)); 23 | }); 24 | OgmaSkipSuite.run(); 25 | -------------------------------------------------------------------------------- /apps/docs/src/components/RightSidebar/RightSidebar.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import TableOfContents from './TableOfContents'; 3 | import MoreMenu from './MoreMenu.astro'; 4 | import type { MarkdownHeading } from 'astro'; 5 | 6 | type Props = { 7 | headings: MarkdownHeading[]; 8 | githubEditUrl: string; 9 | }; 10 | 11 | const { headings, githubEditUrl } = Astro.props as Props; 12 | --- 13 | 14 | 20 | 21 | 35 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/rpc/rabbitmq.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: rabbitmq 3 | title: Platform RabbitMQ 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | The `RabbitMqParser` parser for the `OgmaInterceptor`. This plugin class parses RabbitMQ request and response object to be able to successfully log the data about the request. For more information, check out the [@ogma/nestjs-module](/en/nestjs/module) documentation. 8 | 9 | ## Installation 10 | 11 | Nothing special, standard `npm i @ogma/platform-rabbitmq` or `yarn add @ogma/platform-rabbitmq` 12 | 13 | ## Usage 14 | 15 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 16 | 17 | ```ts 18 | @Module({ 19 | imports: [OgmaModule.forRoot({})], 20 | providers: [RabbitMqParser] 21 | }) 22 | export class AppModule {} 23 | ``` 24 | -------------------------------------------------------------------------------- /integration/src/kafka/server/kafka-server.controller.ts: -------------------------------------------------------------------------------- 1 | import { BadRequestException, Controller, UseFilters } from '@nestjs/common'; 2 | import { MessagePattern } from '@nestjs/microservices'; 3 | import { OgmaSkip } from '@ogma/nestjs-module'; 4 | 5 | import { AppService } from '../../app.service'; 6 | import { ExceptionFilter } from './../../shared/server-exception.filter'; 7 | 8 | @Controller() 9 | export class KafkaServerController { 10 | constructor(private readonly service: AppService) {} 11 | 12 | @MessagePattern('say.hello') 13 | sayHello() { 14 | return this.service.getHello(); 15 | } 16 | 17 | @UseFilters(ExceptionFilter) 18 | @MessagePattern('say.error') 19 | sayError() { 20 | throw new BadRequestException('Borked'); 21 | } 22 | 23 | @OgmaSkip() 24 | @MessagePattern('say.skip') 25 | saySkip() { 26 | return this.service.getHello(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/rpc/overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: overview 3 | title: RPC Overview 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | Ogma also has parsers for every [built in transport](https://docs.nestjs.com/microservices/basics) that Nest has. Something important to note is that due to how microservices work, at least with Nest, to get the client IP of each request, it needs to be added to the payload sent by the client. [If anyone has a way to manage this more cleanly, a pull request is always appreciated](https://github.com/jmcdo29/ogma/compare). [You can find more information here](https://stackoverflow.com/questions/45235080/how-to-know-the-ip-address-of-mqtt-client-in-node-js). 8 | 9 | ``` 10 | [2021-09-06T18:50:28.351Z] [INFO] [jay-pop] [REDIS] [138626] [1630954228350937] [RpcServerController#getMessage] 127.0.0.1 - REDIS {"cmd":"message"} redis 200 1ms - 17 11 | ``` 12 | -------------------------------------------------------------------------------- /apps/docs/src/components/RightSidebar/ThemeToggleButton.css: -------------------------------------------------------------------------------- 1 | .theme-toggle { 2 | display: inline-flex; 3 | align-items: center; 4 | gap: 0.25em; 5 | padding: 0.33em 0.67em; 6 | border-radius: 99em; 7 | background-color: var(--theme-code-inline-bg); 8 | } 9 | 10 | .theme-toggle > label:focus-within { 11 | outline: 2px solid transparent; 12 | box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white; 13 | } 14 | 15 | .theme-toggle > label { 16 | color: var(--theme-code-inline-text); 17 | position: relative; 18 | display: flex; 19 | align-items: center; 20 | justify-content: center; 21 | opacity: 0.5; 22 | } 23 | 24 | .theme-toggle .checked { 25 | color: var(--theme-accent); 26 | opacity: 1; 27 | } 28 | 29 | input[name='theme-toggle'] { 30 | position: absolute; 31 | opacity: 0; 32 | top: 0; 33 | right: 0; 34 | bottom: 0; 35 | left: 0; 36 | z-index: -1; 37 | } 38 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": ["**/*"], 4 | "plugins": ["@nrwl/nx"], 5 | "overrides": [ 6 | { 7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 8 | "rules": { 9 | "@nrwl/nx/enforce-module-boundaries": [ 10 | "error", 11 | { 12 | "enforceBuildableLibDependency": true, 13 | "allow": [], 14 | "depConstraints": [ 15 | { 16 | "sourceTag": "*", 17 | "onlyDependOnLibsWithTags": ["*"] 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | }, 24 | { 25 | "files": ["*.ts", "*.tsx"], 26 | "extends": ["plugin:@nrwl/nx/typescript"], 27 | "rules": {} 28 | }, 29 | { 30 | "files": ["*.js", "*.jsx"], 31 | "extends": ["plugin:@nrwl/nx/javascript"], 32 | "rules": {} 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/http/platform-express.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: platform-express 3 | title: Platform Express 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | The `ExpressInterceptorParser` parser for the `OgmaInterceptor`. This plugin class parses Express request and response object to be able to successfully log the data about the request. For more information, check out the [@ogma/nestjs-module](/en/nestjs/module) documentation. 8 | 9 | ## Installation 10 | 11 | Nothing special, standard `npm i @ogma/platform-express` or `yarn add @ogma/platform-express` 12 | 13 | ## Usage 14 | 15 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 16 | 17 | ```ts 18 | @Module({ 19 | imports: [OgmaModule.forRoot({})], 20 | providers: [ExpressParser] 21 | }) 22 | export class AppModule {} 23 | ``` 24 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/http/platform-fastify.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: platform-fastify 3 | title: Platform Fastify 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | The `FastifyInterceptorParser` parser for the `OgmaInterceptor`. This plugin class parses Fastify request and response object to be able to successfully log the data about the request. For more information, check out the [@ogma/nestjs-module](/en/nestjs/module) documentation. 8 | 9 | ## Installation 10 | 11 | Nothing special, standard `npm i @ogma/platform-fastify` or `yarn add @ogma/platform-fastify` 12 | 13 | ## Usage 14 | 15 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 16 | 17 | ```ts 18 | @Module({ 19 | imports: [OgmaModule.forRoot({})], 20 | providers: [FastifyParser] 21 | }) 22 | export class AppModule {} 23 | ``` 24 | -------------------------------------------------------------------------------- /integration/src/grpc/server/grpc-server.controller.ts: -------------------------------------------------------------------------------- 1 | import { BadRequestException, Controller, UseFilters } from '@nestjs/common'; 2 | import { GrpcMethod } from '@nestjs/microservices'; 3 | import { OgmaSkip } from '@ogma/nestjs-module'; 4 | 5 | import { AppService } from '../../app.service'; 6 | import { ExceptionFilter } from './../../shared/server-exception.filter'; 7 | 8 | @Controller() 9 | export class GrpcServerController { 10 | constructor(private readonly service: AppService) {} 11 | 12 | @GrpcMethod('HelloService', 'SayHello') 13 | sayHello() { 14 | return this.service.getHello(); 15 | } 16 | 17 | @GrpcMethod('HelloService', 'SayError') 18 | @UseFilters(ExceptionFilter) 19 | sayError() { 20 | throw new BadRequestException('Borked'); 21 | } 22 | 23 | @OgmaSkip() 24 | @GrpcMethod('HelloService', 'SaySkip') 25 | saySkip() { 26 | return this.service.getHello(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/styler/src/style.enum.ts: -------------------------------------------------------------------------------- 1 | export const enum Style { 2 | NONE, 3 | BOLD, 4 | FAINT, 5 | ITALIC, 6 | UNDERLINE, 7 | BLINK, 8 | FASTBLINK, 9 | INVERT, 10 | CONCEAL, 11 | STRIKE, 12 | DOUBLEUNDERLINE = 21, 13 | REVEAL, 14 | BLACK = 30, 15 | RED, 16 | GREEN, 17 | YELLOW, 18 | BLUE, 19 | MAGENTA, 20 | CYAN, 21 | WHITE, 22 | COLOR, 23 | BLACKBG = 40, 24 | REDBG, 25 | GREENBG, 26 | YELLOWBG, 27 | BLUEBG, 28 | MAGENTABG, 29 | CYANBG, 30 | WHITEBG, 31 | BGCOLOR, 32 | FRAMED = 51, 33 | ENCIRCLED, 34 | OVERLINED, 35 | SUPER = 73, 36 | SUB, 37 | BRIGHTBLACK = 90, 38 | BRIGHTRED, 39 | BRIGHTGREEN, 40 | BRIGHTYELLOW, 41 | BRIGHTBLUE, 42 | BRIGHTMAGENTA, 43 | BRIGHTCYAN, 44 | BRIGHTWHIET, 45 | BRIGHTBLACKBG = 100, 46 | BRIGHTREDBG, 47 | BRIGHTGREENBG, 48 | BRIGHTYELLOWBG, 49 | BRIGHTBLUEBG, 50 | BRIGHTMAGENTABG, 51 | BIRGHTCYANBG, 52 | BRIGHTWHITEBG, 53 | } 54 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/interceptor/interfaces/interceptor-service.interface.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentsHost, ExecutionContext, HttpException } from '@nestjs/common'; 2 | 3 | import { OgmaInterceptorServiceOptions } from '../../interfaces/ogma-options.interface'; 4 | import { LogObject } from './log.interface'; 5 | 6 | export interface InterceptorMeta { 7 | context: ExecutionContext; 8 | startTime: number; 9 | options: OgmaInterceptorServiceOptions; 10 | correlationId: string; 11 | } 12 | 13 | export interface InterceptorService { 14 | getSuccessContext( 15 | data: number, 16 | context: ArgumentsHost, 17 | startTime: number, 18 | options: OgmaInterceptorServiceOptions, 19 | ): LogObject; 20 | 21 | getErrorContext( 22 | error: Error | HttpException, 23 | context: ArgumentsHost, 24 | startTime: number, 25 | options: OgmaInterceptorServiceOptions, 26 | ): LogObject; 27 | 28 | getStartTime(host: ArgumentsHost): number; 29 | } 30 | -------------------------------------------------------------------------------- /packages/platform-graphql/src/graphql-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | import { GqlExecutionContext } from '@nestjs/graphql'; 3 | import { Parser } from '@ogma/nestjs-module'; 4 | import { ExpressParser } from '@ogma/platform-express'; 5 | import { Request, Response } from 'express'; 6 | 7 | @Parser('graphql') 8 | export class GraphQLParser extends ExpressParser { 9 | protected reqName = 'req'; 10 | getMethod(context: ExecutionContext): string { 11 | return this.getContext(context).getInfo().operation.operation; 12 | } 13 | 14 | private getContext(context: ExecutionContext): GqlExecutionContext { 15 | return GqlExecutionContext.create(context); 16 | } 17 | getRequest(context: ExecutionContext): Request { 18 | return this.getContext(context).getContext().req; 19 | } 20 | 21 | getResponse(context: ExecutionContext): Response { 22 | return this.getContext(context).getContext().res; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/logger/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "logger", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/logger/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/logger", 11 | "main": "packages/logger/src/index.ts", 12 | "tsConfig": "packages/logger/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/logger/package.json", 15 | "assets": ["packages/logger/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": true 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/logger/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/logger/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /packages/styler/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "styler", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/styler/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/styler", 11 | "main": "packages/styler/src/index.ts", 12 | "tsConfig": "packages/styler/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/styler/package.json", 15 | "assets": ["packages/styler/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": true 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/styler/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/styler/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/ogma.constants.ts: -------------------------------------------------------------------------------- 1 | import { Reflector } from '@nestjs/core'; 2 | 3 | import { MODULE_OPTIONS_TOKEN } from './ogma-core.module-definition'; 4 | 5 | export const OGMA_INSTANCE = 'OGMA_INSTANCE'; 6 | export const OGMA_CONTEXT = 'OGMA_CONTEXT'; 7 | export const OGMA_OPTIONS = MODULE_OPTIONS_TOKEN; 8 | export const MESSAGE_METADATA = 'message'; 9 | export const MICROSERVICE_METADATA = 'microservices:pattern'; 10 | export const OGMA_INTERCEPTOR_OPTIONS = 'OGMA_INTERCEPTOR_OPTIONS'; 11 | export const OGMA_SERVICE_OPTIONS = 'OGMA_SERVICE_OPTIONS'; 12 | export const OGMA_INTERCEPTOR_SKIP = 'OGMA_INTERCEPTOR_SKIP'; 13 | export const OGMA_SERVICE_TOKEN = 'OGMA_SERVICE'; 14 | export const OGMA_REQUEST_SCOPED_SERVICE_TOKEN = 'OGMA_REQUEST_SCOPED_SERVICE'; 15 | export const OGMA_INTERCEPTOR_PROVIDERS = [OGMA_INTERCEPTOR_OPTIONS, Reflector]; 16 | export const OGMA_TRACE_METHOD_OPTION = 'OGMA_TRACE_METHOD_OPTION'; 17 | export const OGMA_CONTEXT_PARSER = 'OGMA_CONTEXT_PARSER'; 18 | -------------------------------------------------------------------------------- /integration/test/utils/createModule.ts: -------------------------------------------------------------------------------- 1 | import { DynamicModule, Type } from '@nestjs/common'; 2 | import { APP_INTERCEPTOR } from '@nestjs/core'; 3 | import { Test, TestingModule } from '@nestjs/testing'; 4 | import { AbstractInterceptorService, OgmaModule, OgmaModuleOptions } from '@ogma/nestjs-module'; 5 | import { OgmaInterceptor } from '@ogma/nestjs-module'; 6 | 7 | export async function createTestModule( 8 | AppModule: Type | DynamicModule, 9 | options: OgmaModuleOptions, 10 | providers: Type[] = [], 11 | ): Promise { 12 | const module = Test.createTestingModule({ 13 | imports: [AppModule, OgmaModule.forRoot(options)], 14 | providers: [ 15 | OgmaInterceptor, 16 | { 17 | provide: APP_INTERCEPTOR, 18 | useExisting: OgmaInterceptor, 19 | }, 20 | ...providers, 21 | ], 22 | }); 23 | if (!process.env.CI) { 24 | module.setLogger(console); 25 | } 26 | return module.compile(); 27 | } 28 | -------------------------------------------------------------------------------- /packages/cli/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cli", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/cli/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/cli", 11 | "main": "packages/cli/src/main.ts", 12 | "tsConfig": "packages/cli/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/cli/package.json", 15 | "assets": ["packages/cli/*.md"], 16 | "buildableProjectDepsInPackageJsonType": "dependencies", 17 | "updateBuildableProjectDepsInPackageJson": true 18 | } 19 | }, 20 | "test": { 21 | "executor": "nx-uvu:uvu", 22 | "options": { 23 | "rootDir": "./packages/cli/test", 24 | "coverage": true, 25 | "coverageConfig": "./packages/cli/.c8rc", 26 | "useSwc": true 27 | } 28 | } 29 | }, 30 | "implicitDependencies": [] 31 | } 32 | -------------------------------------------------------------------------------- /packages/platform-graphql-fastify/src/graphql-fastify-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | import { GqlExecutionContext } from '@nestjs/graphql'; 3 | import { Parser } from '@ogma/nestjs-module'; 4 | import { FastifyParser } from '@ogma/platform-fastify'; 5 | import { FastifyReply, FastifyRequest } from 'fastify'; 6 | 7 | @Parser('graphql') 8 | export class GraphQLFastifyParser extends FastifyParser { 9 | protected reqName = 'request'; 10 | getMethod(context: ExecutionContext): string { 11 | return this.getContext(context).getInfo().operation.operation; 12 | } 13 | 14 | private getContext(context: ExecutionContext): GqlExecutionContext { 15 | return GqlExecutionContext.create(context); 16 | } 17 | 18 | getRequest(context: ExecutionContext): FastifyRequest { 19 | return this.getContext(context).getContext().request; 20 | } 21 | 22 | getResponse(context: ExecutionContext): FastifyReply { 23 | return this.getContext(context).getContext().reply; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/platform-tcp/src/tcp-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | import { TcpContext } from '@nestjs/microservices'; 3 | import { Parser, RpcInterceptorService } from '@ogma/nestjs-module'; 4 | 5 | @Parser('rpc') 6 | export class TcpParser extends RpcInterceptorService { 7 | getCallPoint(context: ExecutionContext): string { 8 | return this.getClient(context).getPattern(); 9 | } 10 | 11 | getCallerIp(context: ExecutionContext): string { 12 | const client = this.getClient(context); 13 | const socket = client.getSocketRef().socket; 14 | return socket.remoteAddress + ':' + socket.remotePort; 15 | } 16 | 17 | getMethod(): string { 18 | return 'TCP'; 19 | } 20 | 21 | getProtocol(context: ExecutionContext): string { 22 | const client = this.getClient(context); 23 | return client.getSocketRef().socket.remoteFamily; 24 | } 25 | 26 | getClient(context: ExecutionContext): T { 27 | return super.getClient(context); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/platform-ws/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform-ws", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/platform-ws/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/platform-ws", 11 | "main": "packages/platform-ws/src/index.ts", 12 | "tsConfig": "packages/platform-ws/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/platform-ws/package.json", 15 | "assets": ["packages/platform-ws/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": false 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/platform-ws/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/platform-ws/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /benchmarks/interceptor/README.md: -------------------------------------------------------------------------------- 1 | # OgmaInterceptor Benchmarks 2 | 3 | - Benchmarks were made by setting up identical NestJS applications and attaching either the OgmaModule or [morgan](https://npmjs.org/morgan) via `app.use()`. 4 | - These benchmarks were only ran for an Express server, as morgan is only configured to work for Express servers. 5 | - Each request was made 10 time, and the time shown is the average response time for each request type. 6 | 7 | ## Results 8 | 9 | | Request Logger | GET | POST | PUT | PATCH | DELETE | 10 | | -------------- | ------ | ------ | ------ | ------ | ------ | 11 | | ogma | 3.5 ms | 3 ms | 3.1 ms | 3.3 ms | 3.3 ms | 12 | | morganDev | 3.3 ms | 2.9 ms | 3.3 ms | 3.1 ms | 3.1 ms | 13 | | morganCombined | 3.1 ms | 2.9 ms | 3.4 ms | 3 ms | 3.2 ms | 14 | | none | 3.1 ms | 3.2 ms | 3.3 ms | 3.2 ms | 3.2 ms | 15 | 16 | ## Information 17 | 18 | Benchmarks generated on Linux/linux x64 5.11.0-7614-generic ~Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz (cores/threads): 12 19 | -------------------------------------------------------------------------------- /packages/cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/cli", 3 | "version": "2.2.1", 4 | "description": "A CLI to re-hydrate JSON logs back to a dev readable format, colors included.", 5 | "keywords": [ 6 | "cli", 7 | "ogma", 8 | "logs", 9 | "logger", 10 | "hydrate", 11 | "nodejs" 12 | ], 13 | "author": "Jay McDoniel ", 14 | "homepage": "https://github.com/jmcdo29/ogma", 15 | "license": "MIT", 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/jmcdo29/ogma.git" 22 | }, 23 | "engines": { 24 | "node": ">=10" 25 | }, 26 | "bugs": { 27 | "url": "https://github.com/jmcdo29/ogma/issues" 28 | }, 29 | "dependencies": { 30 | "@nestjs/common": "^10.3.2", 31 | "@nestjs/core": "^10.3.2", 32 | "@ogma/common": "workspace:^1.0.0", 33 | "nest-commander": "3.9.0", 34 | "reflect-metadata": "0.2.1" 35 | }, 36 | "bin": { 37 | "ogma": "./src/main.js" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/logger/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/logger", 3 | "version": "3.4.0", 4 | "description": "A simple, no-nonsense logging package for NodeJS", 5 | "keywords": [ 6 | "logging", 7 | "colors", 8 | "cli", 9 | "terminal", 10 | "nodejs", 11 | "typescript" 12 | ], 13 | "author": "Jay McDoniel ", 14 | "homepage": "https://github.com/jmcdo29/ogma#readme", 15 | "license": "MIT", 16 | "engines": { 17 | "node": ">=10" 18 | }, 19 | "directories": { 20 | "lib": "lib" 21 | }, 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/jmcdo29/ogma.git" 28 | }, 29 | "bugs": { 30 | "url": "https://github.com/jmcdo29/ogma/issues" 31 | }, 32 | "dependencies": { 33 | "@ogma/common": "workspace:^1.0.0", 34 | "@ogma/styler": "workspace:^1.0.0", 35 | "fast-safe-stringify": "2.1.1", 36 | "on-exit-leak-free": "^2.1.0", 37 | "sonic-boom": "^3.2.1" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/platform-tcp/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform-tcp", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/platform-tcp/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/platform-tcp", 11 | "main": "packages/platform-tcp/src/index.ts", 12 | "tsConfig": "packages/platform-tcp/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/platform-tcp/package.json", 15 | "assets": ["packages/platform-tcp/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": false 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/platform-tcp/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/platform-tcp/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /integration/src/grpc/client/grpc-client.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, Inject, OnModuleInit, UseFilters } from '@nestjs/common'; 2 | import { ClientGrpc } from '@nestjs/microservices'; 3 | 4 | import { ExceptionFilter } from './../../shared/exception.filter'; 5 | import { HelloService } from './hello-service.interface'; 6 | 7 | @Controller() 8 | export class GrpcClientController implements OnModuleInit { 9 | private helloService: HelloService; 10 | 11 | constructor(@Inject('GRPC_SERVICE') private readonly grpc: ClientGrpc) {} 12 | 13 | async onModuleInit() { 14 | this.helloService = this.grpc.getService('HelloService'); 15 | } 16 | @Get() 17 | sayHello() { 18 | return this.helloService.sayHello({ ip: '127.0.0.1' }); 19 | } 20 | 21 | @Get('error') 22 | @UseFilters(ExceptionFilter) 23 | sayError() { 24 | return this.helloService.sayError({ ip: '127.0.0.1' }); 25 | } 26 | 27 | @Get('skip') 28 | saySkip() { 29 | return this.helloService.saySkip({ ip: '127.0.0.1' }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/nestjs-module/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nestjs-module", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/nestjs-module/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/nestjs-module", 11 | "main": "packages/nestjs-module/src/index.ts", 12 | "tsConfig": "packages/nestjs-module/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/nestjs-module/package.json", 15 | "assets": ["packages/nestjs-module/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": false 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/nestjs-module/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/nestjs-module/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /packages/platform-grpc/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform-grpc", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/platform-grpc/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/platform-grpc", 11 | "main": "packages/platform-grpc/src/index.ts", 12 | "tsConfig": "packages/platform-grpc/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/platform-grpc/package.json", 15 | "assets": ["packages/platform-grpc/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": false 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/platform-grpc/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/platform-grpc/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /packages/platform-mqtt/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform-mqtt", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/platform-mqtt/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/platform-mqtt", 11 | "main": "packages/platform-mqtt/src/index.ts", 12 | "tsConfig": "packages/platform-mqtt/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/platform-mqtt/package.json", 15 | "assets": ["packages/platform-mqtt/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": false 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/platform-mqtt/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/platform-mqtt/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /packages/platform-nats/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform-nats", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/platform-nats/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/platform-nats", 11 | "main": "packages/platform-nats/src/index.ts", 12 | "tsConfig": "packages/platform-nats/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/platform-nats/package.json", 15 | "assets": ["packages/platform-nats/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": false 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/platform-nats/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/platform-nats/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/interceptor/providers/websocket-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentsHost, Injectable } from '@nestjs/common'; 2 | 3 | import { AbstractInterceptorService } from './abstract-interceptor.service'; 4 | 5 | @Injectable() 6 | export abstract class WebsocketInterceptorService extends AbstractInterceptorService { 7 | getCallPoint(context: ArgumentsHost): string { 8 | return context.switchToWs().getPattern(); 9 | } 10 | 11 | /** 12 | * A helper method to get the websocket client from the Nest Execution Context 13 | * @param context execution context from Nest 14 | * @returns the client object for the websocket adapter 15 | */ 16 | getClient(context: ArgumentsHost) { 17 | return context.switchToWs().getClient(); 18 | } 19 | 20 | setRequestId(context: ArgumentsHost, requestId: any) { 21 | const client = this.getClient(context); 22 | client.requestId = requestId; 23 | } 24 | 25 | getRequestId(context: ArgumentsHost): any { 26 | return this.getClient(context).requestId; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /integration/test/nested-module.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test } from '@nestjs/testing'; 2 | import { createProviderToken } from '@ogma/nestjs-module'; 3 | import { stubMethod } from 'hanbi'; 4 | import { spec } from 'pactum'; 5 | import { test } from 'uvu'; 6 | import { equal, is } from 'uvu/assert'; 7 | 8 | import { NestedModule } from '../src/nested-module/app.module'; 9 | import { AppService } from '../src/nested-module/app.service'; 10 | 11 | test('Nested module should still work', async () => { 12 | const modRef = await Test.createTestingModule({ 13 | imports: [NestedModule], 14 | }).compile(); 15 | const app = modRef.createNestApplication(); 16 | const ogmaService = modRef.get(createProviderToken(AppService.name)); 17 | await app.listen(0); 18 | const ogmaSpy = stubMethod(ogmaService, 'log'); 19 | const baseUrl = await app.getUrl(); 20 | await spec().get(baseUrl.replace('[::1]', 'localhost')); 21 | is(ogmaSpy.callCount, 1); 22 | equal(ogmaSpy.firstCall.args[0], 'Hello NestedModule'); 23 | await app.close(); 24 | }); 25 | 26 | test.run(); 27 | -------------------------------------------------------------------------------- /packages/platform-kafka/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform-kafka", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/platform-kafka/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/platform-kafka", 11 | "main": "packages/platform-kafka/src/index.ts", 12 | "tsConfig": "packages/platform-kafka/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/platform-kafka/package.json", 15 | "assets": ["packages/platform-kafka/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": false 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/platform-kafka/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/platform-kafka/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /packages/platform-redis/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform-redis", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/platform-redis/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/platform-redis", 11 | "main": "packages/platform-redis/src/index.ts", 12 | "tsConfig": "packages/platform-redis/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/platform-redis/package.json", 15 | "assets": ["packages/platform-redis/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": false 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/platform-redis/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/platform-redis/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /packages/platform-express/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform-express", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/platform-express/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/platform-express", 11 | "main": "packages/platform-express/src/index.ts", 12 | "tsConfig": "packages/platform-express/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/platform-express/package.json", 15 | "assets": ["packages/platform-express/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": false 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/platform-express/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/platform-express/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /packages/platform-fastify/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform-fastify", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/platform-fastify/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/platform-fastify", 11 | "main": "packages/platform-fastify/src/index.ts", 12 | "tsConfig": "packages/platform-fastify/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/platform-fastify/package.json", 15 | "assets": ["packages/platform-fastify/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": false 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/platform-fastify/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/platform-fastify/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /packages/platform-graphql/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform-graphql", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/platform-graphql/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/platform-graphql", 11 | "main": "packages/platform-graphql/src/index.ts", 12 | "tsConfig": "packages/platform-graphql/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/platform-graphql/package.json", 15 | "assets": ["packages/platform-graphql/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": false 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/platform-graphql/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/platform-graphql/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /integration/src/kafka/client/kafka-client.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, Inject, OnModuleDestroy, OnModuleInit, UseFilters } from '@nestjs/common'; 2 | import { ClientKafka } from '@nestjs/microservices'; 3 | 4 | import { ExceptionFilter } from './../../shared/exception.filter'; 5 | 6 | @Controller() 7 | export class KafkaClientController implements OnModuleInit, OnModuleDestroy { 8 | constructor(@Inject('KAFKA_SERVICE') private readonly kafka: ClientKafka) {} 9 | 10 | async onModuleInit() { 11 | ['hello', 'error', 'skip'].forEach((key) => this.kafka.subscribeToResponseOf(`say.${key}`)); 12 | } 13 | 14 | async onModuleDestroy() { 15 | await this.kafka.close(); 16 | } 17 | 18 | @Get() 19 | sayHello() { 20 | return this.kafka.send('say.hello', { ip: '127.0.0.1' }); 21 | } 22 | 23 | @Get('error') 24 | @UseFilters(ExceptionFilter) 25 | sayError() { 26 | return this.kafka.send('say.error', { ip: '127.0.0.1' }); 27 | } 28 | 29 | @Get('skip') 30 | saySkip() { 31 | return this.kafka.send('say.skip', { ip: '127.0.0.1' }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/platform-rabbitmq/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform-rabbitmq", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/platform-rabbitmq/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/platform-rabbitmq", 11 | "main": "packages/platform-rabbitmq/src/index.ts", 12 | "tsConfig": "packages/platform-rabbitmq/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/platform-rabbitmq/package.json", 15 | "assets": ["packages/platform-rabbitmq/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": false 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/platform-rabbitmq/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/platform-rabbitmq/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /packages/platform-express/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/platform-express", 3 | "version": "5.1.0", 4 | "description": "A plugin for the OgmaInterceptor to properly handle HTTP requests from Express", 5 | "keywords": [ 6 | "express", 7 | "logging", 8 | "ogma", 9 | "nestjs", 10 | "interceptor", 11 | "http" 12 | ], 13 | "author": "Jay McDoniel ", 14 | "homepage": "https://github.com/jmcdo29/ogma#readme", 15 | "license": "MIT", 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/jmcdo29/ogma.git" 22 | }, 23 | "bugs": { 24 | "url": "https://github.com/jmcdo29/ogma/issues" 25 | }, 26 | "peerDependencies": { 27 | "@nestjs/platform-express": "^9.0.0 || ^10.0.0 || ^11.0.0", 28 | "@ogma/nestjs-module": "workspace:^5.4.0" 29 | }, 30 | "peerDependenciesMeta": { 31 | "@nestjs/platform-express": { 32 | "optional": false 33 | }, 34 | "@ogma/nestjs-module": { 35 | "optional": false 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/platform-socket.io/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform-socket.io", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/platform-socket.io/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/platform-socket.io", 11 | "main": "packages/platform-socket.io/src/index.ts", 12 | "tsConfig": "packages/platform-socket.io/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/platform-socket.io/package.json", 15 | "assets": ["packages/platform-socket.io/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": false 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/platform-socket.io/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/platform-socket.io/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /packages/platform-tcp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/platform-tcp", 3 | "version": "5.1.0", 4 | "description": "A plugin for the OgmaInterceptor to properly handle microservice requests from tcp protocols", 5 | "keywords": [ 6 | "tcp", 7 | "microservice", 8 | "logging", 9 | "ogma", 10 | "nestjs", 11 | "interceptor" 12 | ], 13 | "author": "Jay McDoniel ", 14 | "homepage": "https://github.com/jmcdo29/ogma#readme", 15 | "license": "MIT", 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/jmcdo29/ogma.git" 22 | }, 23 | "bugs": { 24 | "url": "https://github.com/jmcdo29/ogma/issues" 25 | }, 26 | "peerDependencies": { 27 | "@nestjs/microservices": "^9.0.0 || ^10.0.0 || ^11.0.0", 28 | "@ogma/nestjs-module": "workspace:^5.4.0" 29 | }, 30 | "peerDependenciesMeta": { 31 | "@nestjs/microservices": { 32 | "optional": false 33 | }, 34 | "@ogma/nestjs-module": { 35 | "optional": false 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | # The MIT License 2 | 3 | Copyright 2019-2022 Jay McDoniel, contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /benchmarks/logger/README.md: -------------------------------------------------------------------------------- 1 | # Ogma Logger Benchmarks 2 | 3 | Benchmarks were made by testing the logging capabilities of several loggers against each other. All loggers are writing to a writeStream of `/dev/null`. Each logger writes 100000 logs of each log type. Simple is a small string. JSON is a simple json, one key one value. Long is a 2000 random byte string. Deep is a deep JSON, including using the `globalThis`. All timings were made by using the `perf_hooks` module. 4 | 5 | ## Results 6 | 7 | | Logger | Simple | Long | JSON | Deep | 8 | | --------- | ------- | -------- | ------- | -------- | 9 | | Bunyan | 356.4ms | 4508.5ms | 388.1ms | 2245.3ms | 10 | | Ogma | 150.2ms | 1610.1ms | 249.9ms | 423.2ms | 11 | | OgmaMasks | 134.0ms | 1755.2ms | 258.9ms | 631.1ms | 12 | | OgmaJSON | 360.1ms | 4512.1ms | 565.4ms | 754.4ms | 13 | | Pino | 104.1ms | 3929.2ms | 109.9ms | 1773.0ms | 14 | | Winston | 316.9ms | 6494.4ms | 278.8ms | 519.1ms | 15 | 16 | ## Information 17 | 18 | Benchmarks generated on Linux/linux x64 5.15.86 ~Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz (cores/threads): 12 19 | -------------------------------------------------------------------------------- /integration/src/rpc/client/rpc-client.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, Inject, OnApplicationBootstrap, UseFilters } from '@nestjs/common'; 2 | import { ClientProxy } from '@nestjs/microservices'; 3 | 4 | import { ExceptionFilter } from './../../shared/exception.filter'; 5 | 6 | @Controller() 7 | export class RpcClientController implements OnApplicationBootstrap { 8 | constructor(@Inject('RPC-SERVICE') private readonly micro: ClientProxy) {} 9 | 10 | async onApplicationBootstrap() { 11 | await this.micro.connect(); 12 | } 13 | 14 | @Get() 15 | getMessage() { 16 | return this.micro.send({ cmd: 'message' }, { ip: '127.0.0.1' }); 17 | } 18 | 19 | @Get('error') 20 | @UseFilters(ExceptionFilter) 21 | getError() { 22 | return this.micro.send({ cmd: 'error' }, { ip: '127.0.0.1' }); 23 | } 24 | 25 | @Get('skip') 26 | getSkip() { 27 | return this.micro.send({ cmd: 'skip' }, { ip: '127.0.0.1' }); 28 | } 29 | 30 | @Get('fail-guard') 31 | @UseFilters(ExceptionFilter) 32 | failGuard() { 33 | return this.micro.send({ cmd: 'fail-guard' }, { ip: '127.0.0.1' }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/platform-fastify/src/fastify-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | import { HttpInterceptorService, Parser } from '@ogma/nestjs-module'; 3 | import { FastifyRequest } from 'fastify'; 4 | 5 | @Parser('http') 6 | export class FastifyParser extends HttpInterceptorService { 7 | getCallerIp(context: ExecutionContext): string[] | string { 8 | const req = this.getRequest(context); 9 | return req.ips && req.ips.length ? req.ips.join(' ') : req.ip; 10 | } 11 | 12 | getCallPoint(context: ExecutionContext): string { 13 | const req = this.getRequest(context); 14 | return req.raw.url; 15 | } 16 | 17 | getMethod(context: ExecutionContext): string { 18 | const req = this.getRequest(context); 19 | return req.raw.method || 'GET'; 20 | } 21 | 22 | getProtocol(context: ExecutionContext): string { 23 | const req = this.getRequest(context); 24 | return `HTTP/${req.raw.httpVersionMajor}.${req.raw.httpVersionMinor}`; 25 | } 26 | 27 | getRequest(context: ExecutionContext): FastifyRequest { 28 | return super.getRequest(context); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/graphql/overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: overview 3 | title: GraphQL Overview 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | Similar to the [HTTP parsers](/en/nestjs/http/overview) there are two main GQL parsers as well, one for each underlying HTTP adapter, as GQL in Nest is implemented through the HTTP adapter via a middleware from [`apollo-server`](https://www.apollographql.com/docs/apollo-server/). With graphql, all of the endpoints that are called will be `/graphql`, or whatever endpoint you decide to put your GraphQL server at. This is where the `[Controller#method]` context comes in handy, as it helps separate what query is being executed. Also, as GraphQL doesn't have the notion of HTTP statuses, the status will be inferred based on if it's a success or an error, and what the error type is. Ogma will map this back to HTTP status codes, if the exception is a Nest Exception, otherwise it will map to a 500. 8 | 9 | ``` 10 | [2021-09-06T18:50:23.326Z] [INFO] [jay-pop] [GraphQL Express] [138646] [1630954223323447] [GqlResolver#getQuery] ::1 - query /graphql HTTP/1.1 200 2ms - 17 11 | ``` 12 | -------------------------------------------------------------------------------- /integration/src/rpc/server/rpc-server.controller.ts: -------------------------------------------------------------------------------- 1 | import { BadRequestException, Controller, UseFilters, UseGuards } from '@nestjs/common'; 2 | import { MessagePattern } from '@nestjs/microservices'; 3 | import { OgmaSkip } from '@ogma/nestjs-module'; 4 | 5 | import { AppService } from '../../app.service'; 6 | import { FailGuard } from '../../shared/fail.guard'; 7 | import { ExceptionFilter } from './../../shared/server-exception.filter'; 8 | 9 | @Controller() 10 | export class RpcServerController { 11 | constructor(private readonly appService: AppService) {} 12 | 13 | @MessagePattern({ cmd: 'message' }) 14 | getMessage() { 15 | return this.appService.getHello(); 16 | } 17 | 18 | @MessagePattern({ cmd: 'error' }) 19 | @UseFilters(ExceptionFilter) 20 | getError() { 21 | throw new BadRequestException('Borked'); 22 | } 23 | 24 | @OgmaSkip() 25 | @MessagePattern({ cmd: 'skip' }) 26 | getSkip() { 27 | return this.appService.getHello(); 28 | } 29 | 30 | @MessagePattern({ cmd: 'fail-guard' }) 31 | @UseFilters(ExceptionFilter) 32 | @UseGuards(FailGuard) 33 | failGuard() { 34 | /* no op */ 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/styler/src/index.ts: -------------------------------------------------------------------------------- 1 | import { Styler } from './styler'; 2 | 3 | /** 4 | * A class for adding class to your strings. Most of the styles here follow a predictable pattern 5 | * 6 | * #### Use 7 | * 8 | * start off with `style` and then chain whatever you want to apply to the string. Last foreground and background color will be used. After done with the styles, chain `.apply(valueToApplyTo)` and you'll have your proper SGR string 9 | * 10 | * e.g. `style.red.blueBg.underline.apply('Hello World!');` 11 | * 12 | * #### Colors 13 | * 14 | * if the color is prefixed with a `b` it's the "bright" variant 15 | * if it is suffixed with a `bg` it applies to the background 16 | * if the color you want does not exist as a named color you can use `color`. Read more on the method itself 17 | * 18 | * #### Styles 19 | * 20 | * if it's not a color, it's a style or effect. All of the information about these styles and effects ca be found in the related link 21 | * 22 | * @link https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters 23 | */ 24 | export const style = new Styler(); 25 | export * from './styler'; 26 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | rules: { 4 | 'type-enum': [ 5 | 2, 6 | 'always', 7 | [ 8 | 'build', 9 | 'ci', 10 | 'chore', 11 | 'revert', 12 | 'feat', 13 | 'fix', 14 | 'improvement', 15 | 'docs', 16 | 'style', 17 | 'refactor', 18 | 'perf', 19 | 'test', 20 | ], 21 | ], 22 | 'scope-enum': [ 23 | 2, 24 | 'always', 25 | [ 26 | 'all', 27 | 'logger', 28 | 'service', 29 | 'module', 30 | 'interceptor', 31 | 'integration', 32 | 'deps', 33 | 'docs', 34 | 'release', 35 | 'express', 36 | 'socket.io', 37 | 'fastify', 38 | 'ws', 39 | 'tcp', 40 | 'kafka', 41 | 'gql', 42 | 'gql-fastify', 43 | 'grpc', 44 | 'mqtt', 45 | 'nats', 46 | 'rmq', 47 | 'redis', 48 | 'benchmarks', 49 | 'cli', 50 | 'styler', 51 | 'common', 52 | ], 53 | ], 54 | }, 55 | }; 56 | -------------------------------------------------------------------------------- /packages/platform-graphql-fastify/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform-graphql-fastify", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "type": "library", 5 | "sourceRoot": "packages/platform-graphql-fastify/src", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/js:tsc", 9 | "options": { 10 | "outputPath": "dist/platform-graphql-fastify", 11 | "main": "packages/platform-graphql-fastify/src/index.ts", 12 | "tsConfig": "packages/platform-graphql-fastify/tsconfig.build.json", 13 | "clean": true, 14 | "packageJson": "packages/platform-graphql-fastify/package.json", 15 | "assets": ["packages/platform-graphql-fastify/*.md"], 16 | "updateBuildableProjectDepsInPackageJson": false 17 | } 18 | }, 19 | "test": { 20 | "executor": "nx-uvu:uvu", 21 | "options": { 22 | "rootDir": "./packages/platform-graphql-fastify/test", 23 | "coverage": true, 24 | "coverageConfig": "./packages/platform-graphql-fastify/.c8rc", 25 | "useSwc": true 26 | } 27 | } 28 | }, 29 | "implicitDependencies": [] 30 | } 31 | -------------------------------------------------------------------------------- /packages/instrumentation/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "instrumentation", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/instrumentation/src", 5 | "projectType": "library", 6 | "tags": [], 7 | "targets": { 8 | "build": { 9 | "executor": "@nrwl/js:tsc", 10 | "outputs": ["{options.outputPath}"], 11 | "options": { 12 | "outputPath": "dist/instrumentation", 13 | "main": "packages/instrumentation/src/main.ts", 14 | "tsConfig": "packages/instrumentation/tsconfig.build.json", 15 | "clean": true, 16 | "packageJson": "packages/instrumentation/package.json", 17 | "assets": ["packages/instrumentation/*.md"], 18 | "buildableProjectDepsInPackageJsonType": "dependencies", 19 | "updateBuildableProjectDepsInPackageJson": true 20 | } 21 | }, 22 | 23 | "test": { 24 | "executor": "nx-uvu:uvu", 25 | "options": { 26 | "rootDir": "./packages/instrumentation/test", 27 | "coverage": true, 28 | "coverageConfig": "./packages/instrumentation/.c8rc", 29 | "useSwc": true 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/platform-fastify/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/platform-fastify", 3 | "version": "5.1.0", 4 | "description": "A plugin for the OgmaInterceptor to properly handle HTTP requests from Fastify", 5 | "keywords": [ 6 | "fastify", 7 | "logging", 8 | "http", 9 | "ogma", 10 | "nestjs", 11 | "interceptor" 12 | ], 13 | "author": "Jay McDoniel ", 14 | "homepage": "https://github.com/jmcdo29/ogma#readme", 15 | "license": "MIT", 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/jmcdo29/ogma.git" 22 | }, 23 | "bugs": { 24 | "url": "https://github.com/jmcdo29/ogma/issues" 25 | }, 26 | "peerDependencies": { 27 | "@nestjs/platform-fastify": "^9.0.0 || ^10.0.0 || ^11.0.0", 28 | "@ogma/nestjs-module": "workspace:^5.4.0", 29 | "fastify": ">=4.0.0" 30 | }, 31 | "peerDependenciesMeta": { 32 | "@nestjs/platform-fastify": { 33 | "optional": false 34 | }, 35 | "@ogma/nestjs-module": { 36 | "optional": false 37 | }, 38 | "fastify": { 39 | "optional": false 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/platform-nats/README.md: -------------------------------------------------------------------------------- 1 | # `@ogma/platform-nats` 2 | 3 | The `NatsParser` parser for the `OgmaInterceptor`. This plugin class parses NATS request and response object to be able to successfully log the data about the request. For more information, check out [the @ogma/nestjs-module](../nestjs-module/README.md) documentation. 4 | 5 | ## Installation 6 | 7 | Nothing special, standard `npm i @ogma/platform-nats` or `yarn add @ogma/platform-nats` 8 | 9 | ## Usage 10 | 11 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 12 | 13 | ```ts 14 | @Module( 15 | OgmaModule.forRoot({ 16 | interceptor: { 17 | rpc: NatsParser 18 | } 19 | }) 20 | ) 21 | export class AppModule {} 22 | ``` 23 | 24 | ## Important Notes 25 | 26 | Because of how NATS requests are sent and the data available in them, to get the IP address in the request log, an IP property must be sent in the payload. This is the only way to get the IP address. If an IP property is not sent, the interceptor will use an empty string. This is for the same reason as in the [@ogma/platform-mqtt](../platform-mqtt) docs. 27 | -------------------------------------------------------------------------------- /tools/remove-main-from-package.ts: -------------------------------------------------------------------------------- 1 | import { readdirSync, readFileSync, writeFileSync } from 'fs'; 2 | 3 | const mainJson = JSON.parse(readFileSync('./package.json').toString()); 4 | const mainDeps = mainJson.devDependencies; 5 | 6 | const dirs = readdirSync('packages'); 7 | dirs.forEach((dir) => { 8 | const tsConfig = { 9 | extends: './tsconfig.json', 10 | compilerOptions: { 11 | sourceMap: true, 12 | }, 13 | }; 14 | writeFileSync(`packages/${dir}/tsconfig.spec.json`, JSON.stringify(tsConfig, null, 2)); 15 | const packageJson = JSON.parse(readFileSync(`./packages/${dir}/package.json`).toString()); 16 | delete packageJson.main; 17 | delete packageJson.types; 18 | delete packageJson.files; 19 | delete packageJson.scripts; 20 | Object.keys(packageJson.dependencies ?? {}) 21 | .filter((dep) => !Object.keys(mainDeps).includes(dep)) 22 | .filter((dep) => !dep.includes('@ogma')) 23 | .forEach((dep) => (mainDeps[dep] = packageJson.dependencies[dep])); 24 | writeFileSync(`packages/${dir}/package.json`, JSON.stringify(packageJson, null, 2)); 25 | }); 26 | mainJson.devDependencies = mainDeps; 27 | writeFileSync('./package.json', JSON.stringify(mainJson, null, 2)); 28 | -------------------------------------------------------------------------------- /packages/platform-redis/README.md: -------------------------------------------------------------------------------- 1 | # `@ogma/platform-redis` 2 | 3 | The `RedisParser` parser for the `OgmaInterceptor`. This plugin class parses Redis request and response object to be able to successfully log the data about the request. For more information, check out [the @ogma/nestjs-module](../nestjs-module/README.md) documentation. 4 | 5 | ## Installation 6 | 7 | Nothing special, standard `npm i @ogma/platform-redis` or `yarn add @ogma/platform-redis` 8 | 9 | ## Usage 10 | 11 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 12 | 13 | ```ts 14 | @Module( 15 | OgmaModule.forRoot({ 16 | interceptor: { 17 | rpc: RedisParser 18 | } 19 | }) 20 | ) 21 | export class AppModule {} 22 | ``` 23 | 24 | ## Important Notes 25 | 26 | Because of how Redis requests are sent and the data available in them, to get the IP address in the request log, an IP property must be sent in the payload. This is the only way to get the IP address. If an IP property is not sent, the interceptor will use an empty string. This is for the same reason as in the [@ogma/platform-mqtt](../platform-mqtt) docs. 27 | -------------------------------------------------------------------------------- /packages/platform-redis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/platform-redis", 3 | "version": "5.1.0", 4 | "description": "A plugin for the OgmaInterceptor to properly handle microservice requests from redis protocols", 5 | "keywords": [ 6 | "redis", 7 | "microservice", 8 | "logging", 9 | "nestjs", 10 | "ogma", 11 | "interceptor" 12 | ], 13 | "author": "Jay McDoniel ", 14 | "homepage": "https://github.com/jmcdo29/ogma#readme", 15 | "license": "MIT", 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/jmcdo29/ogma.git" 22 | }, 23 | "bugs": { 24 | "url": "https://github.com/jmcdo29/ogma/issues" 25 | }, 26 | "peerDependencies": { 27 | "@nestjs/microservices": "^9.0.0 || ^10.0.0 || ^11.0.0", 28 | "@ogma/nestjs-module": "workspace:^5.4.0", 29 | "redis": "^3.0.0 || ^4.0.0" 30 | }, 31 | "peerDependenciesMeta": { 32 | "@nestjs/microservices": { 33 | "optional": false 34 | }, 35 | "@ogma/nestjs-module": { 36 | "optional": false 37 | }, 38 | "redis": { 39 | "optional": false 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/platform-graphql/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/platform-graphql", 3 | "version": "5.1.0", 4 | "description": "A plugin for the OgmaInterceptor to proplery handle GQL requests with an Express server", 5 | "keywords": [ 6 | "GraphQL", 7 | "logging", 8 | "ogma", 9 | "interceptor", 10 | "nestjs" 11 | ], 12 | "author": "Jay McDoniel ", 13 | "homepage": "https://github.com/jmcdo29/ogma#readme", 14 | "license": "MIT", 15 | "publishConfig": { 16 | "access": "public" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/jmcdo29/ogma.git" 21 | }, 22 | "bugs": { 23 | "url": "https://github.com/jmcdo29/ogma/issues" 24 | }, 25 | "peerDependencies": { 26 | "@nestjs/graphql": "^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0", 27 | "@ogma/nestjs-module": "workspace:^5.4.0", 28 | "@ogma/platform-express": "workspace:^5.1.0" 29 | }, 30 | "peerDependenciesMeta": { 31 | "@nestjs/graphql": { 32 | "optional": false 33 | }, 34 | "@ogma/nestjs-module": { 35 | "optional": false 36 | }, 37 | "@ogma/platform-express": { 38 | "optional": false 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/platform-mqtt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/platform-mqtt", 3 | "version": "5.1.0", 4 | "description": "A plugin for the OgmaInterceptor to properly handle microservice requests from mqtt protocols", 5 | "keywords": [ 6 | "mqtt", 7 | "microservice", 8 | "logging", 9 | "ogma", 10 | "interceptor", 11 | "nestjs" 12 | ], 13 | "author": "Jay McDoniel ", 14 | "homepage": "https://github.com/jmcdo29/ogma#readme", 15 | "license": "MIT", 16 | "private": false, 17 | "publishConfig": { 18 | "access": "public" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/jmcdo29/ogma.git" 23 | }, 24 | "bugs": { 25 | "url": "https://github.com/jmcdo29/ogma/issues" 26 | }, 27 | "peerDependencies": { 28 | "@nestjs/microservices": "^9.0.0 || ^10.0.0 || ^11.0.0", 29 | "@ogma/nestjs-module": "workspace:^5.4.0", 30 | "mqtt": "^4.0.0" 31 | }, 32 | "peerDependenciesMeta": { 33 | "@nestjs/microservices": { 34 | "optional": false 35 | }, 36 | "@ogma/nestjs-module": { 37 | "optional": false 38 | }, 39 | "mqtt": { 40 | "optional": false 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/platform-nats/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/platform-nats", 3 | "version": "5.1.0", 4 | "description": "A plugin for the OgmaInterceptor to properly handle microservice requests from nats protocols", 5 | "keywords": [ 6 | "nats", 7 | "microservice", 8 | "logging", 9 | "ogma", 10 | "nestjs", 11 | "interceptor" 12 | ], 13 | "author": "Jay McDoniel ", 14 | "homepage": "https://github.com/jmcdo29/ogma#readme", 15 | "license": "MIT", 16 | "private": false, 17 | "publishConfig": { 18 | "access": "public" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/jmcdo29/ogma.git" 23 | }, 24 | "bugs": { 25 | "url": "https://github.com/jmcdo29/ogma/issues" 26 | }, 27 | "peerDependencies": { 28 | "@nestjs/microservices": "^9.0.0 || ^10.0.0 || ^11.0.0", 29 | "@ogma/nestjs-module": "workspace:^5.4.0", 30 | "nats": "^1.4.0 || ^2.0.0" 31 | }, 32 | "peerDependenciesMeta": { 33 | "@nestjs/microservices": { 34 | "optional": false 35 | }, 36 | "@ogma/nestjs-module": { 37 | "optional": false 38 | }, 39 | "nats": { 40 | "optional": false 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/platform-grpc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/platform-grpc", 3 | "version": "5.1.0", 4 | "description": "A plugin for the OgmaInterceptor to properly handle microservice requests from grpc protocols", 5 | "keywords": [ 6 | "grpc", 7 | "microservice", 8 | "logging", 9 | "ogma", 10 | "interceptor", 11 | "nestjs" 12 | ], 13 | "author": "Jay McDoniel ", 14 | "homepage": "https://github.com/jmcdo29/ogma#readme", 15 | "license": "MIT", 16 | "private": false, 17 | "publishConfig": { 18 | "access": "public" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/jmcdo29/ogma.git" 23 | }, 24 | "bugs": { 25 | "url": "https://github.com/jmcdo29/ogma/issues" 26 | }, 27 | "peerDependencies": { 28 | "@nestjs/microservices": "^9.0.0 || ^10.0.0 || ^11.0.0", 29 | "@ogma/nestjs-module": "workspace:^5.4.0", 30 | "@grpc/grpc-js": "^1.7.3" 31 | }, 32 | "peerDependenciesMeta": { 33 | "@nestjs/microservices": { 34 | "optional": false 35 | }, 36 | "@ogma/nestjs-module": { 37 | "optional": false 38 | }, 39 | "@grpc/grpc-js": { 40 | "optional": false 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/platform-rabbitmq/README.md: -------------------------------------------------------------------------------- 1 | # `@ogma/platform-rabbitmq` 2 | 3 | The `RabbitMqParser` parser for the `OgmaInterceptor`. This plugin class parses RabbitMQ request and response object to be able to successfully log the data about the request. For more information, check out [the @ogma/nestjs-module](../nestjs-module/README.md) documentation. 4 | 5 | ## Installation 6 | 7 | Nothing special, standard `npm i @ogma/platform-rabbitmq` or `yarn add @ogma/platform-rabbitmq` 8 | 9 | ## Usage 10 | 11 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 12 | 13 | ```ts 14 | @Module( 15 | OgmaModule.forRoot({ 16 | interceptor: { 17 | rpc: RabbitMqParser 18 | } 19 | }) 20 | ) 21 | export class AppModule {} 22 | ``` 23 | 24 | ## Important Notes 25 | 26 | Because of how RabbitMQ requests are sent and the data available in them, to get the IP address in the request log, an IP property must be sent in the payload. This is the only way to get the IP address. If an IP property is not sent, the interceptor will use an empty string. This is for the same reason as in the [@ogma/platform-mqtt](../platform-mqtt) docs. 27 | -------------------------------------------------------------------------------- /packages/platform-rabbitmq/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/platform-rabbitmq", 3 | "version": "5.1.0", 4 | "description": "A plugin for the OgmaInterceptor to properly handle microservice requests from amqp protocols", 5 | "author": "Jay McDoniel ", 6 | "homepage": "https://github.com/jmcdo29/ogma#readme", 7 | "license": "MIT", 8 | "private": false, 9 | "publishConfig": { 10 | "access": "public" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/jmcdo29/ogma.git" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/jmcdo29/ogma/issues" 18 | }, 19 | "peerDependencies": { 20 | "@nestjs/microservices": "^9.0.0 || ^10.0.0 || ^11.0.0", 21 | "@ogma/nestjs-module": "workspace:^5.4.0", 22 | "amqp-connection-manager": "^3.2.0 || ^4.0.0", 23 | "amqplib": "^0.5.0 || ^0.8.0 || ^0.10.0" 24 | }, 25 | "peerDependenciesMeta": { 26 | "@nestjs/microservices": { 27 | "optional": false 28 | }, 29 | "@ogma/nestjs-module": { 30 | "optional": false 31 | }, 32 | "amqp-connection-manager": { 33 | "optional": false 34 | }, 35 | "amqplib": { 36 | "optional": false 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/platform-kafka/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/platform-kafka", 3 | "version": "5.1.0", 4 | "description": "A plugin for the OgmaInterceptor to properly handle microservice requests from Kafka protocols", 5 | "keywords": [ 6 | "kafka", 7 | "microservice", 8 | "logging", 9 | "ogma", 10 | "nestjs", 11 | "interceptor" 12 | ], 13 | "author": "Jay McDoniel ", 14 | "homepage": "https://github.com/jmcdo29/ogma#readme", 15 | "license": "MIT", 16 | "private": false, 17 | "publishConfig": { 18 | "access": "public" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/jmcdo29/ogma.git" 23 | }, 24 | "bugs": { 25 | "url": "https://github.com/jmcdo29/ogma/issues" 26 | }, 27 | "peerDependencies": { 28 | "@nestjs/microservices": "^9.0.0 || ^10.0.0 || ^11.0.0", 29 | "@ogma/nestjs-module": "workspace:^5.4.0", 30 | "kafkajs": "^1.12.0 || ^2.0.0" 31 | }, 32 | "peerDependenciesMeta": { 33 | "@nestjs/microservices": { 34 | "optional": false 35 | }, 36 | "@ogma/nestjs-module": { 37 | "optional": false 38 | }, 39 | "kafkaja": { 40 | "optional": false 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/platform-grpc/README.md: -------------------------------------------------------------------------------- 1 | # `@ogma/platform-grpc` 2 | 3 | The `GrpcParser` parser for the `OgmaInterceptor`. This plugin class parses Kafka request and response object to be able to successfully log the data about the request. For more information, check out [the @ogma/nestjs-module](../nestjs-module/README.md) documentation. 4 | 5 | ## Installation 6 | 7 | Nothing special, standard `npm i @ogma/platform-grpc` or `yarn add @ogma/platform-grpc` 8 | 9 | ## Usage 10 | 11 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 12 | 13 | ```ts 14 | @Module( 15 | OgmaModule.forRoot({ 16 | interceptor: { 17 | rpc: GrpcParser 18 | }) 19 | ) 20 | export class AppModule {} 21 | ``` 22 | 23 | ## Important Notes 24 | 25 | Because of how gRPC requests are sent and the data available in them, to get the IP address in the request log, an IP property must be sent in the payload. This is the only way to get the IP address. If an IP property is not sent, the interceptor will use an empty string. [You can find more information here](https://stackoverflow.com/questions/45235080/how-to-know-the-ip-address-of-mqtt-client-in-node-js). 26 | -------------------------------------------------------------------------------- /packages/platform-graphql-fastify/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/platform-graphql-fastify", 3 | "version": "5.1.0", 4 | "description": "A plugin for the OgmaInterceptor to proplery handle GQL requests with an Fastify server", 5 | "keywords": [ 6 | "fastify", 7 | "graphql", 8 | "logging", 9 | "ogma", 10 | "nestjs", 11 | "interceptor" 12 | ], 13 | "author": "Jay McDoniel ", 14 | "homepage": "https://github.com/jmcdo29/ogma#readme", 15 | "license": "MIT", 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/jmcdo29/ogma.git" 22 | }, 23 | "bugs": { 24 | "url": "https://github.com/jmcdo29/ogma/issues" 25 | }, 26 | "peerDependencies": { 27 | "@nestjs/graphql": "^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0", 28 | "@ogma/nestjs-module": "workspace:^5.4.0", 29 | "@ogma/platform-fastify": "workspace:^5.1.0" 30 | }, 31 | "peerDependenciesMeta": { 32 | "@ogma/nestjs-module": { 33 | "optional": false 34 | }, 35 | "@ogma/platform-fastify": { 36 | "optional": false 37 | }, 38 | "@nestjs/graphql": { 39 | "optional": false 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/platform-kafka/README.md: -------------------------------------------------------------------------------- 1 | # `@ogma/platform-kafka` 2 | 3 | The `KafkaParser` parser for the `OgmaInterceptor`. This plugin class parses Kafka request and response object to be able to successfully log the data about the request. For more information, check out [the @ogma/nestjs-module](../nestjs-module/README.md) documentation. 4 | 5 | ## Installation 6 | 7 | Nothing special, standard `npm i @ogma/platform-kafka` or `yarn add @ogma/platform-kafka` 8 | 9 | ## Usage 10 | 11 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 12 | 13 | ```ts 14 | @Module( 15 | OgmaModule.forRoot({ 16 | interceptor: { 17 | rpc: KafkaParser 18 | }) 19 | ) 20 | export class AppModule {} 21 | ``` 22 | 23 | ## Important Notes 24 | 25 | Because of how Kafka requests are sent and the data available in them, to get the IP address in the request log, an IP property must be sent in the payload. This is the only way to get the IP address. If an IP property is not sent, the interceptor will use an empty string. [You can find more information here](https://stackoverflow.com/questions/45235080/how-to-know-the-ip-address-of-mqtt-client-in-node-js). 26 | -------------------------------------------------------------------------------- /packages/platform-mqtt/README.md: -------------------------------------------------------------------------------- 1 | # `@ogma/platform-mqtt` 2 | 3 | The `MqttParser` parser for the `OgmaInterceptor`. This plugin class parses MQTT request and response object to be able to successfully log the data about the request. For more information, check out [the @ogma/nestjs-module](../nestjs-module/README.md) documentation. 4 | 5 | ## Installation 6 | 7 | Nothing special, standard `npm i @ogma/platform-mqtt` or `yarn add @ogma/platform-mqtt` 8 | 9 | ## Usage 10 | 11 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 12 | 13 | ```ts 14 | @Module( 15 | OgmaModule.forRoot({ 16 | interceptor: { 17 | rpc: MqttParser 18 | } 19 | }) 20 | ) 21 | export class AppModule {} 22 | ``` 23 | 24 | ## Important Notes 25 | 26 | Because of how MQTT requests are sent and the data available in them, to get the IP address in the request log, an IP property must be sent in the payload. This is the only way to get the IP address. If an IP property is not sent, the interceptor will use an empty string. [You can find more information here](https://stackoverflow.com/questions/45235080/how-to-know-the-ip-address-of-mqtt-client-in-node-js). 27 | -------------------------------------------------------------------------------- /packages/nestjs-module/test/noop-interceptor.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { suite } from 'uvu'; 3 | import { equal } from 'uvu/assert'; 4 | 5 | import { NoopInterceptorService } from '../src/interceptor/providers/noop-interceptor.service'; 6 | 7 | const NoopInterceptorServiceSuite = suite<{ service: NoopInterceptorService }>( 8 | 'NoopInterceptorService', 9 | { service: undefined }, 10 | ); 11 | NoopInterceptorServiceSuite.before(async (context) => { 12 | const module: TestingModule = await Test.createTestingModule({ 13 | providers: [NoopInterceptorService], 14 | }).compile(); 15 | 16 | context.service = module.get(NoopInterceptorService); 17 | }); 18 | NoopInterceptorServiceSuite('It should return a success log object', ({ service }) => { 19 | Date.now = () => 133; 20 | equal(service.getSuccessContext(Array(149).fill('o').join(''), {} as any, 50, {} as any), { 21 | callerAddress: 'caller ip', 22 | method: 'method', 23 | callPoint: 'call point', 24 | responseTime: 83, 25 | contentLength: 151, 26 | protocol: 'protocol', 27 | status: 'status', 28 | meta: undefined, 29 | }); 30 | }); 31 | 32 | NoopInterceptorServiceSuite.run(); 33 | -------------------------------------------------------------------------------- /packages/nestjs-module/test/app.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test } from '@nestjs/testing'; 2 | import { spy, Stub } from 'hanbi'; 3 | import { suite } from 'uvu'; 4 | import { equal, ok } from 'uvu/assert'; 5 | 6 | import { AppService } from './app.service'; 7 | 8 | const AppServiceSuite = suite<{ service: AppService; logSpy: Stub<(message: string) => void> }>( 9 | 'AppService', 10 | { 11 | service: undefined, 12 | logSpy: spy(), 13 | }, 14 | ); 15 | AppServiceSuite.before(async (context) => { 16 | try { 17 | const modRef = await Test.createTestingModule({ 18 | providers: [ 19 | AppService, 20 | { 21 | provide: 'OGMA_SERVICE:AppService', 22 | useValue: { 23 | log: context.logSpy.handler, 24 | }, 25 | }, 26 | ], 27 | }).compile(); 28 | context.service = modRef.get(AppService); 29 | } catch (err) { 30 | console.error(err); 31 | } 32 | }); 33 | AppServiceSuite('it should create the service', ({ service }) => { 34 | ok(service); 35 | }); 36 | AppServiceSuite('It should return { hello: world } and log "Say Hello"', ({ service, logSpy }) => { 37 | equal(service.getHello(), { hello: 'world' }); 38 | ok(logSpy.calledWith('Say Hello')); 39 | }); 40 | 41 | AppServiceSuite.run(); 42 | -------------------------------------------------------------------------------- /integration/src/gql/gql.resolver.ts: -------------------------------------------------------------------------------- 1 | import { BadRequestException, UseFilters, UseGuards } from '@nestjs/common'; 2 | import { Mutation, Query, Resolver } from '@nestjs/graphql'; 3 | import { OgmaSkip } from '@ogma/nestjs-module'; 4 | 5 | import { AppService } from '../app.service'; 6 | import { FailGuard } from '../shared/fail.guard'; 7 | import { ExceptionFilter } from './exception.filter'; 8 | import { SimpleObject } from './simple-object.model'; 9 | 10 | @Resolver(() => SimpleObject) 11 | @UseFilters(ExceptionFilter) 12 | export class GqlResolver { 13 | constructor(private readonly appService: AppService) {} 14 | 15 | @Query(() => SimpleObject) 16 | getQuery(): SimpleObject { 17 | return this.appService.getHello(); 18 | } 19 | 20 | @Mutation(() => SimpleObject) 21 | getMutation(): SimpleObject { 22 | return this.appService.getHello(); 23 | } 24 | 25 | @Query(() => SimpleObject) 26 | getError(): never { 27 | throw new BadRequestException('Borked'); 28 | } 29 | 30 | @OgmaSkip() 31 | @Query(() => SimpleObject) 32 | getSkip(): SimpleObject { 33 | return this.appService.getHello(); 34 | } 35 | 36 | @Query(() => SimpleObject) 37 | @UseGuards(FailGuard) 38 | failGuard(): SimpleObject { 39 | return this.appService.getHello(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/platform-ws/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/platform-ws", 3 | "version": "5.1.0", 4 | "description": "A plugin for the OgmaInterceptor to properly handle websocket requests from ws", 5 | "keywords": [ 6 | "ws", 7 | "logging", 8 | "websockets", 9 | "ogma", 10 | "nestjs", 11 | "interceptor" 12 | ], 13 | "author": "Jay McDoniel ", 14 | "homepage": "https://github.com/jmcdo29/ogma#readme", 15 | "license": "MIT", 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/jmcdo29/ogma.git" 22 | }, 23 | "bugs": { 24 | "url": "https://github.com/jmcdo29/ogma/issues" 25 | }, 26 | "peerDependencies": { 27 | "@nestjs/platform-ws": "^9.0.0 || ^10.0.0 || ^11.0.0", 28 | "@nestjs/websockets": "^9.0.0 || ^10.0.0 || ^11.0.0", 29 | "@ogma/nestjs-module": "workspace:^5.4.0", 30 | "ws": "^7.4.2 || ^8.0.0" 31 | }, 32 | "peerDependenciesMeta": { 33 | "@nestjs/websockets": { 34 | "optional": false 35 | }, 36 | "@nestjs/platform-ws": { 37 | "optional": false 38 | }, 39 | "@ogma/nestjs-module": { 40 | "optional": false 41 | }, 42 | "ws": { 43 | "optional": false 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/filter.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: filter 3 | title: Filter Logging Service 4 | layout: ../../../layouts/MainLayout.astro 5 | --- 6 | 7 | There may be times where you need to log an exception that happened outside of the interceptor's control, say like in a guard or a middleware. For this purpose ogma also comes with an `OgmaFilterService` that takes in the exception and the `ArgumentsHost`, and prints out a line just like the interceptor would. The service is also smart, ensuring not to print out another line to the logs if the exception has already been logged by the interceptor. 8 | 9 | To make use of this provider, all that's needed is to inject the service into your filter and call `this.service.log(exception, host)`. This way, any custom filter keeps all of the logic in your hands while allowing for logging of the exception. 10 | 11 | ```ts 12 | import { BaseExceptionFilter, Catch } from '@nestjs/common'; 13 | import { OgmaFilterService } from '@ogma/nestjs-module'; 14 | 15 | @Catch() 16 | export class CustomExceptionFilter extends BaseExceptionFilter { 17 | constructor(private readonly service: OgmaFilterService) {} 18 | 19 | catch(exception: Error, host: ArgumentsHost) { 20 | this.service.log(exception, host); 21 | super.catch(exception, host); 22 | } 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /apps/docs/src/components/Header/LanguageSelect.css: -------------------------------------------------------------------------------- 1 | .language-select { 2 | flex-grow: 1; 3 | width: 48px; 4 | box-sizing: border-box; 5 | margin: 0; 6 | padding: 0.33em 0.5em; 7 | overflow: visible; 8 | font-weight: 500; 9 | font-size: 1rem; 10 | font-family: inherit; 11 | line-height: inherit; 12 | background-color: var(--theme-bg); 13 | border-color: var(--theme-text-lighter); 14 | color: var(--theme-text-light); 15 | border-style: solid; 16 | border-width: 1px; 17 | border-radius: 0.25rem; 18 | outline: 0; 19 | cursor: pointer; 20 | transition-timing-function: ease-out; 21 | transition-duration: 0.2s; 22 | transition-property: border-color, color; 23 | -webkit-font-smoothing: antialiased; 24 | padding-left: 30px; 25 | padding-right: 1rem; 26 | } 27 | .language-select-wrapper .language-select:hover, 28 | .language-select-wrapper .language-select:focus { 29 | color: var(--theme-text); 30 | border-color: var(--theme-text-light); 31 | } 32 | .language-select-wrapper { 33 | color: var(--theme-text-light); 34 | position: relative; 35 | } 36 | .language-select-wrapper > svg { 37 | position: absolute; 38 | top: 7px; 39 | left: 10px; 40 | pointer-events: none; 41 | } 42 | 43 | @media (min-width: 50em) { 44 | .language-select { 45 | width: 100%; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/platform-ws/README.md: -------------------------------------------------------------------------------- 1 | # `@ogma/platform-ws` 2 | 3 | The `WsParser` parser for the `OgmaInterceptor`. This plugin class parses TCP request and response object to be able to successfully log the data about the request. For more information, check out [the @ogma/nestjs-module](../nestjs-module/README.md) documentation. 4 | 5 | ## Installation 6 | 7 | Nothing special, standard `npm i @ogma/platform-ws` or `yarn add @ogma/platform-ws` 8 | 9 | ## Usage 10 | 11 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 12 | 13 | ```ts 14 | @Module( 15 | OgmaModule.forRoot({ 16 | interceptor: { 17 | ws: WsParser 18 | } 19 | }) 20 | ) 21 | export class AppModule {} 22 | ``` 23 | 24 | ### Note 25 | 26 | As the Gateway/Websocket context runs in parallel with the HTTP Context, and as the application configuration is not shared between the two, to bind the `OgmaInterceptor` to the GateWay, you **must** use `@UseInterceptor(OgmaInterceptor)` **and** have `OgmaModule.forFeature()` in the `imports` array of the same module. 27 | 28 | The method for the `WsParser` is always `websocket` and the `protocol` is always `WS`. Until a better method at determining these values is found, this will be a static value. 29 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | extends: [ 4 | 'eslint:recommended', 5 | 'plugin:@typescript-eslint/recommended', 6 | 'plugin:prettier/recommended', 7 | ], 8 | plugins: ['@typescript-eslint', 'simple-import-sort'], 9 | parserOptions: { 10 | source: 'module', 11 | ecmaVersion: 2018, 12 | }, 13 | root: true, 14 | env: { 15 | node: true, 16 | }, 17 | rules: { 18 | 'no-control-regex': 'off', 19 | '@typescript-eslint/no-explicit-any': 'off', 20 | '@typescript-eslint/explicit-function-return-type': 'off', 21 | '@typescript-eslint/interface-name-prefix': 'off', 22 | '@typescript-eslint/explicit-module-boundary-types': 'off', 23 | '@typescript-eslint/no-unused-vars': [ 24 | 'warn', 25 | { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }, 26 | ], 27 | 'simple-import-sort/imports': 'error', 28 | 'simple-import-sort/exports': 'error', 29 | // 'sort-imports': ['error', { ignoreDeclarationSort: true, ignoreCase: true }], 30 | 'prettier/prettier': 'warn', 31 | }, 32 | ignorePatterns: ['*.d.ts', 'dist/*', '**/node_modules/*', 'lib/*', '*.js'], 33 | globals: { 34 | WeakSet: 'readonly', 35 | Promise: 'readonly', 36 | Reflect: 'readonly', 37 | Symbol: 'readonly', 38 | }, 39 | }; 40 | -------------------------------------------------------------------------------- /apps/docs/src/components/PageContent/PageContent.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Frontmatter } from '../../config'; 3 | import MoreMenu from '../RightSidebar/MoreMenu.astro'; 4 | import TableOfContents from '../RightSidebar/TableOfContents'; 5 | import type { MarkdownHeading } from 'astro'; 6 | 7 | type Props = { 8 | frontmatter: Frontmatter; 9 | headings: MarkdownHeading[]; 10 | githubEditUrl: string; 11 | }; 12 | 13 | const { frontmatter, headings, githubEditUrl } = Astro.props as Props; 14 | const title = frontmatter.title; 15 | --- 16 | 17 |
18 |
19 |

{title}

20 | 23 | 24 |
25 | 28 |
29 | 30 | 53 | -------------------------------------------------------------------------------- /packages/platform-express/src/express-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | import { HttpInterceptorService, Parser } from '@ogma/nestjs-module'; 3 | import { Request } from 'express'; 4 | 5 | @Parser('http') 6 | export class ExpressParser extends HttpInterceptorService { 7 | getCallerIp(context: ExecutionContext): string[] | string { 8 | const req = this.getRequest(context); 9 | return req.ips.length ? req.ips.join(' ') : req.ip; 10 | } 11 | 12 | getCallPoint(context: ExecutionContext): string { 13 | const req = this.getRequest(context); 14 | return req.originalUrl; 15 | } 16 | 17 | getMethod(context: ExecutionContext): string { 18 | const req = this.getRequest(context); 19 | const method = req.method; 20 | return method || 'GET'; 21 | } 22 | 23 | getProtocol(context: ExecutionContext): string { 24 | const req = this.getRequest(context); 25 | return `HTTP/${this.getHttpMajor(req)}.${this.getHttpMinor(req)}`; 26 | } 27 | 28 | private getHttpMajor(req: Request): number { 29 | return req.httpVersionMajor; 30 | } 31 | 32 | private getHttpMinor(req: Request): number { 33 | return req.httpVersionMinor; 34 | } 35 | 36 | getRequest(context: ExecutionContext): Request { 37 | return super.getRequest(context); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /integration/src/ws/ws.gateway.ts: -------------------------------------------------------------------------------- 1 | import { BadRequestException, UseFilters, UseGuards, UseInterceptors } from '@nestjs/common'; 2 | import { SubscribeMessage, WebSocketGateway } from '@nestjs/websockets'; 3 | import { OgmaInterceptor, OgmaSkip } from '@ogma/nestjs-module'; 4 | 5 | import { AppService } from '../app.service'; 6 | import { FailGuard } from '../shared/fail.guard'; 7 | import { SimpleObject } from '../simple-object.model'; 8 | import { ExceptionFilter } from './ws.filter'; 9 | 10 | @UseInterceptors(OgmaInterceptor) 11 | @WebSocketGateway() 12 | export class WsGateway { 13 | constructor(private readonly appService: AppService) {} 14 | 15 | @SubscribeMessage('message') 16 | getMessage(): { event: string; data: SimpleObject } { 17 | return { event: 'message', data: this.appService.getHello() }; 18 | } 19 | 20 | @SubscribeMessage('throw') 21 | @UseFilters(ExceptionFilter) 22 | getThrow(): never { 23 | throw new BadRequestException('Borked'); 24 | } 25 | 26 | @SubscribeMessage('skip') 27 | @OgmaSkip() 28 | getSkip(): { event: string; data: SimpleObject } { 29 | return { event: 'message', data: this.appService.getHello() }; 30 | } 31 | 32 | @SubscribeMessage('fail-guard') 33 | @UseGuards(FailGuard) 34 | @UseFilters(ExceptionFilter) 35 | failGuard(): void { 36 | /* no op */ 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /apps/docs/src/components/Header/SidebarToggle.tsx: -------------------------------------------------------------------------------- 1 | /** @jsxImportSource preact */ 2 | import type { FunctionalComponent } from 'preact'; 3 | import { useState, useEffect } from 'preact/hooks'; 4 | 5 | const MenuToggle: FunctionalComponent = () => { 6 | const [sidebarShown, setSidebarShown] = useState(false); 7 | 8 | useEffect(() => { 9 | const body = document.querySelector('body')!; 10 | if (sidebarShown) { 11 | body.classList.add('mobile-sidebar-toggle'); 12 | } else { 13 | body.classList.remove('mobile-sidebar-toggle'); 14 | } 15 | }, [sidebarShown]); 16 | 17 | return ( 18 | 41 | ); 42 | }; 43 | 44 | export default MenuToggle; 45 | -------------------------------------------------------------------------------- /packages/platform-socket.io/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/platform-socket.io", 3 | "version": "5.1.0", 4 | "description": "A plugin for the OgmaInterceptor to properly handle websocket requests from socket.io", 5 | "keywords": [ 6 | "socket.io", 7 | "logging", 8 | "websocket", 9 | "ogma", 10 | "nestjs", 11 | "interceptor" 12 | ], 13 | "author": "Jay McDoniel ", 14 | "homepage": "https://github.com/jmcdo29/ogma#readme", 15 | "license": "MIT", 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/jmcdo29/ogma.git" 22 | }, 23 | "bugs": { 24 | "url": "https://github.com/jmcdo29/ogma/issues" 25 | }, 26 | "peerDependencies": { 27 | "@nestjs/platform-socket.io": "^9.0.0 || ^10.0.0 || ^11.0.0", 28 | "@nestjs/websockets": "^9.0.0 || ^10.0.0 || ^11.0.0", 29 | "@ogma/nestjs-module": "workspace:^5.4.0", 30 | "socket.io": "^4.0.0" 31 | }, 32 | "peerDependenciesMeta": { 33 | "@nestjs/websockets": { 34 | "optional": false 35 | }, 36 | "@nestjs/platform-socket.io": { 37 | "optional": false 38 | }, 39 | "@ogma/nestjs-module": { 40 | "optional": false 41 | }, 42 | "socket.io": { 43 | "optional": false 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/platform-socket.io/README.md: -------------------------------------------------------------------------------- 1 | # `@ogma/platform-socket.io` 2 | 3 | The `SocketIOParser` parser for the `OgmaInterceptor`. This plugin class parses TCP request and response object to be able to successfully log the data about the request. For more information, check out [the @ogma/nestjs-module](../nestjs-module/README.md) documentation. 4 | 5 | ## Installation 6 | 7 | Nothing special, standard `npm i @ogma/platform-socket.io` or `yarn add @ogma/platform-socket.io` 8 | 9 | ## Usage 10 | 11 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 12 | 13 | ```ts 14 | @Module( 15 | OgmaModule.forRoot({ 16 | interceptor: { 17 | ws: SocketIOParser 18 | } 19 | }) 20 | ) 21 | export class AppModule {} 22 | ``` 23 | 24 | ### Note 25 | 26 | As the Gateway/Websocket context runs in parallel with the HTTP Context, and as the application configuration is not shared between the two, to bind the `OgmaInterceptor` to the GateWay, you **must** use `@UseInterceptor(OgmaInterceptor)` **and** have `OgmaModule.forFeature()` in the `imports` array of the same module. 27 | 28 | The method for the `SocketIOParser` is always `socket.io` and the `protocol` is always `WS`. Until a better method at determining these values is found, this will be a static value. 29 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/ws/ws.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: ws 3 | title: Platform WS 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | The `WsParser` parser for the `OgmaInterceptor`. This plugin class parses TCP request and response object to be able to successfully log the data about the request. For more information, check out the [@ogma/nestjs-module](/en/nestjs/module) documentation. 8 | 9 | ## Installation 10 | 11 | Nothing special, standard `npm i @ogma/platform-ws` or `yarn add @ogma/platform-ws` 12 | 13 | ## Usage 14 | 15 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 16 | 17 | ```ts 18 | @Module({ 19 | imports: [OgmaModule.forRoot({})], 20 | providers: [WsParser] 21 | }) 22 | export class AppModule {} 23 | ``` 24 | 25 | ### Note 26 | 27 | As the Gateway/Websocket context runs in parallel with the HTTP Context, and as the application configuration is not shared between the two, to bind the `OgmaInterceptor` to the GateWay, you **must** use `@UseInterceptor(OgmaInterceptor)` **and** have `OgmaModule.forFeature()` in the `imports` array of the same module. 28 | 29 | The method for the `WsParser` is always `websocket` and the `protocol` is always `WS`. Until a better method at determining these values is found, this will be a static value. 30 | -------------------------------------------------------------------------------- /packages/platform-graphql/README.md: -------------------------------------------------------------------------------- 1 | # `@ogma/platform-graphql` 2 | 3 | The `GraphQLParser` parser for the `OgmaInterceptor`. This plugin class parses GraphQL request and response object to be able to successfully log the data about the request. For more information, check out [the @ogma/nestjs-module](../nestjs-module/README.md) documentation. 4 | 5 | ## Installation 6 | 7 | Nothing special, standard `npm i @ogma/platform-graphql` or `yarn add @ogma/platform-graphql` 8 | 9 | ## Usage 10 | 11 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 12 | 13 | ```ts 14 | @Module( 15 | OgmaModule.forRoot({ 16 | interceptor: { 17 | gql: GraphQLParser 18 | } 19 | }) 20 | ) 21 | export class AppModule {} 22 | ``` 23 | 24 | > Note: Due to the nature of subscriptions and the data available from the base ones, it is not possible at this time to log what subscriptions are made in the Ogma fashion. 25 | 26 | Because the interceptor needs access to the request and response objects, when configuring the `GraphqlModule` from Nest, you need to add the `req` and `res` to the GraphQL context. to do this, while configuring the `GraphqlModule`, set the `context` property as such: 27 | 28 | ```ts 29 | GraphqlModule.forRoot({ 30 | context: ({ req, res }) => ({ req, res }) 31 | }); 32 | ``` 33 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/ws/socket.io.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: socket.io 3 | title: Platform Socket.IO 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | The `SocketIOParser` parser for the `OgmaInterceptor`. This plugin class parses TCP request and response object to be able to successfully log the data about the request. For more information, check out the [@ogma/nestjs-module](/en/nestjs/module) documentation. 8 | 9 | ## Installation 10 | 11 | Nothing special, standard `npm i @ogma/platform-socket.io` or `yarn add @ogma/platform-socket.io` 12 | 13 | ## Usage 14 | 15 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 16 | 17 | ```ts 18 | @Module({ 19 | imports: [OgmaModule.forRoot({})], 20 | providers: [SocketIOParser] 21 | }) 22 | export class AppModule {} 23 | ``` 24 | 25 | ### Note 26 | 27 | As the Gateway/Websocket context runs in parallel with the HTTP Context, and as the application configuration is not shared between the two, to bind the `OgmaInterceptor` to the GateWay, you **must** use `@UseInterceptor(OgmaInterceptor)` **and** have `OgmaModule.forFeature()` in the `imports` array of the same module. 28 | 29 | The method for the `SocketIOParser` is always `socket.io` and the `protocol` is always `WS`. Until a better method at determining these values is found, this will be a static value. 30 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/interceptor/providers/gql-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentsHost, Injectable } from '@nestjs/common'; 2 | 3 | import { AbstractInterceptorService } from './abstract-interceptor.service'; 4 | 5 | @Injectable() 6 | export abstract class GqlInterceptorService extends AbstractInterceptorService { 7 | protected reqName: string; 8 | 9 | /** 10 | * A helper method to get the graphql context from the execution context 11 | * 12 | * Note: The only reason this method is not already written, is to keep `@nestjs/graphql` out of the `@ogma/nestjs-module` package 13 | * 14 | * this method _should_ look something like this 15 | * ```ts 16 | * getContext(context: ArgumentsHost) { 17 | * const gql = GqlArgumentsHost.create(context); 18 | * return gql.getContext(); 19 | * } 20 | * ``` 21 | * @param context execution context from Nest 22 | */ 23 | protected abstract getContext(context: ArgumentsHost): any; 24 | setRequestId(context: ArgumentsHost, requestId: string) { 25 | const ctx = this.getContext(context).context; 26 | if (ctx[this.reqName]) { 27 | ctx[this.reqName].requestId = requestId; 28 | } else { 29 | ctx.requestId = requestId; 30 | } 31 | } 32 | 33 | getRequestId(context: ArgumentsHost): any { 34 | const ctx = this.getContext(context).context; 35 | return ctx[this.reqName]?.requestId ?? ctx.requestId; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /integration/test/for-feats.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test } from '@nestjs/testing'; 2 | import { createProviderToken } from '@ogma/nestjs-module'; 3 | import { stubMethod } from 'hanbi'; 4 | import { spec } from 'pactum'; 5 | import { test } from 'uvu'; 6 | import { equal, is } from 'uvu/assert'; 7 | 8 | import { AppController } from '../src/for-feats/app.controller'; 9 | import { ForFeatsModule } from '../src/for-feats/app.module'; 10 | import { AppService } from '../src/for-feats/app.service'; 11 | 12 | test('OgmaModule.forFeature should log with two loggers', async () => { 13 | const modRef = await Test.createTestingModule({ 14 | imports: [ForFeatsModule], 15 | }).compile(); 16 | const ogmaAppService = modRef.get(createProviderToken(AppService.name)); 17 | const ogmaAppController = modRef.get(createProviderToken(AppController.name)); 18 | const app = modRef.createNestApplication(); 19 | await app.listen(0); 20 | const controllerLogSpy = stubMethod(ogmaAppController, 'log'); 21 | const serviceLogSpy = stubMethod(ogmaAppService, 'log'); 22 | is(controllerLogSpy.callCount, 0); 23 | is(serviceLogSpy.callCount, 0); 24 | await spec().get((await app.getUrl()).replace('[::1]', 'localhost')); 25 | 26 | is(controllerLogSpy.callCount, 1); 27 | equal(controllerLogSpy.firstCall.args[0], 'Hello'); 28 | is(serviceLogSpy.callCount, 1); 29 | equal(serviceLogSpy.firstCall.args[0], 'Hello'); 30 | await app.close(); 31 | }); 32 | test.run(); 33 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/interceptor/providers/rpc-interceptor.service.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentsHost, ExecutionContext, Injectable } from '@nestjs/common'; 2 | 3 | import { AbstractInterceptorService } from './abstract-interceptor.service'; 4 | 5 | @Injectable() 6 | export abstract class RpcInterceptorService extends AbstractInterceptorService { 7 | getCallPoint(context: ExecutionContext): any { 8 | return this.reflector.get('microservices:pattern', context.getHandler())[0]; 9 | } 10 | 11 | /** 12 | * A helper method to get the appropriate data object for the adapter 13 | * @param context execution context from Nest 14 | * @returns The data object for the RPC adapter 15 | */ 16 | getData(context: ArgumentsHost): T { 17 | return context.switchToRpc().getData(); 18 | } 19 | 20 | /** 21 | * A helper method to get the RPC client from the execution context 22 | * @param context execution context from Nest 23 | * @returns The client object for the RPC adapter 24 | */ 25 | getClient(context: ArgumentsHost): T { 26 | return context.switchToRpc().getContext(); 27 | } 28 | 29 | setRequestId(context: ArgumentsHost, requestId: any): void { 30 | const client = this.getClient<{ requestId: any }>(context); 31 | client.requestId = requestId; 32 | } 33 | 34 | getRequestId(context: ArgumentsHost): any { 35 | return this.getClient<{ requestId: any }>(context).requestId; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/ogma-filter.service.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentsHost, Injectable } from '@nestjs/common'; 2 | import { OgmaOptions } from '@ogma/logger'; 3 | 4 | import { LogObject } from './interceptor/interfaces/log.interface'; 5 | import { DelegatorService } from './interceptor/providers'; 6 | import { OgmaService } from './ogma.service'; 7 | 8 | @Injectable() 9 | export class OgmaFilterService { 10 | private json: boolean; 11 | private color: boolean; 12 | 13 | constructor(private readonly service: OgmaService, private readonly delegator: DelegatorService) { 14 | const ogmaOptions: OgmaOptions = (this.service as any).ogma.options; 15 | this.json = ogmaOptions.json; 16 | this.color = ogmaOptions.color; 17 | } 18 | 19 | log(exception: Error, host: ArgumentsHost): void { 20 | if (this.hasAlreadyBeenLogged(host)) { 21 | return; 22 | } 23 | const valueToLog = this.delegator.getContextErrorString( 24 | exception, 25 | host, 26 | this.delegator.getStartTime(host), 27 | { 28 | json: this.json, 29 | color: this.color, 30 | }, 31 | ); 32 | this.doLog(valueToLog.log); 33 | } 34 | 35 | private doLog(valueToLog: string | LogObject): void { 36 | this.service.log(valueToLog, { context: 'ExceptionFilter' }); 37 | } 38 | 39 | private hasAlreadyBeenLogged(host: ArgumentsHost): boolean { 40 | return !!this.delegator.getRequestId(host); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/platform-graphql-fastify/README.md: -------------------------------------------------------------------------------- 1 | # `@ogma/platform-graphql-fastify` 2 | 3 | The `GraphQLFastifyParser` parser for the `OgmaInterceptor`. This plugin class parses GraphQL request and response object to be able to successfully log the data about the request. For more information, check out [the @ogma/nestjs-module](../nestjs-module/README.md) documentation. 4 | 5 | ## Installation 6 | 7 | Nothing special, standard `npm i @ogma/platform-graphql-fastify` or `yarn add @ogma/platform-graphql-fastify` 8 | 9 | ## Usage 10 | 11 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 12 | 13 | ```ts 14 | @Module( 15 | OgmaModule.forRoot({ 16 | interceptor: { 17 | gql: GraphQLFastifyParser 18 | } 19 | }) 20 | ) 21 | export class AppModule {} 22 | ``` 23 | 24 | > Note: Due to the nature of subscriptions and the data available from the base ones, it is not possible at this time to log what subscriptions are made in the Ogma fashion. 25 | 26 | Because the interceptor needs access to the request and response objects, when configuring the `GraphqlModule` from Nest, you need to add the `request` and `reply` to the GraphQL context. to do this, while configuring the `GraphqlModule`, set the `context` property as such: 27 | 28 | ```ts 29 | GraphqlModule.forRoot({ 30 | context: ({ request, reply }) => ({ request, reply }) 31 | }); 32 | ``` 33 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | mqtt: 3 | image: eclipse-mosquitto 4 | container_name: ogma_mqtt 5 | ports: 6 | - '1883:1883' 7 | volumes: 8 | - ./mosquitto:/mosquitto/ 9 | rabbitmq: 10 | image: rabbitmq 11 | container_name: ogma_rabbit 12 | ports: 13 | - '5672:5672' 14 | # zookeeper: 15 | # container_name: kafka-zookeeper 16 | # hostname: zookeeper 17 | # image: confluentinc/cp-zookeeper:5.3.2 18 | # ports: 19 | # - '2181:2181' 20 | # environment: 21 | # ZOOKEEPER_CLIENT_PORT: 2181 22 | # ZOOKEEPER_TICK_TIME: 2000 23 | # kafka: 24 | # container_name: kafka 25 | # hostname: kafka 26 | # image: confluentinc/cp-kafka:5.3.2 27 | # depends_on: 28 | # - zookeeper 29 | # ports: 30 | # - '29092:29092' 31 | # - '9092:9092' 32 | # environment: 33 | # KAFKA_BROKER_ID: 1 34 | # KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 35 | # KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT 36 | # KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 37 | # KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 38 | # KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0 39 | nats: 40 | image: nats 41 | container_name: ogma_nats 42 | ports: 43 | - '4222:4222' 44 | redis: 45 | image: redis 46 | container_name: ogma_redis 47 | ports: 48 | - '6379:6379' 49 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/graphql/platform-graphql.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: platform-graphql 3 | title: Platform GraphQL 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | The `GraphQLParser` parser for the `OgmaInterceptor`. This plugin class parses GraphQL request and response object to be able to successfully log the data about the request. For more information, check out the [@ogma/nestjs-module](/en/nestjs/module) documentation. 8 | 9 | ## Installation 10 | 11 | Nothing special, standard `npm i @ogma/platform-graphql` or `yarn add @ogma/platform-graphql` 12 | 13 | ## Usage 14 | 15 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 16 | 17 | ```ts 18 | @Module({ 19 | imports: [OgmaModule.forRoot({})], 20 | providers: [GraphQLParser] 21 | }) 22 | export class AppModule {} 23 | ``` 24 | 25 | :::note 26 | 27 | Due to the nature of subscriptions and the data available from the base ones, it is not possible at this time to log what subscriptions are made in the Ogma fashion. 28 | 29 | ::: 30 | 31 | Because the interceptor needs access to the request and response objects, when configuring the `GraphqlModule` from Nest, you need to add the `req` and `res` to the GraphQL context. to do this, while configuring the `GraphqlModule`, set the `context` property as such: 32 | 33 | ```ts 34 | GraphqlModule.forRoot({ 35 | context: ({ req, res }) => ({ req, res }) 36 | }); 37 | ``` 38 | -------------------------------------------------------------------------------- /packages/nestjs-module/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ogma/nestjs-module", 3 | "version": "5.5.1", 4 | "description": "A NestJS module for the Ogma logger", 5 | "keywords": [ 6 | "nestjs", 7 | "nest", 8 | "logger", 9 | "json", 10 | "json-logging", 11 | "request-logging", 12 | "nestjs-module", 13 | "module", 14 | "logging" 15 | ], 16 | "author": "Jay McDoniel ", 17 | "homepage": "https://github.com/jmcdo29/ogma#readme", 18 | "license": "MIT", 19 | "directories": { 20 | "lib": "lib" 21 | }, 22 | "dependencies": { 23 | "@ogma/logger": "workspace:^3.4.0", 24 | "@ogma/styler": "workspace:^1.0.0", 25 | "decorate-all": "1.2.1" 26 | }, 27 | "peerDependencies": { 28 | "@nestjs/common": "^9.0.0 || ^10.0.0 || ^11.0.0", 29 | "@nestjs/core": "^9.0.0 || ^10.0.0 || ^11.0.0", 30 | "reflect-metadata": "^0.1.0 || ^0.2.1", 31 | "rxjs": "^7.0.0" 32 | }, 33 | "peerDependenciesMeta": { 34 | "@nestjs/common": { 35 | "required": true 36 | }, 37 | "@nestjs/core": { 38 | "required": true 39 | }, 40 | "reflect-metadata": { 41 | "required": true 42 | }, 43 | "rxjs": { 44 | "required": true 45 | } 46 | }, 47 | "publishConfig": { 48 | "access": "public" 49 | }, 50 | "repository": { 51 | "type": "git", 52 | "url": "git+https://github.com/jmcdo29/ogma.git" 53 | }, 54 | "bugs": { 55 | "url": "https://github.com/jmcdo29/ogma/issues" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspaceLayout": { 3 | "libsDir": "packages" 4 | }, 5 | "tasksRunnerOptions": { 6 | "default": { 7 | "options": { 8 | "strictlyOrderedTargets": ["build", "package", "prepare"], 9 | "canTrackAnalytics": false, 10 | "showUsageWarnings": true 11 | } 12 | } 13 | }, 14 | "namedInputs": { 15 | "default": ["{projectRoot}/**/*", "sharedGlobals"], 16 | "sharedGlobals": ["{workspaceRoot}/workspace.json", "{workspaceRoot}/nx.json"], 17 | "production": ["default", "!{projectRoot}/.eslintrc.js"] 18 | }, 19 | "targetDefaults": { 20 | "build": { 21 | "inputs": ["production", "^production"], 22 | "dependsOn": ["^build"], 23 | "cache": true 24 | }, 25 | "test": { 26 | "cache": true 27 | }, 28 | "lint": { 29 | "cache": true 30 | }, 31 | "package": { 32 | "cache": true 33 | }, 34 | "prepare": { 35 | "cache": true 36 | }, 37 | "e2e": { 38 | "cache": true 39 | }, 40 | "e2e-run": { 41 | "cache": true 42 | }, 43 | "docker-up": { 44 | "cache": true 45 | }, 46 | "docker-ready": { 47 | "cache": true 48 | }, 49 | "@nx/js:tsc": { 50 | "cache": true, 51 | "dependsOn": ["^build"], 52 | "inputs": ["production", "^production"] 53 | } 54 | }, 55 | "nxCloudAccessToken": "OTZlM2FmYjYtMGQ2NS00OWMzLWJkOTQtYTBmYzE0N2Y0OTIyfHJlYWQtd3JpdGU=", 56 | "useInferencePlugins": false, 57 | "defaultBase": "main" 58 | } 59 | -------------------------------------------------------------------------------- /apps/docs/src/components/HeadCommon.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import '../styles/theme.css'; 3 | import '../styles/index.css'; 4 | --- 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 22 | 23 | 24 | 27 | 28 | 29 | 38 | 39 | 40 | 47 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Parser_Request.yml: -------------------------------------------------------------------------------- 1 | name: "\U0001F680 Feature Request" 2 | description: "I have a suggestion \U0001F63B!" 3 | title: "[Parser]:" 4 | labels: ["type: enhancement :wolf:"] 5 | body: 6 | - type: checkboxes 7 | attributes: 8 | label: "Is there an existing issue that is already proposing this?" 9 | description: "Please search [here](./?q=is%3Aissue) to see if an issue already exists for the feature you are requesting" 10 | options: 11 | - label: "I have searched the existing issues" 12 | required: true 13 | 14 | - type: textarea 15 | validations: 16 | required: true 17 | attributes: 18 | label: "Is your feature request related to a problem? Please describe it" 19 | description: "A clear and concise description of what the problem is" 20 | placeholder: | 21 | I have an issue when ... 22 | 23 | - type: textarea 24 | validations: 25 | required: true 26 | attributes: 27 | label: "Describe the solution you'd like" 28 | description: "A clear and concise description of what you want to happen. Add any considered drawbacks" 29 | 30 | - type: textarea 31 | attributes: 32 | label: "Teachability, documentation, adoption, migration strategy" 33 | description: "If you can, explain how users will be able to use this and possibly write out a version the docs. Maybe a screenshot or design?" 34 | 35 | - type: textarea 36 | validations: 37 | required: true 38 | attributes: 39 | label: "What is the motivation / use case for changing the behavior?" 40 | description: "Describe the motivation or the concrete use case" 41 | -------------------------------------------------------------------------------- /benchmarks/bench/src/bench.ts: -------------------------------------------------------------------------------- 1 | // to run this file, install: npm i --save benchmark pino @ogma/logger @nestjs/common 2 | // and then just run with: npx ts-node benchmark.ts 3 | 4 | import { Logger } from '@nestjs/common'; 5 | import { Ogma } from '@ogma/logger'; 6 | import Benchmark from 'benchmark'; 7 | import * as fs from 'fs'; 8 | import pino from 'pino'; 9 | 10 | const suite = new Benchmark.Suite(); 11 | 12 | const nestjsLogger = new Logger(); 13 | const ogmaLogger = new Ogma(); 14 | const ogmaJsonLogger = new Ogma({ json: true }); 15 | const pinoLogger = pino(); 16 | 17 | const file = process.cwd() + '/benchmarks/bench/README.md'; 18 | 19 | fs.writeFileSync(file, ''); 20 | 21 | suite.add('NestJS Logger', function () { 22 | nestjsLogger.log('Hello World!'); 23 | }); 24 | 25 | suite.add('Ogma', function () { 26 | ogmaLogger.info('Hello World!'); 27 | }); 28 | 29 | suite.add('OgmaJson', function () { 30 | ogmaJsonLogger.info('Hello World'); 31 | }); 32 | 33 | suite.add('Pino', function () { 34 | pinoLogger.info('Hello World!'); 35 | }); 36 | 37 | suite.add('console.log', function () { 38 | console.log('Hello World!'); 39 | }); 40 | 41 | suite.add('process.stdout', function () { 42 | process.stdout.write('Hello World!\n'); 43 | }); 44 | 45 | const results = []; 46 | 47 | suite 48 | // add listeners 49 | .on('cycle', function (event) { 50 | results.push(String(event.target)); 51 | }) 52 | .on('complete', function () { 53 | results.forEach((result) => fs.appendFileSync(file, result + '
\n')); 54 | 55 | fs.appendFileSync(file, '
Fastest is ' + this.filter('fastest').map('name')); 56 | }) 57 | .run({ 58 | async: true, 59 | }); 60 | -------------------------------------------------------------------------------- /integration/src/http/http.controller.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BadRequestException, 3 | Controller, 4 | Delete, 5 | Get, 6 | HttpCode, 7 | Patch, 8 | Post, 9 | Put, 10 | UseFilters, 11 | UseGuards, 12 | } from '@nestjs/common'; 13 | import { OgmaSkip } from '@ogma/nestjs-module'; 14 | 15 | import { AppService } from '../app.service'; 16 | import { FailGuard } from '../shared/fail.guard'; 17 | import { SimpleObject } from '../simple-object.model'; 18 | import { ErrorLoggingFilter } from './error-logging.filter'; 19 | 20 | @Controller() 21 | @UseFilters(ErrorLoggingFilter) 22 | export class HttpController { 23 | constructor(private readonly appService: AppService) {} 24 | 25 | @Get() 26 | getHello(): SimpleObject { 27 | return this.appService.getHello(); 28 | } 29 | 30 | @Get('status') 31 | @HttpCode(202) 32 | getStatus(): SimpleObject { 33 | return this.appService.getHello(); 34 | } 35 | 36 | @Get('error') 37 | getError(): SimpleObject { 38 | throw new BadRequestException(); 39 | } 40 | 41 | @Get('skip') 42 | @OgmaSkip() 43 | getSkip(): SimpleObject { 44 | return this.appService.getHello(); 45 | } 46 | 47 | @Get('fail-guard') 48 | @UseGuards(FailGuard) 49 | failGuard() { 50 | /* no op */ 51 | } 52 | 53 | @Post() 54 | getPost(): SimpleObject { 55 | return this.appService.getHello(); 56 | } 57 | 58 | @Patch() 59 | getPatch(): SimpleObject { 60 | return this.appService.getHello(); 61 | } 62 | 63 | @Put() 64 | getPut(): SimpleObject { 65 | return this.appService.getHello(); 66 | } 67 | 68 | @Delete() 69 | getDelete(): SimpleObject { 70 | return this.appService.getHello(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/cli.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: cli 3 | title: CLI 4 | layout: ../../layouts/MainLayout.astro 5 | --- 6 | 7 | Rehydration of Ogma JSON logs without a problem. 8 | 9 | Ogma comes with a command line function to rehydrate your json formatted logs back into the human readable format that can be installed with `@ogma/cli`. The command takes one to two arguments, a log file relative to where the command is run from, and an optional flag to force the cli to print out with color. Find the table below to learn more about the arguments. 10 | 11 | | argument | required | default | description | 12 | | --- | --- | --- | --- | 13 | | file | yes | none | The log file to be "hydrated". This file should contain newline separated Ogma formatted JSON logs. | 14 | | --color | no | terminal's TTY argument | you can pass `--color` or `--color=true` to force colors to be used. `--color=false` will force the command to not print the logs back out in color. Depending on the terminal you are using, colors may not be used by default. | 15 | 16 | The arguments can be passed in any order for ease of use. 17 | 18 | ## Example 19 | 20 | An example of the command's usage could be like so: 21 | 22 | ```sh 23 | ogma production.log --color 24 | ``` 25 | 26 | or if you have a TTY enabled command prompt 27 | 28 | ```sh 29 | ogma production.log 30 | ``` 31 | 32 | As this prints out to `process.stdout` it is possible to pipe this output to another file using the `>` operator. Like so: 33 | 34 | ```sh 35 | ogma production.log > production.hydrated.log 36 | ``` 37 | 38 | ## Demo 39 | 40 |
41 | Ogma CLI gif 42 |
43 | -------------------------------------------------------------------------------- /packages/nestjs-module/src/ogma-core.module.ts: -------------------------------------------------------------------------------- 1 | import { Global, Module } from '@nestjs/common'; 2 | import { DiscoveryModule } from '@nestjs/core'; 3 | 4 | import { DelegatorService } from './interceptor/providers'; 5 | import { 6 | OGMA_INSTANCE, 7 | OGMA_OPTIONS, 8 | OGMA_SERVICE_OPTIONS, 9 | OGMA_TRACE_METHOD_OPTION, 10 | } from './ogma.constants'; 11 | import { 12 | createOgmaProvider, 13 | createOgmaServiceOptions, 14 | createOgmaTraceOptions, 15 | createProviderToken, 16 | } from './ogma.provider'; 17 | import { OgmaService } from './ogma.service'; 18 | import { ConfigurableModuleClass } from './ogma-core.module-definition'; 19 | import { OgmaFilterService } from './ogma-filter.service'; 20 | 21 | @Global() 22 | @Module({ 23 | imports: [DiscoveryModule], 24 | providers: [ 25 | { 26 | provide: OGMA_SERVICE_OPTIONS, 27 | useFactory: createOgmaServiceOptions, 28 | inject: [OGMA_OPTIONS], 29 | }, 30 | { 31 | provide: OGMA_TRACE_METHOD_OPTION, 32 | useFactory: createOgmaTraceOptions, 33 | inject: [OGMA_SERVICE_OPTIONS], 34 | }, 35 | { 36 | provide: OGMA_INSTANCE, 37 | useFactory: createOgmaProvider, 38 | inject: [OGMA_SERVICE_OPTIONS], 39 | }, 40 | { 41 | provide: createProviderToken(DelegatorService.name), 42 | useFactory: (options) => 43 | createOgmaProvider({ 44 | ...options, 45 | context: DelegatorService.name, 46 | }), 47 | inject: [OGMA_SERVICE_OPTIONS], 48 | }, 49 | OgmaService, 50 | DelegatorService, 51 | OgmaFilterService, 52 | ], 53 | exports: [OGMA_INSTANCE, OgmaService, DelegatorService, OgmaFilterService], 54 | }) 55 | export class OgmaCoreModule extends ConfigurableModuleClass {} 56 | -------------------------------------------------------------------------------- /apps/docs/src/pages/en/nestjs/graphql/platform-graphql-fastify.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: platform-graphql-fastify 3 | title: Platform GraphQL Fastify 4 | layout: ../../../../layouts/MainLayout.astro 5 | --- 6 | 7 | :::info 8 | 9 | If you are using `@nestjs/apollo` make sure you are using fastify v3 and `@nestjs/common` version 8. If you are using`@nestjs/mercurius`you may use fastify v4 and`@nestjs/common` version 9. 10 | 11 | ::: 12 | 13 | The `GraphQLFastifyParser` parser for the `OgmaInterceptor`. This plugin class parses GraphQL request and response object to be able to successfully log the data about the request. For more information, check out the [@ogma/nestjs-module](/en/nestjs/module) documentation. 14 | 15 | ## Installation 16 | 17 | Nothing special, standard `npm i @ogma/platform-graphql-fastify` or `yarn add @ogma/platform-graphql-fastify` 18 | 19 | ## Usage 20 | 21 | This plugin is to be used in the `OgmaInterceptorOptions` portion of the `OgmaModule` during `forRoot` or `forRootAsync` registration. It can be used like so: 22 | 23 | ```ts 24 | @Module({ 25 | imports: [OgmaModule.forRoot({})], 26 | providers: [GraphQLFastifyParser] 27 | }) 28 | export class AppModule {} 29 | ``` 30 | 31 | :::note 32 | 33 | Due to the nature of subscriptions and the data available from the base ones, it is not possible at this time to log what subscriptions are made in the Ogma fashion. 34 | 35 | ::: 36 | 37 | Because the interceptor needs access to the request and response objects, when configuring the `GraphqlModule` from Nest, you need to add the `request` and `reply` to the GraphQL context. to do this, while configuring the `GraphqlModule`, set the `context` property as such: 38 | 39 | ```ts 40 | GraphqlModule.forRoot({ 41 | context: ({ request, reply }) => ({ request, reply }) 42 | }); 43 | ``` 44 | -------------------------------------------------------------------------------- /integration/test/utils/ws-promise.ts: -------------------------------------------------------------------------------- 1 | import { Socket } from 'socket.io-client'; 2 | import WebSocket from 'ws'; 3 | 4 | export const makeWs = ( 5 | client: (url: string) => Socket | WebSocket, 6 | url: string, 7 | sendMethod: 'send' | 'emit', 8 | ) => { 9 | return new Promise<{ send: (message: string) => Promise; close: () => Promise }>( 10 | (resolve, reject) => { 11 | const socket = client(url); 12 | const send = (message: string) => { 13 | return new Promise((resolve, reject) => { 14 | socket[sendMethod](message, {}, (data) => { 15 | if (data) { 16 | resolve(data); 17 | } 18 | }); 19 | socket.on('data', (data) => { 20 | resolve(data); 21 | }); 22 | socket.on('message', (data) => { 23 | resolve(data); 24 | }); 25 | socket.on('exception', resolve); 26 | socket.on('error', reject); 27 | }); 28 | }; 29 | const close = () => { 30 | return new Promise((resolve) => { 31 | if (wsIsWebsocket(socket)) { 32 | socket.terminate(); 33 | socket.onclose = () => resolve(); 34 | } else { 35 | socket.on('disconnect', () => resolve()); 36 | socket.disconnect(); 37 | } 38 | }); 39 | }; 40 | socket.on('connect', () => { 41 | resolve({ send, close }); 42 | }); 43 | socket.on('open', () => { 44 | resolve({ send, close }); 45 | }); 46 | socket.on('error', (err) => { 47 | console.error(err); 48 | reject(err); 49 | }); 50 | }, 51 | ); 52 | }; 53 | 54 | const wsIsWebsocket = (ws: unknown): ws is WebSocket => { 55 | return ws instanceof WebSocket; 56 | }; 57 | --------------------------------------------------------------------------------