├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── project.clj ├── src └── com │ └── climate │ └── newrelic │ └── trace.clj └── test ├── clojure └── test_helper.clj └── com └── climate └── newrelic └── trace_tests.clj /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /classes 3 | /checkouts 4 | pom.xml 5 | pom.xml.asc 6 | *.jar 7 | *.class 8 | /.lein-* 9 | /.nrepl-port 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: clojure 2 | lein: lein2 3 | script: lein do check, test, ancient :all 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 The Climate Corporation 2 | 3 | The majority of the clj-Newrelic software is licensed with Apache 2.0, which is 4 | the preferred license and cited below. Exceptions are handled on a 5 | case-by-case basis. Specifically, the excerpted Clojure source code in 6 | test/clojure/test_helper.clj is licensed under the Eclipse Public License 1.0, 7 | found at http://clojure.org/license. 8 | 9 | 10 | Apache License 11 | Version 2.0, January 2004 12 | http://www.apache.org/licenses/ 13 | 14 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 15 | 16 | 1. Definitions. 17 | 18 | "License" shall mean the terms and conditions for use, reproduction, 19 | and distribution as defined by Sections 1 through 9 of this document. 20 | 21 | "Licensor" shall mean the copyright owner or entity authorized by 22 | the copyright owner that is granting the License. 23 | 24 | "Legal Entity" shall mean the union of the acting entity and all 25 | other entities that control, are controlled by, or are under common 26 | control with that entity. For the purposes of this definition, 27 | "control" means (i) the power, direct or indirect, to cause the 28 | direction or management of such entity, whether by contract or 29 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 30 | outstanding shares, or (iii) beneficial ownership of such entity. 31 | 32 | "You" (or "Your") shall mean an individual or Legal Entity 33 | exercising permissions granted by this License. 34 | 35 | "Source" form shall mean the preferred form for making modifications, 36 | including but not limited to software source code, documentation 37 | source, and configuration files. 38 | 39 | "Object" form shall mean any form resulting from mechanical 40 | transformation or translation of a Source form, including but 41 | not limited to compiled object code, generated documentation, 42 | and conversions to other media types. 43 | 44 | "Work" shall mean the work of authorship, whether in Source or 45 | Object form, made available under the License, as indicated by a 46 | copyright notice that is included in or attached to the work 47 | (an example is provided in the Appendix below). 48 | 49 | "Derivative Works" shall mean any work, whether in Source or Object 50 | form, that is based on (or derived from) the Work and for which the 51 | editorial revisions, annotations, elaborations, or other modifications 52 | represent, as a whole, an original work of authorship. For the purposes 53 | of this License, Derivative Works shall not include works that remain 54 | separable from, or merely link (or bind by name) to the interfaces of, 55 | the Work and Derivative Works thereof. 56 | 57 | "Contribution" shall mean any work of authorship, including 58 | the original version of the Work and any modifications or additions 59 | to that Work or Derivative Works thereof, that is intentionally 60 | submitted to Licensor for inclusion in the Work by the copyright owner 61 | or by an individual or Legal Entity authorized to submit on behalf of 62 | the copyright owner. For the purposes of this definition, "submitted" 63 | means any form of electronic, verbal, or written communication sent 64 | to the Licensor or its representatives, including but not limited to 65 | communication on electronic mailing lists, source code control systems, 66 | and issue tracking systems that are managed by, or on behalf of, the 67 | Licensor for the purpose of discussing and improving the Work, but 68 | excluding communication that is conspicuously marked or otherwise 69 | designated in writing by the copyright owner as "Not a Contribution." 70 | 71 | "Contributor" shall mean Licensor and any individual or Legal Entity 72 | on behalf of whom a Contribution has been received by Licensor and 73 | subsequently incorporated within the Work. 74 | 75 | 2. Grant of Copyright License. Subject to the terms and conditions of 76 | this License, each Contributor hereby grants to You a perpetual, 77 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 78 | copyright license to reproduce, prepare Derivative Works of, 79 | publicly display, publicly perform, sublicense, and distribute the 80 | Work and such Derivative Works in Source or Object form. 81 | 82 | 3. Grant of Patent License. Subject to the terms and conditions of 83 | this License, each Contributor hereby grants to You a perpetual, 84 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 85 | (except as stated in this section) patent license to make, have made, 86 | use, offer to sell, sell, import, and otherwise transfer the Work, 87 | where such license applies only to those patent claims licensable 88 | by such Contributor that are necessarily infringed by their 89 | Contribution(s) alone or by combination of their Contribution(s) 90 | with the Work to which such Contribution(s) was submitted. If You 91 | institute patent litigation against any entity (including a 92 | cross-claim or counterclaim in a lawsuit) alleging that the Work 93 | or a Contribution incorporated within the Work constitutes direct 94 | or contributory patent infringement, then any patent licenses 95 | granted to You under this License for that Work shall terminate 96 | as of the date such litigation is filed. 97 | 98 | 4. Redistribution. You may reproduce and distribute copies of the 99 | Work or Derivative Works thereof in any medium, with or without 100 | modifications, and in Source or Object form, provided that You 101 | meet the following conditions: 102 | 103 | (a) You must give any other recipients of the Work or 104 | Derivative Works a copy of this License; and 105 | 106 | (b) You must cause any modified files to carry prominent notices 107 | stating that You changed the files; and 108 | 109 | (c) You must retain, in the Source form of any Derivative Works 110 | that You distribute, all copyright, patent, trademark, and 111 | attribution notices from the Source form of the Work, 112 | excluding those notices that do not pertain to any part of 113 | the Derivative Works; and 114 | 115 | (d) If the Work includes a "NOTICE" text file as part of its 116 | distribution, then any Derivative Works that You distribute must 117 | include a readable copy of the attribution notices contained 118 | within such NOTICE file, excluding those notices that do not 119 | pertain to any part of the Derivative Works, in at least one 120 | of the following places: within a NOTICE text file distributed 121 | as part of the Derivative Works; within the Source form or 122 | documentation, if provided along with the Derivative Works; or, 123 | within a display generated by the Derivative Works, if and 124 | wherever such third-party notices normally appear. The contents 125 | of the NOTICE file are for informational purposes only and 126 | do not modify the License. You may add Your own attribution 127 | notices within Derivative Works that You distribute, alongside 128 | or as an addendum to the NOTICE text from the Work, provided 129 | that such additional attribution notices cannot be construed 130 | as modifying the License. 131 | 132 | You may add Your own copyright statement to Your modifications and 133 | may provide additional or different license terms and conditions 134 | for use, reproduction, or distribution of Your modifications, or 135 | for any such Derivative Works as a whole, provided Your use, 136 | reproduction, and distribution of the Work otherwise complies with 137 | the conditions stated in this License. 138 | 139 | 5. Submission of Contributions. Unless You explicitly state otherwise, 140 | any Contribution intentionally submitted for inclusion in the Work 141 | by You to the Licensor shall be under the terms and conditions of 142 | this License, without any additional terms or conditions. 143 | Notwithstanding the above, nothing herein shall supersede or modify 144 | the terms of any separate license agreement you may have executed 145 | with Licensor regarding such Contributions. 146 | 147 | 6. Trademarks. This License does not grant permission to use the trade 148 | names, trademarks, service marks, or product names of the Licensor, 149 | except as required for reasonable and customary use in describing the 150 | origin of the Work and reproducing the content of the NOTICE file. 151 | 152 | 7. Disclaimer of Warranty. Unless required by applicable law or 153 | agreed to in writing, Licensor provides the Work (and each 154 | Contributor provides its Contributions) on an "AS IS" BASIS, 155 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 156 | implied, including, without limitation, any warranties or conditions 157 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 158 | PARTICULAR PURPOSE. You are solely responsible for determining the 159 | appropriateness of using or redistributing the Work and assume any 160 | risks associated with Your exercise of permissions under this License. 161 | 162 | 8. Limitation of Liability. In no event and under no legal theory, 163 | whether in tort (including negligence), contract, or otherwise, 164 | unless required by applicable law (such as deliberate and grossly 165 | negligent acts) or agreed to in writing, shall any Contributor be 166 | liable to You for damages, including any direct, indirect, special, 167 | incidental, or consequential damages of any character arising as a 168 | result of this License or out of the use or inability to use the 169 | Work (including but not limited to damages for loss of goodwill, 170 | work stoppage, computer failure or malfunction, or any and all 171 | other commercial damages or losses), even if such Contributor 172 | has been advised of the possibility of such damages. 173 | 174 | 9. Accepting Warranty or Additional Liability. While redistributing 175 | the Work or Derivative Works thereof, You may choose to offer, 176 | and charge a fee for, acceptance of support, warranty, indemnity, 177 | or other liability obligations and/or rights consistent with this 178 | License. However, in accepting such obligations, You may act only 179 | on Your own behalf and on Your sole responsibility, not on behalf 180 | of any other Contributor, and only if You agree to indemnify, 181 | defend, and hold each Contributor harmless for any liability 182 | incurred by, or claims asserted against, such Contributor by reason 183 | of your accepting any such warranty or additional liability. 184 | 185 | Eclipse Public License -v 1.0 186 | 187 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC 188 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM 189 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 190 | 191 | 1. DEFINITIONS 192 | 193 | "Contribution" means: 194 | 195 | a) in the case of the initial Contributor, the initial code and documentation 196 | distributed under this Agreement, and 197 | 198 | b) in the case of each subsequent Contributor: 199 | 200 | i) changes to the Program, and 201 | 202 | ii) additions to the Program; 203 | 204 | where such changes and/or additions to the Program originate from and are 205 | distributed by that particular Contributor. A Contribution 'originates' from a 206 | Contributor if it was added to the Program by such Contributor itself or anyone 207 | acting on such Contributor's behalf. Contributions do not include additions to 208 | the Program which: (i) are separate modules of software distributed in 209 | conjunction with the Program under their own license agreement, and (ii) are 210 | not derivative works of the Program. 211 | 212 | "Contributor" means any person or entity that distributes the Program. 213 | 214 | "Licensed Patents " mean patent claims licensable by a Contributor which are 215 | necessarily infringed by the use or sale of its Contribution alone or when 216 | combined with the Program. 217 | 218 | "Program" means the Contributions distributed in accordance with this 219 | Agreement. 220 | 221 | "Recipient" means anyone who receives the Program under this Agreement, 222 | including all Contributors. 223 | 224 | 2. GRANT OF RIGHTS 225 | 226 | a) Subject to the terms of this Agreement, each Contributor hereby grants 227 | Recipient a non-exclusive, worldwide, royalty-free copyright license to 228 | reproduce, prepare derivative works of, publicly display, publicly perform, 229 | distribute and sublicense the Contribution of such Contributor, if any, and 230 | such derivative works, in source code and object code form. 231 | 232 | b) Subject to the terms of this Agreement, each Contributor hereby grants 233 | Recipient a non-exclusive, worldwide, royalty-free patent license under 234 | Licensed Patents to make, use, sell, offer to sell, import and otherwise 235 | transfer the Contribution of such Contributor, if any, in source code and 236 | object code form. This patent license shall apply to the combination of the 237 | Contribution and the Program if, at the time the Contribution is added by the 238 | Contributor, such addition of the Contribution causes such combination to be 239 | covered by the Licensed Patents. The patent license shall not apply to any 240 | other combinations which include the Contribution. No hardware per se is 241 | licensed hereunder. 242 | 243 | c) Recipient understands that although each Contributor grants the licenses to 244 | its Contributions set forth herein, no assurances are provided by any 245 | Contributor that the Program does not infringe the patent or other intellectual 246 | property rights of any other entity. Each Contributor disclaims any liability 247 | to Recipient for claims brought by any other entity based on infringement of 248 | intellectual property rights or otherwise. As a condition to exercising the 249 | rights and licenses granted hereunder, each Recipient hereby assumes sole 250 | responsibility to secure any other intellectual property rights needed, if any. 251 | For example, if a third party patent license is required to allow Recipient to 252 | distribute the Program, it is Recipient's responsibility to acquire that 253 | license before distributing the Program. 254 | 255 | d) Each Contributor represents that to its knowledge it has sufficient 256 | copyright rights in its Contribution, if any, to grant the copyright license 257 | set forth in this Agreement. 258 | 259 | 3. REQUIREMENTS 260 | 261 | A Contributor may choose to distribute the Program in object code form under 262 | its own license agreement, provided that: 263 | 264 | a) it complies with the terms and conditions of this Agreement; and 265 | 266 | b) its license agreement: 267 | 268 | i) effectively disclaims on behalf of all Contributors all warranties and 269 | conditions, express and implied, including warranties or conditions of title 270 | and non-infringement, and implied warranties or conditions of merchantability 271 | and fitness for a particular purpose; 272 | 273 | ii) effectively excludes on behalf of all Contributors all liability for 274 | damages, including direct, indirect, special, incidental and consequential 275 | damages, such as lost profits; 276 | 277 | iii) states that any provisions which differ from this Agreement are offered by 278 | that Contributor alone and not by any other party; and 279 | 280 | iv) states that source code for the Program is available from such Contributor, 281 | and informs licensees how to obtain it in a reasonable manner on or through a 282 | medium customarily used for software exchange. 283 | 284 | When the Program is made available in source code form: 285 | 286 | a) it must be made available under this Agreement; and 287 | 288 | b) a copy of this Agreement must be included with each copy of the Program. 289 | 290 | Contributors may not remove or alter any copyright notices contained within the 291 | Program. 292 | 293 | Each Contributor must identify itself as the originator of its Contribution, if 294 | any, in a manner that reasonably allows subsequent Recipients to identify the 295 | originator of the Contribution. 296 | 297 | 4. COMMERCIAL DISTRIBUTION 298 | 299 | Commercial distributors of software may accept certain responsibilities with 300 | respect to end users, business partners and the like. While this license is 301 | intended to facilitate the commercial use of the Program, the Contributor who 302 | includes the Program in a commercial product offering should do so in a manner 303 | which does not create potential liability for other Contributors. Therefore, if 304 | a Contributor includes the Program in a commercial product offering, such 305 | Contributor ("Commercial Contributor") hereby agrees to defend and indemnify 306 | every other Contributor ("Indemnified Contributor") against any losses, damages 307 | and costs (collectively "Losses") arising from claims, lawsuits and other legal 308 | actions brought by a third party against the Indemnified Contributor to the 309 | extent caused by the acts or omissions of such Commercial Contributor in 310 | connection with its distribution of the Program in a commercial product 311 | offering. The obligations in this section do not apply to any claims or Losses 312 | relating to any actual or alleged intellectual property infringement. In order 313 | to qualify, an Indemnified Contributor must: a) promptly notify the Commercial 314 | Contributor in writing of such claim, and b) allow the Commercial Contributor 315 | to control, and cooperate with the Commercial Contributor in, the defense and 316 | any related settlement negotiations. The Indemnified Contributor may 317 | participate in any such claim at its own expense. 318 | 319 | For example, a Contributor might include the Program in a commercial product 320 | offering, Product X. That Contributor is then a Commercial Contributor. If that 321 | Commercial Contributor then makes performance claims, or offers warranties 322 | related to Product X, those performance claims and warranties are such 323 | Commercial Contributor's responsibility alone. Under this section, the 324 | Commercial Contributor would have to defend claims against the other 325 | Contributors related to those performance claims and warranties, and if a court 326 | requires any other Contributor to pay any damages as a result, the Commercial 327 | Contributor must pay those damages. 328 | 329 | 5. NO WARRANTY 330 | 331 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN 332 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 333 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, 334 | NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each 335 | Recipient is solely responsible for determining the appropriateness of using 336 | and distributing the Program and assumes all risks associated with its exercise 337 | of rights under this Agreement , including but not limited to the risks and 338 | costs of program errors, compliance with applicable laws, damage to or loss of 339 | data, programs or equipment, and unavailability or interruption of operations. 340 | 341 | 6. DISCLAIMER OF LIABILITY 342 | 343 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 344 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, 345 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST 346 | PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 347 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 348 | WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS 349 | GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 350 | 351 | 7. GENERAL 352 | 353 | If any provision of this Agreement is invalid or unenforceable under applicable 354 | law, it shall not affect the validity or enforceability of the remainder of the 355 | terms of this Agreement, and without further action by the parties hereto, such 356 | provision shall be reformed to the minimum extent necessary to make such 357 | provision valid and enforceable. 358 | 359 | If Recipient institutes patent litigation against any entity (including a 360 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself 361 | (excluding combinations of the Program with other software or hardware) 362 | infringes such Recipient's patent(s), then such Recipient's rights granted 363 | under Section 2(b) shall terminate as of the date such litigation is filed. 364 | 365 | All Recipient's rights under this Agreement shall terminate if it fails to 366 | comply with any of the material terms or conditions of this Agreement and does 367 | not cure such failure in a reasonable period of time after becoming aware of 368 | such noncompliance. If all Recipient's rights under this Agreement terminate, 369 | Recipient agrees to cease use and distribution of the Program as soon as 370 | reasonably practicable. However, Recipient's obligations under this Agreement 371 | and any licenses granted by Recipient relating to the Program shall continue 372 | and survive. 373 | 374 | Everyone is permitted to copy and distribute copies of this Agreement, but in 375 | order to avoid inconsistency the Agreement is copyrighted and may only be 376 | modified in the following manner. The Agreement Steward reserves the right to 377 | publish new versions (including revisions) of this Agreement from time to time. 378 | No one other than the Agreement Steward has the right to modify this Agreement. 379 | The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation 380 | may assign the responsibility to serve as the Agreement Steward to a suitable 381 | separate entity. Each new version of the Agreement will be given a 382 | distinguishing version number. The Program (including Contributions) may always 383 | be distributed subject to the version of the Agreement under which it was 384 | received. In addition, after a new version of the Agreement is published, 385 | Contributor may elect to distribute the Program (including its Contributions) 386 | under the new version. Except as expressly stated in Sections 2(a) and 2(b) 387 | above, Recipient receives no rights or licenses to the intellectual property of 388 | any Contributor under this Agreement, whether expressly, by implication, 389 | estoppel or otherwise. All rights in the Program not expressly granted under 390 | this Agreement are reserved. 391 | 392 | This Agreement is governed by the laws of the State of New York and the 393 | intellectual property laws of the United States of America. No party to this 394 | Agreement will bring a legal action under this Agreement more than one year 395 | after the cause of action arose. Each party waives its rights to a jury trial 396 | in any resulting litigation. 397 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | clj-newrelic 2 | ====== 3 | 4 | [![Build Status](https://travis-ci.org/TheClimateCorporation/clj-newrelic.png?branch=master)](https://travis-ci.org/TheClimateCorporation/clj-newrelic) 5 | [![Dependencies Status](http://jarkeeper.com/TheClimateCorporation/clj-newrelic/status.svg)](http://jarkeeper.com/TheClimateCorporation/clj-newrelic) 6 | 7 | This project exports one macro, `com.climate.newrelic.trace/defn-traced`. Use it as a 8 | drop-in replacement for defn if you want calls to a function to show up in 9 | New Relic transaction tracing. 10 | 11 | To include in your project, add 12 | 13 | [![Clojars Project](http://clojars.org/com.climate/clj-newrelic/latest-version.svg)](http://clojars.org/com.climate/clj-newrelic) 14 | 15 | to your lein dependencies. 16 | 17 | General strategy adapted from [Sean Corfield](http://corfield.org/blog/post.cfm/instrumenting-clojure-for-new-relic-monitoring). 18 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject com.climate/clj-newrelic "0.2.2-SNAPSHOT" 2 | :description "Mark functions for newrelic tracing" 3 | :license {:name "Apache License 2.0" 4 | :url "http://www.apache.org/licenses/LICENSE-2.0.html" 5 | :distribution :repo} 6 | :url "http://www.github.com/TheClimateCorporation/clj-newrelic" 7 | :plugins [[lein-ancient "0.6.2"]] 8 | :dependencies [[org.clojure/clojure "1.6.0"] 9 | [com.newrelic.agent.java/newrelic-api "3.13.0"]]) 10 | -------------------------------------------------------------------------------- /src/com/climate/newrelic/trace.clj: -------------------------------------------------------------------------------- 1 | (ns com.climate.newrelic.trace) 2 | 3 | (defn- traced-meta [fname] 4 | {'com.newrelic.api.agent.Trace {:metricName (str *ns* \. fname) 5 | :dispatcher true}}) 6 | 7 | (defn- make-traced [tname fname arg-list body] 8 | (let [i-args (for [_ arg-list] (gensym)) 9 | iname (gensym)] 10 | `(do 11 | (definterface ~iname (~'invoke [~@i-args])) 12 | (deftype ~tname [] 13 | ~iname 14 | (~(with-meta 'invoke (traced-meta fname)) [~'_ ~@i-args] 15 | (let [~@(interleave arg-list i-args)] 16 | ~@body)))))) 17 | 18 | (defn- is-varargs 19 | "checks whether an args list uses varargs" 20 | [arg-list] 21 | (some #{'&} arg-list)) 22 | 23 | (defn- insert-amp [arg-list] 24 | `[~@(drop-last arg-list) & ~(last arg-list)]) 25 | 26 | (defn- remove-amp [arg-list] 27 | (remove #{'&} arg-list)) 28 | 29 | (defn- preproc-decl [fname fdecl] 30 | ; mostly stolen from clojure.core/defn 31 | (let [; get docstring 32 | m (if (string? (first fdecl)) 33 | {:doc (first fdecl)} 34 | {}) 35 | fdecl (if (string? (first fdecl)) 36 | (next fdecl) 37 | fdecl) 38 | ; look for meta at beginning 39 | m (if (map? (first fdecl)) 40 | (conj m (first fdecl)) 41 | m) 42 | fdecl (if (map? (first fdecl)) 43 | (next fdecl) 44 | fdecl) 45 | ; allow for single-arity functions 46 | fdecl (if (vector? (first fdecl)) 47 | (list fdecl) 48 | fdecl) 49 | ; look for meta at end 50 | m (if (map? (last fdecl)) 51 | (conj m (last fdecl)) 52 | m) 53 | fdecl (if (map? (last fdecl)) 54 | (butlast fdecl) 55 | fdecl) 56 | ; track what's var-args and what's not 57 | ann-fdecl (for [[args & body] fdecl] 58 | (let [var-args (is-varargs args)] 59 | {:var-args var-args 60 | :args (if var-args (remove-amp args) args) 61 | :oname (gensym) 62 | :tname (gensym fname) 63 | :body body}))] 64 | [m ann-fdecl])) 65 | 66 | (defmacro defn-traced 67 | "Drop-in replacement for clojure.core/defn. 68 | 69 | Tells Newrelic that entry/exit to this function should be traced. 70 | Allows time spent in this function to be tracked as a % of total 71 | request time. 72 | 73 | If one function defined with defn-traced calls another defined with 74 | defn-traced, Newrelic will correctly show both in its transaction 75 | trace and show how much time was spent inside/outside the inner 76 | function." 77 | [fname & fdecl] 78 | (let [[m ann-fdecl] (preproc-decl fname fdecl)] 79 | `(do 80 | (def ~fname) 81 | ~@(for [{:keys [args body tname]} ann-fdecl] 82 | (make-traced tname fname args body)) 83 | (let [~@(apply concat (for [{:keys [tname oname]} ann-fdecl] 84 | `(~oname (new ~tname))))] 85 | (defn 86 | ~fname ~m 87 | ~@(for [{:keys [var-args args oname]} ann-fdecl] 88 | (let [dumb-args (for [_ args] (gensym))] 89 | `([~@(if var-args (insert-amp dumb-args) dumb-args)] 90 | (.invoke ~oname ~@dumb-args))))))))) 91 | -------------------------------------------------------------------------------- /test/clojure/test_helper.clj: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | ; 9 | 10 | ;; clojure.test-helper 11 | ;; 12 | ;; Utility functions shared by various tests in the Clojure 13 | ;; test suite 14 | ;; 15 | ;; tomfaulhaber (gmail) 16 | ;; Created 04 November 2010 17 | 18 | (ns clojure.test-helper 19 | (:use clojure.test)) 20 | 21 | (let [nl (System/getProperty "line.separator")] 22 | (defn platform-newlines [s] (.replace s "\n" nl))) 23 | 24 | (defn temp-ns 25 | "Create and return a temporary ns, using clojure.core + uses" 26 | [& uses] 27 | (binding [*ns* *ns*] 28 | (in-ns (gensym)) 29 | (apply clojure.core/use 'clojure.core uses) 30 | *ns*)) 31 | 32 | (defmacro eval-in-temp-ns [& forms] 33 | `(binding [*ns* *ns*] 34 | (in-ns (gensym)) 35 | (clojure.core/use 'clojure.core) 36 | (eval 37 | '(do ~@forms)))) 38 | 39 | (defn causes 40 | [^Throwable throwable] 41 | (loop [causes [] 42 | t throwable] 43 | (if t (recur (conj causes t) (.getCause t)) causes))) 44 | 45 | ;; this is how I wish clojure.test/thrown? worked... 46 | ;; Does body throw expected exception, anywhere in the .getCause chain? 47 | (defmethod assert-expr 'fails-with-cause? 48 | [msg [_ exception-class msg-re & body :as form]] 49 | `(try 50 | ~@body 51 | (report {:type :fail, :message ~msg, :expected '~form, :actual nil}) 52 | (catch Throwable t# 53 | (if (some (fn [cause#] 54 | (and 55 | (= ~exception-class (class cause#)) 56 | (re-find ~msg-re (.getMessage cause#)))) 57 | (causes t#)) 58 | (report {:type :pass, :message ~msg, 59 | :expected '~form, :actual t#}) 60 | (report {:type :fail, :message ~msg, 61 | :expected '~form, :actual t#}))))) 62 | 63 | 64 | (defn get-field 65 | "Access to private or protected field. field-name is a symbol or 66 | keyword." 67 | ([klass field-name] 68 | (get-field klass field-name nil)) 69 | ([klass field-name inst] 70 | (-> klass (.getDeclaredField (name field-name)) 71 | (doto (.setAccessible true)) 72 | (.get inst)))) 73 | 74 | (defn set-var-roots 75 | [maplike] 76 | (doseq [[var val] maplike] 77 | (alter-var-root var (fn [_] val)))) 78 | 79 | (defn with-var-roots* 80 | "Temporarily set var roots, run block, then put original roots back." 81 | [root-map f & args] 82 | (let [originals (doall (map (fn [[var _]] [var @var]) root-map))] 83 | (set-var-roots root-map) 84 | (try 85 | (apply f args) 86 | (finally 87 | (set-var-roots originals))))) 88 | 89 | (defmacro with-var-roots 90 | [root-map & body] 91 | `(with-var-roots* ~root-map (fn [] ~@body))) 92 | 93 | (defn exception 94 | "Use this function to ensure that execution of a program doesn't 95 | reach certain point." 96 | [] 97 | (throw (new Exception "Exception which should never occur"))) 98 | 99 | (defmacro with-err-print-writer 100 | "Evaluate with err pointing to a temporary PrintWriter, and 101 | return err contents as a string." 102 | [& body] 103 | `(let [s# (java.io.StringWriter.) 104 | p# (java.io.PrintWriter. s#)] 105 | (binding [*err* p#] 106 | ~@body 107 | (str s#)))) 108 | 109 | (defmacro with-err-string-writer 110 | "Evaluate with err pointing to a temporary StringWriter, and 111 | return err contents as a string." 112 | [& body] 113 | `(let [s# (java.io.StringWriter.)] 114 | (binding [*err* s#] 115 | ~@body 116 | (str s#)))) 117 | 118 | (defmacro should-print-err-message 119 | "Turn on all warning flags, and test that error message prints 120 | correctly for all semi-reasonable bindings of *err*." 121 | [msg-re form] 122 | `(binding [*warn-on-reflection* true] 123 | (is (re-matches ~msg-re (with-err-string-writer (eval-in-temp-ns ~form)))) 124 | (is (re-matches ~msg-re (with-err-print-writer (eval-in-temp-ns ~form)))))) 125 | 126 | (defmacro should-not-reflect 127 | "Turn on all warning flags, and test that reflection does not occur 128 | (as identified by messages to *err*)." 129 | [form] 130 | `(binding [*warn-on-reflection* true] 131 | (is (nil? (re-find #"^Reflection warning" (with-err-string-writer (eval-in-temp-ns ~form))))) 132 | (is (nil? (re-find #"^Reflection warning" (with-err-print-writer (eval-in-temp-ns ~form))))))) 133 | -------------------------------------------------------------------------------- /test/com/climate/newrelic/trace_tests.clj: -------------------------------------------------------------------------------- 1 | (ns com.climate.newrelic.trace-tests 2 | (:require [clojure.test :refer :all] 3 | [clojure.test-helper :as util] 4 | [com.climate.newrelic.trace :as nr])) 5 | 6 | (nr/defn-traced adds "adds some numbers" 7 | ([] 0) 8 | ([a] a) 9 | ([a b] (+ a b)) 10 | ([a b c & ds] 11 | (apply + a b c ds))) 12 | 13 | (deftest test-adds 14 | (is (= (adds) 0)) 15 | (is (= (adds 1) 1)) 16 | (is (= (adds 1 2) 3)) 17 | (is (= (adds 1 2 3) 6)) 18 | (is (= (adds 1 2 3 4) 10)) 19 | (is (= (adds 1 2 3 4 5) 15))) 20 | 21 | 22 | (deftest test-reflection 23 | (util/should-not-reflect 24 | (com.climate.newrelic.trace/defn-traced get-length 25 | [^java.util.List l] 26 | (.size l)))) 27 | 28 | (nr/defn-traced destructures [[foo bar] {:keys [baz qux]}] 29 | {:foo foo 30 | :bar bar 31 | :baz baz 32 | :qux qux}) 33 | 34 | (deftest test-destructure 35 | (is (= (destructures [1 2] {:baz 3 :qux 4}) 36 | {:foo 1 :bar 2 :baz 3 :qux 4}))) 37 | 38 | (nr/defn-traced self-ref 39 | ([] (self-ref 5)) 40 | ([x] x)) 41 | 42 | (deftest test-self-ref 43 | (is (= (self-ref 7) 7)) 44 | (is (= (self-ref) 5))) 45 | --------------------------------------------------------------------------------