Blame view

src/main/java/com/huaheng/framework/aspectj/ApiLogAspect.java 20.1 KB
周峰 authored
1
2
3
4
package com.huaheng.framework.aspectj;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
tongzhonghao authored
5
import com.huaheng.common.constant.QuantityConstant;
周峰 authored
6
7
import com.huaheng.common.utils.ServletUtils;
import com.huaheng.common.utils.StringUtils;
tongzhonghao authored
8
import com.huaheng.common.utils.security.ShiroUtils;
肖超群 authored
9
import com.huaheng.common.utils.spring.SpringUtils;
周峰 authored
10
11
12
13
14
15
import com.huaheng.framework.aspectj.lang.annotation.ApiLogger;
import com.huaheng.framework.web.domain.AjaxResult;
import com.huaheng.pc.config.address.domain.Address;
import com.huaheng.pc.config.address.service.AddressService;
import com.huaheng.pc.monitor.apilog.domain.ApiLog;
import com.huaheng.pc.monitor.apilog.service.IApiLogService;
tongzhonghao authored
16
17
import okhttp3.Request;
import okhttp3.Response;
周峰 authored
18
19
import org.apache.commons.lang.exception.ExceptionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
肖超群 authored
20
21
22
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
周峰 authored
23
import org.aspectj.lang.reflect.MethodSignature;
周鸿 authored
24
import org.json.JSONException;
周峰 authored
25
26
27
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
肖超群 authored
28
29
import org.springframework.http.HttpHeaders;
import org.springframework.scheduling.annotation.Async;
周峰 authored
30
31
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
32
33
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
周峰 authored
34
35
36
37
38
39
40
41
42

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

/**
 * Api调用日志记录处理
肖超群 authored
43
 *
周峰 authored
44
45
46
47
 * @author huaheng
 */
@Aspect
@Component
肖超群 authored
48
@EnableAsync
tongzhonghao authored
49
50
public class ApiLogAspect
{
周峰 authored
51
52
53
54
55
56
57
58
    private static final Logger log = LoggerFactory.getLogger(ApiLogAspect.class);

    private static IApiLogService apiLogService;

    private static AddressService addressService;


    @Autowired
tongzhonghao authored
59
    public void setApiLogService(IApiLogService apiLogService){
周峰 authored
60
61
62
63
        ApiLogAspect.apiLogService = apiLogService;
    }

    @Autowired
tongzhonghao authored
64
    public void setAddressService(AddressService addressService){
周峰 authored
65
66
67
68
69
        ApiLogAspect.addressService = addressService;
    }

    // 配置织入点
    @Pointcut("@annotation(com.huaheng.framework.aspectj.lang.annotation.ApiLogger)")
tongzhonghao authored
70
71
    public void logPointCut()
    {
周峰 authored
72
73
74
    }

