Skip to content

Commit ef3ffd1

Browse files
committed
Support stable code.* attributes
1 parent 751a37d commit ef3ffd1

File tree

2 files changed

+156
-0
lines changed
  • sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src

2 files changed

+156
-0
lines changed

sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/main/java/com/azure/monitor/opentelemetry/autoconfigure/implementation/LogDataMapper.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.azure.monitor.opentelemetry.autoconfigure.implementation.models.ContextTagKeys;
1212
import com.azure.monitor.opentelemetry.autoconfigure.implementation.models.SeverityLevel;
1313
import com.azure.monitor.opentelemetry.autoconfigure.implementation.models.TelemetryItem;
14+
import com.azure.monitor.opentelemetry.autoconfigure.implementation.semconv.CodeAttributes;
1415
import com.azure.monitor.opentelemetry.autoconfigure.implementation.semconv.incubating.CodeIncubatingAttributes;
1516
import com.azure.monitor.opentelemetry.autoconfigure.implementation.semconv.incubating.ThreadIncubatingAttributes;
1617
import com.azure.monitor.opentelemetry.autoconfigure.implementation.utils.FormattedTime;
@@ -67,6 +68,13 @@ public class LogDataMapper {
6768
.exactString(CodeIncubatingAttributes.CODE_NAMESPACE, "ClassName")
6869
.exactString(CodeIncubatingAttributes.CODE_FUNCTION, "MethodName")
6970
.exactLong(CodeIncubatingAttributes.CODE_LINENO, "LineNumber")
71+
.exactString(CodeAttributes.CODE_FILE_PATH, "FileName")
72+
.exactLong(CodeAttributes.CODE_LINE_NUMBER, "LineNumber")
73+
.exact(CodeAttributes.CODE_FUNCTION_NAME.getKey(), (telemetryBuilder, value) -> {
74+
if (value instanceof String) {
75+
addFunctionNameProperties(telemetryBuilder, (String) value);
76+
}
77+
})
7078
.exactString(LOG4J_MARKER, "Marker")
7179
.exactStringArray(LOGBACK_MARKER, "Marker");
7280

@@ -196,6 +204,25 @@ private static void setOperationName(AbstractTelemetryBuilder telemetryBuilder,
196204
}
197205
}
198206

207+
private static void addFunctionNameProperties(AbstractTelemetryBuilder telemetryBuilder, String functionName) {
208+
int separatorIndex = functionName.lastIndexOf('.');
209+
210+
if (separatorIndex == -1) {
211+
telemetryBuilder.addProperty("MethodName", functionName);
212+
return;
213+
}
214+
215+
String methodName = functionName.substring(separatorIndex + 1);
216+
if (!methodName.isEmpty()) {
217+
telemetryBuilder.addProperty("MethodName", methodName);
218+
}
219+
220+
String className = functionName.substring(0, separatorIndex);
221+
if (!className.isEmpty()) {
222+
telemetryBuilder.addProperty("ClassName", className);
223+
}
224+
}
225+
199226
private static void setTime(AbstractTelemetryBuilder telemetryBuilder, LogRecordData log) {
200227
telemetryBuilder.setTime(FormattedTime.offSetDateTimeFromEpochNanos(getTimestampEpochNanosWithFallback(log)));
201228
}

sdk/monitor/azure-monitor-opentelemetry-autoconfigure/src/test/java/com/azure/monitor/opentelemetry/autoconfigure/implementation/logging/LogDataMapperTest.java

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55

66
import static org.junit.jupiter.api.Assertions.assertEquals;
77
import static org.junit.jupiter.api.Assertions.assertNotNull;
8+
import static org.junit.jupiter.api.Assertions.assertNull;
89

910
import java.time.Instant;
11+
import java.util.Map;
1012

1113
import io.opentelemetry.api.trace.SpanContext;
1214
import io.opentelemetry.api.trace.SpanId;
@@ -19,8 +21,11 @@
1921
import org.junit.jupiter.api.Test;
2022

2123
import com.azure.monitor.opentelemetry.autoconfigure.implementation.LogDataMapper;
24+
import com.azure.monitor.opentelemetry.autoconfigure.implementation.models.MessageData;
2225
import com.azure.monitor.opentelemetry.autoconfigure.implementation.models.TelemetryEventData;
2326
import com.azure.monitor.opentelemetry.autoconfigure.implementation.models.TelemetryItem;
27+
import com.azure.monitor.opentelemetry.autoconfigure.implementation.semconv.CodeAttributes;
28+
import com.azure.monitor.opentelemetry.autoconfigure.implementation.semconv.incubating.CodeIncubatingAttributes;
2429

