@@ -75,6 +75,114 @@ void main() {
75
75
76
76
verifyCaptureLog (SentryLogLevel .fatal);
77
77
});
78
+
79
+ test ('logs to hub options when provided' , () {
80
+ final mockLogCallback = _MockSdkLogCallback ();
81
+
82
+ // Set the mock log callback on the fixture hub
83
+ fixture.hub.options.log = mockLogCallback.call;
84
+ fixture.hub.options.debug = true ;
85
+ fixture.hub.options.diagnosticLevel = SentryLevel .debug;
86
+
87
+ final logger = SentryLogger (
88
+ () => fixture.timestamp,
89
+ hub: fixture.hub,
90
+ );
91
+
92
+ logger.trace ('test message' , attributes: fixture.attributes);
93
+
94
+ // Verify that both hub.captureLog and our callback were called
95
+ expect (fixture.hub.captureLogCalls.length, 1 );
96
+ expect (mockLogCallback.calls.length, 1 );
97
+
98
+ // Verify the captured log has the right content
99
+ final capturedLog = fixture.hub.captureLogCalls[0 ].log;
100
+ expect (capturedLog.level, SentryLogLevel .trace);
101
+ expect (capturedLog.body, 'test message' );
102
+ expect (capturedLog.attributes, fixture.attributes);
103
+
104
+ // Verify the log callback was called with the right parameters
105
+ final logCall = mockLogCallback.calls[0 ];
106
+ expect (logCall.level, SentryLevel .debug); // trace maps to debug
107
+ expect (logCall.message,
108
+ 'test message {"string": "string", "int": 1, "double": 1.23456789, "bool": true, "double_int": 1.0, "nan": NaN, "positive_infinity": Infinity, "negative_infinity": -Infinity}' );
109
+ expect (logCall.logger, 'sentry_logger' );
110
+ });
111
+
112
+ test ('bridges SentryLogLevel to SentryLevel correctly' , () {
113
+ final mockLogCallback = _MockSdkLogCallback ();
114
+
115
+ // Set the mock log callback on the fixture hub's options
116
+ fixture.hub.options.log = mockLogCallback.call;
117
+ fixture.hub.options.debug = true ;
118
+ fixture.hub.options.diagnosticLevel = SentryLevel .debug;
119
+
120
+ final logger = SentryLogger (
121
+ () => fixture.timestamp,
122
+ hub: fixture.hub,
123
+ );
124
+
125
+ // Test all log levels to ensure proper bridging
126
+ logger.trace ('trace message' );
127
+ logger.debug ('debug message' );
128
+ logger.info ('info message' );
129
+ logger.warn ('warn message' );
130
+ logger.error ('error message' );
131
+ logger.fatal ('fatal message' );
132
+
133
+ // Verify that all calls were made to both the hub and the log callback
134
+ expect (fixture.hub.captureLogCalls.length, 6 );
135
+ expect (mockLogCallback.calls.length, 6 );
136
+
137
+ // Verify the bridging is correct
138
+ expect (mockLogCallback.calls[0 ].level, SentryLevel .debug); // trace -> debug
139
+ expect (mockLogCallback.calls[1 ].level, SentryLevel .debug); // debug -> debug
140
+ expect (mockLogCallback.calls[2 ].level, SentryLevel .info); // info -> info
141
+ expect (
142
+ mockLogCallback.calls[3 ].level, SentryLevel .warning); // warn -> warning
143
+ expect (mockLogCallback.calls[4 ].level, SentryLevel .error); // error -> error
144
+ expect (mockLogCallback.calls[5 ].level, SentryLevel .fatal); // fatal -> fatal
145
+ });
146
+
147
+ test ('handles NaN and infinite values correctly' , () {
148
+ final mockLogCallback = _MockSdkLogCallback ();
149
+
150
+ // Set the mock log callback on the fixture hub's options
151
+ fixture.hub.options.log = mockLogCallback.call;
152
+ fixture.hub.options.debug = true ;
153
+ fixture.hub.options.diagnosticLevel = SentryLevel .debug;
154
+
155
+ final logger = SentryLogger (
156
+ () => fixture.timestamp,
157
+ hub: fixture.hub,
158
+ );
159
+
160
+ // Test with special double values
161
+ final specialAttributes = < String , SentryLogAttribute > {
162
+ 'nan' : SentryLogAttribute .double (double .nan),
163
+ 'positive_infinity' : SentryLogAttribute .double (double .infinity),
164
+ 'negative_infinity' : SentryLogAttribute .double (double .negativeInfinity),
165
+ };
166
+
167
+ logger.info ('special values' , attributes: specialAttributes);
168
+
169
+ // Verify that both hub.captureLog and our callback were called
170
+ expect (fixture.hub.captureLogCalls.length, 1 );
171
+ expect (mockLogCallback.calls.length, 1 );
172
+
173
+ // Verify the captured log has the right content
174
+ final capturedLog = fixture.hub.captureLogCalls[0 ].log;
175
+ expect (capturedLog.level, SentryLogLevel .info);
176
+ expect (capturedLog.body, 'special values' );
177
+ expect (capturedLog.attributes, specialAttributes);
178
+
179
+ // Verify the log callback was called with the right parameters
180
+ final logCall = mockLogCallback.calls[0 ];
181
+ expect (logCall.level, SentryLevel .info);
182
+ expect (logCall.message,
183
+ 'special values {"nan": NaN, "positive_infinity": Infinity, "negative_infinity": -Infinity}' );
184
+ expect (logCall.logger, 'sentry_logger' );
185
+ });
78
186
}
79
187
80
188
class Fixture {
@@ -85,11 +193,42 @@ class Fixture {
85
193
final attributes = < String , SentryLogAttribute > {
86
194
'string' : SentryLogAttribute .string ('string' ),
87
195
'int' : SentryLogAttribute .int (1 ),
88
- 'double' : SentryLogAttribute .double (1.0 ),
196
+ 'double' : SentryLogAttribute .double (1.23456789 ),
89
197
'bool' : SentryLogAttribute .bool (true ),
198
+ 'double_int' : SentryLogAttribute .double (1.0 ),
199
+ 'nan' : SentryLogAttribute .double (double .nan),
200
+ 'positive_infinity' : SentryLogAttribute .double (double .infinity),
201
+ 'negative_infinity' : SentryLogAttribute .double (double .negativeInfinity),
90
202
};
91
203
92
204
SentryLogger getSut () {
93
205
return SentryLogger (() => timestamp, hub: hub);
94
206
}
95
207
}
208
+
209
+ /// Simple mock for SdkLogCallback to track calls
210
+ class _MockSdkLogCallback {
211
+ final List <_LogCall > calls = [];
212
+
213
+ void call (
214
+ SentryLevel level,
215
+ String message, {
216
+ String ? logger,
217
+ Object ? exception,
218
+ StackTrace ? stackTrace,
219
+ }) {
220
+ calls.add (_LogCall (level, message, logger, exception, stackTrace));
221
+ }
222
+ }
223
+
224
+ /// Data class to store log call information
225
+ class _LogCall {
226
+ final SentryLevel level;
227
+ final String message;
228
+ final String ? logger;
229
+ final Object ? exception;
230
+ final StackTrace ? stackTrace;
231
+
232
+ _LogCall (
233
+ this .level, this .message, this .logger, this .exception, this .stackTrace);
234
+ }
0 commit comments