| 
5 | 5 | 
 
  | 
6 | 6 | import static org.junit.jupiter.api.Assertions.assertEquals;  | 
7 | 7 | import static org.junit.jupiter.api.Assertions.assertNotNull;  | 
 | 8 | +import static org.junit.jupiter.api.Assertions.assertNull;  | 
8 | 9 | 
 
  | 
9 | 10 | import java.time.Instant;  | 
 | 11 | +import java.util.Map;  | 
10 | 12 | 
 
  | 
11 | 13 | import io.opentelemetry.api.trace.SpanContext;  | 
12 | 14 | import io.opentelemetry.api.trace.SpanId;  | 
 | 
19 | 21 | import org.junit.jupiter.api.Test;  | 
20 | 22 | 
 
  | 
21 | 23 | import com.azure.monitor.opentelemetry.autoconfigure.implementation.LogDataMapper;  | 
 | 24 | +import com.azure.monitor.opentelemetry.autoconfigure.implementation.models.MessageData;  | 
22 | 25 | import com.azure.monitor.opentelemetry.autoconfigure.implementation.models.TelemetryEventData;  | 
23 | 26 | 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;  | 
24 | 29 | 
 
  | 
25 | 30 | import io.opentelemetry.api.common.Attributes;  | 
26 | 31 | import io.opentelemetry.api.logs.Severity;  | 
@@ -96,4 +101,128 @@ public int getTotalAttributeCount() {  | 
96 | 101 |         TelemetryEventData eventData = (TelemetryEventData) result.getData().getBaseData();  | 
97 | 102 |         assertEquals("TestEvent", eventData.getName());  | 
98 | 103 |     }  | 
 | 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 | +    }  | 
99 | 228 | }  | 
0 commit comments