@@ -311,6 +311,20 @@ def test_emit(self):
311311 ),
312312 )
313313
314+ def test_emit_minimal (self ):
315+ from google .cloud .logging_v2 .logger import _GLOBAL_RESOURCE
316+
317+ client = _Client (self .PROJECT )
318+ handler = self ._make_one (
319+ client , transport = _Transport , resource = _GLOBAL_RESOURCE
320+ )
321+ record = logging .LogRecord (None , logging .INFO , None , None , None , None , None )
322+ handler .handle (record )
323+ self .assertEqual (
324+ handler .transport .send_called_with ,
325+ (record , None , _GLOBAL_RESOURCE , None , None , None , None , None ,),
326+ )
327+
314328 def test_emit_manual_field_override (self ):
315329 from google .cloud .logging_v2 .logger import _GLOBAL_RESOURCE
316330 from google .cloud .logging_v2 .resource import Resource
@@ -401,6 +415,70 @@ def test_emit_with_custom_formatter(self):
401415 ),
402416 )
403417
418+ def test_emit_dict (self ):
419+ """
420+ Handler should support logging dictionaries
421+ """
422+ from google .cloud .logging_v2 .logger import _GLOBAL_RESOURCE
423+
424+ client = _Client (self .PROJECT )
425+ handler = self ._make_one (
426+ client , transport = _Transport , resource = _GLOBAL_RESOURCE ,
427+ )
428+ message = {"x" : "test" }
429+ logname = "logname"
430+ expected_label = {"python_logger" : logname }
431+ record = logging .LogRecord (
432+ logname , logging .INFO , None , None , message , None , None
433+ )
434+ handler .handle (record )
435+
436+ self .assertEqual (
437+ handler .transport .send_called_with ,
438+ (
439+ record ,
440+ message ,
441+ _GLOBAL_RESOURCE ,
442+ expected_label ,
443+ None ,
444+ None ,
445+ None ,
446+ None ,
447+ ),
448+ )
449+
450+ def test_emit_with_encoded_json (self ):
451+ """
452+ Handler should parse json encoded as a string
453+ """
454+ from google .cloud .logging_v2 .logger import _GLOBAL_RESOURCE
455+
456+ client = _Client (self .PROJECT )
457+ handler = self ._make_one (
458+ client , transport = _Transport , resource = _GLOBAL_RESOURCE ,
459+ )
460+ logFormatter = logging .Formatter (fmt = '{ "x" : "%(name)s" }' )
461+ handler .setFormatter (logFormatter )
462+ logname = "logname"
463+ expected_result = {"x" : logname }
464+ expected_label = {"python_logger" : logname }
465+ record = logging .LogRecord (logname , logging .INFO , None , None , None , None , None )
466+ handler .handle (record )
467+
468+ self .assertEqual (
469+ handler .transport .send_called_with ,
470+ (
471+ record ,
472+ expected_result ,
473+ _GLOBAL_RESOURCE ,
474+ expected_label ,
475+ None ,
476+ None ,
477+ None ,
478+ None ,
479+ ),
480+ )
481+
404482 def test_format_with_arguments (self ):
405483 """
406484 Handler should support format string arguments
@@ -425,6 +503,112 @@ def test_format_with_arguments(self):
425503 )
426504
427505
506+ class TestFormatAndParseMessage (unittest .TestCase ):
507+ def test_none (self ):
508+ """
509+ None messages with no special formatting should return
510+ None after formatting
511+ """
512+ from google .cloud .logging_v2 .handlers .handlers import _format_and_parse_message
513+
514+ message = None
515+ record = logging .LogRecord (None , None , None , None , message , None , None )
516+ handler = logging .StreamHandler ()
517+ result = _format_and_parse_message (record , handler )
518+ self .assertEqual (result , None )
519+
520+ def test_none_formatted (self ):
521+ """
522+ None messages with formatting rules should return formatted string
523+ """
524+ from google .cloud .logging_v2 .handlers .handlers import _format_and_parse_message
525+
526+ message = None
527+ record = logging .LogRecord ("logname" , None , None , None , message , None , None )
528+ handler = logging .StreamHandler ()
529+ formatter = logging .Formatter ("name: %(name)s" )
530+ handler .setFormatter (formatter )
531+ result = _format_and_parse_message (record , handler )
532+ self .assertEqual (result , "name: logname" )
533+
534+ def test_unformatted_string (self ):
535+ """
536+ Unformated strings should be returned unchanged
537+ """
538+ from google .cloud .logging_v2 .handlers .handlers import _format_and_parse_message
539+
540+ message = '"test"'
541+ record = logging .LogRecord ("logname" , None , None , None , message , None , None )
542+ handler = logging .StreamHandler ()
543+ result = _format_and_parse_message (record , handler )
544+ self .assertEqual (result , message )
545+
546+ def test_empty_string (self ):
547+ """
548+ Empty strings should be returned unchanged
549+ """
550+ from google .cloud .logging_v2 .handlers .handlers import _format_and_parse_message
551+
552+ message = ""
553+ record = logging .LogRecord ("logname" , None , None , None , message , None , None )
554+ handler = logging .StreamHandler ()
555+ result = _format_and_parse_message (record , handler )
556+ self .assertEqual (result , message )
557+
558+ def test_string_formatted_with_args (self ):
559+ """
560+ string messages should properly apply formatting and arguments
561+ """
562+ from google .cloud .logging_v2 .handlers .handlers import _format_and_parse_message
563+
564+ message = "argument: %s"
565+ arg = "test"
566+ record = logging .LogRecord ("logname" , None , None , None , message , arg , None )
567+ handler = logging .StreamHandler ()
568+ formatter = logging .Formatter ("name: %(name)s :: message: %(message)s" )
569+ handler .setFormatter (formatter )
570+ result = _format_and_parse_message (record , handler )
571+ self .assertEqual (result , "name: logname :: message: argument: test" )
572+
573+ def test_dict (self ):
574+ """
575+ dict messages should be unchanged
576+ """
577+ from google .cloud .logging_v2 .handlers .handlers import _format_and_parse_message
578+
579+ message = {"a" : "b" }
580+ record = logging .LogRecord ("logname" , None , None , None , message , None , None )
581+ handler = logging .StreamHandler ()
582+ formatter = logging .Formatter ("name: %(name)s" )
583+ handler .setFormatter (formatter )
584+ result = _format_and_parse_message (record , handler )
585+ self .assertEqual (result , message )
586+
587+ def test_string_encoded_dict (self ):
588+ """
589+ dicts should be extracted from string messages
590+ """
591+ from google .cloud .logging_v2 .handlers .handlers import _format_and_parse_message
592+
593+ message = '{ "x": { "y" : "z" } }'
594+ record = logging .LogRecord ("logname" , None , None , None , message , None , None )
595+ handler = logging .StreamHandler ()
596+ result = _format_and_parse_message (record , handler )
597+ self .assertEqual (result , {"x" : {"y" : "z" }})
598+
599+ def test_broken_encoded_dict (self ):
600+ """
601+ unparseable encoded dicts should be kept as strings
602+ """
603+ from google .cloud .logging_v2 .handlers .handlers import _format_and_parse_message
604+
605+ message = '{ "x": { "y" : '
606+ record = logging .LogRecord ("logname" , None , None , None , message , None , None )
607+ handler = logging .StreamHandler ()
608+ result = _format_and_parse_message (record , handler )
609+ self .assertEqual (result , message )
610+
611+
428612class TestSetupLogging (unittest .TestCase ):
429613 def _call_fut (self , handler , excludes = None ):
430614 from google .cloud .logging .handlers import setup_logging
0 commit comments