|
7 | 7 | * Licensed under the Apache License, Version 2.0 (the "License"); |
8 | 8 | * you may not use this file except in compliance with the License. |
9 | 9 | * You may obtain a copy of the License at |
10 | | - * |
| 10 | + * |
11 | 11 | * http://www.apache.org/licenses/LICENSE-2.0 |
12 | | - * |
| 12 | + * |
13 | 13 | * Unless required by applicable law or agreed to in writing, software |
14 | 14 | * distributed under the License is distributed on an "AS IS" BASIS, |
15 | 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
19 | 19 | */ |
20 | 20 | package co.elastic.apm.api; |
21 | 21 |
|
| 22 | +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; |
| 23 | + |
22 | 24 | import javax.annotation.Nonnull; |
23 | | -import javax.annotation.Nullable; |
| 25 | +import java.util.Collections; |
| 26 | +import java.util.Map; |
| 27 | +import java.util.function.Function; |
24 | 28 |
|
25 | 29 | /** |
26 | 30 | * This class is the main entry point of the public API for the Elastic APM agent. |
|
35 | 39 | * ElasticApm.currentTransaction().setName("SuchController#muchMethod"); |
36 | 40 | * }</pre> |
37 | 41 | */ |
38 | | -public class ElasticApm { |
39 | | - |
40 | | - private ElasticApm() { |
41 | | - // do not instantiate |
42 | | - } |
| 42 | +/* |
| 43 | + * Implementation note: |
| 44 | + * The parameters of static methods are linked eagerly. |
| 45 | + * In order to be able to refer to Java 8 types but still be Java 7 compatible, |
| 46 | + * The Java 7 compatible code is extracted to a super class. |
| 47 | + * We take advantage of the fact that static methods are inherited as well. |
| 48 | + * So on Java 8, you can just call ElasticApm.startTransaction(), |
| 49 | + * even though that method is defined in ElasticApm's super class ElasticApmJava7. |
| 50 | + * |
| 51 | + * When stuck on Java 7, just call ElasticApmJava7.startTransaction(). |
| 52 | + * Observation: actually, it also seems to work to call ElasticApm.startTransaction(). |
| 53 | + * I assume the JVM does not eagerly link the methods when only referring to static methods of the super class. |
| 54 | + */ |
| 55 | +public class ElasticApm extends ElasticApmJava7 { |
43 | 56 |
|
44 | 57 | /** |
45 | | - * Use this method to create a custom transaction. |
46 | | - * <p> |
47 | | - * Note that the agent will do this for you automatically when ever your application receives an incoming HTTP request. |
48 | | - * You only need to use this method to create custom transactions. |
49 | | - * </p> |
| 58 | + * Similar to {@link ElasticApm#startTransaction()} but creates this transaction as the child of a remote parent. |
| 59 | + * |
50 | 60 | * <p> |
51 | | - * It is important to call {@link Transaction#end()} when the transaction has ended. |
52 | | - * A best practice is to use the transaction in a try-catch-finally block. |
53 | 61 | * Example: |
54 | 62 | * </p> |
55 | 63 | * <pre> |
56 | | - * Transaction transaction = ElasticApm.startTransaction(); |
57 | | - * try { |
58 | | - * transaction.setName("MyController#myAction"); |
59 | | - * transaction.setType(Transaction.TYPE_REQUEST); |
60 | | - * // do your thing... |
61 | | - * } catch (Exception e) { |
62 | | - * transaction.captureException(e); |
63 | | - * throw e; |
64 | | - * } finally { |
65 | | - * transaction.end(); |
66 | | - * } |
| 64 | + * Transaction transaction = ElasticApm.startTransactionWithRemoteParent(request::getHeader); |
67 | 65 | * </pre> |
68 | 66 | * <p> |
69 | | - * Note: Transactions created via this method can not be retrieved by calling {@link #currentSpan()} or {@link #currentTransaction()}. |
70 | | - * See {@link Transaction#activate()} on how to achieve that. |
71 | | - * </p> |
72 | | - * |
73 | | - * @return the started transaction. |
74 | | - */ |
75 | | - @Nonnull |
76 | | - public static Transaction startTransaction() { |
77 | | - Object transaction = doStartTransaction(); |
78 | | - return transaction != null ? new TransactionImpl(transaction) : NoopTransaction.INSTANCE; |
79 | | - } |
80 | | - |
81 | | - private static Object doStartTransaction() { |
82 | | - // co.elastic.apm.api.ElasticApmInstrumentation.StartTransactionInstrumentation.doStartTransaction |
83 | | - return null; |
84 | | - } |
85 | | - |
86 | | - /** |
87 | | - * Returns the currently running transaction. |
88 | | - * <p> |
89 | | - * If there is no current transaction, this method will return a noop transaction, |
90 | | - * which means that you never have to check for {@code null} values. |
| 67 | + * Note: If the protocol supports multi-value headers, use {@link #startTransactionWithRemoteParent(Function, Function)} |
91 | 68 | * </p> |
92 | 69 | * <p> |
93 | | - * NOTE: Transactions created via {@link #startTransaction()} can not be retrieved by calling this method. |
94 | | - * See {@link Transaction#activate()} on how to achieve that. |
| 70 | + * Note: This method can only be used on Java 8+. |
| 71 | + * If you are stuck on Java 7, use {@link ElasticApm#startTransactionWithRemoteParent(Map)}. |
95 | 72 | * </p> |
96 | 73 | * |
97 | | - * @return The currently running transaction, or a noop transaction (never {@code null}). |
| 74 | + * @param getFirstHeader a function which receives a header name and returns the fist header with that name |
| 75 | + * @return the started transaction |
| 76 | + * @since 1.3.0 |
98 | 77 | */ |
99 | 78 | @Nonnull |
100 | | - public static Transaction currentTransaction() { |
101 | | - Object transaction = doGetCurrentTransaction(); |
102 | | - return transaction != null ? new TransactionImpl(transaction) : NoopTransaction.INSTANCE; |
103 | | - } |
104 | | - |
105 | | - private static Object doGetCurrentTransaction() { |
106 | | - // co.elastic.apm.api.ElasticApmInstrumentation.CurrentTransactionInstrumentation.doGetCurrentTransaction |
107 | | - return null; |
| 79 | + @IgnoreJRERequirement |
| 80 | + public static Transaction startTransactionWithRemoteParent(final Function<String, String> getFirstHeader) { |
| 81 | + return startTransactionWithRemoteParent(getFirstHeader, new Function<String, Iterable<String>>() { |
| 82 | + @Override |
| 83 | + public Iterable<String> apply(String key) { |
| 84 | + return Collections.singletonList(getFirstHeader.apply(key)); |
| 85 | + } |
| 86 | + }); |
108 | 87 | } |
109 | 88 |
|
110 | 89 | /** |
111 | | - * Returns the currently active span or transaction. |
| 90 | + * Similar to {@link ElasticApm#startTransaction()} but creates this transaction as the child of a remote parent. |
| 91 | + * |
112 | 92 | * <p> |
113 | | - * If there is no current span, this method will return a noop span, |
114 | | - * which means that you never have to check for {@code null} values. |
| 93 | + * Example: |
115 | 94 | * </p> |
| 95 | + * <pre> |
| 96 | + * Transaction transaction = ElasticApm.startTransactionWithRemoteParent(request::getHeader, request::getHeaders); |
| 97 | + * </pre> |
116 | 98 | * <p> |
117 | | - * Note that even if this method is returning a noop span, |
118 | | - * you can still {@link Span#captureException(Throwable) capture exceptions} on it. |
119 | | - * These exceptions will not have a link to a Span or a Transaction. |
| 99 | + * Note: If the protocol does not support multi-value headers, use {@link #startTransactionWithRemoteParent(Function)} |
120 | 100 | * </p> |
121 | 101 | * <p> |
122 | | - * NOTE: Transactions created via {@link Span#createSpan()} can not be retrieved by calling this method. |
123 | | - * See {@link Span#activate()} on how to achieve that. |
| 102 | + * Note: This method can only be used on Java 8+. |
| 103 | + * If you are stuck on Java 7, use {@link ElasticApm#startTransactionWithRemoteParent(Map)}. |
124 | 104 | * </p> |
125 | | - * @return The currently active span, or transaction, or a noop span (never {@code null}). |
| 105 | + * |
| 106 | + * @param getFirstHeader a function which receives a header name and returns the fist header with that name |
| 107 | + * @param getAllHeaders a function which receives a header name and returns all headers with that name |
| 108 | + * @return the started transaction |
| 109 | + * @since 1.3.0 |
126 | 110 | */ |
127 | 111 | @Nonnull |
128 | | - public static Span currentSpan() { |
129 | | - Object span = doGetCurrentSpan(); |
130 | | - return span != null ? new SpanImpl(span) : NoopSpan.INSTANCE; |
| 112 | + @IgnoreJRERequirement |
| 113 | + public static Transaction startTransactionWithRemoteParent(Function<String, String> getFirstHeader, Function<String, Iterable<String>> getAllHeaders) { |
| 114 | + Object transaction = doStartTransactionWithRemoteParentFunction(getFirstHeader, getAllHeaders); |
| 115 | + return transaction != null ? new TransactionImpl(transaction) : NoopTransaction.INSTANCE; |
131 | 116 | } |
132 | 117 |
|
133 | | - private static Object doGetCurrentSpan() { |
134 | | - // co.elastic.apm.api.ElasticApmInstrumentation.CurrentSpanInstrumentation.doGetCurrentSpan |
| 118 | + @IgnoreJRERequirement |
| 119 | + private static Object doStartTransactionWithRemoteParentFunction(Function<String, String> getFirstHeader, Function<String, Iterable<String>> getAllHeaders) { |
| 120 | + // co.elastic.apm.agent.plugin.api.ElasticApmApiInstrumentation.StartTransactionWithRemoteParentInstrumentation |
135 | 121 | return null; |
136 | 122 | } |
137 | | - |
138 | | - /** |
139 | | - * Captures an exception and reports it to the APM server. |
140 | | - * |
141 | | - * @param e the exception to record |
142 | | - * @deprecated use {@link #currentSpan()}.{@link Span#captureException(Throwable) captureException(Throwable)} instead |
143 | | - */ |
144 | | - @Deprecated |
145 | | - public static void captureException(@Nullable Throwable e) { |
146 | | - // co.elastic.apm.api.ElasticApmInstrumentation.CaptureExceptionInstrumentation.captureException |
147 | | - } |
148 | | - |
149 | 123 | } |
0 commit comments