npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@xiaoyue9527/audit-log-client

v1.0.0

Published

TypeScript/JavaScript client for audit logging services

Readme

审计日志客户端 (Audit Log Client) - TypeScript/JavaScript

npm version Node Version TypeScript License

用于审计日志服务的 TypeScript/JavaScript 客户端库,支持同步和异步两种使用模式。提供自动缓冲、批量发送、重试机制和降级策略,确保审计日志的可靠记录。

✨ 主要特性

  • 🚀 双模式支持:同步和异步 API,适应不同应用场景
  • 📦 智能缓冲:自动缓冲日志,批量发送,提高性能
  • 🔄 自动重试:指数退避重试策略,提高可靠性
  • 💾 降级策略:网络失败时自动写入本地文件,确保日志不丢失
  • 🔍 灵活查询:支持多维度条件查询审计日志
  • 🔒 安全认证:基于 AppID 和 SecretKey 的应用级认证
  • 📊 类型安全:完整的 TypeScript 类型定义
  • 🌐 框架支持:支持 Node.js、Express、Fastify、NestJS 等

📦 安装

npm install audit-log-client
# 或
yarn add audit-log-client
# 或
pnpm add audit-log-client

依赖要求

  • Node.js >= 14.0.0
  • TypeScript >= 5.0.0 (可选,但推荐)

🚀 快速开始

同步客户端

import {
  SyncAuditLogClient,
  AuditLog,
  AuditAction,
  AuditTarget,
} from "audit-log-client";

// 初始化客户端
const client = new SyncAuditLogClient({
  base_url: "http://audit.service/api",
  app_id: "your-app-id",
  secret_key: "your-secret-key",
});

// 创建审计日志
const log: AuditLog = {
  action: AuditAction.UPDATE,
  target_type: AuditTarget.USER,
  user_id: "admin",
  description: "用户资料更新",
  target_id: "user123",
  ip_address: "192.168.1.1",
  before: { name: "张三" },
  after: { name: "张三丰" },
};

// 记录日志(自动缓冲,批量发送)
client.log(log);

// 重要:程序退出前关闭客户端,确保缓冲区刷新
await client.close();

异步客户端

import {
  AsyncAuditLogClient,
  AuditLog,
  AuditAction,
  AuditTarget,
} from "audit-log-client";

async function main() {
  // 初始化客户端
  const client = new AsyncAuditLogClient({
    base_url: "http://audit.service/api",
    app_id: "your-app-id",
    secret_key: "your-secret-key",
  });

  // 重要:异步客户端需要先初始化,启动后台刷新任务
  await client.initialize();

  // 创建审计日志
  const log: AuditLog = {
    action: AuditAction.CREATE,
    target_type: AuditTarget.ORDER,
    user_id: "sales",
    description: "新建订单",
    target_id: "order456",
  };

  // 记录日志
  await client.log(log);

  // 重要:关闭客户端,确保缓冲区刷新
  await client.shutdown();
}

main();

⚙️ 配置选项

客户端初始化参数

interface ClientOptions {
  base_url: string;        // 服务地址(必需)
  app_id: string;          // 应用ID(必需)
  secret_key: string;      // 应用密钥(必需)
  buffer_size?: number;    // 缓冲区大小,默认100
  flush_interval?: number; // 刷新间隔(秒),默认10
  max_retries?: number;    // 最大重试次数,默认3
  timeout?: number;        // 请求超时(毫秒),默认10000
}

缓冲机制说明

  • 自动刷新触发条件

    • 缓冲区达到 buffer_size 时立即刷新
    • 每隔 flush_interval 秒自动刷新
    • 调用 close()shutdown() 时执行最终刷新
  • 推荐配置

    • 高频场景buffer_size: 500, flush_interval: 5(更频繁发送)
    • 低频场景buffer_size: 50, flush_interval: 30(减少请求)
    • 实时性要求高buffer_size: 10, flush_interval: 2(快速发送)

📝 使用示例

批量记录日志

// 同步客户端
const logs: AuditLog[] = Array.from({ length: 100 }, (_, i) => ({
  action: AuditAction.CREATE,
  target_type: AuditTarget.USER,
  user_id: "admin",
  description: `创建用户 ${i}`,
}));
client.batchLog(logs);

