• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018, OpenCensus 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 package io.opencensus.contrib.spring.aop;
18 
19 import io.opencensus.trace.Tracer;
20 import org.aspectj.lang.ProceedingJoinPoint;
21 import org.aspectj.lang.annotation.Around;
22 import org.aspectj.lang.annotation.Aspect;
23 import org.aspectj.lang.annotation.Pointcut;
24 import org.springframework.beans.factory.annotation.Configurable;
25 
26 /**
27  * CensusSpringSqlAspect captures span from all SQL invocations that utilize
28  * java.sql.Statement.execute*
29  *
30  * @since 0.16.0
31  */
32 @Aspect
33 @Configurable
34 public final class CensusSpringSqlAspect {
35   private final Tracer tracer;
36 
37   /**
38    * Creates a {@code CensusSpringSqlAspect} with the given tracer.
39    *
40    * @param tracer the tracer responsible for building new spans
41    * @since 0.16.0
42    */
CensusSpringSqlAspect(Tracer tracer)43   public CensusSpringSqlAspect(Tracer tracer) {
44     this.tracer = tracer;
45   }
46 
47   /**
48    * trace handles invocations of java.sql.Statement.execute*. A new span will be created whose name
49    * is (execute|executeQuery|executeQuery)-(hash of sql).
50    *
51    * @since 0.16.0
52    */
53   @Around("execute() || testing()")
trace(ProceedingJoinPoint call)54   public Object trace(ProceedingJoinPoint call) throws Throwable {
55     if (call.getArgs().length == 0 || call.getArgs()[0] == null) {
56       return call.proceed();
57     }
58 
59     String sql = (String) call.getArgs()[0];
60     String spanName = makeSpanName(call, sql);
61 
62     return Handler.proceed(call, tracer, spanName, sql);
63   }
64 
65   /**
66    * execute creates spans around all invocations of Statement.execute*. The raw SQL will be stored
67    * in an annotation associated with the Span
68    */
69   @Pointcut("execution(public !void java.sql.Statement.execute*(java.lang.String))")
execute()70   protected void execute() {}
71 
72   @Pointcut("execution(public void Sample.execute*(java.lang.String))")
testing()73   protected void testing() {}
74 
makeSpanName(ProceedingJoinPoint call, String sql)75   private static String makeSpanName(ProceedingJoinPoint call, String sql) {
76     String hash = Integer.toHexString(hashCode(sql.toCharArray()));
77     return call.getSignature().getName() + "-" + hash;
78   }
79 
hashCode(char[] seq)80   private static int hashCode(char[] seq) {
81     if (seq == null) {
82       return 0;
83     }
84 
85     int hash = 0;
86     for (char c : seq) {
87       hash = 31 * hash + c;
88     }
89     return hash;
90   }
91 }
92