View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements. See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache license, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License. You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the license for the specific language governing permissions and
    15   * limitations under the license.
    16   */
    17  package org.apache.logging.log4j.core.layout;
    18
    19  import java.nio.charset.Charset;
    20  import java.util.HashMap;
    21  import java.util.Map;
    22
    23  import org.apache.logging.log4j.core.Layout;
    24  import org.apache.logging.log4j.core.config.Node;
    25  import org.apache.logging.log4j.core.config.plugins.Plugin;
    26  import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
    27  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
    28  import org.apache.logging.log4j.core.util.Constants;
    29
    30  /**
    31   * Appends a series of JSON events as strings serialized as bytes.
    32   *
    33   * <h3>Complete well-formed JSON vs. fragment JSON</h3>
    34   * <p>
    35   * If you configure {@code complete="true"}, the appender outputs a well-formed JSON document. By default, with {@code complete="false"},
    36   * you should include the output as an <em>external file</em> in a separate file to form a well-formed JSON document.
    37   * </p>
    38   * <p>
    39   * A well-formed JSON event follows this pattern:
    40   * </p>
    41   *
    42   * <pre>
    43   * {
    44    "timeMillis": 1,
    45    "thread": "MyThreadName",
    46    "level": "DEBUG",
    47    "loggerName": "a.B",
    48    "marker": {
    49      "name": "Marker1",
    50      "parents": [{
    51        "name": "ParentMarker1",
    52        "parents": [{
    53          "name": "GrandMotherMarker"
    54        }, {
    55          "name": "GrandFatherMarker"
    56        }]
    57      }, {
    58        "name": "GrandFatherMarker"
    59      }]
    60    },
    61    "message": "Msg",
    62    "thrown": {
    63      "cause": {
    64        "commonElementCount": 27,
    65        "extendedStackTrace": [{
    66          "class": "org.apache.logging.log4j.core.layout.LogEventFixtures",
    67          "method": "createLogEvent",
    68          "file": "LogEventFixtures.java",
    69          "line": 53,
    70          "exact": false,
    71          "location": "test-classes/",
    72          "version": "?"
    73        }],
    74        "localizedMessage": "testNPEx",
    75        "message": "testNPEx",
    76        "name": "java.lang.NullPointerException"
    77      },
    78      "commonElementCount": 0,
    79      "extendedStackTrace": [{
    80        "class": "org.apache.logging.log4j.core.layout.LogEventFixtures",
    81        "method": "createLogEvent",
    82        "file": "LogEventFixtures.java",
    83        "line": 56,
    84        "exact": true,
    85        "location": "test-classes/",
    86        "version": "?"
    87      }, {
    88        "class": "org.apache.logging.log4j.core.layout.JsonLayoutTest",
    89        "method": "testAllFeatures",
    90        "file": "JsonLayoutTest.java",
    91        "line": 105,
    92        "exact": true,
    93        "location": "test-classes/",
    94        "version": "?"
    95      }, {
    96        "class": "org.apache.logging.log4j.core.layout.JsonLayoutTest",
    97        "method": "testLocationOnCompactOnMdcOn",
    98        "file": "JsonLayoutTest.java",
    99        "line": 268,
    100       "exact": true,
    101       "location": "test-classes/",
    102       "version": "?"
    103     }, {
    104       "class": "sun.reflect.NativeMethodAccessorImpl",
    105       "method": "invoke",
    106       "line": -1,
    107       "exact": false,
    108       "location": "?",
    109       "version": "1.7.0_55"
    110     }, {
    111       "class": "sun.reflect.NativeMethodAccessorImpl",
    112       "method": "invoke",
    113       "line": -1,
    114       "exact": false,
    115       "location": "?",
    116       "version": "1.7.0_55"
    117     }, {
    118       "class": "sun.reflect.DelegatingMethodAccessorImpl",
    119       "method": "invoke",
    120       "line": -1,
    121       "exact": false,
    122       "location": "?",
    123       "version": "1.7.0_55"
    124     }, {
    125       "class": "java.lang.reflect.Method",
    126       "method": "invoke",
    127       "line": -1,
    128       "exact": false,
    129       "location": "?",
    130       "version": "1.7.0_55"
    131     }, {
    132       "class": "org.junit.runners.model.FrameworkMethod$1",
    133       "method": "runReflectiveCall",
    134       "file": "FrameworkMethod.java",
    135       "line": 47,
    136       "exact": true,
    137       "location": "junit-4.11.jar",
    138       "version": "?"
    139     }, {
    140       "class": "org.junit.internal.runners.model.ReflectiveCallable",
    141       "method": "run",
    142       "file": "ReflectiveCallable.java",
    143       "line": 12,
    144       "exact": true,
    145       "location": "junit-4.11.jar",
    146       "version": "?"
    147     }, {
    148       "class": "org.junit.runners.model.FrameworkMethod",
    149       "method": "invokeExplosively",
    150       "file": "FrameworkMethod.java",
    151       "line": 44,
    152       "exact": true,
    153       "location": "junit-4.11.jar",
    154       "version": "?"
    155     }, {
    156       "class": "org.junit.internal.runners.statements.InvokeMethod",
    157       "method": "evaluate",
    158       "file": "InvokeMethod.java",
    159       "line": 17,
    160       "exact": true,
    161       "location": "junit-4.11.jar",
    162       "version": "?"
    163     }, {
    164       "class": "org.junit.runners.ParentRunner",
    165       "method": "runLeaf",
    166       "file": "ParentRunner.java",
    167       "line": 271,
    168       "exact": true,
    169       "location": "junit-4.11.jar",
    170       "version": "?"
    171     }, {
    172       "class": "org.junit.runners.BlockJUnit4ClassRunner",
    173       "method": "runChild",
    174       "file": "BlockJUnit4ClassRunner.java",
    175       "line": 70,
    176       "exact": true,
    177       "location": "junit-4.11.jar",
    178       "version": "?"
    179     }, {
    180       "class": "org.junit.runners.BlockJUnit4ClassRunner",
    181       "method": "runChild",
    182       "file": "BlockJUnit4ClassRunner.java",
    183       "line": 50,
    184       "exact": true,
    185       "location": "junit-4.11.jar",
    186       "version": "?"
    187     }, {
    188       "class": "org.junit.runners.ParentRunner$3",
    189       "method": "run",
    190       "file": "ParentRunner.java",
    191       "line": 238,
    192       "exact": true,
    193       "location": "junit-4.11.jar",
    194       "version": "?"
    195     }, {
    196       "class": "org.junit.runners.ParentRunner$1",
    197       "method": "schedule",
    198       "file": "ParentRunner.java",
    199       "line": 63,
    200       "exact": true,
    201       "location": "junit-4.11.jar",
    202       "version": "?"
    203     }, {
    204       "class": "org.junit.runners.ParentRunner",
    205       "method": "runChildren",
    206       "file": "ParentRunner.java",
    207       "line": 236,
    208       "exact": true,
    209       "location": "junit-4.11.jar",
    210       "version": "?"
    211     }, {
    212       "class": "org.junit.runners.ParentRunner",
    213       "method": "access$000",
    214       "file": "ParentRunner.java",
    215       "line": 53,
    216       "exact": true,
    217       "location": "junit-4.11.jar",
    218       "version": "?"
    219     }, {
    220       "class": "org.junit.runners.ParentRunner$2",
    221       "method": "evaluate",
    222       "file": "ParentRunner.java",
    223       "line": 229,
    224       "exact": true,
    225       "location": "junit-4.11.jar",
    226       "version": "?"
    227     }, {
    228       "class": "org.junit.internal.runners.statements.RunBefores",
    229       "method": "evaluate",
    230       "file": "RunBefores.java",
    231       "line": 26,
    232       "exact": true,
    233       "location": "junit-4.11.jar",
    234       "version": "?"
    235     }, {
    236       "class": "org.junit.internal.runners.statements.RunAfters",
    237       "method": "evaluate",
    238       "file": "RunAfters.java",
    239       "line": 27,
    240       "exact": true,
    241       "location": "junit-4.11.jar",
    242       "version": "?"
    243     }, {
    244       "class": "org.junit.runners.ParentRunner",
    245       "method": "run",
    246       "file": "ParentRunner.java",
    247       "line": 309,
    248       "exact": true,
    249       "location": "junit-4.11.jar",
    250       "version": "?"
    251     }, {
    252       "class": "org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference",
    253       "method": "run",
    254       "file": "JUnit4TestReference.java",
    255       "line": 50,
    256       "exact": true,
    257       "location": ".cp/",
    258       "version": "?"
    259     }, {
    260       "class": "org.eclipse.jdt.internal.junit.runner.TestExecution",
    261       "method": "run",
    262       "file": "TestExecution.java",
    263       "line": 38,
    264       "exact": true,
    265       "location": ".cp/",
    266       "version": "?"
    267     }, {
    268       "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    269       "method": "runTests",
    270       "file": "RemoteTestRunner.java",
    271       "line": 467,
    272       "exact": true,
    273       "location": ".cp/",
    274       "version": "?"
    275     }, {
    276       "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    277       "method": "runTests",
    278       "file": "RemoteTestRunner.java",
    279       "line": 683,
    280       "exact": true,
    281       "location": ".cp/",
    282       "version": "?"
    283     }, {
    284       "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    285       "method": "run",
    286       "file": "RemoteTestRunner.java",
    287       "line": 390,
    288       "exact": true,
    289       "location": ".cp/",
    290       "version": "?"
    291     }, {
    292       "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    293       "method": "main",
    294       "file": "RemoteTestRunner.java",
    295       "line": 197,
    296       "exact": true,
    297       "location": ".cp/",
    298       "version": "?"
    299     }],
    300     "localizedMessage": "testIOEx",
    301     "message": "testIOEx",
    302     "name": "java.io.IOException",
    303     "suppressed": [{
    304       "commonElementCount": 0,
    305       "extendedStackTrace": [{
    306         "class": "org.apache.logging.log4j.core.layout.LogEventFixtures",
    307         "method": "createLogEvent",
    308         "file": "LogEventFixtures.java",
    309         "line": 57,
    310         "exact": true,
    311         "location": "test-classes/",
    312         "version": "?"
    313       }, {
    314         "class": "org.apache.logging.log4j.core.layout.JsonLayoutTest",
    315         "method": "testAllFeatures",
    316         "file": "JsonLayoutTest.java",
    317         "line": 105,
    318         "exact": true,
    319         "location": "test-classes/",
    320         "version": "?"
    321       }, {
    322         "class": "org.apache.logging.log4j.core.layout.JsonLayoutTest",
    323         "method": "testLocationOnCompactOnMdcOn",
    324         "file": "JsonLayoutTest.java",
    325         "line": 268,
    326         "exact": true,
    327         "location": "test-classes/",
    328         "version": "?"
    329       }, {
    330         "class": "sun.reflect.NativeMethodAccessorImpl",
    331         "method": "invoke",
    332         "line": -1,
    333         "exact": false,
    334         "location": "?",
    335         "version": "1.7.0_55"
    336       }, {
    337         "class": "sun.reflect.NativeMethodAccessorImpl",
    338         "method": "invoke",
    339         "line": -1,
    340         "exact": false,
    341         "location": "?",
    342         "version": "1.7.0_55"
    343       }, {
    344         "class": "sun.reflect.DelegatingMethodAccessorImpl",
    345         "method": "invoke",
    346         "line": -1,
    347         "exact": false,
    348         "location": "?",
    349         "version": "1.7.0_55"
    350       }, {
    351         "class": "java.lang.reflect.Method",
    352         "method": "invoke",
    353         "line": -1,
    354         "exact": false,
    355         "location": "?",
    356         "version": "1.7.0_55"
    357       }, {
    358         "class": "org.junit.runners.model.FrameworkMethod$1",
    359         "method": "runReflectiveCall",
    360         "file": "FrameworkMethod.java",
    361         "line": 47,
    362         "exact": true,
    363         "location": "junit-4.11.jar",
    364         "version": "?"
    365       }, {
    366         "class": "org.junit.internal.runners.model.ReflectiveCallable",
    367         "method": "run",
    368         "file": "ReflectiveCallable.java",
    369         "line": 12,
    370         "exact": true,
    371         "location": "junit-4.11.jar",
    372         "version": "?"
    373       }, {
    374         "class": "org.junit.runners.model.FrameworkMethod",
    375         "method": "invokeExplosively",
    376         "file": "FrameworkMethod.java",
    377         "line": 44,
    378         "exact": true,
    379         "location": "junit-4.11.jar",
    380         "version": "?"
    381       }, {
    382         "class": "org.junit.internal.runners.statements.InvokeMethod",
    383         "method": "evaluate",
    384         "file": "InvokeMethod.java",
    385         "line": 17,
    386         "exact": true,
    387         "location": "junit-4.11.jar",
    388         "version": "?"
    389       }, {
    390         "class": "org.junit.runners.ParentRunner",
    391         "method": "runLeaf",
    392         "file": "ParentRunner.java",
    393         "line": 271,
    394         "exact": true,
    395         "location": "junit-4.11.jar",
    396         "version": "?"
    397       }, {
    398         "class": "org.junit.runners.BlockJUnit4ClassRunner",
    399         "method": "runChild",
    400         "file": "BlockJUnit4ClassRunner.java",
    401         "line": 70,
    402         "exact": true,
    403         "location": "junit-4.11.jar",
    404         "version": "?"
    405       }, {
    406         "class": "org.junit.runners.BlockJUnit4ClassRunner",
    407         "method": "runChild",
    408         "file": "BlockJUnit4ClassRunner.java",
    409         "line": 50,
    410         "exact": true,
    411         "location": "junit-4.11.jar",
    412         "version": "?"
    413       }, {
    414         "class": "org.junit.runners.ParentRunner$3",
    415         "method": "run",
    416         "file": "ParentRunner.java",
    417         "line": 238,
    418         "exact": true,
    419         "location": "junit-4.11.jar",
    420         "version": "?"
    421       }, {
    422         "class": "org.junit.runners.ParentRunner$1",
    423         "method": "schedule",
    424         "file": "ParentRunner.java",
    425         "line": 63,
    426         "exact": true,
    427         "location": "junit-4.11.jar",
    428         "version": "?"
    429       }, {
    430         "class": "org.junit.runners.ParentRunner",
    431         "method": "runChildren",
    432         "file": "ParentRunner.java",
    433         "line": 236,
    434         "exact": true,
    435         "location": "junit-4.11.jar",
    436         "version": "?"
    437       }, {
    438         "class": "org.junit.runners.ParentRunner",
    439         "method": "access$000",
    440         "file": "ParentRunner.java",
    441         "line": 53,
    442         "exact": true,
    443         "location": "junit-4.11.jar",
    444         "version": "?"
    445       }, {
    446         "class": "org.junit.runners.ParentRunner$2",
    447         "method": "evaluate",
    448         "file": "ParentRunner.java",
    449         "line": 229,
    450         "exact": true,
    451         "location": "junit-4.11.jar",
    452         "version": "?"
    453       }, {
    454         "class": "org.junit.internal.runners.statements.RunBefores",
    455         "method": "evaluate",
    456         "file": "RunBefores.java",
    457         "line": 26,
    458         "exact": true,
    459         "location": "junit-4.11.jar",
    460         "version": "?"
    461       }, {
    462         "class": "org.junit.internal.runners.statements.RunAfters",
    463         "method": "evaluate",
    464         "file": "RunAfters.java",
    465         "line": 27,
    466         "exact": true,
    467         "location": "junit-4.11.jar",
    468         "version": "?"
    469       }, {
    470         "class": "org.junit.runners.ParentRunner",
    471         "method": "run",
    472         "file": "ParentRunner.java",
    473         "line": 309,
    474         "exact": true,
    475         "location": "junit-4.11.jar",
    476         "version": "?"
    477       }, {
    478         "class": "org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference",
    479         "method": "run",
    480         "file": "JUnit4TestReference.java",
    481         "line": 50,
    482         "exact": true,
    483         "location": ".cp/",
    484         "version": "?"
    485       }, {
    486         "class": "org.eclipse.jdt.internal.junit.runner.TestExecution",
    487         "method": "run",
    488         "file": "TestExecution.java",
    489         "line": 38,
    490         "exact": true,
    491         "location": ".cp/",
    492         "version": "?"
    493       }, {
    494         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    495         "method": "runTests",
    496         "file": "RemoteTestRunner.java",
    497         "line": 467,
    498         "exact": true,
    499         "location": ".cp/",
    500         "version": "?"
    501       }, {
    502         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    503         "method": "runTests",
    504         "file": "RemoteTestRunner.java",
    505         "line": 683,
    506         "exact": true,
    507         "location": ".cp/",
    508         "version": "?"
    509       }, {
    510         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    511         "method": "run",
    512         "file": "RemoteTestRunner.java",
    513         "line": 390,
    514         "exact": true,
    515         "location": ".cp/",
    516         "version": "?"
    517       }, {
    518         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    519         "method": "main",
    520         "file": "RemoteTestRunner.java",
    521         "line": 197,
    522         "exact": true,
    523         "location": ".cp/",
    524         "version": "?"
    525       }],
    526       "localizedMessage": "I am suppressed exception 1",
    527       "message": "I am suppressed exception 1",
    528       "name": "java.lang.IndexOutOfBoundsException"
    529     }, {
    530       "commonElementCount": 0,
    531       "extendedStackTrace": [{
    532         "class": "org.apache.logging.log4j.core.layout.LogEventFixtures",
    533         "method": "createLogEvent",
    534         "file": "LogEventFixtures.java",
    535         "line": 58,
    536         "exact": true,
    537         "location": "test-classes/",
    538         "version": "?"
    539       }, {
    540         "class": "org.apache.logging.log4j.core.layout.JsonLayoutTest",
    541         "method": "testAllFeatures",
    542         "file": "JsonLayoutTest.java",
    543         "line": 105,
    544         "exact": true,
    545         "location": "test-classes/",
    546         "version": "?"
    547       }, {
    548         "class": "org.apache.logging.log4j.core.layout.JsonLayoutTest",
    549         "method": "testLocationOnCompactOnMdcOn",
    550         "file": "JsonLayoutTest.java",
    551         "line": 268,
    552         "exact": true,
    553         "location": "test-classes/",
    554         "version": "?"
    555       }, {
    556         "class": "sun.reflect.NativeMethodAccessorImpl",
    557         "method": "invoke",
    558         "line": -1,
    559         "exact": false,
    560         "location": "?",
    561         "version": "1.7.0_55"
    562       }, {
    563         "class": "sun.reflect.NativeMethodAccessorImpl",
    564         "method": "invoke",
    565         "line": -1,
    566         "exact": false,
    567         "location": "?",
    568         "version": "1.7.0_55"
    569       }, {
    570         "class": "sun.reflect.DelegatingMethodAccessorImpl",
    571         "method": "invoke",
    572         "line": -1,
    573         "exact": false,
    574         "location": "?",
    575         "version": "1.7.0_55"
    576       }, {
    577         "class": "java.lang.reflect.Method",
    578         "method": "invoke",
    579         "line": -1,
    580         "exact": false,
    581         "location": "?",
    582         "version": "1.7.0_55"
    583       }, {
    584         "class": "org.junit.runners.model.FrameworkMethod$1",
    585         "method": "runReflectiveCall",
    586         "file": "FrameworkMethod.java",
    587         "line": 47,
    588         "exact": true,
    589         "location": "junit-4.11.jar",
    590         "version": "?"
    591       }, {
    592         "class": "org.junit.internal.runners.model.ReflectiveCallable",
    593         "method": "run",
    594         "file": "ReflectiveCallable.java",
    595         "line": 12,
    596         "exact": true,
    597         "location": "junit-4.11.jar",
    598         "version": "?"
    599       }, {
    600         "class": "org.junit.runners.model.FrameworkMethod",
    601         "method": "invokeExplosively",
    602         "file": "FrameworkMethod.java",
    603         "line": 44,
    604         "exact": true,
    605         "location": "junit-4.11.jar",
    606         "version": "?"
    607       }, {
    608         "class": "org.junit.internal.runners.statements.InvokeMethod",
    609         "method": "evaluate",
    610         "file": "InvokeMethod.java",
    611         "line": 17,
    612         "exact": true,
    613         "location": "junit-4.11.jar",
    614         "version": "?"
    615       }, {
    616         "class": "org.junit.runners.ParentRunner",
    617         "method": "runLeaf",
    618         "file": "ParentRunner.java",
    619         "line": 271,
    620         "exact": true,
    621         "location": "junit-4.11.jar",
    622         "version": "?"
    623       }, {
    624         "class": "org.junit.runners.BlockJUnit4ClassRunner",
    625         "method": "runChild",
    626         "file": "BlockJUnit4ClassRunner.java",
    627         "line": 70,
    628         "exact": true,
    629         "location": "junit-4.11.jar",
    630         "version": "?"
    631       }, {
    632         "class": "org.junit.runners.BlockJUnit4ClassRunner",
    633         "method": "runChild",
    634         "file": "BlockJUnit4ClassRunner.java",
    635         "line": 50,
    636         "exact": true,
    637         "location": "junit-4.11.jar",
    638         "version": "?"
    639       }, {
    640         "class": "org.junit.runners.ParentRunner$3",
    641         "method": "run",
    642         "file": "ParentRunner.java",
    643         "line": 238,
    644         "exact": true,
    645         "location": "junit-4.11.jar",
    646         "version": "?"
    647       }, {
    648         "class": "org.junit.runners.ParentRunner$1",
    649         "method": "schedule",
    650         "file": "ParentRunner.java",
    651         "line": 63,
    652         "exact": true,
    653         "location": "junit-4.11.jar",
    654         "version": "?"
    655       }, {
    656         "class": "org.junit.runners.ParentRunner",
    657         "method": "runChildren",
    658         "file": "ParentRunner.java",
    659         "line": 236,
    660         "exact": true,
    661         "location": "junit-4.11.jar",
    662         "version": "?"
    663       }, {
    664         "class": "org.junit.runners.ParentRunner",
    665         "method": "access$000",
    666         "file": "ParentRunner.java",
    667         "line": 53,
    668         "exact": true,
    669         "location": "junit-4.11.jar",
    670         "version": "?"
    671       }, {
    672         "class": "org.junit.runners.ParentRunner$2",
    673         "method": "evaluate",
    674         "file": "ParentRunner.java",
    675         "line": 229,
    676         "exact": true,
    677         "location": "junit-4.11.jar",
    678         "version": "?"
    679       }, {
    680         "class": "org.junit.internal.runners.statements.RunBefores",
    681         "method": "evaluate",
    682         "file": "RunBefores.java",
    683         "line": 26,
    684         "exact": true,
    685         "location": "junit-4.11.jar",
    686         "version": "?"
    687       }, {
    688         "class": "org.junit.internal.runners.statements.RunAfters",
    689         "method": "evaluate",
    690         "file": "RunAfters.java",
    691         "line": 27,
    692         "exact": true,
    693         "location": "junit-4.11.jar",
    694         "version": "?"
    695       }, {
    696         "class": "org.junit.runners.ParentRunner",
    697         "method": "run",
    698         "file": "ParentRunner.java",
    699         "line": 309,
    700         "exact": true,
    701         "location": "junit-4.11.jar",
    702         "version": "?"
    703       }, {
    704         "class": "org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference",
    705         "method": "run",
    706         "file": "JUnit4TestReference.java",
    707         "line": 50,
    708         "exact": true,
    709         "location": ".cp/",
    710         "version": "?"
    711       }, {
    712         "class": "org.eclipse.jdt.internal.junit.runner.TestExecution",
    713         "method": "run",
    714         "file": "TestExecution.java",
    715         "line": 38,
    716         "exact": true,
    717         "location": ".cp/",
    718         "version": "?"
    719       }, {
    720         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    721         "method": "runTests",
    722         "file": "RemoteTestRunner.java",
    723         "line": 467,
    724         "exact": true,
    725         "location": ".cp/",
    726         "version": "?"
    727       }, {
    728         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    729         "method": "runTests",
    730         "file": "RemoteTestRunner.java",
    731         "line": 683,
    732         "exact": true,
    733         "location": ".cp/",
    734         "version": "?"
    735       }, {
    736         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    737         "method": "run",
    738         "file": "RemoteTestRunner.java",
    739         "line": 390,
    740         "exact": true,
    741         "location": ".cp/",
    742         "version": "?"
    743       }, {
    744         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    745         "method": "main",
    746         "file": "RemoteTestRunner.java",
    747         "line": 197,
    748         "exact": true,
    749         "location": ".cp/",
    750         "version": "?"
    751       }],
    752       "localizedMessage": "I am suppressed exception 2",
    753       "message": "I am suppressed exception 2",
    754       "name": "java.lang.IndexOutOfBoundsException"
    755     }]
    756   },
    757   "loggerFQCN": "f.q.c.n",
    758   "endOfBatch": false,
    759   "contextMap": [{
    760     "key": "MDC.B",
    761     "value": "B_Value"
    762   }, {
    763     "key": "MDC.A",
    764     "value": "A_Value"
    765   }],
    766   "contextStack": ["stack_msg1", "stack_msg2"],
    767   "source": {
    768     "class": "org.apache.logging.log4j.core.layout.LogEventFixtures",
    769     "method": "createLogEvent",
    770     "file": "LogEventFixtures.java",
    771     "line": 54
    772   }
    773 }
    774  * </pre>
    775  * <p>
    776  * If {@code complete="false"}, the appender does not write the JSON open array character "[" at the start of the document. and "]" and the
    777  * end.
    778  * </p>
    779  * <p>
    780  * This approach enforces the independence of the JsonLayout and the appender where you embed it.
    781  * </p>
    782  * <h3>Encoding</h3>
    783  * <p>
    784  * Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise events containing non
    785  * ASCII characters could result in corrupted log files.
    786  * </p>
    787  * <h3>Pretty vs. compact XML</h3>
    788  * <p>
    789  * By default, the JSON layout is not compact (a.k.a. not "pretty") with {@code compact="false"}, which means the appender uses end-of-line
    790  * characters and indents lines to format the text. If {@code compact="true"}, then no end-of-line or indentation is used. Message content
    791  * may contain, of course, escaped end-of-lines.
    792  * </p>
    793  */
    794 @Plugin(name = "JsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
    795 public final class JsonLayout extends AbstractJacksonLayout {
    796
    797     static final String CONTENT_TYPE = "application/json";
    798
    799     private static final long serialVersionUID = 1L;
    800
    801     protected JsonLayout(final boolean locationInfo, final boolean properties, final boolean complete, final boolean compact,
    802             boolean eventEol, final Charset charset) {
    803         super(new JacksonFactory.JSON().newWriter(locationInfo, properties, compact), charset, compact, complete, eventEol);
    804     }
    805
    806     /**
    807      * Returns appropriate JSON header.
    808      *
    809      * @return a byte array containing the header, opening the JSON array.
    810      */
    811     @Override
    812     public byte[] getHeader() {
    813         if (!this.complete) {
    814             return null;
    815         }
    816         final StringBuilder buf = new StringBuilder();
    817         buf.append('[');
    818         buf.append(this.eol);
    819         return getBytes(buf.toString());
    820     }
    821
    822     /**
    823      * Returns appropriate JSON footer.
    824      *
    825      * @return a byte array containing the footer, closing the JSON array.
    826      */
    827     @Override
    828     public byte[] getFooter() {
    829         if (!this.complete) {
    830             return null;
    831         }
    832         return getBytes(this.eol + ']' + this.eol);
    833     }
    834
    835     @Override
    836     public Map<String, String> getContentFormat() {
    837         final Map<String, String> result = new HashMap<String, String>();
    838         result.put("version", "2.0");
    839         return result;
    840     }
    841
    842     @Override
    843     /**
    844      * @return The content type.
    845      */
    846     public String getContentType() {
    847         return CONTENT_TYPE + "; charset=" + this.getCharset();
    848     }
    849
    850     /**
    851      * Creates a JSON Layout.
    852      *
    853      * @param locationInfo
    854      *        If "true", includes the location information in the generated JSON.
    855      * @param properties
    856      *        If "true", includes the thread context in the generated JSON.
    857      * @param complete
    858      *        If "true", includes the JSON header and footer, defaults to "false".
    859      * @param compact
    860      *        If "true", does not use end-of-lines and indentation, defaults to "false".
    861      * @param eventEol
    862      *        If "true", forces an EOL after each log event (even if compact is "true"), defaults to "false". This
    863      *        allows one even per line, even in compact mode.
    864      * @param charset
    865      *        The character set to use, if {@code null}, uses "UTF-8".
    866      * @return A JSON Layout.
    867      */
    868     @PluginFactory
    869     public static AbstractJacksonLayout createLayout(
    870             // @formatter:off
    871             @PluginAttribute(value = "locationInfo", defaultBoolean = false) final boolean locationInfo,
    872             @PluginAttribute(value = "properties", defaultBoolean = false) final boolean properties,
    873             @PluginAttribute(value = "complete", defaultBoolean = false) final boolean complete,
    874             @PluginAttribute(value = "compact", defaultBoolean = false) final boolean compact,
    875             @PluginAttribute(value = "eventEol", defaultBoolean = false) final boolean eventEol,
    876             @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset
    877             // @formatter:on
    878     ) {
    879         return new JsonLayout(locationInfo, properties, complete, compact, eventEol, charset);
    880     }
    881
    882     /**
    883      * Creates a JSON Layout using the default settings.
    884      *
    885      * @return A JSON Layout.
    886      */
    887     public static AbstractJacksonLayout createDefaultLayout() {
    888         return new JsonLayout(false, false, false, false, false, Constants.UTF_8);
    889     }
    890 }