Skip to content

Commit 0106855

Browse files
authored
Add manual Otel instrumentation for Spans (#837)
1 parent 5d57f0b commit 0106855

6 files changed

Lines changed: 510 additions & 0 deletions

File tree

gxobservability/pom.xml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<groupId>com.genexus</groupId>
9+
<artifactId>parent</artifactId>
10+
<version>${revision}${changelist}</version>
11+
</parent>
12+
13+
<artifactId>gxobservability</artifactId>
14+
<name>GeneXus Observability</name>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>io.opentelemetry</groupId>
19+
<artifactId>opentelemetry-api</artifactId>
20+
</dependency>
21+
<dependency>
22+
<groupId>io.opentelemetry</groupId>
23+
<artifactId>opentelemetry-sdk-trace</artifactId>
24+
</dependency>
25+
<dependency>
26+
<groupId>io.opentelemetry</groupId>
27+
<artifactId>opentelemetry-exporter-otlp</artifactId>
28+
</dependency>
29+
<dependency>
30+
<groupId>io.opentelemetry</groupId>
31+
<artifactId>opentelemetry-sdk</artifactId>
32+
</dependency>
33+
<dependency>
34+
<groupId>io.opentelemetry</groupId>
35+
<artifactId>opentelemetry-semconv</artifactId>
36+
<version>1.30.1-alpha</version>
37+
</dependency>
38+
<dependency>
39+
<groupId>io.opentelemetry</groupId>
40+
<artifactId>opentelemetry-extension-annotations</artifactId>
41+
</dependency>
42+
<dependency>
43+
<groupId>io.opentelemetry</groupId>
44+
<artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
45+
<version>1.36.0</version>
46+
</dependency>
47+
</dependencies>
48+
<dependencyManagement>
49+
<dependencies>
50+
<dependency>
51+
<groupId>io.opentelemetry</groupId>
52+
<artifactId>opentelemetry-bom</artifactId>
53+
<version>1.23.0</version>
54+
<type>pom</type>
55+
<scope>import</scope>
56+
</dependency>
57+
</dependencies>
58+
</dependencyManagement>
59+
60+
<build>
61+
<finalName>gxobservability</finalName>
62+
</build>
63+
</project>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.genexus.opentelemetry;
2+
3+
import io.opentelemetry.api.trace.Span;
4+
import io.opentelemetry.api.trace.Tracer;
5+
import io.opentelemetry.api.GlobalOpenTelemetry;
6+
import io.opentelemetry.api.OpenTelemetry;
7+
import io.opentelemetry.api.trace.StatusCode;
8+
import io.opentelemetry.context.Context;
9+
public class GXSpanContext
10+
{
11+
private io.opentelemetry.api.trace.SpanContext _spanContext;
12+
13+
public io.opentelemetry.api.trace.SpanContext getSpanContext()
14+
{
15+
return _spanContext;
16+
}
17+
public GXSpanContext(io.opentelemetry.api.trace.SpanContext spanContext)
18+
{
19+
this._spanContext = spanContext;
20+
}
21+
public GXSpanContext()
22+
{
23+
_spanContext = Span.current().getSpanContext();
24+
}
25+
public String traceId()
26+
{
27+
return _spanContext.getTraceId();
28+
}
29+
public String spanId()
30+
{
31+
return _spanContext.getSpanId();
32+
}
33+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.genexus.opentelemetry;
2+
3+
import io.opentelemetry.api.trace.Span;
4+
import io.opentelemetry.api.trace.Tracer;
5+
import io.opentelemetry.api.GlobalOpenTelemetry;
6+
import io.opentelemetry.api.OpenTelemetry;
7+
import io.opentelemetry.api.trace.StatusCode;
8+
import io.opentelemetry.context.Context;
9+
10+
public class GXTraceContext
11+
{
12+
private Context context;
13+
public GXTraceContext(io.opentelemetry.context.Context context)
14+
{
15+
this.context = context;
16+
}
17+
public Context getTraceContext()
18+
{
19+
return this.context;
20+
}
21+
}
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
package com.genexus.opentelemetry;
2+
3+
import java.util.concurrent.atomic.AtomicReference;
4+
import io.opentelemetry.api.trace.Span;
5+
import io.opentelemetry.api.trace.Tracer;
6+
import io.opentelemetry.api.GlobalOpenTelemetry;
7+
import io.opentelemetry.api.OpenTelemetry;
8+
import io.opentelemetry.api.trace.StatusCode;
9+
import io.opentelemetry.context.Context;
10+
import io.opentelemetry.context.Scope;
11+
import io.opentelemetry.extension.annotations.SpanAttribute;
12+
import io.opentelemetry.extension.annotations.WithSpan;
13+
import io.opentelemetry.api.common.AttributeKey;
14+
import io.opentelemetry.api.common.Attributes;
15+
import io.opentelemetry.api.baggage.Baggage;
16+
import io.opentelemetry.api.baggage.BaggageBuilder;
17+
public class OtelSpan {
18+
private Span span;
19+
public enum SpanStatusCode
20+
{
21+
UNSET,
22+
OK,
23+
ERROR
24+
}
25+
public OtelSpan(Span span)
26+
{
27+
this.span=span;
28+
}
29+
public OtelSpan()
30+
{}
31+
//region EO Properties
32+
public String getTraceId()
33+
{
34+
if (span != null)
35+
return span.getSpanContext().getTraceId();
36+
return "";
37+
}
38+
public String getSpanId()
39+
{
40+
if (span != null)
41+
return span.getSpanContext().getSpanId();
42+
return "";
43+
}
44+
public Boolean isRecording()
45+
{
46+
if (span != null)
47+
return span.isRecording();
48+
return false;
49+
}
50+
public GXSpanContext getSpanContext() {
51+
return new GXSpanContext(getSpanContext(span));
52+
}
53+
//endregion
54+
//region EO Methods
55+
public void endSpan()
56+
{
57+
if (span!=null)
58+
span.end();
59+
}
60+
public GXTraceContext addBaggage(String key, String value)
61+
{
62+
return new GXTraceContext(addBaggageReturnContext(key, value));
63+
}
64+
public String getBaggaeItem(String key,GXTraceContext gxTraceContext)
65+
{
66+
return getBaggaeItemInContext(gxTraceContext.getTraceContext(),key);
67+
}
68+
public GXTraceContext getGXTraceContext()
69+
{
70+
return new GXTraceContext(getContext());
71+
}
72+
public void recordException(String message)
73+
{
74+
recordException(span,new Throwable(message));
75+
}
76+
public void setStringAttribute(String key, String value)
77+
{
78+
if (span != null)
79+
span.setAttribute(key,value);
80+
}
81+
public void setBooleanAttribute(String key, boolean value)
82+
{
83+
if (span != null)
84+
span.setAttribute(key,value);
85+
}
86+
public void setDoubleAttribute(String key, double value)
87+
{
88+
if (span != null)
89+
span.setAttribute(key,value);
90+
}
91+
public void setLongAttribute(String key, long value)
92+
{
93+
if (span != null)
94+
span.setAttribute(key,value);
95+
}
96+
public void setStatus(Byte spanStatusCodeByte)
97+
{
98+
StatusCode statusCode = toStatusCode(spanStatusCodeByte);
99+
if (span != null)
100+
span.setStatus(statusCode);
101+
}
102+
public void setStatus(Byte spanStatusCodeByte, String message)
103+
{
104+
StatusCode statusCode = toStatusCode(spanStatusCodeByte);
105+
if (span != null)
106+
span.setStatus(statusCode, message);
107+
}
108+
//endregion
109+
110+
//region Private methods
111+
112+
private String getBaggaeItemInContext(Context context, String key)
113+
{
114+
AtomicReference<String> value = new AtomicReference<>("");
115+
Baggage.fromContext(context).asMap().forEach((k, v) -> {
116+
if (k.equals(key)) {
117+
value.set(v.getValue());
118+
}
119+
});
120+
if (value != null)
121+
return value.get();
122+
return "";
123+
}
124+
private Context addBaggageReturnContext(String key, String value)
125+
{
126+
Baggage baggage = Baggage.current().toBuilder().put(key,value).build();
127+
return baggage.storeInContext(getContext());
128+
}
129+
private Context getContext()
130+
{
131+
if (span != null)
132+
return Context.current().with(span);
133+
return null;
134+
}
135+
private Context getContextCurrentSpan()
136+
{
137+
return Context.current();
138+
}
139+
140+
private static void recordException(Span span, Throwable exc) {
141+
if (span != null && exc != null) {
142+
span.recordException(exc);
143+
}
144+
}
145+
private io.opentelemetry.api.trace.SpanContext getSpanContext(Span span)
146+
{
147+
if (span != null)
148+
return span.getSpanContext();
149+
return null;
150+
}
151+
private boolean isRecording(Span span)
152+
{
153+
if (span != null)
154+
return span.isRecording();
155+
return false;
156+
}
157+
private Span current()
158+
{
159+
return Span.current();
160+
161+
}
162+
private static StatusCode toStatusCode (Byte spanStatusCode){
163+
switch (spanStatusCode) {
164+
case 0:
165+
return StatusCode.UNSET;
166+
case 1:
167+
return StatusCode.OK;
168+
case 2:
169+
return StatusCode.ERROR;
170+
}
171+
return null;
172+
}
173+
private static SpanStatusCode fromStatusCode (StatusCode statusCode){
174+
switch (statusCode) {
175+
case UNSET:
176+
return SpanStatusCode.UNSET;
177+
case OK:
178+
return SpanStatusCode.OK;
179+
case ERROR:
180+
return SpanStatusCode.ERROR;
181+
}
182+
return null;
183+
}
184+
//endregion
185+
186+
}

0 commit comments

Comments
 (0)