View Javadoc
1   /*
2    * Copyright 2021 TiKV Project Authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   */
17  
18  package org.tikv.common.log;
19  
20  import com.google.gson.JsonElement;
21  import com.google.gson.JsonObject;
22  import java.text.SimpleDateFormat;
23  import java.util.HashMap;
24  import java.util.Map;
25  
26  public class SlowLogSpanImpl implements SlowLogSpan {
27    private final String name;
28    private final long requestStartInstantNS;
29    private final long requestStartUnixNS;
30  
31    /** Key-Value pairs which will be logged, e.g. function name, key, region, etc. */
32    private final Map<String, String> properties;
33  
34    /**
35     * use System.nanoTime() to calculate duration, cause System.currentTimeMillis() is not monotonic
36     */
37    private long startInstantNS;
38  
39    private long endInstantNS;
40  
41    public SlowLogSpanImpl(String name, long requestStartMS, long requestStartInstantNS) {
42      this.name = name;
43      this.requestStartUnixNS = requestStartMS * 1_000_000;
44      this.requestStartInstantNS = requestStartInstantNS;
45      this.properties = new HashMap<>();
46      this.startInstantNS = 0;
47      this.endInstantNS = 0;
48    }
49  
50    @Override
51    public void addProperty(String key, String value) {
52      properties.put(key, value);
53    }
54  
55    @Override
56    public void start() {
57      startInstantNS = System.nanoTime();
58    }
59  
60    @Override
61    public void end() {
62      endInstantNS = System.nanoTime();
63    }
64  
65    @Override
66    public JsonElement toJsonElement() {
67      SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
68      JsonObject jsonObject = new JsonObject();
69      jsonObject.addProperty("event", name);
70      jsonObject.addProperty("begin", dateFormat.format(getStartUnixNS() / 1_000_000));
71      jsonObject.addProperty("duration_ms", getDurationNS() / 1_000_000);
72  
73      if (!properties.isEmpty()) {
74        JsonObject propertiesObject = new JsonObject();
75        for (Map.Entry<String, String> entry : properties.entrySet()) {
76          propertiesObject.addProperty(entry.getKey(), entry.getValue());
77        }
78        jsonObject.add("properties", propertiesObject);
79      }
80  
81      return jsonObject;
82    }
83  
84    private long getStartUnixNS() {
85      return requestStartUnixNS + (startInstantNS - requestStartInstantNS);
86    }
87  
88    private long getDurationNS() {
89      if (startInstantNS == 0 || endInstantNS == 0) {
90        return -1;
91      }
92      return endInstantNS - startInstantNS;
93    }
94  }