Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/@graphql-hive_gateway-642-dependencies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@graphql-hive/gateway': patch
---

dependencies updates:

- Added dependency [`@graphql-hive/logger-json@workspace:^` ↗︎](https://www.npmjs.com/package/@graphql-hive/logger-json/v/workspace:^) (to `dependencies`)
11 changes: 11 additions & 0 deletions .changeset/big-waves-prove.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@graphql-mesh/transport-http-callback': patch
'@graphql-mesh/plugin-opentelemetry': patch
'@graphql-mesh/fusion-runtime': patch
'@graphql-mesh/transport-ws': patch
'@graphql-hive/importer': patch
'@graphql-hive/gateway': patch
'@graphql-hive/gateway-runtime': patch
---

New JSON-based logger
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
"vitest": "^3.0.1"
},
"resolutions": {
"@graphql-mesh/types": "0.103.16-alpha-20250212125252-6167fff12fe4017202b35363ff2769aafe28f98a",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update this before merging?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!

"@graphql-mesh/utils": "0.103.16-alpha-20250212125252-6167fff12fe4017202b35363ff2769aafe28f98a",
"@graphql-tools/delegate": "workspace:^",
"@opentelemetry/exporter-trace-otlp-http": "patch:@opentelemetry/exporter-trace-otlp-http@npm%3A0.56.0#~/.yarn/patches/@opentelemetry-exporter-trace-otlp-http-npm-0.56.0-dddd282e41.patch",
"@opentelemetry/otlp-exporter-base": "patch:@opentelemetry/otlp-exporter-base@npm%3A0.56.0#~/.yarn/patches/@opentelemetry-otlp-exporter-base-npm-0.56.0-ba3dc5f5c5.patch",
Expand Down
6 changes: 4 additions & 2 deletions packages/fusion-runtime/src/federation/supergraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,11 +311,13 @@ export const handleFederationSupergraph: UnifiedGraphHandler = function ({
if (context?.request) {
requestId = requestIdByRequest.get(context.request);
if (requestId) {
currentLogger = currentLogger?.child(requestId);
currentLogger = currentLogger?.child({ requestId });
}
}
if (sourceSubschema.name) {
currentLogger = currentLogger?.child(sourceSubschema.name);
currentLogger = currentLogger?.child({
subgraph: sourceSubschema.name,
});
}
for (const onDelegationPlan of onDelegationPlanHooks) {
const onDelegationPlanDone = onDelegationPlan({
Expand Down
12 changes: 6 additions & 6 deletions packages/fusion-runtime/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ function getTransportExecutor({
let logger = transportContext?.logger;
if (logger) {
if (subgraphName) {
logger = logger.child(subgraphName);
logger = logger.child({ subgraph: subgraphName });
}
logger?.debug(`Loading transport "${kind}"`);
}
Expand Down Expand Up @@ -195,10 +195,10 @@ export function getOnSubgraphExecute({
executionRequest.context?.request,
);
if (requestId) {
logger = logger.child(requestId);
logger = logger.child({ requestId });
}
if (subgraphName) {
logger = logger.child(subgraphName);
logger = logger.child({ subgraph: subgraphName });
}
logger.debug(`Initializing executor`);
}
Expand Down Expand Up @@ -287,7 +287,7 @@ export function wrapExecutorWithHooks({
let execReqLogger = transportContext?.logger;
if (execReqLogger) {
if (requestId) {
execReqLogger = execReqLogger.child(requestId);
execReqLogger = execReqLogger.child({ requestId });
}
loggerForExecutionRequest.set(baseExecutionRequest, execReqLogger);
}
Expand Down Expand Up @@ -548,11 +548,11 @@ export function wrapMergedTypeResolver<TContext extends Record<string, any>>(
if (logger && context['request']) {
requestId = requestIdByRequest.get(context['request']);
if (requestId) {
logger = logger.child(requestId);
logger = logger.child({ requestId });
}
}
if (subschema.name) {
logger = logger?.child(subschema.name);
logger = logger?.child({ subgraph: subschema.name });
}
let resolver = originalResolver as MergedTypeResolver<TContext>;
function setResolver(newResolver: MergedTypeResolver<TContext>) {
Expand Down
5 changes: 3 additions & 2 deletions packages/fusion-runtime/tests/polling.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { setTimeout } from 'timers/promises';
import { JSONLogger } from '@graphql-hive/logger-json';
import { getUnifiedGraphGracefully } from '@graphql-mesh/fusion-composition';
import { getExecutorForUnifiedGraph } from '@graphql-mesh/fusion-runtime';
import {
createDefaultExecutor,
type DisposableExecutor,
} from '@graphql-mesh/transport-common';
import { DefaultLogger, makeDisposable } from '@graphql-mesh/utils';
import { makeDisposable } from '@graphql-mesh/utils';
import { normalizedExecutor } from '@graphql-tools/executor';
import {
createDeferred,
Expand Down Expand Up @@ -334,7 +335,7 @@ describe('Polling', () => {
const unifiedGraphFetcher = vi.fn(() => {
return graphDeferred ? graphDeferred.promise : unifiedGraph;
});
const logger = new DefaultLogger();
const logger = new JSONLogger();
await using executor = getExecutorForUnifiedGraph({
getUnifiedGraph: unifiedGraphFetcher,
pollingInterval: 10_000,
Expand Down
1 change: 1 addition & 0 deletions packages/gateway/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@envelop/core": "^5.0.2",
"@graphql-hive/gateway-runtime": "workspace:^",
"@graphql-hive/importer": "workspace:^",
"@graphql-hive/logger-json": "workspace:^",
"@graphql-mesh/cache-cfw-kv": "^0.104.12",
"@graphql-mesh/cache-localforage": "^0.103.13",
"@graphql-mesh/cache-redis": "^0.103.13",
Expand Down
4 changes: 2 additions & 2 deletions packages/gateway/src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import 'dotenv/config'; // inject dotenv options to process.env

import module from 'node:module';
import { JSONLogger } from '@graphql-hive/gateway-runtime';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Consider passing a logger name for clarity.

When constructing JSONLogger, you can add a name property (e.g., { name: 'gateway' }) to help distinguish logs in multi-service environments.

import type { InitializeData } from '@graphql-hive/importer/hooks';
import { DefaultLogger } from '@graphql-mesh/utils';
import { enableModuleCachingIfPossible, handleNodeWarnings, run } from './cli';

// @inject-version globalThis.__VERSION__ here
Expand All @@ -20,7 +20,7 @@ module.register('@graphql-hive/importer/hooks', {
enableModuleCachingIfPossible();
handleNodeWarnings();

const log = new DefaultLogger();
const log = new JSONLogger();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Verify documentation updates.

You are introducing a new logging feature in the Gateway. Per the guidelines, ensure that user-facing docs are updated in the relevant console project or that a follow-up issue is created to track the additions.

Do you need help drafting the necessary documentation or opening a new issue in graphql-hive/console?


run({ log }).catch((err) => {
log.error(err);
Expand Down
8 changes: 4 additions & 4 deletions packages/gateway/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type {
GatewayGraphOSReportingOptions,
GatewayHiveReportingOptions,
} from '@graphql-hive/gateway-runtime';
import { JSONLogger } from '@graphql-hive/logger-json';
import type UpstashRedisCache from '@graphql-mesh/cache-upstash-redis';
import type { JWTAuthPluginOptions } from '@graphql-mesh/plugin-jwt-auth';
import type { OpenTelemetryMeshPluginOptions } from '@graphql-mesh/plugin-opentelemetry';
Expand All @@ -26,7 +27,6 @@ import type {
MeshPubSub,
YamlConfig,
} from '@graphql-mesh/types';
import { DefaultLogger } from '@graphql-mesh/utils';
import parseDuration from 'parse-duration';
import { addCommands } from './commands/index';
import { createDefaultConfigPaths } from './config';
Expand Down Expand Up @@ -177,7 +177,7 @@ export function defineConfig(config: GatewayCLIConfig) {

/** The context of the running program. */
export interface CLIContext {
/** @default new DefaultLogger() */
/** @default new JSONLogger() */
log: Logger;
/** @default 'Mesh Serve' */
productName: string;
Expand Down Expand Up @@ -347,7 +347,7 @@ let cli = new Command()

export async function run(userCtx: Partial<CLIContext>) {
const ctx: CLIContext = {
log: userCtx.log || new DefaultLogger(),
log: userCtx.log || new JSONLogger(),
productName: 'Hive Gateway',
productDescription: 'Federated GraphQL Gateway',
productPackageName: '@graphql-hive/gateway',
Expand All @@ -362,7 +362,7 @@ export async function run(userCtx: Partial<CLIContext>) {
cli = cli.name(binName).description(productDescription).version(version);

if (cluster.worker?.id) {
ctx.log = ctx.log.child(`Worker #${cluster.worker.id}`);
ctx.log = ctx.log.child({ worker: cluster.worker.id });
}

addCommands(ctx, cli);
Expand Down
17 changes: 12 additions & 5 deletions packages/gateway/src/commands/handleLoggingOption.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { JSONLogger } from '@graphql-hive/logger-json';
import { Logger } from '@graphql-mesh/types';
import { CLIContext, DefaultLogger, LogLevel } from '..';
import { CLIContext, LogLevel } from '..';

export function handleLoggingConfig(
loggingConfig: boolean | Logger | LogLevel | undefined,
Expand All @@ -9,17 +10,23 @@ export function handleLoggingConfig(
ctx.log = loggingConfig;
} else if (typeof loggingConfig === 'boolean') {
if (!loggingConfig) {
if (ctx.log instanceof DefaultLogger) {
if ('logLevel' in ctx.log) {
ctx.log.logLevel = LogLevel.silent;
} else {
ctx.log = new DefaultLogger(ctx.log.name, LogLevel.silent);
ctx.log = new JSONLogger({
name: ctx.log.name,
level: LogLevel.silent,
});
}
}
} else if (typeof loggingConfig === 'number') {
if (ctx.log instanceof DefaultLogger) {
if ('logLevel' in ctx.log) {
ctx.log.logLevel = loggingConfig;
} else {
ctx.log = new DefaultLogger(ctx.log.name, loggingConfig);
ctx.log = new JSONLogger({
name: ctx.log.name,
level: loggingConfig,
});
}
}
}
14 changes: 9 additions & 5 deletions packages/importer/src/debug.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
export const isDebug = ['1', 'y', 'yes', 't', 'true'].includes(
String(process.env['DEBUG']),
);
export const isDebug = ['importer'].includes(String(process.env['DEBUG']));

export function debug(msg: string) {
export function debug(message: string) {
if (isDebug) {
process.stderr.write(`[${new Date().toISOString()}] HOOKS ${msg}\n`);
process.stderr.write(
`${JSON.stringify({
name: 'importer',
level: 'debug',
message,
})}\n`,
);
Comment on lines +1 to +11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Optional enhancement for debug condition and logging consistency.

  1. The debug check is strictly ['importer'].includes(String(process.env['DEBUG'])); consider partial matching (includes('importer')) if you want simpler usage (e.g., DEBUG=importer,other).
  2. The output format is consistent with the JSON-based logging approach. Optionally, you could centralize all logging via JSONLogger for consistency across the codebase.

}
}
55 changes: 55 additions & 0 deletions packages/logger-json/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"name": "@graphql-hive/logger-json",
"version": "0.0.0",
"type": "module",
Comment on lines +1 to +4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Missing changeset file for the new package.

According to the coding guidelines, a changeset file is required for new packages. Please create one using yarn changeset with:

  • A description of the new JSON-based logger feature
  • An example of usage
  • A "minor" semver bump since this is a new feature

Let me check if a changeset file exists:


🏁 Script executed:

#!/bin/bash
# Look for changeset files
fd -e md . .changeset/

Length of output: 1716


Missing changeset file for @graphql-hive/logger-json package
No changeset file referencing @graphql-hive/logger-json was found in the repository's .changeset directory. Please add a new changeset file (using yarn changeset) that includes a description of the JSON-based logger feature, an example of usage, and specifies a "minor" semver bump.

"repository": {
"type": "git",
"url": "git+https://github.com/graphql-hive/gateway.git",
"directory": "packages/logger-json"
},
"author": {
"email": "[email protected]",
"name": "The Guild",
"url": "https://the-guild.dev"
},
"license": "MIT",
"engines": {
"node": ">=18.0.0"
},
"main": "./dist/index.js",
"exports": {
".": {
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
},
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"./package.json": "./package.json"
},
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "pkgroll --clean-dist",
"prepack": "yarn build"
},
Comment on lines +37 to +40
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Add test script to package.json.

Consider adding a test script to ensure the logger functionality is properly tested:

 "scripts": {
   "build": "pkgroll --clean-dist",
-  "prepack": "yarn build"
+  "prepack": "yarn build",
+  "test": "jest"
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"scripts": {
"build": "pkgroll --clean-dist",
"prepack": "yarn build"
},
"scripts": {
"build": "pkgroll --clean-dist",
"prepack": "yarn build",
"test": "jest"
},

"peerDependencies": {
"graphql": "^15.9.0 || ^16.9.0"
},
"dependencies": {
"@graphql-mesh/cross-helpers": "^0.4.9",
"@graphql-mesh/types": "^0.103.6",
"@graphql-mesh/utils": "^0.103.6",
"tslib": "^2.8.1"
},
"devDependencies": {
"graphql": "^16.9.0",
"pkgroll": "2.8.2"
},
"sideEffects": false
}
Loading
Loading