    @Around("logPointCut()  && @annotation(apiLogger)")
tongzhonghao authored
75
76
77
78
79
    public Object around(ProceedingJoinPoint point, ApiLogger apiLogger) throws Throwable
    {
        if("WMS".equalsIgnoreCase(apiLogger.from()))
        //实际上静态方法上的Aop注解无法拦截到
        {
周峰 authored
80
            return aroundWms2XXX(point, apiLogger);
tongzhonghao authored
81
        } else {
周峰 authored
82
            return aroundXXX2Wms(point, apiLogger);
周鸿 authored
83
        }
周峰 authored
84
85
    }
tongzhonghao authored
86
87
    /**处理xxx调用wms接口的日志**/
    private Object aroundXXX2Wms(ProceedingJoinPoint point, ApiLogger apiLogger){
周峰 authored
88
89
        Object ret = null;
        ApiLog log = initApiLog(apiLogger, point);
tongzhonghao authored
90
        try{
周峰 authored
91
            ret = point.proceed();
tongzhonghao authored
92
        }catch (Exception e){
周峰 authored
93
            setApiLogException(log, e);
肖超群 authored
94
            ret = AjaxResult.error(e.getMessage());
tongzhonghao authored
95
        }finally{
周峰 authored
96
97
98
99
100
            finishApiLog(log, ret);
            return ret;
        }
    }
tongzhonghao authored
101
102
    /**处理WMS调用xxx接口的日志**/
    private Object aroundWms2XXX(ProceedingJoinPoint point, ApiLogger apiLogger){
周峰 authored
103
104
105
106
107
108
109
        Object ret = null;
        ApiLog log = new ApiLog();

        HttpURLConnection connection = null;
        String body = null;

        try {
110
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
周峰 authored
111
112
            connection = (HttpURLConnection) point.getArgs()[0];
            body = (String) point.getArgs()[1];
tongzhonghao authored
113
            initApiLog(connection, body, ShiroUtils.getWarehouseCode());
tongzhonghao authored
114
        }catch (Exception e){
周峰 authored
115
116
117

        }
tongzhonghao authored
118
        try{
周峰 authored
119
            ret = point.proceed();
tongzhonghao authored
120
        }catch (Exception e){
周峰 authored
121
122
            setApiLogException(log, e);
            throw e;
tongzhonghao authored
123
124
        }finally{
            if(ret != null) {
游杰 authored
125
126
                finishApiLog(log, connection, ret.toString());
            }
周峰 authored
127
128
129
130
            return ret;
        }
    }
肖超群 authored
131
    /**
tongzhonghao authored
132
     * 记录响应头信息
肖超群 authored
133
     **/
tongzhonghao authored
134
    public static void finishApiLog(ApiLog log, HttpURLConnection connection, String body) {
周峰 authored
135
        try {
tongzhonghao authored
136
137
138
139
140
            log.setResponseBody(body);
            log.setResponseTime(new Date());
            Long duration = log.getResponseTime().getTime() - log.getRequestTime().getTime();
            log.setDuration(duration.intValue());
            log.setHttpCode(String.valueOf(connection.getResponseCode()));
周峰 authored
141
tongzhonghao authored
142
143
            //响应头
            Set<String> keyset = connection.getHeaderFields().keySet();
周峰 authored
144
            ArrayList<String> headerList = new ArrayList<>();
tongzhonghao authored
145
            Iterator<String> it = keyset.iterator();
周峰 authored
146
147
            while (it.hasNext()) {
                String name = it.next();
tongzhonghao authored
148
149
150
151
152
153
154
                String header = connection.getHeaderField(name);
                if (name == null || "".equals(name))
                    //第一行没有name
                    //HTTP/1.1 200 OK
                    headerList.add(header);
                else
                    headerList.add(name + ": " + header);
周峰 authored
155
            }
tongzhonghao authored
156
157
158
            log.setResponseHeader(org.apache.commons.lang3.StringUtils.join(headerList, "\n"));
            AjaxResult json = JSON.parseObject(body, AjaxResult.class);
            log.setRetCode(String.valueOf(json.getCode()));
肖超群 authored
159
        } catch (Exception e) {
周峰 authored
160
            e.printStackTrace();
tongzhonghao authored
161
162
        } finally {
            SpringUtils.getBean(ApiLogAspect.class).saveApiLog(log);
周峰 authored
163
        }
tongzhonghao authored
164
    }
周峰 authored
165
tongzhonghao authored
166
167
168
169
170
171
172
173
174
175
    /**
     * 根据url,address表中判断调用的去向
     **/
    public static void parseUrl(ApiLog log, URL url, String warehouseCode) {
        try {
            String[] spList = url.toString().split("/");
            String apiName = spList[spList.length - 1];
            int index = url.toString().lastIndexOf(apiName);
            String addUrl = url.toString().substring(0, index);
tongzhonghao authored
176
            Address address = addressService.getAddressByUrl(url.toString(), warehouseCode);
tongzhonghao authored
177
178
            log.setApiName(apiName);
            log.setRequestFrom("WMS");
xumiao authored
179
180
181
182
183
184
            if(address!=null){
                log.setResponseBy(address.getParam().toUpperCase());
            }else {
                log.setResponseBy("XX");
            }
tongzhonghao authored
185
186
187
        } catch (Exception e) {
            e.printStackTrace();
        }
周峰 authored
188
189
    }
tongzhonghao authored
190
肖超群 authored
191
192
193
194
    /**
     * 记录WMS调用外接口的请求信息
     * HttpUtils.bodypost方法中直接调用本类static方法
     **/
tongzhonghao authored
195
    public static ApiLog  initApiLog(String Method, String url, String body, HttpHeaders headers, String warehouseCode) {
肖超群 authored
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
        ApiLog log = new ApiLog();
        try {
            URL url1 = new URL(url);
            log.setApiMethod(Method);
            log.setUrl(url);
            log.setRequestTime(new Date());
            parseUrl(log, url1, warehouseCode);

            //请求头
            Set<String> keySet = headers.keySet();
            ArrayList<String> headerList = new ArrayList<>();
            Iterator<String> it = keySet.iterator();
            while (it.hasNext()) {
                String name = it.next();
                String header = String.valueOf(headers.getContentType());
                headerList.add(name + ": " + header);
            }

            log.setRequestHeader(org.apache.commons.lang3.StringUtils.join(headerList, "\n"));
            log.setRequestBody(body);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return log;
    }
tongzhonghao authored
223
224
    /**记录WMS调用外接口的请求信息
     * HttpUtils.bodypost方法中直接调用本类static方法**/
tongzhonghao authored
225
    public static  ApiLog initApiLog(HttpURLConnection connection, String body,String warehouseCode){
tongzhonghao authored
226
        ApiLog log = new ApiLog();
周峰 authored
227
        try {
tongzhonghao authored
228
229
230
            log.setApiMethod(connection.getRequestMethod());
            log.setUrl(connection.getURL().toString());
            log.setRequestTime(new Date());
tongzhonghao authored
231
            parseUrl(log, connection.getURL(),warehouseCode);
周峰 authored
232
tongzhonghao authored
233
234
235
236
237
238
239
240
241
242
243
244
245
            //请求头
            Set<String> keySet = connection.getRequestProperties().keySet();
            ArrayList<String> headerList = new ArrayList<>();
            Iterator<String> it = keySet.iterator();
            while (it.hasNext()) {
                String name = it.next();
                String header = connection.getRequestProperty(name);
                headerList.add(name + ": " + header);
            }

            log.setRequestHeader(org.apache.commons.lang3.StringUtils.join(headerList, "\n"));
            log.setRequestBody(body);
        }catch (Exception e){
周峰 authored
246
247
            e.printStackTrace();
        }
tongzhonghao authored
248
249

        return log;
周峰 authored
250
251
    }
周鸿 authored
252
253
周鸿 authored
254
255
    /**记录WMS调用外接口的请求信息
     * HttpUtils.bodypost方法中直接调用本类static方法**/
tongzhonghao authored
256
    public static ApiLog initApiLog(Request request, String body,String warehouseCode){
周鸿 authored
257
258
259
260
261
        ApiLog log = new ApiLog();
        try {
            log.setApiMethod(request.method());
            log.setUrl(request.url().toString());
            log.setRequestTime(new Date());
tongzhonghao authored
262
            parseUrl(log, request.url().url(),warehouseCode);
周鸿 authored
263
264
265
266
267
268
269
            log.setRequestHeader(request.headers().toString());
            log.setRequestBody(body);
        }catch (Exception e){
            e.printStackTrace();
        }
        return log;
    }
tongzhonghao authored
270
271
272

    /**记录响应头信息**/
    public static void finishApiLog(ApiLog log, Response response, String body){
周峰 authored
273
274
275
276
277
        try {
            log.setResponseBody(body);
            log.setResponseTime(new Date());
            Long duration = log.getResponseTime().getTime() - log.getRequestTime().getTime();
            log.setDuration(duration.intValue());
tongzhonghao authored
278
            log.setHttpCode(String.valueOf(response.code()));
周峰 authored
279
280

            //响应头
tongzhonghao authored
281
282
283
284
285
286
287
            log.setResponseHeader(response.headers().toString());
            AjaxResult ajaxResult = null;
            try{
                ajaxResult = JSON.parseObject(body, AjaxResult.class);
            }catch(Exception ex){
                body = JSON.parse(body).toString();
                ajaxResult = JSON.parseObject(body, AjaxResult.class);
周峰 authored
288
            }
tongzhonghao authored
289
290
            log.setRetCode(String.valueOf(ajaxResult.getCode()));
        }catch (Exception e){
周峰 authored
291
            e.printStackTrace();
tongzhonghao authored
292
293
294
295
296
297
298
299
        }finally {
            try {
                if (StringUtils.isNotEmpty(log.getResponseBody()) && log.getResponseBody().length() > 2001) {
                    log.setResponseBody(log.getResponseBody().substring(0, 2000) + "\n太长了...后面省略。\n" + log.getResponseBody().length());
                }
            }catch (Exception e){

            }
肖超群 authored
300
            SpringUtils.getBean(ApiLogAspect.class).saveApiLog(log);
周峰 authored
301
302
303
        }
    }
肖超群 authored
304
tongzhonghao authored
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321

    /**根据url,从address表中判断调用的去向**/
    public static void parseUrl(ApiLog log, URL url){
        try {
            String[] spList = url.toString().split("/");
            String apiName = spList[spList.length - 1];
            int index = url.toString().lastIndexOf(apiName);
            String addUrl = url.toString().substring(0, index);

            Address address = addressService.getAddressByUrl(url.toString(), "CS0001");
            log.setApiName(apiName);
            log.setRequestFrom("WMS");
            log.setResponseBy(address.getParam().toUpperCase());
        }catch (Exception e){
            e.printStackTrace();
        }
    }
周鸿 authored
322
肖超群 authored
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
    /**
     * 记录响应头信息
     **/
    public static void finishApiLog(ApiLog log, HttpHeaders headers, String body) {
        try {
            log.setResponseBody(body);
            log.setResponseTime(new Date());
            Long duration = log.getResponseTime().getTime() - log.getRequestTime().getTime();
            log.setDuration(duration.intValue());
            log.setHttpCode(String.valueOf(200));

            //响应头
            Set<String> keyset = headers.keySet();
            ArrayList<String> headerList = new ArrayList<>();
            Iterator<String> it = keyset.iterator();
            while (it.hasNext()) {
                String name = it.next();
                String header = String.valueOf(headers.getContentType());
341
                if (name == null || "".equals(name)){
肖超群 authored
342
343
344
                    //第一行没有name
                    //HTTP/1.1 200 OK
                    headerList.add(header);
345
                }else{
肖超群 authored
346
                    headerList.add(name + ": " + header);
347
                }
肖超群 authored
348
349
            }
            log.setResponseHeader(org.apache.commons.lang3.StringUtils.join(headerList, "\n"));
xumiao authored
350
351
352
353
354
355
            if(StringUtils.isNotEmpty(body)){
                AjaxResult json = JSON.parseObject(body, AjaxResult.class);
                log.setRetCode(String.valueOf(json.getCode()));
            }else{
                log.setRetCode("400");
            }
肖超群 authored
356
357
358
359
360
361
362
363
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            SpringUtils.getBean(ApiLogAspect.class).saveApiLog(log);
        }
    }
tongzhonghao authored
364
    private ApiLog initApiLog(ApiLogger apiLogger, ProceedingJoinPoint point){
周峰 authored
365
        ApiLog log = new ApiLog();
tongzhonghao authored
366
        try{
周峰 authored
367
368
369
370
371
372
373
374
375
            log.setRequestTime(new Date());
            log.setRequestFrom(apiLogger.from());
            log.setResponseBy(apiLogger.to());
            log.setApiName(apiLogger.apiName());

            HttpServletRequest request = ServletUtils.getRequest();

            String qryStr = request.getQueryString();
            String url = request.getRequestURL().toString();
tongzhonghao authored
376
            if(StringUtils.isNotEmpty(qryStr)) {
周峰 authored
377
                url = url + "?" + qryStr;
周鸿 authored
378
            }
周峰 authored
379
380
381
382
383
384
385
386
387
388
            log.setUrl(url);

            log.setApiMethod(request.getMethod());
            log.setIp(request.getRemoteAddr());

            rebuildRequestHeader(log);

            rebuildRequestBody(log, request);

            //如果reqeust中取不到post参数,就从接口方法参数中取json对象
tongzhonghao authored
389
            if(StringUtils.isEmpty(log.getRequestBody())) {
周峰 authored
390
                rebuildRequestBody(log, point);
周鸿 authored
391
            }
tongzhonghao authored
392
393

        }catch (Exception e){
周峰 authored
394
395
396
397
398
399
            e.printStackTrace();
        }

        return log;
    }
tongzhonghao authored
400
    private void finishApiLog(ApiLog log, Object ret){
周峰 authored
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
        try {
            rebuildResponseHeader(log);
            rebuildResponseBody(log, ret);

            log.setResponseTime(new Date());
            Long duration = log.getResponseTime().getTime() - log.getRequestTime().getTime();
            log.setDuration(duration.intValue());

            HttpServletResponse resp = ServletUtils.getResponse();
            log.setHttpCode(String.valueOf(resp.getStatus()));

            if (ret instanceof AjaxResult) {
                int retCode = ((AjaxResult) ret).getCode();
                log.setRetCode(String.valueOf(retCode));
            }
tongzhonghao authored
416
        }catch (Exception e){
周峰 authored
417
            e.printStackTrace();
tongzhonghao authored
418
        }finally {
周峰 authored
419
420
421
422
            saveApiLog(log);
        }
    }
tongzhonghao authored
423
    public static void setApiLogException(ApiLog log, Exception e){
周峰 authored
424
425
        try {
            String exception = ExceptionUtils.getFullStackTrace(e);
周峰 authored
426
            String shortExpInfo = e.getMessage() + "\n" + org.apache.commons.lang3.StringUtils.left(exception, 1000);
周峰 authored
427
            log.setException(shortExpInfo);
tongzhonghao authored
428
        }catch (Exception ex){
周峰 authored
429
430
431
432
            ex.printStackTrace();
        }
    }
tongzhonghao authored
433
    private void rebuildRequestHeader(ApiLog log){
周峰 authored
434
435
436
437
        try {
            HttpServletRequest req = ServletUtils.getRequest();
            Enumeration names = req.getHeaderNames();
            ArrayList<String> headerList = new ArrayList<>();
tongzhonghao authored
438
439
            while(names.hasMoreElements()){
                String name = (String)names.nextElement();
周峰 authored
440
441
442
443
444
                String header = req.getHeader(name);
                headerList.add(name + ": " + header);
            }
            String headers = org.apache.commons.lang3.StringUtils.join(headerList, "\n");
            log.setRequestHeader(headers);
tongzhonghao authored
445
        }catch (Exception e){
周峰 authored
446
447
448
449
            e.printStackTrace();
        }
    }
tongzhonghao authored
450
451
452
    /**先从post参数中构造request body*/
    private void rebuildRequestBody(ApiLog log, HttpServletRequest request){
        try{
周峰 authored
453
454
455
            Set<String> keySet = request.getParameterMap().keySet();
            Iterator<String> it = keySet.iterator();
            StringBuffer sbf = new StringBuffer();
tongzhonghao authored
456
            while(it.hasNext()){
周峰 authored
457
458
459
                String key = it.next();
                String value = request.getParameter(key);
                sbf.append(key).append("=").append(value);
tongzhonghao authored
460
                if(it.hasNext()) {
周峰 authored
461
                    sbf.append("&");
周鸿 authored
462
                }
周峰 authored
463
464
            }
            log.setRequestBody(sbf.toString());
tongzhonghao authored
465
        }catch (Exception e){
周峰 authored
466
467
468
469
470
471
472
            e.printStackTrace();
        }
    }

    /**
     * 根据接口中的参数构造request body
     */
tongzhonghao authored
473
474
    private void rebuildRequestBody(ApiLog log, ProceedingJoinPoint point)
    {
周峰 authored
475
476
        try {
            if (point.getArgs().length == 1) {
477
478
479
                String str=JSONObject.toJSONString(point.getArgs()[0]);
                log=parseJson(str,log);
                log.setRequestBody(str);
tongzhonghao authored
480
                log.setRequestBody(JSONObject.toJSONString(point.getArgs()[0]));
周峰 authored
481
482
                return;
            }
tongzhonghao authored
483
周峰 authored
484
485
486
487
488
489
490
491
            MethodSignature m = (MethodSignature) point.getSignature();
            HashMap<String, Object> map = new HashMap<>();
            Object[] args = point.getArgs();
            for (int i = 0; i < m.getParameterNames().length; i++) {
                String name = m.getParameterNames()[i];
//                Class type = m.getParameterTypes()[i];
                map.put(name, args[i]);
            }
tongzhonghao authored
492
493

            if(!map.isEmpty()) {
周峰 authored
494
                log.setRequestBody(JSONObject.toJSONString(map));
周鸿 authored
495
            }
tongzhonghao authored
496
        }catch (Exception e){
周峰 authored
497
498
499
500
            e.printStackTrace();
        }
    }
tongzhonghao authored
501
    private void rebuildResponseHeader(ApiLog log){
周峰 authored
502
503
504
505
506
        try {
            HttpServletResponse resp = ServletUtils.getResponse();
            Collection names = resp.getHeaderNames();
            ArrayList<String> headerList = new ArrayList<>();
            Iterator<String> it = names.iterator();
tongzhonghao authored
507
            while(it.hasNext()){
周峰 authored
508
509
510
511
512
513
                String name = it.next();
                String header = resp.getHeader(name);
                headerList.add(name + ": " + header);
            }
            String headers = org.apache.commons.lang3.StringUtils.join(headerList, "\n");
            log.setResponseHeader(headers);
tongzhonghao authored
514
        }catch (Exception e){
周峰 authored
515
516
517
518
            e.printStackTrace();
        }
    }
tongzhonghao authored
519
    private void rebuildResponseBody(ApiLog log, Object ret){
周峰 authored
520
521
        try {
            log.setResponseBody(JSONObject.toJSON(ret).toString());
tongzhonghao authored
522
        }catch (Exception e){
周峰 authored
523
524
525
526
            e.printStackTrace();
        }
    }
肖超群 authored
527
    @Async
tongzhonghao authored
528
529
    public void saveApiLog(ApiLog log){
        try{
周峰 authored
530
            apiLogService.saveOrUpdate(log);
tongzhonghao authored
531
        }catch (Exception e){
周峰 authored
532
533
534
            e.printStackTrace();
        }
    }
周鸿 authored
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563


    /**
     * 解析json
     * @param str
     * @param log
     */
    public ApiLog parseJson(String str,ApiLog log){
        try {

            org.json.JSONObject object=new org.json.JSONObject(str);
            Iterator<String> it = object.keys();
            while (it.hasNext()) {
                String json_key = it.next();
                Object json_value = object.get(json_key);
                if(json_key.equals("warehouseCode")){
                    log.setWarehouseCode(json_value.toString());
                    break;
                }
                if(json_value.getClass().getSimpleName().equals("JSONObject")){
                    parseJson(json_value.toString(),log);
                }
                /*if (json_value!=null){
                    System.out.println("CCC"+"json_key:" + json_key + ",json_value:" + json_value + ",类型:" + json_value.getClass().getSimpleName());
                }*/
            }
        } catch (JSONException e) {
            String replaceAll = str.replaceAll("\\\\", "");
            String replaceAll1=replaceAll.substring(1,replaceAll.length()-1);
564
565
566
567
568
569
570
            try{
                List<String> list =JSON.parseArray(replaceAll1,String.class);
                String strnew=StringUtils.join(list,",");
                log=parseJson(strnew,log);
            }catch (Exception e1){
                log=parseJson(replaceAll1,log);
            }
周鸿 authored
571
572
573
574

        }
        return log;
    }
周峰 authored
575
}