// 异步客户端
await client.batchLog(logs);

查询审计日志

import { AuditLogFilter } from "audit-log-client";

// 查询最近1小时的用户更新日志
const endTime = new Date();
const startTime = new Date(endTime.getTime() - 60 * 60 * 1000);

const filter: AuditLogFilter = {
  action: "UPDATE",
  target_type: "USER",
  user_id: "admin",
  start_time: startTime,
  end_time: endTime,
  limit: 100,
};

const logs = await client.queryLogs(filter);

logs.forEach((log) => {
  console.log(`${log.timestamp}: ${log.description}`);
});

在 Express 应用中使用

import express from "express";
import {
  SyncAuditLogClient,
  AuditLog,
  AuditAction,
  AuditTarget,
} from "audit-log-client";

const app = express();
app.use(express.json());

// 全局客户端实例
const auditClient = new SyncAuditLogClient({
  base_url: process.env.AUDIT_SERVICE_URL!,
  app_id: process.env.AUDIT_APP_ID!,
  secret_key: process.env.AUDIT_SECRET_KEY!,
});

app.put("/users/:userId", async (req, res) => {
  // 业务逻辑...

  // 记录审计日志
  auditClient.log({
    action: AuditAction.UPDATE,
    target_type: AuditTarget.USER,
    user_id: req.user.id,
    target_id: req.params.userId,
    description: `更新用户 ${req.params.userId}`,
    ip_address: req.ip,
    before: { status: "active" },
    after: { status: "inactive" },
  });

  res.json({ status: "ok" });
});

// 应用关闭时清理
process.on("SIGTERM", async () => {
  await auditClient.close();
  process.exit(0);
});

在 Fastify 应用中使用

import Fastify from "fastify";
import {
  AsyncAuditLogClient,
  AuditLog,
  AuditAction,
  AuditTarget,
} from "audit-log-client";

const fastify = Fastify();

// 全局客户端实例
let auditClient: AsyncAuditLogClient;

fastify.addHook("onReady", async () => {
  auditClient = new AsyncAuditLogClient({
    base_url: process.env.AUDIT_SERVICE_URL!,
    app_id: process.env.AUDIT_APP_ID!,
    secret_key: process.env.AUDIT_SECRET_KEY!,
  });
  await auditClient.initialize();
});

fastify.addHook("onClose", async () => {
  if (auditClient) {
    await auditClient.shutdown();
  }
});

fastify.put("/users/:userId", async (request, reply) => {
  // 业务逻辑...

  // 记录审计日志
  await auditClient.log({
    action: AuditAction.UPDATE,
    target_type: AuditTarget.USER,
    user_id: request.user.id,
    target_id: request.params.userId,
    description: `更新用户 ${request.params.userId}`,
  });

  return { status: "ok" };
});

在 NestJS 应用中使用

// audit-log.service.ts
import { Injectable, OnModuleInit, OnModuleDestroy } from "@nestjs/common";
import {
  AsyncAuditLogClient,
  AuditLog,
  AuditAction,
  AuditTarget,
} from "audit-log-client";

@Injectable()
export class AuditLogService implements OnModuleInit, OnModuleDestroy {
  private client: AsyncAuditLogClient;

  async onModuleInit() {
    this.client = new AsyncAuditLogClient({
      base_url: process.env.AUDIT_SERVICE_URL!,
      app_id: process.env.AUDIT_APP_ID!,
      secret_key: process.env.AUDIT_SECRET_KEY!,
    });
    await this.client.initialize();
  }

  async onModuleDestroy() {
    if (this.client) {
      await this.client.shutdown();
    }
  }

  async log(log: AuditLog): Promise<void> {
    await this.client.log(log);
  }
}

// user.controller.ts
import { Controller, Put, Param } from "@nestjs/common";
import { AuditLogService } from "./audit-log.service";
import { AuditAction, AuditTarget } from "audit-log-client";

@Controller("users")
export class UserController {
  constructor(private readonly auditLogService: AuditLogService) {}

