Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(subs): disable save/kwargs mutation + better LOG_LEVEL #915

Merged
merged 6 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 5 additions & 1 deletion src/typegate/src/config/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@

import { sharedConfigSchema } from "./types.ts";
import { configOrExit } from "./loader.ts";
import type { LevelName } from "@std/log";

if (!Deno.env.has("VERSION")) {
// set version for config and workers, only running in main engine
const { get_version } = await import("native");
Deno.env.set("VERSION", get_version());
}

export const MAIN_DEFAULT_LEVEL = "INFO" satisfies LevelName;
export const ADDRESSED_DEFAULT_LEVEL = "ERROR" satisfies LevelName;

export const envSharedWithWorkers = [
"TEST_OVERRIDE_GQL_ORIGIN",
...Object.keys(sharedConfigSchema.shape).map((k) => k.toUpperCase()),
Expand All @@ -18,7 +22,7 @@ export const envSharedWithWorkers = [
export const sharedConfig = await configOrExit(
sharedConfigSchema,
{
log_level: "INFO",
log_level: MAIN_DEFAULT_LEVEL,
},
[
Object.fromEntries(
Expand Down
35 changes: 32 additions & 3 deletions src/typegate/src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { RefinementCtx, z } from "zod";
import { decodeBase64 } from "@std/encoding/base64";
import type { RedisConnectOptions } from "redis";
import type { S3ClientConfig } from "aws-sdk/client-s3";
import type { LevelName } from "@std/log";

const zBooleanString = z.preprocess(
(a: unknown) => z.coerce.string().parse(a) === "true",
Expand Down Expand Up @@ -127,12 +128,40 @@ export type TypegateConfig = {
sync: SyncConfigX | null;
};

export const logLevelItemSchema = z.enum(
["NOTSET", "DEBUG", "INFO", "WARN", "ERROR", "CRITICAL"] as readonly [
LevelName,
...LevelName[],
],
{
description: "log_level item",
},
);

export const logLevelSchema = z.string().transform((value) => {
let defaultLevel: LevelName = "ERROR";
const loggerConfs: Record<string, LevelName> = {};
const confs = value.toUpperCase().split(",");

for (const confSection of confs) {
const [left, ...right] = confSection.split("=");
if (right.length == 0) {
defaultLevel = logLevelItemSchema.parse(left.trim());
} else {
loggerConfs[left.toLowerCase()] = logLevelItemSchema.parse(
right.join("=").trim(),
);
}
}

loggerConfs["default"] = defaultLevel;
return loggerConfs;
});

// Those envs are split from the config as only a subset of them are shared with the workers
export const sharedConfigSchema = z.object({
debug: zBooleanString,
log_level: z
.enum(["NOTSET", "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"])
.optional(),
log_level: logLevelSchema.optional(),
rust_log: z.string().optional(),
version: z.string(),
deno_testing: zBooleanString,
Expand Down
8 changes: 2 additions & 6 deletions src/typegate/src/errors.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0.
// SPDX-License-Identifier: MPL-2.0

import { basename, dirname } from "@std/url";
import { extname } from "@std/path";
import { basename, dirname, extname } from "@std/path";
import { getLogger } from "./log.ts";
import { globalConfig } from "./config.ts";

Expand Down Expand Up @@ -55,10 +54,7 @@ export class BaseError extends Error {
return this;
}

toResponse(
headers: Headers = new Headers(),
graphqlFormat = true,
): Response {
toResponse(headers: Headers = new Headers(), graphqlFormat = true): Response {
const type = this.#type ?? this.constructor.name;
logger.error(
"{}[{}:{}]: {}",
Expand Down
49 changes: 33 additions & 16 deletions src/typegate/src/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
// SPDX-License-Identifier: MPL-2.0

import { ConsoleHandler, type LevelName, Logger } from "@std/log";
import { basename, dirname } from "@std/url";
import { extname } from "@std/path";
import { sharedConfig } from "./config/shared.ts";
import { basename, dirname, extname } from "@std/path";
import {
ADDRESSED_DEFAULT_LEVEL,
MAIN_DEFAULT_LEVEL,
sharedConfig,
} from "./config/shared.ts";

// set rust log level is not explicit set
if (!sharedConfig.rust_log) {
const set = (level: string) => Deno.env.set("RUST_LOG", level);
switch (sharedConfig.log_level) {
switch (sharedConfig.log_level?.default) {

Check warning on line 15 in src/typegate/src/log.ts

View check run for this annotation

Codecov / codecov/patch

src/typegate/src/log.ts#L15

Added line #L15 was not covered by tests
case "NOTSET":
set("off");
break;
Expand All @@ -18,7 +21,7 @@
"info,native=trace,sql_schema_connector=warn,tracing=warn,schema_core=warn,quaint=warn",
);
break;
case "WARNING":
case "WARN":

Check warning on line 24 in src/typegate/src/log.ts

View check run for this annotation

Codecov / codecov/patch

src/typegate/src/log.ts#L24

Added line #L24 was not covered by tests
set("warn");
break;
case "ERROR":
Expand All @@ -32,18 +35,21 @@
}
}

const consoleHandler = new ConsoleHandler(sharedConfig.log_level as LevelName, {
formatter: (log) => {
let msg = log.msg;
for (const arg of log.args) {
msg = msg.replace(
"{}",
typeof arg === "string" ? arg : JSON.stringify(arg),
);
}
return `${log.datetime.toISOString()} [${log.levelName} ${log.loggerName}] ${msg}`;
const consoleHandler = new ConsoleHandler(

Check warning on line 38 in src/typegate/src/log.ts

View check run for this annotation

Codecov / codecov/patch

src/typegate/src/log.ts#L38

Added line #L38 was not covered by tests
sharedConfig.log_level?.default ?? MAIN_DEFAULT_LEVEL,
{

Check warning on line 40 in src/typegate/src/log.ts

View check run for this annotation

Codecov / codecov/patch

src/typegate/src/log.ts#L40

Added line #L40 was not covered by tests
formatter: (log) => {
let msg = log.msg;
for (const arg of log.args) {
msg = msg.replace(
"{}",
typeof arg === "string" ? arg : JSON.stringify(arg),
);
}
return `${log.datetime.toISOString()} [${log.levelName} ${log.loggerName}] ${msg}`;
},
},
});
);

const loggers = new Map<string, Logger>();
const defaultLogger = new Logger("default", "NOTSET", {
Expand All @@ -70,4 +76,15 @@
return logger;
}

export function getLoggerByAddress(
name: ImportMeta | string | null = null,
address: string,
) {
const levelForAddress = sharedConfig?.log_level?.[address];

return levelForAddress

Check warning on line 85 in src/typegate/src/log.ts

View check run for this annotation

Codecov / codecov/patch

src/typegate/src/log.ts#L85

Added line #L85 was not covered by tests
? getLogger(name, levelForAddress)
: getLogger(name, ADDRESSED_DEFAULT_LEVEL);

Check warning on line 87 in src/typegate/src/log.ts

View check run for this annotation

Codecov / codecov/patch

src/typegate/src/log.ts#L87

Added line #L87 was not covered by tests
}

export { Logger };
4 changes: 2 additions & 2 deletions src/typegate/src/runtimes/substantial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Resolver, RuntimeInitParams } from "../types.ts";
import { ComputeStage } from "../engine/query_engine.ts";
import { TypeGraph, TypeGraphDS, TypeMaterializer } from "../typegraph/mod.ts";
import { registerRuntime } from "./mod.ts";
import { getLogger, Logger } from "../log.ts";
import { getLogger, getLoggerByAddress, Logger } from "../log.ts";
import * as ast from "graphql/ast";
import { path } from "compress/deps.ts";
import { Artifact } from "../typegraph/types.ts";
Expand Down Expand Up @@ -70,7 +70,7 @@ export class SubstantialRuntime extends Runtime {
private secrets: Record<string, string>,
) {
super(typegraphName);
this.logger = getLogger(`substantial:'${typegraphName}'`);
this.logger = getLoggerByAddress(import.meta, "substantial");
this.backend = backend;
this.queue = queue;
this.agent = agent;
Expand Down
Loading
Loading