Обновить

🤔 Как не терять requestId в логах не пробрасывая его через параметры методов?

Классическая проблема NodeJS разработки: логи не читаемы. При дебаге когда пользователь один, разобрать что происходит ещё можно. Но после запуска в прод в логах сборная солянка из запросов и восстановить трейс вызова композиции методов нельзя

import { scoped } from "di-scoped";

export interface IRequestContext {
  userId: string;
  requestId: string;
  serviceName: "mobile" | "desktop";
  version: number;
}

export const RequestContextService = scoped(
  class {
    constructor(readonly context: IRequestContext) {}
  }
);

export type TRequestContextService = InstanceType<
  typeof RequestContextService
>;

export default RequestContextService;

Согласно MVC, делается два слоя: View и Controller. На уровне view кладем requestId в контекст исполнения через RequestContextService.runInContext

import { inject } from "di-kit";

export class SocketViewService {
  readonly loggerService = inject<LoggerService>(TYPES.loggerService);
  readonly socketControllerService = inject<SocketControllerService>(TYPES.socketControllerService);

  public sendNewOrder = async (
    request: TRequest<{ room: string; orderId: string }>,
  ): Promise<TResponse<SendNewOrder>> => {
    this.loggerService.log("socketViewService sendNewOrder", { request });
    try {
      const data = await RequestContextService.runInContext(
//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        async () =>
          await this.socketControllerService.sendNewOrder(request.data),
        request,
      );
      return { status: "ok", serviceName: request.serviceName, version: request.version, userId: request.userId, requestId: request.requestId, data };
    } catch (error: any) {
      this.loggerService.log("socketViewService sendNewOrder error", { request, error: errorData(error) });
      return { status: "error", error: VerificationError.getErrorMessage(error), errorCode: VerificationError.getErrorCode(error), serviceName: request.serviceName, version: request.version, userId: request.userId, requestId: request.requestId };
    }
  };
}

Voila! Во всех вложенных сервисах к записи в лог будет приложен идентификатор requestId. Дополнительно, этот код позволяет сериализовать ошибки так, чтобы передавать их по шине gRPC

import { inject } from "di-kit";
import { createLogger } from 'pinolog';

const logger = createLogger("socket.log");

export class LoggerService {

  readonly requestContextService = inject<TRequestContextService>(TYPES.requestContextService);

  private get context() {
    if (RequestContextService.hasContext()) {
      // в лог - только конверт IRequestContext; scoped-контекст. но дебаггеру виден весь запрос
      const { serviceName, version, userId, requestId } = this.contextService.context;
      return { serviceName, version, userId, requestId };
    }
    return {};
  }

  public log = (topic: string, ...args: any[]) => {
    logger.log(topic, ...args, this.context);
  }

}
Теги:
+4
Комментарии0

Как мы запустили Qwen3.8–27B целиком на RTX 5060 8 GB и получили ~30 токенов/с

Наш проект называется ExVRAM Lab. Это открытая исследовательская лаборатория, в которой мы проверяем, насколько большие локальные LLM можно запускать на обычных видеокартах с ограниченным объёмом VRAM, если использовать ultra‑low‑bit quantization, полное размещение весов на GPU и существующие open‑source inference‑технологии.

ExVRAM расшифровывается как Exchange Compute for VRAM. Основная идея проекта — в ряде сценариев выгоднее потратить часть свободной вычислительной мощности GPU на работу с более компактным представлением весов, чем хранить часть модели в оперативной памяти и постоянно передавать данные через PCIe.

Когда мы начинали проект, исходный вопрос был достаточно простой: можно ли запустить dense‑модель примерно на 27 миллиардов параметров на видеокарте всего с 8 ГБ VRAM так, чтобы она не просто «запустилась», а работала полностью на GPU, поддерживала длинный контекст и обеспечивала нормальную интерактивную скорость генерации.

В качестве основной тестовой системы мы используем NVIDIA GeForce RTX 5060 8 GB на архитектуре Blackwell. Основная модель в текущих экспериментах — Qwen3.8–27B.

Сначала результат выглядел не слишком впечатляюще. Модель запускалась, но значительная часть весов оставалась в системной памяти. Около 5,7 GiB весов находилось на GPU, ещё примерно 2,5 GiB — на CPU. Скорость генерации составляла порядка 3,8–5,5 токена в секунду.

При этом сама видеокарта была загружена далеко не полностью.

Это стало одним из первых важных наблюдений проекта. Проблема заключалась не столько в нехватке вычислительной мощности RTX 5060, сколько в том, что часть decoder weights находилась в RAM. Во время autoregressive generation данные приходилось постоянно передавать между CPU и GPU через PCIe.

Как мы запустили Qwen3.8–27B целиком на RTX 5060 8 GB и получили ~30 токенов/с

Публикации