  @Put(":id")
  async updateUser(@Param("id") id: string) {
    // 业务逻辑...

    await this.auditLogService.log({
      action: AuditAction.UPDATE,
      target_type: AuditTarget.USER,
      user_id: "current_user",
      target_id: id,
      description: `更新用户 ${id}`,
    });
  }
}

🔐 认证方式

客户端使用 AppID + SecretKey 进行身份验证:

  1. 获取凭证:从审计日志服务管理员处获取应用的 app_idsecret_key
  2. 配置客户端:初始化时传入凭证
  3. 自动认证:客户端自动在请求头中添加认证信息
// 推荐:使用环境变量管理密钥
const client = new SyncAuditLogClient({
  base_url: process.env.AUDIT_SERVICE_URL!,
  app_id: process.env.AUDIT_APP_ID!,
  secret_key: process.env.AUDIT_SECRET_KEY!, // 不要硬编码密钥!
});

🛡️ 错误处理和降级策略

自动重试机制

客户端内置指数退避重试机制:

  • 默认重试 3 次
  • 重试间隔:1秒 → 2秒 → 4秒
  • 可配置 max_retries 参数

降级到本地文件

当所有重试失败后,日志会自动写入本地文件 audit_fallback.log(JSON Lines 格式):

// 降级文件位置:当前工作目录下的 audit_fallback.log
// 格式:每行一个 JSON 对象

处理降级文件

import * as fs from "fs";
import * as readline from "readline";
import { AuditLog } from "audit-log-client";

// 读取降级日志并重新发送
const fileStream = fs.createReadStream("audit_fallback.log");
const rl = readline.createInterface({
  input: fileStream,
  crlfDelay: Infinity,
});

for await (const line of rl) {
  const logData: AuditLog = JSON.parse(line);
  await client.log(logData); // 重新发送
}

// 清空已处理的日志
fs.writeFileSync("audit_fallback.log", "");

错误处理示例

try {
  client.log(log);
} catch (error) {
  // 客户端内部已处理重试和降级
  // 这里可以记录监控指标或告警
  console.error(`Failed to send audit log: ${error}`);
  // 日志已写入降级文件,不会丢失
}

📊 支持的审计操作类型

基础操作

CREATE, UPDATE, DELETE, LOGIN, LOGOUT, ACCESS, DOWNLOAD, UPLOAD, APPROVE, REJECT, EXPORT, IMPORT, EXECUTE, GRANT, REVOKE

项目管理

RESTORE, CHANGE_STATUS, ADD_MEMBER, UPDATE_MEMBER_ROLE, REMOVE_MEMBER

文件管理

RENAME_FILE, MOVE_FILE, SHARE_FILE, REVOKE_FILE_SHARE

任务管理

CREATE_TASK, ASSIGN_TASK, COMPLETE_TASK, REOPEN_TASK, CHANGE_TASK_PRIORITY, ADD_TASK_COMMENT

支付管理

INITIATE_PAYMENT, PROCESS_PAYMENT, REFUND_PAYMENT, CANCEL_PAYMENT, CREATE_INVOICE, VERIFY_PAYMENT

系统管理

CHANGE_ROLE, UPDATE_PERMISSION, RESET_PASSWORD, LOCK_ACCOUNT, UNLOCK_ACCOUNT

更多操作类型请参考 AuditAction 枚举。

🎯 支持的目标类型

基础实体

USER, FILE, ROLE, PERMISSION, CONFIG, SETTING, PRODUCT, ORDER, CUSTOMER, SESSION, API_KEY, DATABASE, REPORT, PAYMENT

网关和追踪

API, GATEWAY, TRACE, ENDPOINT, ROUTER

业务实体

PROJECT, PROJECT_MEMBER, APPLICATION, FOLDER, SHARED_FILE, TASK, TASK_COMMENT, NOTIFICATION, INVOICE, REFUND, ACCOUNT, DATA_REPORT, DASHBOARD

更多目标类型请参考 AuditTarget 枚举。

💡 最佳实践

1. 资源管理

同步客户端