2530
import io.opentelemetry.api.common.Attributes;
2631
import io.opentelemetry.api.logs.Severity;
@@ -96,4 +101,128 @@ public int getTotalAttributeCount() {
96101
TelemetryEventData eventData = (TelemetryEventData) result.getData().getBaseData();
97102
assertEquals("TestEvent", eventData.getName());
98103
}
104+
105+
@Test
106+
void testStableCodeAttributesMappedToProperties() {
107+
Attributes attributes = Attributes.builder()
108+
.put(CodeAttributes.CODE_FILE_PATH, "/src/main/java/com/example/App.java")
109+
.put(CodeAttributes.CODE_FUNCTION_NAME, "com.example.App.process")
110+
.put(CodeAttributes.CODE_LINE_NUMBER, 42L)
111+
.build();
112+
113+
LogDataMapper logDataMapper = new LogDataMapper(false, false, (b, r) -> {
114+
});
115+
116+
TelemetryItem telemetryItem = logDataMapper.map(new SimpleLogRecordData(attributes), null, null);
117+
118+
MessageData messageData = (MessageData) telemetryItem.getData().getBaseData();
119+
Map<String, String> properties = messageData.getProperties();
120+
121+
assertNotNull(properties);
122+
assertEquals("/src/main/java/com/example/App.java", properties.get("FileName"));
123+
assertEquals("com.example.App", properties.get("ClassName"));
124+
assertEquals("process", properties.get("MethodName"));
125+
assertEquals("42", properties.get("LineNumber"));
126+
}
127+
128+
@Test
129+
void testIncubatingCodeAttributesStillMapped() {
130+
Attributes attributes = Attributes.builder()
131+
.put(CodeIncubatingAttributes.CODE_FILEPATH, "/src/main/java/com/example/App.java")
132+
.put(CodeIncubatingAttributes.CODE_NAMESPACE, "com.example.App")
133+
.put(CodeIncubatingAttributes.CODE_FUNCTION, "process")
134+
.put(CodeIncubatingAttributes.CODE_LINENO, 42L)
135+
.build();
136+
137+
LogDataMapper logDataMapper = new LogDataMapper(false, false, (b, r) -> {
138+
});
139+
140+
TelemetryItem telemetryItem = logDataMapper.map(new SimpleLogRecordData(attributes), null, null);
141+
142+
MessageData messageData = (MessageData) telemetryItem.getData().getBaseData();
143+
Map<String, String> properties = messageData.getProperties();
144+
145+
assertNotNull(properties);
146+
assertEquals("/src/main/java/com/example/App.java", properties.get("FileName"));
147+
assertEquals("com.example.App", properties.get("ClassName"));
148+
assertEquals("process", properties.get("MethodName"));
149+
assertEquals("42", properties.get("LineNumber"));
150+
}
151+
152+
@Test
153+
void testStableCodeFunctionWithoutNamespace() {
154+
Attributes attributes = Attributes.builder().put(CodeAttributes.CODE_FUNCTION_NAME, "fopen").build();
155+
156+
LogDataMapper logDataMapper = new LogDataMapper(false, false, (b, r) -> {
157+
});
158+
159+
TelemetryItem telemetryItem = logDataMapper.map(new SimpleLogRecordData(attributes), null, null);
160+
161+
MessageData messageData = (MessageData) telemetryItem.getData().getBaseData();
162+
Map<String, String> properties = messageData.getProperties();
163+
164+
assertNotNull(properties);
165+
assertEquals("fopen", properties.get("MethodName"));
166+
assertNull(properties.get("ClassName"));
167+
}
168+
169+
private static final class SimpleLogRecordData implements LogRecordData {
170+
private final Attributes attributes;
171+
private final long timestamp;
172+
173+
private SimpleLogRecordData(Attributes attributes) {
174+
this.attributes = attributes;
175+
this.timestamp = Instant.now().toEpochMilli() * 1_000_000;
176+
}
177+
178+
@Override
179+
public Resource getResource() {
180+
return Resource.empty();
181+
}
182+
183+
@Override
184+
public Attributes getAttributes() {
185+
return attributes;
186+
}
187+
188+
@Override
189+
public InstrumentationScopeInfo getInstrumentationScopeInfo() {
190+
return InstrumentationScopeInfo.create("TestScope", null, null);
191+
}
192+
193+
@Override
194+
public long getTimestampEpochNanos() {
195+
return timestamp;
196+
}
197+
198+
@Override
199+
public long getObservedTimestampEpochNanos() {
200+
return timestamp;
201+
}
202+
203+
@Override
204+
public SpanContext getSpanContext() {
205+
return SpanContext.getInvalid();
206+
}
207+
208+
@Override
209+
public Severity getSeverity() {
210+
return Severity.INFO;
211+
}
212+
213+
@Override
214+
public String getSeverityText() {
215+
return "INFO";
216+
}
217+
218+
@Override
219+
public Body getBody() {
220+
return Body.string("Test log message");
221+
}
222+
223+
@Override
224+
public int getTotalAttributeCount() {
225+
return attributes.size();
226+
}
227+
}
99228
}

0 commit comments

Comments
 (0)