@8pattern/jlogger 中文文档教程

发布于 5年前 浏览 25 项目主页 更新于 3年前

jLogger

一个小小的& 的灵活记录器

JS [toc]

Install

npm install -S @8pattern/jlogger

Usage

Demo with default appenders

import JLogger from '@8pattern/jlogger'
const logger = new JLogger()
logger.info('hello, world')

如果你执行前面的代码,你会发现控制台打印一个像 {"level":"INFO", …,"count":1,"content":"hello,世界”自动。

Demo with appenders

import JLogger, { appender } from '@8pattern/jlogger'
const logger = new JLogger()
logger.Appender.register(new appender.FileAppender())
logger.info('hello, world')

执行前面的代码,不仅控制台会打印出类似 {"level":"INFO", …,"count":1,"content":"hello, world"} 的 JSON,而且还可以在具有相同 JSON 的相同目录中找到日志文件 (yyyy-mm-dd.log)(在 Node 环境中)。

Procedure

Preparation

在使用 jLogger 打印日志之前,需要生成一个实例。 它允许用户在实例上绑定一些参数和配置。 构造函数可以接收两个参数。

const logArguments = {}, logConfig = {}
const logger = new JLogger(logArguments, logConfig)
  1. logArguments :接收该实例范围内的一些默认参数,即每个日志都会接收这些参数。

    Node环境下,默认值为:

  • pid:同process.pid

    浏览器下,默认值为:

  • wid:小于10万的随机数

  • url :当前路由路径,即不带协议的href,主机和端口

    可以指定一些自定义参数,例如:文件路径,作者等。

   const logArguments = { hello: 'world' }
   const logger = new JLogger(logArguments)
   logger.info('') // { ..., hello: 'world', ... }
  1. logConfig : some配置来改变记录器的行为。

    只有以下配置有效。

  • 类别

    默认值:

     {
         notice: 'NOTICE',
         action: 'ACTION',
         function: 'FUNCTION',
     }
    

注意:您可以更改这些类别值或添加一些新类别。 删除是没有用的(因为我们在里面用到了)。

  • 级别

    默认值:

     {
         error: 'ERROR',
         warn: 'WARN',
         info: 'INFO',
         debug: 'DEBUG',
     }
    

注意:与类别相同,更改值并添加新级别有效,但删除无用

  • 格式<功能>

    • 参数:logArguments ;

    • 返回: logString <字符串>;

      默认值:

     (logArgs) => JSON.stringify(logArgs)
    
  1. The content of logArguments will be presented at the following section.
  2. If some log arguments don't wanted to be printed, such as some levels or categories, you can modify this format implementation.
  • printLevel

    默认值:

     ['debug', 'info', 'warn', 'error']
    

logConfig.level 中的元素必须是键而不是值

Control appenders

Pre-given appenders

Appenders 说明了每个日志的打印方法。 您可以从 jLogger 的 appender 中找到一些预先给定的 appender。

import { appender } from '@8pattern/jlogger'
const { Appender, ConsoleAppender, FileAppender } = appender
  • Appender

    每个特定 appender 的抽象类。 只有一个抽象方法 print 绑定在它上面。 当您设计自定义附加程序时,您必须从这个父类(稍后介绍)扩展。

  • ConsoleAppender

    将日志打印到控制台。 它也是默认的 appender,所以除了工作你什么都不做。

  • FileAppender

    将日志打印到文件中(仅适用于 Node)。

  import JLogger, { appender } from '@8pattern/jlogger'
  const logger = new JLogger()
  logger.Appender.set([new appender.FileAppender()])

它也可以用一些配置来实例化。

  const fileAppender = new FileAppender({
      filePath: './',
      fileName: `${dateformat(Date.now(), 'yyyy-mm-dd')}`,
      fileExtension: 'log',
  })
  • filePath :日志文件的相关路径。

    默认值:'./'

  • fileName :日志文件的名称。

    默认值:${dateformat(Date.now(), 'yyyy-mm-dd')}

  • fileExtension :日志文件的扩展名。

    默认值:log

Update appenders

要激活一个 appender,您需要处理 logger.Appender,它提供了一些方法来控制已注册的 appender。

  • appenders <array>: store the registered appenders.
  const logger = new JLogger()
  console.log(logger.Appenders.appenders.length)
  // 1, there is a instance of ConsoleAppender by default
  • 设置<函数>;

  • 参数:appenders ;

  • 返回:currentRegisteredAppendersNumber ;

  logger.Appenders.set([new ConsoleAppender(), new FileAppender()])

注意:

  1. This method will replace all appenders.
  2. Any appenders which not extended from the abstract class Appender will be filtered.
  • get ;

  • 参数:null

  • 返回:appenders

  logger.Appender.get() // === logger.Appender.appenders
  • 注册 <功能>

  • 参数:appender

  • 返回:null

    logger.Appender.register(new FileAppender()) // logger.Appender.appenders.length === 2
    

注意:

  1. Compare to set method, it only add a new appender RATHER THAN replace all of them.
  2. ONLY instance of abstract class Appender will make effect as well.
  3. If the appender has been registered, it won't add a new one.
  logger.set([new ConsoleAppender()])
  // logger.Appenders.appenders.length === 1

  const fileAppender = new FileAppender()

  logger.Appender.register(fileAppender)
  // logger.Appenders.appenders.length === 2, register a new FileAppender instance

  logger.Appender.register(fileAppender)
  // logger.Appenders.appenders.length === 2, because it has been registered before

  logger.Appender.register(new FileAppender())
  // logger.Appenders.appenders.length === 3, a new FileAppender registered

  logger.Appender.register({})
  // throw a error, because the provided appender is illegal.
  • delete ;

  • 参数:appender

  • 返回:isSuccess ;

  const fileAppender = new FileAppender()

  logger.Appender.set([fileAppender])
  // logger.Appenders.appenders.length === 1

  logger.Appender.delete(new FileAppender())
  // === false, logger.Appenders.appenders.length === 1, the given appender doesen't exist

  const fileAppender = new FileAppender()

  logger.Appender.delete(fileAppender)
  // === true, logger.Appenders.appenders.length === 0
Design a custom appender

如果你想自定义一个appender,你只需要从Appender扩展你的类并实现打印方法。

import { appender } from '@8pattern/jlogger'

class CustomAppender extends appender.Appender {
    print(logArgs) {
        console.log(logArgs)
    }
}

jlogger.Appender.register(new CustomAppender())

Call to log

logArgument

logArgument 包含日志的所有字段,可用于格式化记录器或在附加程序中打印。 它必须包含以下值。

  • level: the log level. Default value: logger.config.level.info.
  • timeStamp: current time stamp (without formation). Value: Date.now().
  • count: the number of log called. Value: automatically increased from 0.
  • content: the log content.

此外,可以从构造或日志调用函数中添加一些自定义参数。 并且调用函数的参数比构造函数具有更高的优先级。 但是,"timeStamp" 和 "count" 具有更高的优先级,不能被覆盖。

const logger = new Logger({a: 1, b: 2})
logger.info('', { b: 3, c: 4 })
// { ..., a: 1, b: 3, c: 4, ... }

如果你想改变时间或计数最终日志,添加另一个参数并更改格式功能。

Ordinary log method
  • log

  • 参数:content , logArgs ;

  • 返回:finalLogArgs ;

  logger.log('hello world', { a: 1 })
  // { a: 1, ... content: 'hello world', ... }
  • debug / info / warn

  • 参数:content , logArgs ;

  • 返回:finalLogArgs ;

    它们都是带有级别的日志糖。

  logger.debug('') // { ..., level: 'DEBUG', ... }
  logger.info('') // { ..., level: 'INFO', ... }
  logger.warn('') // { ..., level: 'WARN', ... }
  • error

  • 参数:content ; | <错误>, logArgs ;

  • 返回:finalLogArgs ;

    也是error级别的log的糖,但是可以接收Error作为内容。 如果调用时出现Error,"errType"和"errDesc"将被添加到finalLogArgs中,Error的堆栈将被视为

  logger.error('')
  // { ..., content: '', ..., level: 'ERROR', ... }

  const err = new Error('Some errors')
  logger.error(err)
  // { ..., content: 'Error: Some errors at ...', ..., errDesc: 'Some errors', errType: 'Error', ... }
  • config中定义的其他级别

    的内容如果配置中定义的其他一些级别,它也提供这些糖。

  const level = {
      fatal: 'FATAL',
  }
  const logger = new JLogger({}, { level })
  logger.fatal('')
  // { ..., level: 'FATAL', ... }
Function log

由于函数日志非常重要,但它们相同的结构使编码人员感到厌烦,因此我们专门为函数日志提供了两种方法。

  • logWrap

  • argument: wrapped , logArgs ;

  • 返回:<函数>;

    此方法将打印包装函数输入和输出的日志。 如果函数抛出错误,它会自动打印错误日志。

  const fun(a) {
      return a + 1;
  }

  const wrappedFun = jLogger.logWrap(fun, { t: 1 })

  wrappedFun(1)
  // { ..., content: 'INPUT: [1]',category: 'FUNCTION', funName: 'fun', t: 1, ...}
  // { ..., content: 'OUTPUT: 2',category: 'FUNCTION', funName: 'fun', t: 1, ...}
```javascript

常量乐趣(){ throw new Error('一些错误') }

const wrappedFun = jLogger.logWrap(fun)

wrappedFun('你好') // { …, 内容:'INPUT: ['hello']', 类别:'FUNCTION', funName: 'fun', …} // { …, category: 'FUNCTION', funName: 'fun', level: 'ERROR', …} ```

  • logDecorator

  • 参数:logArgs

  • 返回:<函数>;

    有类方法的装饰器提案,我们也提供了一个基于logWrap的logDecorator。

  const log = logger.logDecorator({ test: 1 })

  class T {
      @log
      test1(a) {
          return a + 1
      }

      @logger.logDecorator({ test: 2 })
      test2() {
          throw new Error('some errors')
      }
  }

  const t = T()

  t.test1(1)
  // { ..., content: 'INPUT: [1]', category: 'FUNCTION', className: 'T', funName: 'test1', t: 1, ...}
  // { ..., content: 'OUTPUT: 2',category: 'FUNCTION', className: 'T', funName: 'test1', t: 1, ...}

  t.test(2)
  // { ..., content: 'INPUT: [2]', category: 'FUNCTION', className: 'T', funName: 'test2', t: 2, ...}
  // { ..., category: 'FUNCTION', level: 'ERROR', className: 'T', funName: 'test2', t: 2, ...}

Util

我们提供了一些与日志相关的有用工具,可以从 jLogger.util 中找到。

import { util } from '@8pattern/jlogger'
const { dateformat, contentLengthFormat, logTag } = util

dateformat

  • argument:
  • date <Date> | <number>. Default value: new Date()
  • formatStr <string>. Default value: 'yyyy-mm-dd HH:MM:ss.l'
  • return: <string>

这个方法是一个格式化日期的小函数。 用法与其他成熟库类似,即,

y -> year
m -> month
d -> day
H -> hour
M -> minute
s -> second
l -> millisecond

例如:

dateformat(0, 'yyyy-mm-dd') // 1970-01-01
dateformat(new Date(0), 'yy-m-d') // 70-1-1
dateformat(0, 'HH:MM:ss') // 00:00:00
dateformat(0, 'H:M:s.l') // 0:0:0.0000

contentLengthFormat

  • argument:
  • content <string>.
  • lengthLimit <number> | <null>. Default value: null
  • replaceString <string>. Default value: ' <<<… $IGNOREDSTRINGLENGTH chars are ignored …>>> '
  • return: <string>
contentLengthFormat('123456789')
// 123456789, because lengthLimit === null

contentLengthFormat('123456789', 4)
// 12 <<<... 5 chars are ignored ...>>> 89

contentLengthFormat('123456789', 4, '...igonred...')
// 12...ignored...89

logTag

日志内容模板字符串的标签。 它将函数、数组和对象转换为更具可读性的形式。

function fun(a) { return a + 1; }
`${fun}` // "function fun(a) { return a + 1; }"
logTag`${fun}` // "-Function[fun]-"
const arr = [1,2,3,4,5]
`${arr}` // "1,2,3,4,5"
logTag`${fun}` // "[1,2,3,4,5]"
const dict = { a: 1 }
`${dict}` // "[object Object]"
logTag`${dict}` // "{ a: 1 }"
class CustomClass {}
const t = new CustomClass()
`${t}` // "[object Object]"
logTag`${t}` // "-CustomClass-"

一个完整的例子:

const obj = {
    arr: [1, 2, function() {}],
    fun() {},
}

`content is ${obj}` // "content is [object Object]"
logTag`content is ${obj}` // "content is {arr:[1,2,-Function-], fun:-Function[fun]-}"

jLogger

A tiny & flexible logger for JS

[toc]

Install

npm install -S @8pattern/jlogger

Usage

Demo with default appenders

import JLogger from '@8pattern/jlogger'
const logger = new JLogger()
logger.info('hello, world')

if you execute the previous codes, you will find the console prints a JSON like {"level":"INFO", … ,"count":1,"content":"hello, world"} automatically.

Demo with appenders

import JLogger, { appender } from '@8pattern/jlogger'
const logger = new JLogger()
logger.Appender.register(new appender.FileAppender())
logger.info('hello, world')

Execute the previous codes, not only the console will print a JSON like {"level":"INFO", … ,"count":1,"content":"hello, world"}, but also a log file (yyyy-mm-dd.log) can be found in same dir with the same JSON (in Node environment).

Procedure

Preparation

Before print logs by jLogger, a instance should be generated. It allows users to bind some arguments and configurations on the instance. The construction function can receive two arguments.

const logArguments = {}, logConfig = {}
const logger = new JLogger(logArguments, logConfig)
  1. logArguments <object>: receive some default arguments within this instance scope, i.e., each log will receive these arguments.

    In Node environment, the default value is:

  • pid: same as process.pid

    In browser, the default value are:

  • wid: a random number less than 100,000

  • url: the current route path, i.e., the href without protocol, host and port

    You CAN assign some custom arguments, such as: filePath, author and etc.

   const logArguments = { hello: 'world' }
   const logger = new JLogger(logArguments)
   logger.info('') // { ..., hello: 'world', ... }
  1. logConfig <object>: some configurations to change the logger behavior.

    Only the following configurations is valid.

  • category <JSON>

    Default value:

     {
         notice: 'NOTICE',
         action: 'ACTION',
         function: 'FUNCTION',
     }
    

NOTE: you can change these category values or add some new categories. Deletion is useless (Because we use them inside).

  • level <JSON>

    Default value:

     {
         error: 'ERROR',
         warn: 'WARN',
         info: 'INFO',
         debug: 'DEBUG',
     }
    

NOTE: Same as category, change values and add new levels works but Deletion is useless.

  • format <function>

    • argument: logArguments <JSON>

    • return: logString <string>

      Default value:

     (logArgs) => JSON.stringify(logArgs)
    
  1. The content of logArguments will be presented at the following section.
  2. If some log arguments don't wanted to be printed, such as some levels or categories, you can modify this format implementation.
  • printLevel <array>

    Default value:

     ['debug', 'info', 'warn', 'error']
    

The elements must be the keys rather than values in logConfig.level

Control appenders

Pre-given appenders

Appenders illustrates the print methods of every logs. You can find some pre-given appenders from appender of the jLogger.

import { appender } from '@8pattern/jlogger'
const { Appender, ConsoleAppender, FileAppender } = appender
  • Appender

    Abstract class for every specific appender. Only a abstract method print is binded on it. When you design a custom appender, you MUST extend from this parent class (presented later).

  • ConsoleAppender

    Print the logs into the console. It's also the default appenders, so you won't do anything but work.

  • FileAppender

    Print the logs into the file (only works in Node).

  import JLogger, { appender } from '@8pattern/jlogger'
  const logger = new JLogger()
  logger.Appender.set([new appender.FileAppender()])

It can be instantiated with some configurations as well.

  const fileAppender = new FileAppender({
      filePath: './',
      fileName: `${dateformat(Date.now(), 'yyyy-mm-dd')}`,
      fileExtension: 'log',
  })
  • filePath <string>: the revelant path of the log file.

    Default value: './'

  • fileName <string>: the name of the log file.

    Default value: ${dateformat(Date.now(), 'yyyy-mm-dd')}

  • fileExtension <string>: the extension of the log file.

    Default value: log

Update appenders

To activate an appender, you need process the logger.Appender, and it provides some methods to control registered appenders.

  • appenders <array>: store the registered appenders.
  const logger = new JLogger()
  console.log(logger.Appenders.appenders.length)
  // 1, there is a instance of ConsoleAppender by default
  • set <function>

  • argument: appenders <array>

  • return: currentRegisteredAppendersNumber <number>

  logger.Appenders.set([new ConsoleAppender(), new FileAppender()])

NOTE:

  1. This method will replace all appenders.
  2. Any appenders which not extended from the abstract class Appender will be filtered.
  • get <function>

  • argument: null

  • return: appenders<array>

  logger.Appender.get() // === logger.Appender.appenders
  • register <function>

  • argument: appender

  • return: null

    logger.Appender.register(new FileAppender()) // logger.Appender.appenders.length === 2
    

NOTE:

  1. Compare to set method, it only add a new appender RATHER THAN replace all of them.
  2. ONLY instance of abstract class Appender will make effect as well.
  3. If the appender has been registered, it won't add a new one.
  logger.set([new ConsoleAppender()])
  // logger.Appenders.appenders.length === 1

  const fileAppender = new FileAppender()

  logger.Appender.register(fileAppender)
  // logger.Appenders.appenders.length === 2, register a new FileAppender instance

  logger.Appender.register(fileAppender)
  // logger.Appenders.appenders.length === 2, because it has been registered before

  logger.Appender.register(new FileAppender())
  // logger.Appenders.appenders.length === 3, a new FileAppender registered

  logger.Appender.register({})
  // throw a error, because the provided appender is illegal.
  • delete <function>

  • argument: appender

  • return: isSuccess <boolean>

  const fileAppender = new FileAppender()

  logger.Appender.set([fileAppender])
  // logger.Appenders.appenders.length === 1

  logger.Appender.delete(new FileAppender())
  // === false, logger.Appenders.appenders.length === 1, the given appender doesen't exist

  const fileAppender = new FileAppender()

  logger.Appender.delete(fileAppender)
  // === true, logger.Appenders.appenders.length === 0
Design a custom appender

If you want to customize a appender, you only need to extend your class from Appender and implement the print method.

import { appender } from '@8pattern/jlogger'

class CustomAppender extends appender.Appender {
    print(logArgs) {
        console.log(logArgs)
    }
}

jlogger.Appender.register(new CustomAppender())

Call to log

logArgument

The logArgument contains all fields of a log, and it may be used to format the logger or print in the appender. It must contains the following values.

  • level: the log level. Default value: logger.config.level.info.
  • timeStamp: current time stamp (without formation). Value: Date.now().
  • count: the number of log called. Value: automatically increased from 0.
  • content: the log content.

Besides, some custom arguments can be added from construction or log call function. And the arguments from call function has higher priority than the construction. But, "timeStamp" and "count" have the higher priority and can't be overridden.

const logger = new Logger({a: 1, b: 2})
logger.info('', { b: 3, c: 4 })
// { ..., a: 1, b: 3, c: 4, ... }

If you want change the time or count in final logs, add another arguments and change the format function.

Ordinary log method
  • log

  • argument: content <string>, logArgs <JSON>

  • return: finalLogArgs <JSON>

  logger.log('hello world', { a: 1 })
  // { a: 1, ... content: 'hello world', ... }
  • debug / info / warn

  • argument: content <string>, logArgs <JSON>

  • return: finalLogArgs <JSON>

    They are all sugar of log with levels.

  logger.debug('') // { ..., level: 'DEBUG', ... }
  logger.info('') // { ..., level: 'INFO', ... }
  logger.warn('') // { ..., level: 'WARN', ... }
  • error

  • argument: content <string> | <Error>, logArgs <JSON>

  • return: finalLogArgs <JSON>

    It is also the sugar of log with error level, but it can receive Error as content. If called with an Error, "errType" and "errDesc" will be added into finalLogArgs, and the stack of Error will be regarded as the content

  logger.error('')
  // { ..., content: '', ..., level: 'ERROR', ... }

  const err = new Error('Some errors')
  logger.error(err)
  // { ..., content: 'Error: Some errors at ...', ..., errDesc: 'Some errors', errType: 'Error', ... }
  • other level defined in config

    If some other levels defined in config, it provides these sugars as well.

  const level = {
      fatal: 'FATAL',
  }
  const logger = new JLogger({}, { level })
  logger.fatal('')
  // { ..., level: 'FATAL', ... }
Function log

Since function logs are so important but their same structures bored the coder, we provide two methods for function logs particularly.

  • logWrap

  • argument: wrapped <Function>, logArgs <JSON>

  • return: <Function>

    This method will print logs of the wrapped function input and output. If the function throws an error, it will print a error log automatically.

  const fun(a) {
      return a + 1;
  }

  const wrappedFun = jLogger.logWrap(fun, { t: 1 })

  wrappedFun(1)
  // { ..., content: 'INPUT: [1]',category: 'FUNCTION', funName: 'fun', t: 1, ...}
  // { ..., content: 'OUTPUT: 2',category: 'FUNCTION', funName: 'fun', t: 1, ...}
```javascript

const fun() { throw new Error('some errors') }

const wrappedFun = jLogger.logWrap(fun)

wrappedFun('hello') // { …, content: 'INPUT: ['hello']', category: 'FUNCTION', funName: 'fun', …} // { …, category: 'FUNCTION', funName: 'fun', level: 'ERROR', …} ```

  • logDecorator

  • argument: logArgs <JSON>

  • return: <Function>

    There is a proposal for decorator for class method,and we also provide a logDecorator which is based on logWrap.

  const log = logger.logDecorator({ test: 1 })

  class T {
      @log
      test1(a) {
          return a + 1
      }

      @logger.logDecorator({ test: 2 })
      test2() {
          throw new Error('some errors')
      }
  }

  const t = T()

  t.test1(1)
  // { ..., content: 'INPUT: [1]', category: 'FUNCTION', className: 'T', funName: 'test1', t: 1, ...}
  // { ..., content: 'OUTPUT: 2',category: 'FUNCTION', className: 'T', funName: 'test1', t: 1, ...}

  t.test(2)
  // { ..., content: 'INPUT: [2]', category: 'FUNCTION', className: 'T', funName: 'test2', t: 2, ...}
  // { ..., category: 'FUNCTION', level: 'ERROR', className: 'T', funName: 'test2', t: 2, ...}

Util

We provide some useful tools relevant to logs, which can be found from jLogger.util

import { util } from '@8pattern/jlogger'
const { dateformat, contentLengthFormat, logTag } = util

dateformat

  • argument:
  • date <Date> | <number>. Default value: new Date()
  • formatStr <string>. Default value: 'yyyy-mm-dd HH:MM:ss.l'
  • return: <string>

This method is a tiny function to format date. The usage is similar with the other mature library, i.e.,

y -> year
m -> month
d -> day
H -> hour
M -> minute
s -> second
l -> millisecond

For example:

dateformat(0, 'yyyy-mm-dd') // 1970-01-01
dateformat(new Date(0), 'yy-m-d') // 70-1-1
dateformat(0, 'HH:MM:ss') // 00:00:00
dateformat(0, 'H:M:s.l') // 0:0:0.0000

contentLengthFormat

  • argument:
  • content <string>.
  • lengthLimit <number> | <null>. Default value: null
  • replaceString <string>. Default value: ' <<<… $IGNOREDSTRINGLENGTH chars are ignored …>>> '
  • return: <string>
contentLengthFormat('123456789')
// 123456789, because lengthLimit === null

contentLengthFormat('123456789', 4)
// 12 <<<... 5 chars are ignored ...>>> 89

contentLengthFormat('123456789', 4, '...igonred...')
// 12...ignored...89

logTag

The tag for the template string for a log content. It will transform Function, Array and Object into more readable formation.

function fun(a) { return a + 1; }
`${fun}` // "function fun(a) { return a + 1; }"
logTag`${fun}` // "-Function[fun]-"
const arr = [1,2,3,4,5]
`${arr}` // "1,2,3,4,5"
logTag`${fun}` // "[1,2,3,4,5]"
const dict = { a: 1 }
`${dict}` // "[object Object]"
logTag`${dict}` // "{ a: 1 }"
class CustomClass {}
const t = new CustomClass()
`${t}` // "[object Object]"
logTag`${t}` // "-CustomClass-"

A complete example:

const obj = {
    arr: [1, 2, function() {}],
    fun() {},
}

`content is ${obj}` // "content is [object Object]"
logTag`content is ${obj}` // "content is {arr:[1,2,-Function-], fun:-Function[fun]-}"
更多

友情链接

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文