const client = new SyncAuditLogClient({...});
try {
  // 使用客户端
  client.log(log);
} finally {
  await client.close(); // 确保刷新缓冲区
}

异步客户端

const client = new AsyncAuditLogClient({...});
try {
  await client.initialize();
  await client.log(log);
} finally {
  await client.shutdown(); // 确保刷新缓冲区
}

2. 配置管理

// 推荐:使用环境变量或配置文件
const config = {
  base_url: process.env.AUDIT_SERVICE_URL || "http://localhost:8080",
  app_id: process.env.AUDIT_APP_ID!,
  secret_key: process.env.AUDIT_SECRET_KEY!,
  buffer_size: parseInt(process.env.AUDIT_BUFFER_SIZE || "100"),
  flush_interval: parseInt(process.env.AUDIT_FLUSH_INTERVAL || "10"),
};

const client = new SyncAuditLogClient(config);

3. 性能优化

  • 高频场景:增大 buffer_size,减少网络请求
  • 低延迟要求:减小 buffer_sizeflush_interval
  • 批量操作:使用 batchLog() 而不是多次调用 log()

4. 监控和告警

import * as fs from "fs";

// 监控降级文件大小
const fallbackSize = fs.statSync("audit_fallback.log").size;
if (fallbackSize > 10 * 1024 * 1024) {
  // 发送告警
  console.warn("Audit log fallback file too large");
}

🔧 故障排查

问题:日志没有发送

检查项

  1. 确认调用了 close()shutdown()
  2. 检查 audit_fallback.log 文件
  3. 查看控制台日志输出
  4. 验证网络连接和服务地址

问题:认证失败

检查项

  1. 确认 app_idsecret_key 正确
  2. 检查服务端配置中是否包含该应用
  3. 查看服务端日志

问题:查询返回空结果

检查项

  1. 确认时间范围正确
  2. 检查查询条件是否匹配
  3. 验证服务端是否有数据

📚 API 参考

SyncAuditLogClient

  • log(log: AuditLog): void - 记录单条日志
  • batchLog(logs: AuditLog[]): void - 批量记录日志
  • flush(): Promise<boolean> - 手动刷新缓冲区
  • queryLogs(filter: AuditLogFilter): Promise<AuditLog[]> - 查询日志
  • close(): Promise<void> - 关闭客户端并刷新缓冲区

AsyncAuditLogClient

  • initialize(): Promise<void> - 初始化客户端(必须调用)
  • log(log: AuditLog): Promise<boolean> - 异步记录单条日志
  • batchLog(logs: AuditLog[]): Promise<boolean> - 异步批量记录日志
  • flushAsync(): Promise<boolean> - 异步刷新缓冲区
  • queryLogs(filter: AuditLogFilter): Promise<AuditLog[]> - 异步查询日志
  • shutdown(): Promise<void> - 关闭客户端并刷新缓冲区

AuditLog 接口

interface AuditLog {
  action: AuditAction | string;        // 操作类型(必需)
  target_type: AuditTarget | string;   // 目标类型(必需)
  user_id: string;                     // 用户ID(必需)
  description: string;                 // 描述(必需)
  target_id?: string;                   // 目标ID
  ip_address?: string;                  // IP地址
  before?: Record<string, any>;         // 变更前数据
  after?: Record<string, any>;          // 变更后数据
  timestamp?: Date | string;            // 时间戳(默认当前时间)
  user_agent?: string;                  // 用户代理
  request_path?: string;                // 请求路径
  method?: string;                      // HTTP方法
  status_code?: number;                 // 状态码
  parameters?: Record<string, any>;     // 参数
  metadata?: Record<string, any>;       // 元数据
  id?: string;                          // 日志ID(服务端生成)
}

🛠️ 开发

构建

npm run build

测试

npm test

代码检查

npm run lint

格式化

npm run format

📄 许可证

MIT License

🤝 贡献

欢迎提交 Issue 和 Pull Request!

📞 支持


注意:生产环境使用前,请确保:

  1. ✅ 使用环境变量管理敏感信息(SecretKey)
  2. ✅ 配置合适的缓冲参数
  3. ✅ 监控降级文件大小
  4. ✅ 定期处理降级日志文件