This file is indexed.

/usr/share/perl5/Log/Log4perl/FAQ.pm is in liblog-log4perl-perl 1.41-1.1ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
1;

__END__

=head1 NAME

Log::Log4perl::FAQ - Frequently Asked Questions on Log::Log4perl

=head1 DESCRIPTION

This FAQ shows a wide variety of 
commonly encountered logging tasks and how to solve them 
in the most elegant way with Log::Log4perl. Most of the time, this will
be just a matter of smartly configuring your Log::Log4perl configuration files.

=head2 Why use Log::Log4perl instead of any other logging module on CPAN?

That's a good question. There's dozens of logging modules on CPAN.
When it comes to logging, people typically think: "Aha. Writing out
debug and error messages. Debug is lower than error. Easy. I'm gonna
write my own." Writing a logging module is like a rite of passage for
every Perl programmer, just like writing your own templating system.

Of course, after getting the basics right, features need to
be added. You'd like to write a timestamp with every message. Then
timestamps with microseconds. Then messages need to be written to both
the screen and a log file.

And, as your application grows in size you might wonder: Why doesn't
my logging system scale along with it? You would like to switch on
logging in selected parts of the application, and not all across the
board, because this kills performance. This is when people turn to
Log::Log4perl, because it handles all of that.

Avoid this costly switch. 

Use C<Log::Log4perl> right from the start. C<Log::Log4perl>'s C<:easy>
mode supports easy logging in simple scripts:

    use Log::Log4perl qw(:easy);
    Log::Log4perl->easy_init($DEBUG);

    DEBUG "A low-level message";
    ERROR "Won't make it until level gets increased to ERROR";

And when your application inevitably grows, your logging system grows
with it without you having to change any code.

Please, don't re-invent logging. C<Log::Log4perl> is here, it's easy
to use, it scales, and covers many areas you haven't thought of yet,
but will enter soon.

=head2 What's the easiest way to use Log4perl?

If you just want to get all the comfort of logging, without much
overhead, use I<Stealth Loggers>. If you use Log::Log4perl in 
C<:easy> mode like

    use Log::Log4perl qw(:easy);

you'll have the following functions available in the current package:

    DEBUG("message");
    INFO("message");
    WARN("message");
    ERROR("message");
    FATAL("message");

Just make sure that every package of your code where you're using them in
pulls in C<use Log::Log4perl qw(:easy)> first, then you're set.
Every stealth logger's category will be equivalent to the name of the
package it's located in.

These stealth loggers
will be absolutely silent until you initialize Log::Log4perl in 
your main program with either 

        # Define any Log4perl behavior
    Log::Log4perl->init("foo.conf");

(using a full-blown Log4perl config file) or the super-easy method

        # Just log to STDERR
    Log::Log4perl->easy_init($DEBUG);

or the parameter-style method with a complexity somewhat in between:

        # Append to a log file
    Log::Log4perl->easy_init( { level   => $DEBUG,
                                file    => ">>test.log" } );

For more info, please check out L<Log::Log4perl/"Stealth Loggers">.

=head2 How can I simply log all my ERROR messages to a file?

After pulling in the C<Log::Log4perl> module, just initialize its
behavior by passing in a configuration to its C<init> method as a string
reference. Then, obtain a logger instance and write out a message
with its C<error()> method:

    use Log::Log4perl qw(get_logger);

        # Define configuration
    my $conf = q(
        log4perl.logger                    = ERROR, FileApp
        log4perl.appender.FileApp          = Log::Log4perl::Appender::File
        log4perl.appender.FileApp.filename = test.log
        log4perl.appender.FileApp.layout   = PatternLayout
        log4perl.appender.FileApp.layout.ConversionPattern = %d> %m%n
    );

        # Initialize logging behavior
    Log::Log4perl->init( \$conf );

        # Obtain a logger instance
    my $logger = get_logger("Bar::Twix");
    $logger->error("Oh my, a dreadful error!");
    $logger->warn("Oh my, a dreadful warning!");

This will append something like

    2002/10/29 20:11:55> Oh my, a dreadful error!

to the log file C<test.log>. How does this all work? 

While the Log::Log4perl C<init()> method typically 
takes the name of a configuration file as its input parameter like
in

    Log::Log4perl->init( "/path/mylog.conf" );

the example above shows how to pass in a configuration as text in a 
scalar reference.

The configuration as shown
defines a logger of the root category, which has an appender of type 
C<Log::Log4perl::Appender::File> attached. The line

    log4perl.logger = ERROR, FileApp

doesn't list a category, defining a root logger. Compare that with

    log4perl.logger.Bar.Twix = ERROR, FileApp

which would define a logger for the category C<Bar::Twix>,
showing probably different behavior. C<FileApp> on
the right side of the assignment is
an arbitrarily defined variable name, which is only used to somehow 
reference an appender defined later on.

Appender settings in the configuration are defined as follows:

    log4perl.appender.FileApp          = Log::Log4perl::Appender::File
    log4perl.appender.FileApp.filename = test.log

It selects the file appender of the C<Log::Log4perl::Appender>
hierarchy, which will append to the file C<test.log> if it already
exists. If we wanted to overwrite a potentially existing file, we would
have to explicitly set the appropriate C<Log::Log4perl::Appender::File>
parameter C<mode>:

    log4perl.appender.FileApp          = Log::Log4perl::Appender::File
    log4perl.appender.FileApp.filename = test.log
    log4perl.appender.FileApp.mode     = write

Also, the configuration defines a PatternLayout format, adding
the nicely formatted current date and time, an arrow (E<gt>) and
a space before the messages, which is then followed by a newline:

    log4perl.appender.FileApp.layout   = PatternLayout
    log4perl.appender.FileApp.layout.ConversionPattern = %d> %m%n

Obtaining a logger instance and actually logging something is typically
done in a different system part as the Log::Log4perl initialisation section,
but in this example, it's just done right after init for the 
sake of compactness:

        # Obtain a logger instance
    my $logger = get_logger("Bar::Twix");
    $logger->error("Oh my, a dreadful error!");

This retrieves an instance of the logger of the category C<Bar::Twix>, 
which, as all other categories, inherits behavior from the root logger if no
other loggers are defined in the initialization section. 

The C<error()>
method fires up a message, which the root logger catches. Its
priority is equal to
or higher than the root logger's priority (ERROR), which causes the root logger
to forward it to its attached appender. By contrast, the following

    $logger->warn("Oh my, a dreadful warning!");

doesn't make it through, because the root logger sports a higher setting
(ERROR and up) than the WARN priority of the message.

=head2 How can I install Log::Log4perl on Microsoft Windows?

You can install Log::Log4perl using the CPAN client.

Alternatively you can install it using 

    ppm install Log-Log4perl

if you're using ActiveState perl.


That's it! Afterwards, just create a Perl script like

    use Log::Log4perl qw(:easy);
    Log::Log4perl->easy_init($DEBUG);

    my $logger = get_logger("Twix::Bar");
    $logger->debug("Watch me!");

and run it. It should print something like 

    2002/11/06 01:22:05 Watch me!

If you find that something doesn't work, please let us know at
log4perl-devel@lists.sourceforge.net -- we'll appreciate it. Have fun!

=head2 How can I include global (thread-specific) data in my log messages?

Say, you're writing a web application and want all your
log messages to include the current client's IP address. Most certainly,
you don't want to include it in each and every log message like in

    $logger->debug( $r->connection->remote_ip,
                    " Retrieving user data from DB" );

do you? Instead, you want to set it in a global data structure and
have Log::Log4perl include it automatically via a PatternLayout setting
in the configuration file:

    log4perl.appender.FileApp.layout.ConversionPattern = %X{ip} %m%n

The conversion specifier C<%X{ip}> references an entry under the key
C<ip> in the global C<MDC> (mapped diagnostic context) table, which 
you've set once via

    Log::Log4perl::MDC->put("ip", $r->connection->remote_ip);

at the start of the request handler. Note that this is a
I<static> (class) method, there's no logger object involved.
You can use this method with as many key/value pairs as you like as long
as you reference them under different names.

The mappings are stored in a global hash table within Log::Log4perl.
Luckily, because the thread
model in 5.8.0 doesn't share global variables between threads unless
they're explicitly marked as such, there's no problem with multi-threaded
environments.

For more details on the MDC, please refer to 
L<Log::Log4perl/"Mapped Diagnostic Context (MDC)"> and
L<Log::Log4perl::MDC>.

=head2 My application is already logging to a file. How can I duplicate all messages to also go to the screen?

Assuming that you already have a Log4perl configuration file like

    log4perl.logger                    = DEBUG, FileApp

    log4perl.appender.FileApp          = Log::Log4perl::Appender::File
    log4perl.appender.FileApp.filename = test.log
    log4perl.appender.FileApp.layout   = PatternLayout
    log4perl.appender.FileApp.layout.ConversionPattern = %d> %m%n

and log statements all over your code,
it's very easy with Log4perl to have the same messages both printed to
the logfile and the screen. No reason to change your code, of course, 
just add another appender to the configuration file and you're done:

    log4perl.logger                    = DEBUG, FileApp, ScreenApp

    log4perl.appender.FileApp          = Log::Log4perl::Appender::File
    log4perl.appender.FileApp.filename = test.log
    log4perl.appender.FileApp.layout   = PatternLayout
    log4perl.appender.FileApp.layout.ConversionPattern = %d> %m%n

    log4perl.appender.ScreenApp          = Log::Log4perl::Appender::Screen
    log4perl.appender.ScreenApp.stderr   = 0
    log4perl.appender.ScreenApp.layout   = PatternLayout
    log4perl.appender.ScreenApp.layout.ConversionPattern = %d> %m%n

The configuration file above is assuming that both appenders are
active in the same logger hierarchy, in this case the C<root> category.
But even if you've got file loggers defined in several parts of your system,
belonging to different logger categories,
each logging to different files, you can gobble up all logged messages
by defining a root logger with a screen appender, which would duplicate 
messages from all your file loggers to the screen due to Log4perl's 
appender inheritance. Check 

    http://www.perl.com/pub/a/2002/09/11/log4perl.html

for details. Have fun!

=head2 How can I make sure my application logs a message when it dies unexpectedly?

Whenever you encounter a fatal error in your application, instead of saying
something like

    open FILE, "<blah" or die "Can't open blah -- bailing out!";

just use Log::Log4perl's fatal functions instead:

    my $log = get_logger("Some::Package");
    open FILE, "<blah" or $log->logdie("Can't open blah -- bailing out!");

This will both log the message with priority FATAL according to your current
Log::Log4perl configuration and then call Perl's C<die()> 
afterwards to terminate the program. It works the same with 
stealth loggers (see L<Log::Log4perl/"Stealth Loggers">), 
all you need to do is call

    use Log::Log4perl qw(:easy);
    open FILE, "<blah" or LOGDIE "Can't open blah -- bailing out!";

What can you do if you're using some library which doesn't use Log::Log4perl
and calls C<die()> internally if something goes wrong? Use a
C<$SIG{__DIE__}> pseudo signal handler

    use Log::Log4perl qw(get_logger);

    $SIG{__DIE__} = sub {
        if($^S) {
            # We're in an eval {} and don't want log
            # this message but catch it later
            return;
        }
        local $Log::Log4perl::caller_depth =
              $Log::Log4perl::caller_depth + 1;
        my $logger = get_logger("");
        $logger->fatal(@_);
        die @_; # Now terminate really
    };

This will catch every C<die()>-Exception of your
application or the modules it uses. In case you want to 
It
will fetch a root logger and pass on the C<die()>-Message to it.
If you make sure you've configured with a root logger like this:

    Log::Log4perl->init(\q{
        log4perl.category         = FATAL, Logfile
        log4perl.appender.Logfile = Log::Log4perl::Appender::File
        log4perl.appender.Logfile.filename = fatal_errors.log
        log4perl.appender.Logfile.layout = \
                   Log::Log4perl::Layout::PatternLayout
        log4perl.appender.Logfile.layout.ConversionPattern = %F{1}-%L (%M)> %m%n
    });

then all C<die()> messages will be routed to a file properly. The line

     local $Log::Log4perl::caller_depth =
           $Log::Log4perl::caller_depth + 1;

in the pseudo signal handler above merits a more detailed explanation. With
the setup above, if a module calls C<die()> in one of its functions, 
the fatal message will be logged in the signal handler and not in the
original function -- which will cause the %F, %L and %M placeholders
in the pattern layout to be replaced by the filename, the line number
and the function/method name of the signal handler, not the error-throwing
module. To adjust this, Log::Log4perl has the C<$caller_depth> variable, 
which defaults to 0, but can be set to positive integer values
to offset the caller level. Increasing
it by one will cause it to log the calling function's parameters, not
the ones of the signal handler. 
See L<Log::Log4perl/"Using Log::Log4perl from wrapper classes"> for more
details.

=head2 How can I hook up the LWP library with Log::Log4perl?

Or, to put it more generally: How can you utilize a third-party
library's embedded logging and debug statements in Log::Log4perl? 
How can you make them print
to configurable appenders, turn them on and off, just as if they 
were regular Log::Log4perl logging statements?

The easiest solution is to map the third-party library logging statements
to Log::Log4perl's stealth loggers via a typeglob assignment.

As an example, let's take LWP, one of the most popular Perl modules, 
which makes handling WWW requests and responses a breeze.
Internally, LWP uses its own logging and debugging system, 
utilizing the following calls 
inside the LWP code (from the LWP::Debug man page):

        # Function tracing
    LWP::Debug::trace('send()');

        # High-granular state in functions
    LWP::Debug::debug('url ok');

        # Data going over the wire
    LWP::Debug::conns("read $n bytes: $data");

First, let's assign Log::Log4perl priorities 
to these functions: I'd suggest that
C<debug()> messages have priority C<INFO>, 
C<trace()> uses C<DEBUG> and C<conns()> also logs with C<DEBUG> -- 
although your mileage may certainly vary.

Now, in order to transpartently hook up LWP::Debug with Log::Log4perl,
all we have to do is say

    package LWP::Debug;
    use Log::Log4perl qw(:easy);

    *trace = *INFO;
    *conns = *DEBUG;
    *debug = *DEBUG;

    package main;
    # ... go on with your regular program ...

at the beginning of our program. In this way, every time the, say, 
C<LWP::UserAgent> module calls C<LWP::Debug::trace()>, it will implicitely 
call INFO(), which is the C<info()> method of a stealth logger defined for
the Log::Log4perl category C<LWP::Debug>. Is this cool or what?

Here's a complete program:

    use LWP::UserAgent;
    use HTTP::Request::Common;
    use Log::Log4perl qw(:easy);

    Log::Log4perl->easy_init(
        { category => "LWP::Debug",
          level    => $DEBUG,
          layout   => "%r %p %M-%L %m%n",
        });

    package LWP::Debug;
    use Log::Log4perl qw(:easy);
    *trace = *INFO;
    *conns = *DEBUG;
    *debug = *DEBUG;

    package main;
    my $ua = LWP::UserAgent->new();
    my $resp = $ua->request(GET "http://amazon.com");

    if($resp->is_success()) {
        print "Success: Received ", 
              length($resp->content()), "\n";
    } else {
        print "Error: ", $resp->code(), "\n";
    }

This will generate the following output on STDERR:

    174 INFO LWP::UserAgent::new-164 ()
    208 INFO LWP::UserAgent::request-436 ()
    211 INFO LWP::UserAgent::send_request-294 GET http://amazon.com
    212 DEBUG LWP::UserAgent::_need_proxy-1123 Not proxied
    405 INFO LWP::Protocol::http::request-122 ()
    859 DEBUG LWP::Protocol::collect-206 read 233 bytes
    863 DEBUG LWP::UserAgent::request-443 Simple response: Found
    869 INFO LWP::UserAgent::request-436 ()
    871 INFO LWP::UserAgent::send_request-294 
     GET http://www.amazon.com:80/exec/obidos/gateway_redirect
    872 DEBUG LWP::UserAgent::_need_proxy-1123 Not proxied
    873 INFO LWP::Protocol::http::request-122 ()
    1016 DEBUG LWP::UserAgent::request-443 Simple response: Found
    1020 INFO LWP::UserAgent::request-436 ()
    1022 INFO LWP::UserAgent::send_request-294 
     GET http://www.amazon.com/exec/obidos/subst/home/home.html/
    1023 DEBUG LWP::UserAgent::_need_proxy-1123 Not proxied
    1024 INFO LWP::Protocol::http::request-122 ()
    1382 DEBUG LWP::Protocol::collect-206 read 632 bytes
    ...
    2605 DEBUG LWP::Protocol::collect-206 read 77 bytes
    2607 DEBUG LWP::UserAgent::request-443 Simple response: OK
    Success: Received 42584

Of course, in this way, the embedded logging and debug statements within
LWP can be utilized in any Log::Log4perl way you can think of. You can
have them sent to different appenders, block them based on the
category and everything else Log::Log4perl has to offer.

Only drawback of this method: Steering logging behavior via category 
is always based on the C<LWP::Debug> package. Although the logging
statements reflect the package name of the issuing module properly, 
the stealth loggers in C<LWP::Debug> are all of the category C<LWP::Debug>.
This implies that you can't control the logging behavior based on the
package that's I<initiating> a log request (e.g. LWP::UserAgent) but only
based on the package that's actually I<executing> the logging statement, 
C<LWP::Debug> in this case.

To work around this conundrum, we need to write a wrapper function and
plant it into the C<LWP::Debug> package. It will determine the caller and
create a logger bound to a category with the same name as the caller's
package:

    package LWP::Debug;

    use Log::Log4perl qw(:levels get_logger);

    sub l4p_wrapper {
        my($prio, @message) = @_;
        $Log::Log4perl::caller_depth += 2;
        get_logger(scalar caller(1))->log($prio, @message);
        $Log::Log4perl::caller_depth -= 2;
    }

    no warnings 'redefine';
    *trace = sub { l4p_wrapper($INFO, @_); };
    *debug = *conns = sub { l4p_wrapper($DEBUG, @_); };

    package main;
    # ... go on with your main program ...

This is less performant than the previous approach, because every
log request will request a reference to a logger first, then call
the wrapper, which will in turn call the appropriate log function.

This hierarchy shift has to be compensated for by increasing
C<$Log::Log4perl::caller_depth> by 2 before calling the log function
and decreasing it by 2 right afterwards. Also, the C<l4p_wrapper>
function shown above calls C<caller(1)> which determines the name
of the package I<two> levels down the calling hierarchy (and 
therefore compensates for both the wrapper function and the
anonymous subroutine calling it).

C<no warnings 'redefine'> suppresses a warning Perl would generate
otherwise
upon redefining C<LWP::Debug>'s C<trace()>, C<debug()> and C<conns()>
functions. In case you use a perl prior to 5.6.x, you need
to manipulate C<$^W> instead.

To make things easy for you when dealing with LWP, Log::Log4perl 0.47 
introduces C<Log::Log4perl-E<gt>infiltrate_lwp()> which does exactly the
above.

=head2 What if I need dynamic values in a static Log4perl configuration file?

Say, your application uses Log::Log4perl for logging and 
therefore comes with a Log4perl configuration file, specifying the logging
behavior.
But, you also want it to take command line parameters to set values
like the name of the log file.
How can you have
both a static Log4perl configuration file and a dynamic command line
interface?

As of Log::Log4perl 0.28, every value in the configuration file
can be specified as a I<Perl hook>. So, instead of saying

    log4perl.appender.Logfile.filename = test.log

you could just as well have a Perl subroutine deliver the value
dynamically:

    log4perl.appender.Logfile.filename = sub { logfile(); };

given that C<logfile()> is a valid function in your C<main> package
returning a string containing the path to the log file.

Or, think about using the value of an environment variable:

    log4perl.appender.DBI.user = sub { $ENV{USERNAME} };

When C<Log::Log4perl-E<gt>init()> parses the configuration
file, it will notice the assignment above because of its
C<sub {...}> pattern and treat it in a special way:
It will evaluate the subroutine (which can contain
arbitrary Perl code) and take its return value as the right side
of the assignment.

A typical application would be called like this on the command line:

    app                # log file is "test.log"
    app -l mylog.txt   # log file is "mylog.txt"

Here's some sample code implementing the command line interface above:

    use Log::Log4perl qw(get_logger);
    use Getopt::Std;

    getopt('l:', \our %OPTS);

    my $conf = q(
    log4perl.category.Bar.Twix         = WARN, Logfile
    log4perl.appender.Logfile          = Log::Log4perl::Appender::File
    log4perl.appender.Logfile.filename = sub { logfile(); };
    log4perl.appender.Logfile.layout   = SimpleLayout
    );

    Log::Log4perl::init(\$conf);

    my $logger = get_logger("Bar::Twix");
    $logger->error("Blah");

    ###########################################
    sub logfile {
    ###########################################
        if(exists $OPTS{l}) {
            return $OPTS{l};
        } else {
            return "test.log";
        }
    }

Every Perl hook may contain arbitrary perl code,
just make sure to fully qualify eventual variable names
(e.g. C<%main::OPTS> instead of C<%OPTS>).

B<SECURITY NOTE>: this feature means arbitrary perl code
can be embedded in the config file.  In the rare case
where the people who have access to your config file
are different from the people who write your code and
shouldn't have execute rights, you might want to call

    $Log::Log4perl::Config->allow_code(0);

before you call init(). This will prevent Log::Log4perl from
executing I<any> Perl code in the config file (including
code for custom conversion specifiers 
(see L<Log::Log4perl::Layout::PatternLayout/"Custom cspecs">).

=head2 How can I roll over my logfiles automatically at midnight?

Long-running applications tend to produce ever-increasing logfiles.
For backup and cleanup purposes, however, it is often desirable to move
the current logfile to a different location from time to time and
start writing a new one.

This is a non-trivial task, because it has to happen in sync with 
the logging system in order not to lose any messages in the process.

Luckily, I<Mark Pfeiffer>'s C<Log::Dispatch::FileRotate> appender
works well with Log::Log4perl to rotate your logfiles in a variety of ways.

Note, however, that having the application deal with rotating a log
file is not cheap. Among other things, it requires locking the log file 
with every write to avoid race conditions.
There are good reasons to use external rotators like C<newsyslog>
instead.
See the entry C<How can I rotate a logfile with newsyslog?> in the
FAQ for more information on how to configure it.

When using C<Log::Dispatch::FileRotate>, 
all you have to do is specify it in your Log::Log4perl configuration file
and your logfiles will be rotated automatically.

You can choose between rolling based on a maximum size ("roll if greater
than 10 MB") or based on a date pattern ("roll everyday at midnight").
In both cases, C<Log::Dispatch::FileRotate> allows you to define a 
number C<max> of saved files to keep around until it starts overwriting
the oldest ones. If you set the C<max> parameter to 2 and the name of
your logfile is C<test.log>, C<Log::Dispatch::FileRotate> will
move C<test.log> to C<test.log.1> on the first rollover. On the second
rollover, it will move C<test.log.1> to C<test.log.2> and then C<test.log>
to C<test.log.1>. On the third rollover, it will move C<test.log.1> to 
C<test.log.2> (therefore discarding the old C<test.log.2>) and 
C<test.log> to C<test.log.1>. And so forth. This way, there's always 
going to be a maximum of 2 saved log files around.

Here's an example of a Log::Log4perl configuration file, defining a
daily rollover at midnight (date pattern C<yyyy-MM-dd>), keeping
a maximum of 5 saved logfiles around:

    log4perl.category         = WARN, Logfile
    log4perl.appender.Logfile = Log::Dispatch::FileRotate
    log4perl.appender.Logfile.filename    = test.log
    log4perl.appender.Logfile.max         = 5
    log4perl.appender.Logfile.DatePattern = yyyy-MM-dd
    log4perl.appender.Logfile.TZ          = PST
    log4perl.appender.Logfile.layout = \
        Log::Log4perl::Layout::PatternLayout 
    log4perl.appender.Logfile.layout.ConversionPattern = %d %m %n 

Please see the C<Log::Dispatch::FileRotate> documentation for details.
C<Log::Dispatch::FileRotate> is available on CPAN.

=head2 What's the easiest way to turn off all logging, even with a lengthy Log4perl configuration file?

In addition to category-based levels and appender thresholds,
Log::Log4perl supports system-wide logging thresholds. This is the 
minimum level the system will require of any logging events in order for them 
to make it through to any configured appenders.

For example, putting the line

    log4perl.threshold = ERROR

anywhere in your configuration file will limit any output to any appender
to events with priority of ERROR or higher (ERROR or FATAL that is). 

However, in order to suppress all logging entirely, you need to use a
priority that's higher than FATAL: It is simply called C<OFF>, and it is never
used by any logger. By definition, it is higher than the highest 
defined logger level.

Therefore, if you keep the line

    log4perl.threshold = OFF

somewhere in your Log::Log4perl configuration, the system will be quiet
as a graveyard. If you deactivate the line (e.g. by commenting it out), 
the system will, upon config reload, snap back to normal operation, providing 
logging messages according to the rest of the configuration file again.

=head2 I keep getting duplicate log messages! What's wrong?

Having several settings for related categories in the Log4perl 
configuration file sometimes leads to a phenomenon called 
"message duplication". It can be very confusing at first,
but if thought through properly, it turns out that Log4perl behaves
as advertised. But, don't despair, of course there's a number of 
ways to avoid message duplication in your logs.

Here's a sample Log4perl configuration file that produces the
phenomenon:

    log4perl.logger.Cat        = ERROR, Screen
    log4perl.logger.Cat.Subcat = WARN, Screen

    log4perl.appender.Screen   = Log::Log4perl::Appender::Screen
    log4perl.appender.Screen.layout = SimpleLayout

It defines two loggers, one for category C<Cat> and one for
C<Cat::Subcat>, which is obviously a subcategory of C<Cat>.
The parent logger has a priority setting of ERROR, the child
is set to the lower C<WARN> level.

Now imagine the following code in your program:

    my $logger = get_logger("Cat.Subcat");
    $logger->warn("Warning!");

What do you think will happen? An unexperienced Log4perl user
might think: "Well, the message is being sent with level WARN, so the 
C<Cat::Subcat> logger will accept it and forward it to the 
attached C<Screen> appender. Then, the message will percolate up 
the logger hierarchy, find
the C<Cat> logger, which will suppress the message because of its
ERROR setting."
But, perhaps surprisingly, what you'll get with the
code snippet above is not one but two log messages written 
to the screen:

    WARN - Warning!
    WARN - Warning!

What happened? The culprit is that once the logger C<Cat::Subcat> 
decides to fire, it will forward the message I<unconditionally> 
to all directly or indirectly attached appenders. The C<Cat> logger 
will never be asked if it wants the message or not -- the message 
will just be pushed through to the appender attached to C<Cat>.

One way to prevent the message from bubbling up the logger
hierarchy is to set the C<additivity> flag of the subordinate logger to
C<0>:

    log4perl.logger.Cat            = ERROR, Screen
    log4perl.logger.Cat.Subcat     = WARN, Screen
    log4perl.additivity.Cat.Subcat = 0

    log4perl.appender.Screen   = Log::Log4perl::Appender::Screen
    log4perl.appender.Screen.layout = SimpleLayout

The message will now be accepted by the C<Cat::Subcat> logger,
forwarded to its appender, but then C<Cat::Subcat> will suppress
any further action. While this setting avoids duplicate messages
as seen before, it is often not the desired behavior. Messages
percolating up the hierarchy are a useful Log4perl feature.

If you're defining I<different> appenders for the two loggers,
one other option is to define an appender threshold for the
higher-level appender. Typically it is set to be 
equal to the logger's level setting:

    log4perl.logger.Cat           = ERROR, Screen1
    log4perl.logger.Cat.Subcat    = WARN, Screen2

    log4perl.appender.Screen1   = Log::Log4perl::Appender::Screen
    log4perl.appender.Screen1.layout = SimpleLayout
    log4perl.appender.Screen1.Threshold = ERROR

    log4perl.appender.Screen2   = Log::Log4perl::Appender::Screen
    log4perl.appender.Screen2.layout = SimpleLayout

Since the C<Screen1> appender now blocks every message with
a priority less than ERROR, even if the logger in charge
lets it through, the message percolating up the hierarchy is
being blocked at the last minute and I<not> appended to C<Screen1>.

So far, we've been operating well within the boundaries of the 
Log4j standard, which Log4perl adheres to. However, if 
you would really, really like to use a single appender 
and keep the message percolation intact without having to deal
with message duplication, there's a non-standard solution for you:

    log4perl.logger.Cat        = ERROR, Screen
    log4perl.logger.Cat.Subcat = WARN, Screen

    log4perl.appender.Screen   = Log::Log4perl::Appender::Screen
    log4perl.appender.Screen.layout = SimpleLayout

    log4perl.oneMessagePerAppender = 1

The C<oneMessagePerAppender> flag will suppress duplicate messages
to the same appender. Again, that's non-standard. But way cool :).

=head2 How can I configure Log::Log4perl to send me email if something happens?

Some incidents require immediate action. You can't wait until someone
checks the log files, you need to get notified on your pager right away.

The easiest way to do that is by using the C<Log::Dispatch::Email::MailSend>
module as an appender. It comes with the C<Log::Dispatch> bundle and
allows you to specify recipient and subject of outgoing emails in the Log4perl
configuration file:

    log4perl.category = FATAL, Mailer
    log4perl.appender.Mailer         = Log::Dispatch::Email::MailSend
    log4perl.appender.Mailer.to      = drone@pageme.net
    log4perl.appender.Mailer.subject = Something's broken!
    log4perl.appender.Mailer.layout  = SimpleLayout

The message of every log incident this appender gets
will then be forwarded to the given
email address. Check the C<Log::Dispatch::Email::MailSend> documentation
for details. And please make sure there's not a flood of email messages 
sent out by your application, filling up the receipient's inbox.

There's one caveat you need to know about: The C<Log::Dispatch::Email>
hierarchy of appenders turns on I<buffering> by default. This means that
the appender will not send out messages right away but wait until a 
certain threshold has been reached. If you'd rather have your alerts
sent out immeditately, use

    log4perl.appender.Mailer.buffered = 0

to turn buffering off.

=head2 How can I write my own appender?

First off, Log::Log4perl comes with a set of standard appenders. Then,
there's a lot of Log4perl-compatible appenders already
available on CPAN: Just run a search for C<Log::Dispatch> on 
http://search.cpan.org and chances are that what you're looking for 
has already been developed, debugged and been used successfully 
in production -- no need for you to reinvent the wheel.

Also, Log::Log4perl ships with a nifty database appender named
Log::Log4perl::Appender::DBI -- check it out if talking to databases is your
desire.

But if you're up for a truly exotic task, you might have to write
an appender yourself. That's very easy -- it takes no longer
than a couple of minutes.

Say, we wanted to create an appender of the class
C<ColorScreenAppender>, which logs messages
to the screen in a configurable color. Just create a new class 
in C<ColorScreenAppender.pm>:

    package ColorScreenAppender;

Now let's assume that your Log::Log4perl
configuration file C<test.conf> looks like this:

    log4perl.logger = INFO, ColorApp

    log4perl.appender.ColorApp=ColorScreenAppender
    log4perl.appender.ColorApp.color=blue

    log4perl.appender.ColorApp.layout = PatternLayout
    log4perl.appender.ColorApp.layout.ConversionPattern=%d %m %n

This will cause Log::Log4perl on C<init()> to look for a class
ColorScreenAppender and call its constructor new(). Let's add
new() to ColorScreenAppender.pm:

    sub new {
        my($class, %options) = @_;

        my $self = { %options };
        bless $self, $class;

        return $self;
    }

To initialize this appender, Log::Log4perl will call 
and pass all attributes of the appender as defined in the configuration
file to the constructor as name/value pairs (in this case just one):

    ColorScreenAppender->new(color => "blue");

The new() method listed above stores the contents of the
%options hash in the object's
instance data hash (referred to by $self).
That's all for initializing a new appender with Log::Log4perl.

Second, ColorScreenAppender needs to expose a 
C<log()> method, which will be called by Log::Log4perl 
every time it thinks the appender should fire. Along with the
object reference (as usual in Perl's object world), log()
will receive a list of name/value pairs, of which only the one
under the key C<message> shall be of interest for now since it is the
message string to be logged. At this point, Log::Log4perl has already taken
care of joining the message to be a single string.

For our special appender ColorScreenAppender, we're using the
Term::ANSIColor module to colorize the output:

    use Term::ANSIColor;

    sub log {
        my($self, %params) = @_;

        print colored($params{message},
                      $self->{color});
    }

The color (as configured in the Log::Log4perl configuration file) 
is available as $self-E<gt>{color} in the appender object. Don't
forget to return

    1;

at the end of ColorScreenAppender.pm and you're done. Install the new appender
somewhere where perl can find it and try it with a test script like 

    use Log::Log4perl qw(:easy);
    Log::Log4perl->init("test.conf");
    ERROR("blah");

to see the new colored output. Is this cool or what? 

And it gets even better: You can write dynamically generated appender 
classes using the C<Class::Prototyped> module. Here's an example of
an appender prepending every outgoing message with a configurable
number of bullets:

    use Class::Prototyped;

    my $class = Class::Prototyped->newPackage(
      "MyAppenders::Bulletizer",
      bullets => 1,
      log     => sub {
        my($self, %params) = @_;
        print "*" x $self->bullets(),
              $params{message};
      },
    );

    use Log::Log4perl qw(:easy);

    Log::Log4perl->init(\ q{
      log4perl.logger = INFO, Bully
    
      log4perl.appender.Bully=MyAppenders::Bulletizer
      log4perl.appender.Bully.bullets=3
    
      log4perl.appender.Bully.layout = PatternLayout
      log4perl.appender.Bully.layout.ConversionPattern=%m %n
    });

        # ... prints: "***Boo!\n";
    INFO "Boo!";

=head2 How can I drill down on references before logging them?

If you've got a reference to a nested structure or object, then 
you probably don't want to log it as C<HASH(0x81141d4)> but rather
dump it as something like

    $VAR1 = {
              'a' => 'b',
              'd' => 'e'
            };

via a module like Data::Dumper. While it's syntactically correct to say

    $logger->debug(Data::Dumper::Dumper($ref));

this call imposes a huge performance penalty on your application
if the message is suppressed by Log::Log4perl, because Data::Dumper
will perform its expensive operations in any case, because it doesn't
know that its output will be thrown away immediately.

As of Log::Log4perl 0.28, there's a better way: Use the 
message output filter format as in

    $logger->debug( {filter => \&Data::Dumper::Dumper,
                     value  => $ref} );

and Log::Log4perl won't call the filter function unless the message really
gets written out to an appender. Just make sure to pass the whole slew as a
reference to a hash specifying a filter function (as a sub reference)
under the key C<filter> and the value to be passed to the filter function in
C<value>). 
When it comes to logging, Log::Log4perl will call the filter function,
pass the C<value> as an argument and log the return value.
Saves you serious cycles.

=head2 How can I collect all FATAL messages in an extra log file?

Suppose you have employed Log4perl all over your system and you've already
activated logging in various subsystems. On top of that, without disrupting
any other settings, how can you collect all FATAL messages all over the system
and send them to a separate log file? 

If you define a root logger like this:

    log4perl.logger                  = FATAL, File
    log4perl.appender.File           = Log::Log4perl::Appender::File
    log4perl.appender.File.filename  = /tmp/fatal.txt
    log4perl.appender.File.layout    = PatternLayout
    log4perl.appender.File.layout.ConversionPattern= %d %m %n
        # !!! Something's missing ...

you'll be surprised to not only receive all FATAL messages
issued anywhere in the system,
but also everything else -- gazillions of 
ERROR, WARN, INFO and even DEBUG messages will end up in
your fatal.txt logfile!
Reason for this is Log4perl's (or better: Log4j's) appender additivity. 
Once a 
lower-level logger decides to fire, the message is going to be forwarded
to all appenders upstream -- without further priority checks with their
attached loggers.

There's a way to prevent this, however: If your appender defines a
minimum threshold, only messages of this priority or higher are going
to be logged. So, just add

    log4perl.appender.File.Threshold = FATAL 

to the configuration above, and you'll get what you wanted in the 
first place: An overall system FATAL message collector.

=head2 How can I bundle several log messages into one?

Would you like to tally the messages arriving at your appender and
dump out a summary once they're exceeding a certain threshold?
So that something like

    $logger->error("Blah");
    $logger->error("Blah");
    $logger->error("Blah");

won't be logged as 

    Blah
    Blah
    Blah

but as

    [3] Blah

instead? If you'd like to hold off on logging a message until it has been
sent a couple of times, you can roll that out by creating a buffered 
appender.

Let's define a new appender like

    package TallyAppender;

    sub new {
        my($class, %options) = @_;

        my $self = { maxcount => 5,
                     %options
                   };

        bless $self, $class;

        $self->{last_message}        = "";
        $self->{last_message_count}  = 0;

        return $self;
    }

with two additional instance variables C<last_message> and 
C<last_message_count>, storing the content of the last message sent
and a counter of how many times this has happened. Also, it features
a configuration parameter C<maxcount> which defaults to 5 in the
snippet above but can be set in the Log4perl configuration file like this:

    log4perl.logger = INFO, A
    log4perl.appender.A=TallyAppender
    log4perl.appender.A.maxcount = 3

The main tallying logic lies in the appender's C<log> method,
which is called every time Log4perl thinks a message needs to get logged
by our appender:

    sub log {
        my($self, %params) = @_;

            # Message changed? Print buffer.
        if($self->{last_message} and
           $params{message} ne $self->{last_message}) {
            print "[$self->{last_message_count}]: " .
                  "$self->{last_message}";
            $self->{last_message_count} = 1;
            $self->{last_message} = $params{message};
            return;
        }

        $self->{last_message_count}++;
        $self->{last_message} = $params{message};

            # Threshold exceeded? Print, reset counter
        if($self->{last_message_count} >= 
           $self->{maxcount}) {
            print "[$self->{last_message_count}]: " .
                  "$params{message}";
            $self->{last_message_count} = 0;
            $self->{last_message}       = "";
            return;
        }
    }

We basically just check if the oncoming message in C<$param{message}>
is equal to what we've saved before in the C<last_message> instance
variable. If so, we're increasing C<last_message_count>.
We print the message in two cases: If the new message is different
than the buffered one, because then we need to dump the old stuff
and store the new. Or, if the counter exceeds the threshold, as
defined by the C<maxcount> configuration parameter.

Please note that the appender always gets the fully rendered message and
just compares it as a whole -- so if there's a date/timestamp in there,
that might confuse your logic. You can work around this by specifying
%m %n as a layout and add the date later on in the appender. Or, make
the comparison smart enough to omit the date.

At last, don't forget what happens if the program is being shut down.
If there's still messages in the buffer, they should be printed out
at that point. That's easy to do in the appender's DESTROY method,
which gets called at object destruction time:

    sub DESTROY {
        my($self) = @_;

        if($self->{last_message_count}) {
            print "[$self->{last_message_count}]: " .
                  "$self->{last_message}";
            return;
        }
    }

This will ensure that none of the buffered messages are lost. 
Happy buffering!

=head2 I want to log ERROR and WARN messages to different files! How can I do that?

Let's assume you wanted to have each logging statement written to a
different file, based on the statement's priority. Messages with priority
C<WARN> are supposed to go to C</tmp/app.warn>, events prioritized
as C<ERROR> should end up in C</tmp/app.error>.

Now, if you define two appenders C<AppWarn> and C<AppError>
and assign them both to the root logger,
messages bubbling up from any loggers below will be logged by both
appenders because of Log4perl's message propagation feature. If you limit
their exposure via the appender threshold mechanism and set 
C<AppWarn>'s threshold to C<WARN> and C<AppError>'s to C<ERROR>, you'll
still get C<ERROR> messages in C<AppWarn>, because C<AppWarn>'s C<WARN>
setting will just filter out messages with a I<lower> priority than
C<WARN> -- C<ERROR> is higher and will be allowed to pass through.

What we need for this is a Log4perl I<Custom Filter>, available with 
Log::Log4perl 0.30.

Both appenders need to verify that
the priority of the oncoming messages exactly I<matches> the priority 
the appender is supposed to log messages of. To accomplish this task,
let's define two custom filters, C<MatchError> and C<MatchWarn>, which,
when attached to their appenders, will limit messages passed on to them
to those matching a given priority: 

    log4perl.logger = WARN, AppWarn, AppError

        # Filter to match level ERROR
    log4perl.filter.MatchError = Log::Log4perl::Filter::LevelMatch
    log4perl.filter.MatchError.LevelToMatch  = ERROR
    log4perl.filter.MatchError.AcceptOnMatch = true

        # Filter to match level WARN
    log4perl.filter.MatchWarn  = Log::Log4perl::Filter::LevelMatch
    log4perl.filter.MatchWarn.LevelToMatch  = WARN
    log4perl.filter.MatchWarn.AcceptOnMatch = true

        # Error appender
    log4perl.appender.AppError = Log::Log4perl::Appender::File
    log4perl.appender.AppError.filename = /tmp/app.err
    log4perl.appender.AppError.layout   = SimpleLayout
    log4perl.appender.AppError.Filter   = MatchError

        # Warning appender
    log4perl.appender.AppWarn = Log::Log4perl::Appender::File
    log4perl.appender.AppWarn.filename = /tmp/app.warn
    log4perl.appender.AppWarn.layout   = SimpleLayout
    log4perl.appender.AppWarn.Filter   = MatchWarn

The appenders C<AppWarn> and C<AppError> defined above are logging to C</tmp/app.warn> and
C</tmp/app.err> respectively and have the custom filters C<MatchWarn> and C<MatchError>
attached.
This setup will direct all WARN messages, issued anywhere in the system, to /tmp/app.warn (and 
ERROR messages to /tmp/app.error) -- without any overlaps.

=head2 On our server farm, Log::Log4perl configuration files differ slightly from host to host. Can I roll them all into one?

You sure can, because Log::Log4perl allows you to specify attribute values 
dynamically. Let's say that one of your appenders expects the host's IP address
as one of its attributes. Now, you could certainly roll out different 
configuration files for every host and specify the value like

    log4perl.appender.MyAppender    = Log::Log4perl::Appender::SomeAppender
    log4perl.appender.MyAppender.ip = 10.0.0.127

but that's a maintenance nightmare. Instead, you can have Log::Log4perl 
figure out the IP address at configuration time and set the appender's
value correctly:

        # Set the IP address dynamically
    log4perl.appender.MyAppender    = Log::Log4perl::Appender::SomeAppender
    log4perl.appender.MyAppender.ip = sub { \
       use Sys::Hostname; \
       use Socket; \
       return inet_ntoa(scalar gethostbyname hostname); \
    }

If Log::Log4perl detects that an attribute value starts with something like
C<"sub {...">, it will interpret it as a perl subroutine which is to be executed
once at configuration time (not runtime!) and its return value is
to be used as the attribute value. This comes in handy
for rolling out applications whichs Log::Log4perl configuration files
show small host-specific differences, because you can deploy the unmodified
application distribution on all instances of the server farm.

=head2 Log4perl doesn't interpret my backslashes correctly!

If you're using Log4perl's feature to specify the configuration as a
string in your program (as opposed to a separate configuration file),
chances are that you've written it like this:

    # *** WRONG! ***

    Log::Log4perl->init( \ <<END_HERE);
        log4perl.logger = WARN, A1
        log4perl.appender.A1 = Log::Log4perl::Appender::Screen
        log4perl.appender.A1.layout = \
            Log::Log4perl::Layout::PatternLayout
        log4perl.appender.A1.layout.ConversionPattern = %m%n
    END_HERE

    # *** WRONG! ***

and you're getting the following error message:

    Layout not specified for appender A1 at .../Config.pm line 342.

What's wrong? The problem is that you're using a here-document with
substitution enabled (C<E<lt>E<lt>END_HERE>) and that Perl won't 
interpret backslashes at line-ends as continuation characters but 
will essentially throw them out. So, in the code above, the layout line
will look like

    log4perl.appender.A1.layout =

to Log::Log4perl which causes it to report an error. To interpret the backslash
at the end of the line correctly as a line-continuation character, use
the non-interpreting mode of the here-document like in 

    # *** RIGHT! ***

    Log::Log4perl->init( \ <<'END_HERE');
        log4perl.logger = WARN, A1
        log4perl.appender.A1 = Log::Log4perl::Appender::Screen
        log4perl.appender.A1.layout = \
            Log::Log4perl::Layout::PatternLayout
        log4perl.appender.A1.layout.ConversionPattern = %m%n
    END_HERE

    # *** RIGHT! ***

(note the single quotes around C<'END_HERE'>) or use C<q{...}> 
instead of a here-document and Perl will treat the backslashes at 
line-end as intended.

=head2 I want to suppress certain messages based on their content!

Let's assume you've plastered all your functions with Log4perl 
statements like

    sub some_func {

        INFO("Begin of function");

        # ... Stuff happens here ...

        INFO("End of function");
    }

to issue two log messages, one at the beginning and one at the end of
each function. Now you want to suppress the message at the beginning
and only keep the one at the end, what can you do? You can't use the category
mechanism, because both messages are issued from the same package.

Log::Log4perl's custom filters (0.30 or better) provide an interface for the 
Log4perl user to step in right before a message gets logged and decide if 
it should be written out or suppressed, based on the message content or other
parameters:

    use Log::Log4perl qw(:easy);

    Log::Log4perl::init( \ <<'EOT' );
        log4perl.logger             = INFO, A1
        log4perl.appender.A1        = Log::Log4perl::Appender::Screen
        log4perl.appender.A1.layout = \
            Log::Log4perl::Layout::PatternLayout
        log4perl.appender.A1.layout.ConversionPattern = %m%n

        log4perl.filter.M1 = Log::Log4perl::Filter::StringMatch
        log4perl.filter.M1.StringToMatch = Begin
        log4perl.filter.M1.AcceptOnMatch = false

        log4perl.appender.A1.Filter = M1
EOT

The last four statements in the configuration above are defining a custom 
filter C<M1> of type C<Log::Log4perl::Filter::StringMatch>, which comes with 
Log4perl right out of the box and allows you to define a text pattern to match
(as a perl regular expression) and a flag C<AcceptOnMatch> indicating
if a match is supposed to suppress the message or let it pass through.

The last line then assigns this filter to the C<A1> appender, which will
call it every time it receives a message to be logged and throw all
messages out I<not> matching the regular expression C<Begin>.

Instead of using the standard C<Log::Log4perl::Filter::StringMatch> filter,
you can define your own, simply using a perl subroutine:

    log4perl.filter.ExcludeBegin  = sub { !/Begin/ }
    log4perl.appender.A1.Filter   = ExcludeBegin

For details on custom filters, check L<Log::Log4perl::Filter>.

=head2 My new module uses Log4perl -- but what happens if the calling program didn't configure it?

If a Perl module uses Log::Log4perl, it will typically rely on the
calling program to initialize it. If it is using Log::Log4perl in C<:easy>
mode, like in 

    package MyMod;
    use Log::Log4perl qw(:easy);

    sub foo {
        DEBUG("In foo");
    }

    1;

and the calling program doesn't initialize Log::Log4perl at all (e.g. because
it has no clue that it's available), Log::Log4perl will silently
ignore all logging messages. However, if the module is using Log::Log4perl 
in regular mode like in

    package MyMod;
    use Log::Log4perl qw(get_logger);

    sub foo {
        my $logger = get_logger("");
        $logger->debug("blah");
    }

    1;

and the main program is just using the module like in

    use MyMode;
    MyMode::foo();

then Log::Log4perl will also ignore all logging messages but
issue a warning like

    Log4perl: Seems like no initialization happened. 
    Forgot to call init()?

(only once!) to remind novice users to not forget to initialize 
the logging system before using it. 
However, if you want to suppress this message, just
add the C<:nowarn> target to the module's C<use Log::Log4perl> call:

    use Log::Log4perl qw(get_logger :nowarn);

This will have Log::Log4perl silently ignore all logging statements if
no initialization has taken place. If, instead of using init(), you're 
using Log4perl's API to define loggers and appenders, the same 
notification happens if no call to add_appenders() is made, i.e. no
appenders are defined.

If the module wants to figure out if some other program part has 
already initialized Log::Log4perl, it can do so by calling

    Log::Log4perl::initialized()

which will return a true value in case Log::Log4perl has been initialized 
and a false value if not.

=head2 How can I synchronize access to an appender?

If you're using the same instance of an appender in multiple processes, 
and each process is passing on messages to the appender in parallel,
you might end up with overlapping log entries.

Typical scenarios include a file appender that you create in the main 
program, and which will then be shared between the parent and a 
forked child process. Or two separate processes, each initializing a
Log4perl file appender on the same logfile.

Log::Log4perl won't synchronize access to the shared logfile by
default. Depending on your operating system's flush mechanism,
buffer size and the size of your messages, there's a small chance of
an overlap.

The easiest way to prevent overlapping messages in logfiles written to
by multiple processes is setting the 
file appender's C<syswrite> flag along with a file write mode of C<"append">. 
This makes sure that
C<Log::Log4perl::Appender::File> uses C<syswrite()> (which is guaranteed
to run uninterrupted) instead of C<print()> which might buffer
the message or get interrupted by the OS while it is writing. And in
C<"append"> mode, the OS kernel ensures that multiple processes share
one end-of-file marker, ensuring that each process writes to the I<real> 
end of the file. (The value of C<"append"> 
for the C<mode> parameter is the default setting in Log4perl's file 
appender so you don't have to set it explicitly.)

      # Guarantees atomic writes

    log4perl.category.Bar.Twix          = WARN, Logfile

    log4perl.appender.Logfile           = Log::Log4perl::Appender::File
    log4perl.appender.Logfile.mode      = append
    log4perl.appender.Logfile.syswrite  = 1
    log4perl.appender.Logfile.filename  = test.log
    log4perl.appender.Logfile.layout    = SimpleLayout

Another guaranteed way of having messages separated with any kind of
appender is putting a Log::Log4perl::Appender::Synchronized composite
appender in between Log::Log4perl and the real appender. It will make
sure to let messages pass through this virtual gate one by one only.

Here's a sample configuration to synchronize access to a file appender:

    log4perl.category.Bar.Twix          = WARN, Syncer

    log4perl.appender.Logfile           = Log::Log4perl::Appender::File
    log4perl.appender.Logfile.autoflush = 1
    log4perl.appender.Logfile.filename  = test.log
    log4perl.appender.Logfile.layout    = SimpleLayout

    log4perl.appender.Syncer            = Log::Log4perl::Appender::Synchronized
    log4perl.appender.Syncer.appender   = Logfile

C<Log::Log4perl::Appender::Synchronized> uses 
the C<IPC::Shareable> module and its semaphores, which will slow down writing
the log messages, but ensures sequential access featuring atomic checks.
Check L<Log::Log4perl::Appender::Synchronized> for details.

=head2 Can I use Log::Log4perl with log4j's Chainsaw?

Yes, Log::Log4perl can be configured to send its events to log4j's 
graphical log UI I<Chainsaw>.

=for html
<p>
<TABLE><TR><TD>
<A HREF="http://log4perl.sourceforge.net/images/chainsaw2.jpg"><IMG SRC="http://log4perl.sourceforge.net/images/chainsaw2s.jpg"></A>
<TR><TD>
<I>Figure 1: Chainsaw receives Log::Log4perl events</I>
</TABLE>
<p>

=for text
Figure1: Chainsaw receives Log::Log4perl events

Here's how it works:

=over 4

=item *

Get Guido Carls' E<lt>gcarls@cpan.orgE<gt> Log::Log4perl extension
C<Log::Log4perl::Layout::XMLLayout> from CPAN and install it:

    perl -MCPAN -eshell
    cpan> install Log::Log4perl::Layout::XMLLayout

=item *

Install and start Chainsaw, which is part of the C<log4j> distribution now
(see http://jakarta.apache.org/log4j ). Create a configuration file like

  <log4j:configuration debug="true">
    <plugin name="XMLSocketReceiver" 
            class="org.apache.log4j.net.XMLSocketReceiver">
      <param name="decoder" value="org.apache.log4j.xml.XMLDecoder"/> 
      <param name="Port" value="4445"/> 
    </plugin>
    <root> <level value="debug"/> </root> 
  </log4j:configuration>

and name it e.g. C<config.xml>. Then start Chainsaw like

  java -Dlog4j.debug=true -Dlog4j.configuration=config.xml \
    -classpath ".:log4j-1.3alpha.jar:log4j-chainsaw-1.3alpha.jar" \
    org.apache.log4j.chainsaw.LogUI

and watch the GUI coming up.

=item *

Configure Log::Log4perl to use a socket appender with an XMLLayout, pointing
to the host/port where Chainsaw (as configured above) is waiting with its
XMLSocketReceiver:

  use Log::Log4perl qw(get_logger);
  use Log::Log4perl::Layout::XMLLayout;

  my $conf = q(
    log4perl.category.Bar.Twix          = WARN, Appender
    log4perl.appender.Appender          = Log::Log4perl::Appender::Socket
    log4perl.appender.Appender.PeerAddr = localhost
    log4perl.appender.Appender.PeerPort = 4445
    log4perl.appender.Appender.layout   = Log::Log4perl::Layout::XMLLayout
  );

  Log::Log4perl::init(\$conf);

    # Nasty hack to suppress encoding header
  my $app = Log::Log4perl::appenders->{"Appender"};
  $app->layout()->{enc_set} = 1;

  my $logger = get_logger("Bar.Twix");
  $logger->error("One");

The nasty hack shown in the code snippet above is currently (October 2003) 
necessary, because Chainsaw expects XML messages to arrive in a format like

  <log4j:event logger="Bar.Twix"
               timestamp="1066794904310"
               level="ERROR"
               thread="10567">
    <log4j:message><![CDATA[Two]]></log4j:message>
    <log4j:NDC><![CDATA[undef]]></log4j:NDC>
    <log4j:locationInfo class="main"
      method="main"
      file="./t"
      line="32">
    </log4j:locationInfo>
  </log4j:event>

without a preceding 

  <?xml version = "1.0" encoding = "iso8859-1"?>

which Log::Log4perl::Layout::XMLLayout applies to the first event sent
over the socket.

=back

See figure 1 for a screenshot of Chainsaw in action, receiving events from
the Perl script shown above.

Many thanks to Chainsaw's
Scott Deboy <sdeboy@comotivsystems.com> for his support!

=head2 How can I run Log::Log4perl under mod_perl?

In persistent environments it's important to play by the rules outlined
in section L<Log::Log4perl/"Initialize once and only once">. 
If you haven't read this yet, please go ahead and read it right now. It's 
very important.

And no matter if you use a startup handler to init() Log::Log4perl or use the
init_once() strategy (added in 0.42), either way you're very likely to have
unsynchronized writes to logfiles.

If Log::Log4perl is configured with a log file appender, and it is 
initialized via
the Apache startup handler, the file handle created initially will be
shared among all Apache processes. Similarly, with the init_once()
approach: although every process has a separate L4p configuration,
processes are gonna share the appender file I<names> instead, effectively
opening several different file handles on the same file.

Now, having several appenders using the same file handle or having
several appenders logging to the same file unsynchronized, this might
result in overlapping messages. Sometimes, this is acceptable. If it's
not, here's two strategies:

=over 4

=item *

Use the L<Log::Log4perl::Appender::Synchronized> appender to connect to 
your file appenders. Here's the writeup: 
http://log4perl.sourceforge.net/releases/Log-Log4perl/docs/html/Log/Log4perl/FAQ.html#23804 

=item *

Use a different logfile for every process like in

     #log4perl.conf
     ...
     log4perl.appender.A1.filename = sub { "mylog.$$.log" }

=back

=head2 My program already uses warn() and die(). How can I switch to Log4perl?

If your program already uses Perl's C<warn()> function to spew out 
error messages and you'd like to channel those into the Log4perl world,
just define a C<__WARN__> handler where your program or module resides:

    use Log::Log4perl qw(:easy);

    $SIG{__WARN__} = sub {
        local $Log::Log4perl::caller_depth =
            $Log::Log4perl::caller_depth + 1;
        WARN @_;
    };

Why the C<local> setting of C<$Log::Log4perl::caller_depth>? 
If you leave that out,
C<PatternLayout> conversion specifiers like C<%M> or C<%F> (printing
the current function/method and source filename) will refer
to where the __WARN__ handler resides, not the environment 
Perl's C<warn()> function was issued from. Increasing C<caller_depth> 
adjusts for this offset. Having it C<local>, makes sure the level 
gets set back after the handler exits.

Once done, if your program does something like 

    sub some_func {
        warn "Here's a warning";
    }

you'll get (depending on your Log::Log4perl configuration) something like

    2004/02/19 20:41:02-main::some_func: Here's a warning at ./t line 25.

in the appropriate appender instead of having a screen full of STDERR
messages. It also works with the C<Carp> module and its C<carp()>
and C<cluck()> functions.

If, on the other hand, catching C<die()> and friends is 
required, a C<__DIE__> handler is appropriate:

    $SIG{__DIE__} = sub {
        if($^S) {
            # We're in an eval {} and don't want log
            # this message but catch it later
            return;
        }
        local $Log::Log4perl::caller_depth =
            $Log::Log4perl::caller_depth + 1;
        LOGDIE @_;
    };

This will call Log4perl's C<LOGDIE()> function, which will log a fatal
error and then call die() internally, causing the program to exit. Works
equally well with C<Carp>'s C<croak()> and C<confess()> functions.

=head2 Some module prints messages to STDERR. How can I funnel them to Log::Log4perl?

If a module you're using doesn't use Log::Log4perl but prints logging
messages to STDERR instead, like

    ########################################
    package IgnorantModule;
    ########################################

    sub some_method {
        print STDERR "Parbleu! An error!\n";
    }

    1;

there's still a way to capture these messages and funnel them 
into Log::Log4perl, even without touching the module. What you need is
a trapper module like

    ########################################
    package Trapper;
    ########################################
    
    use Log::Log4perl qw(:easy);
    
    sub TIEHANDLE {
        my $class = shift;
        bless [], $class;
    }
    
    sub PRINT {
        my $self = shift;
        $Log::Log4perl::caller_depth++;
        DEBUG @_;
        $Log::Log4perl::caller_depth--;
    }

    1;

and a C<tie> command in the main program to tie STDERR to the trapper
module along with regular Log::Log4perl initialization:

    ########################################
    package main;
    ########################################

    use Log::Log4perl qw(:easy);

    Log::Log4perl->easy_init(
        {level  => $DEBUG, 
         file   => 'stdout',   # make sure not to use stderr here!
         layout => "%d %M: %m%n",
        });

    tie *STDERR, "Trapper";

Make sure not to use STDERR as Log::Log4perl's file appender
here (which would be the default in C<:easy> mode), because it would 
end up in an endless recursion.

Now, calling

    IgnorantModule::some_method();

will result in the desired output

    2004/05/06 11:13:04 IgnorantModule::some_method: Parbleu! An error!

=head2 How come PAR (Perl Archive Toolkit) creates executables which then can't find their Log::Log4perl appenders?

If not instructed otherwise, C<Log::Log4perl> dynamically pulls in 
appender classes found in its configuration. If you specify

    #!/usr/bin/perl
    # mytest.pl

    use Log::Log4perl qw(get_logger);

    my $conf = q(
      log4perl.category.Bar.Twix = WARN, Logfile
      log4perl.appender.Logfile  = Log::Log4perl::Appender::Screen
      log4perl.appender.Logfile.layout = SimpleLayout
    );

    Log::Log4perl::init(\$conf);
    my $logger = get_logger("Bar::Twix");
    $logger->error("Blah");

then C<Log::Log4perl::Appender::Screen> will be pulled in while the program
runs, not at compile time. If you have PAR compile the script above to an
executable binary via

    pp -o mytest mytest.pl

and then run C<mytest> on a machine without having Log::Log4perl installed,
you'll get an error message like

    ERROR: can't load appenderclass 'Log::Log4perl::Appender::Screen'
    Can't locate Log/Log4perl/Appender/Screen.pm in @INC ...

Why? At compile time, C<pp> didn't realize that 
C<Log::Log4perl::Appender::Screen> would be needed later on and didn't
wrap it into the executable created. To avoid this, either say
C<use Log::Log4perl::Appender::Screen> in the script explicitly or
compile it with

    pp -o mytest -M Log::Log4perl::Appender::Screen mytest.pl

to make sure the appender class gets included.

=head2 How can I access a custom appender defined in the configuration?

Any appender defined in the configuration file or somewhere in the code
can be accessed later via 
C<Log::Log4perl-E<gt>appender_by_name("appender_name")>,
which returns a reference the the appender object.

Once you've got a hold of the object, it can be queried or modified to 
your liking. For example, see the custom C<IndentAppender> defined below:
After calling C<init()> to define the Log4perl settings, the
appender object is retrieved to call its C<indent_more()> and C<indent_less()>
methods to control indentation of messages:

    package IndentAppender;

    sub new {
        bless { indent => 0 }, $_[0];
    }

    sub indent_more  { $_[0]->{indent}++ }
    sub indent_less  { $_[0]->{indent}-- }

    sub log {
        my($self, %params) = @_;
        print " " x $self->{indent}, $params{message};
    }

    package main;

    use Log::Log4perl qw(:easy);

    my $conf = q(
    log4perl.category          = DEBUG, Indented
    log4perl.appender.Indented = IndentAppender
    log4perl.appender.Indented.layout = Log::Log4perl::Layout::SimpleLayout
    );
    
    Log::Log4perl::init(\$conf);

    my $appender = Log::Log4perl->appender_by_name("Indented");
    
    DEBUG "No identation";
    $appender->indent_more();
    DEBUG "One more";
    $appender->indent_more();
    DEBUG "Two more";
    $appender->indent_less();
    DEBUG "One less";

As you would expect, this will print

    DEBUG - No identation
     DEBUG - One more
      DEBUG - Two more
     DEBUG - One less

because the very appender used by Log4perl is modified dynamically at
runtime.

=head2 I don't know if Log::Log4perl is installed. How can I prepare my script?

In case your script needs to be prepared for environments that may or may 
not have Log::Log4perl installed, there's a trick.

If you put the following BEGIN blocks at the top of the program,
you'll be able to use the DEBUG(), INFO(), etc. macros in
Log::Log4perl's C<:easy> mode.
If Log::Log4perl
is installed in the target environment, the regular Log::Log4perl rules
apply. If not, all of DEBUG(), INFO(), etc. are "stubbed" out, i.e. they
turn into no-ops:

    use warnings;
    use strict;

    BEGIN {
        eval { require Log::Log4perl; };
    
        if($@) {
            print "Log::Log4perl not installed - stubbing.\n";
            no strict qw(refs);
            *{"main::$_"} = sub { } for qw(DEBUG INFO WARN ERROR FATAL);
        } else {
            no warnings;
            print "Log::Log4perl installed - life is good.\n";
            require Log::Log4perl::Level;
            Log::Log4perl::Level->import(__PACKAGE__);
            Log::Log4perl->import(qw(:easy));
            Log::Log4perl->easy_init($main::DEBUG);
        }
    }

        # The regular script begins ...
    DEBUG "Hey now!";

This snippet will first probe for Log::Log4perl, and if it can't be found,
it will alias DEBUG(), INFO(), with empty subroutines via typeglobs.
If Log::Log4perl is available, its level constants are first imported
(C<$DEBUG>, C<$INFO>, etc.) and then C<easy_init()> gets called to initialize
the logging system.

=head2 Can file appenders create files with different permissions?

Typically, when C<Log::Log4perl::Appender::File> creates a new file,
its permissions are set to C<rw-r--r-->. Why? Because your
environment's I<umask> most likely defaults to
C<0022>, that's the standard setting. 

What's a I<umask>, you're asking? It's a template that's applied to
the permissions of all newly created files. While calls like
C<open(FILE, "E<gt>foo")> will always try to create files in C<rw-rw-rw-
> mode, the system will apply the current I<umask> template to
determine the final permission setting. I<umask> is a bit mask that's
inverted and then applied to the requested permission setting, using a
bitwise AND:

    $request_permission &~ $umask

So, a I<umask> setting of 0000 (the leading 0 simply indicates an
octal value) will create files in C<rw-rw-rw-> mode, a setting of 0277
will use C<r-------->, and the standard 0022 will use C<rw-r--r-->.

As an example, if you want your log files to be created with
C<rw-r--rw-> permissions, use a I<umask> of C<0020> before
calling Log::Log4perl->init():

    use Log::Log4perl;

    umask 0020;
        # Creates log.out in rw-r--rw mode
    Log::Log4perl->init(\ q{
        log4perl.logger = WARN, File
        log4perl.appender.File = Log::Log4perl::Appender::File
        log4perl.appender.File.filename = log.out
        log4perl.appender.File.layout = SimpleLayout
    });

=head2 Using Log4perl in an END block causes a problem!

It's not easy to get to this error, but if you write something like

    END { Log::Log4perl::get_logger()->debug("Hey there."); }

    use Log::Log4perl qw(:easy);
    Log::Log4perl->easy_init($DEBUG);

it won't work. The reason is that C<Log::Log4perl> defines an
END block that cleans up all loggers. And perl will run END blocks
in the reverse order as they're encountered in the compile phase,
so in the scenario above, the END block will run I<after> Log4perl
has cleaned up its loggers.

Placing END blocks using Log4perl I<after>
a C<use Log::Log4perl> statement fixes the problem:

    use Log::Log4perl qw(:easy);
    Log::Log4perl->easy_init($DEBUG);

    END { Log::Log4perl::get_logger()->debug("Hey there."); }

In this scenario, the shown END block is executed I<before> Log4perl
cleans up and the debug message will be processed properly.

=head2 Help! My appender is throwing a "Wide character in print" warning!

This warning shows up when Unicode strings are printed without
precautions. The warning goes away if the complaining appender is
set to utf-8 mode:

      # Either in the log4perl configuration file:
  log4perl.appender.Logfile.filename = test.log
  log4perl.appender.Logfile.utf8     = 1

      # Or, in easy mode:
  Log::Log4perl->easy_init( {
    level => $DEBUG,
    file  => ":utf8> test.log" 
  } );

If the complaining appender is a screen appender, set its C<utf8> option:

      log4perl.appender.Screen.stderr = 1
      log4perl.appender.Screen.utf8   = 1

Alternatively, C<binmode> does the trick:

      # Either STDOUT ...
    binmode(STDOUT, ":utf8);

      # ... or STDERR.
    binmode(STDERR, ":utf8);

Some background on this: Perl's strings are either byte strings or
Unicode strings. C<"Mike"> is a byte string.
C<"\x{30DE}\x{30A4}\x{30AF}"> is a Unicode string. Unicode strings are
marked specially and are UTF-8 encoded internally. 

If you print a byte string to STDOUT,
all is well, because STDOUT is by default set to byte mode. However,
if you print a Unicode string to STDOUT without precautions, C<perl>
will try to transform the Unicode string back to a byte string before
printing it out. This is troublesome if the Unicode string contains
'wide' characters which can't be represented in Latin-1.

For example, if you create a Unicode string with three japanese Katakana
characters as in

    perl -le 'print "\x{30DE}\x{30A4}\x{30AF}"'

(coincidentally pronounced Ma-i-ku, the japanese pronounciation of 
"Mike"), STDOUT is in byte mode and the warning

    Wide character in print at ./script.pl line 14.

appears. Setting STDOUT to UTF-8 mode as in

    perl -le 'binmode(STDOUT, ":utf8"); print "\x{30DE}\x{30A4}\x{30AF}"'

will silently print the Unicode string to STDOUT in UTF-8. To see the 
characters printed, you'll need a UTF-8 terminal with a font including
japanese Katakana characters.

=head2 How can I send errors to the screen, and debug messages to a file?

Let's assume you want to maintain a detailed DEBUG output in a file
and only messages of level ERROR and higher should be printed on the
screen. Often times, developers come up with something like this:

     # Wrong!!!
    log4perl.logger = DEBUG, FileApp
    log4perl.logger = ERROR, ScreenApp
     # Wrong!!!

This won't work, however. Logger definitions aren't additive, and the
second statement will overwrite the first one. Log4perl versions
below 1.04 were silently accepting this, leaving people confused why
it wouldn't work as expected.
As of 1.04, this will throw a I<fatal error> to notify the user of
the problem.

What you want to do instead, is this:

    log4perl.logger                    = DEBUG, FileApp, ScreenApp

    log4perl.appender.FileApp          = Log::Log4perl::Appender::File
    log4perl.appender.FileApp.filename = test.log
    log4perl.appender.FileApp.layout   = SimpleLayout

    log4perl.appender.ScreenApp          = Log::Log4perl::Appender::Screen
    log4perl.appender.ScreenApp.stderr   = 0
    log4perl.appender.ScreenApp.layout   = SimpleLayout
       ### limiting output to ERROR messages
    log4perl.appender.ScreenApp.Threshold = ERROR
       ###

Note that without the second appender's C<Threshold> setting, both appenders
would receive all messages prioritized DEBUG and higher. With the
threshold set to ERROR, the second appender will filter the messages
as required.

=head2 Where should I put my logfiles?

Your log files may go anywhere you want them, but the effective
user id of the calling process must have write access. 

If the log file doesn't exist at program start, Log4perl's file appender
will create it. For this, it needs write access to the directory where
the new file will be located in. If the log file already exists at startup,
the process simply needs write access to the file. Note that it will
need write access to the file's directory if you're encountering situations
where the logfile gets recreated, e.g. during log rotation.

If Log::Log4perl is used by a web server application (e.g. in a CGI script
or mod_perl), then the webserver's user (usually C<nobody> or C<www>)
must have the permissions mentioned above.

To prepare your web server to use log4perl, we'd recommend:

    webserver:~$ su -
    webserver:~# mkdir /var/log/cgiapps
    webserver:~# chown nobody:root /var/log/cgiapps/
    webserver:~# chown nobody:root -R /var/log/cgiapps/
    webserver:~# chmod 02755 -R /var/log/cgiapps/

Then set your /etc/log4perl.conf file to include:

    log4perl.appender.FileAppndr1.filename = 
        /var/log/cgiapps/<app-name>.log

=head2 How can my file appender deal with disappearing log files?

The file appender that comes with Log4perl, L<Log::Log4perl::Appender::File>,
will open a specified log file at initialization time and will
keep writing to it via a file handle.

In case the associated file goes way, messages written by a 
long-running process will still be written
to the file handle. In case the file has been moved to a different 
location on the same file system, the writer will keep writing to
it under the new filename. In case the file has been removed from
the file system, the log messages will end up in nowhere land. This 
is not a bug in Log4perl, this is how Unix works. There is
no error message in this case, because the writer has no idea that
the file handle is not associated with a visible file.

To prevent the loss of log messages when log files disappear, the
file appender's C<recreate> option needs to be set to a true value:

    log4perl.appender.Logfile.recreate = 1

This will instruct the file appender to check in regular intervals
(default: 30 seconds) if the log file is still there. If it finds
out that the file is missing, it will recreate it.

Continuously checking if the log file still exists is fairly
expensive. For this reason it is only performed every 30 seconds. To
change this interval, the option C<recreate_check_interval> can be set
to the number of seconds between checks. In the extreme case where the
check should be performed before every write, it can even be set to 0:

    log4perl.appender.Logfile.recreate = 1
    log4perl.appender.Logfile.recreate_check_interval = 0

To avoid having to check the file system so frequently, a signal
handler can be set up:

    log4perl.appender.Logfile.recreate = 1
    log4perl.appender.Logfile.recreate_check_signal = USR1

This will install a signal handler which will recreate a missing log file
immediatly when it receives the defined signal. 

Note that the init_and_watch() method for Log4perl's initialization
can also be instructed to install a signal handler, usually using the
HUP signal. Make sure to use a different signal if you're using both
of them at the same time.

=head2 How can I rotate a logfile with newsyslog?

Here's a few things that need to be taken care of when using the popular
log file rotating utilty C<newsyslog>
(http://www.courtesan.com/newsyslog) with Log4perl's file appender
in long-running processes.

For example, with a newsyslog configuration like

    # newsyslog.conf
    /tmp/test.log 666  12  5  *  B

and a call to 

    # newsyslog -f /path/to/newsyslog.conf

C<newsyslog> will take action if C</tmp/test.log> is larger than the 
specified 5K in size. It will move the current log file C</tmp/test.log> to 
C</tmp/test.log.0> and create a new and empty C</tmp/test.log> with
the specified permissions (this is why C<newsyslog> needs to run as root). 
An already existing C</tmp/test.log.0> would be moved to
C</tmp/test.log.1>, C</tmp/test.log.1> to C</tmp/test.log.2>, and so
forth, for every one of a max number of 12 archived logfiles that have
been configured in C<newsyslog.conf>.

Although a new file has been created, from Log4perl's appender's point
of view, this situation is identical to the one described in the
previous FAQ entry, labeled C<How can my file appender deal with
disappearing log files>.

To make sure that log messages are written to the new log file and not
to an archived one or end up in nowhere land,
the appender's C<recreate> and C<recreate_check_interval> have to be
configured to deal with the 'disappearing' log file.

The situation gets interesting when C<newsyslog>'s option
to compress archived log files is enabled. This causes the
original log file not to be moved, but to disappear. If the
file appender isn't configured to recreate the logfile in this situation,
log messages will actually be lost without warning. This also
applies for the short time frame of C<recreate_check_interval> seconds
in between the recreator's file checks.

To make sure that no messages get lost, one option is to set the
interval to

    log4perl.appender.Logfile.recreate_check_interval = 0

However, this is fairly expensive. A better approach is to define
a signal handler:

    log4perl.appender.Logfile.recreate = 1
    log4perl.appender.Logfile.recreate_check_signal  = USR1
    log4perl.appender.Logfile.recreate_pid_write = /tmp/myappid

As a service for C<newsyslog> users, Log4perl's file appender writes
the current process ID to a PID file specified by the C<recreate_pid_write>
option.  C<newsyslog> then needs to be configured as in

    # newsyslog.conf configuration for compressing archive files and
    # sending a signal to the Log4perl-enabled application
    /tmp/test.log 666  12  5  *  B /tmp/myappid 30

to send the defined signal (30, which is USR1 on FreeBSD) to the
application process at rotation time. Note that the signal number
is different on Linux, where USR1 denotes as 10. Check C<man signal>
for details.

=head2 How can a process under user id A log to a file under user id B?

This scenario often occurs in configurations where processes run under
various user IDs but need to write to a log file under a fixed, but 
different user id. 

With a traditional file appender, the log file will probably be created
under one user's id and appended to under a different user's id. With
a typical umask of 0002, the file will be created with -rw-rw-r--
permissions. If a user who's not in the first user's group
subsequently appends to the log file, it will fail because of a
permission problem.

Two potential solutions come to mind:

=over 4

=item *

Creating the file with a umask of 0000 will allow all users to append
to the log file. Log4perl's file appender C<Log::Log4perl::Appender::File>
has an C<umask> option that can be set to support this:

    log4perl.appender.File = Log::Log4perl::Appender::File
    log4perl.appender.File.umask = sub { 0000 };

This way, the log file will be created with -rw-rw-rw- permissions and
therefore has world write permissions. This might open up the logfile
for unwanted manipulations by arbitrary users, though.

=item *

Running the process under an effective user id of C<root> will allow
it to write to the log file, no matter who started the process.
However, this is not a good idea, because of security concerns.

=back

Luckily, under Unix, there's the syslog daemon which runs as root and
takes log requests from user processes over a socket and writes them
to log files as configured in C</etc/syslog.conf>.

By modifying C</etc/syslog.conf> and HUPing the syslog daemon, you can
configure new log files:

    # /etc/syslog.conf
    ...
    user.* /some/path/file.log

Using the C<Log::Dispatch::Syslog> appender, which comes with the
C<Log::Log4perl> distribution, you can then send messages via syslog:

    use Log::Log4perl qw(:easy);

    Log::Log4perl->init(\<<EOT);
        log4perl.logger = DEBUG, app
        log4perl.appender.app=Log::Dispatch::Syslog
        log4perl.appender.app.Facility=user
        log4perl.appender.app.layout=SimpleLayout
    EOT
    
        # Writes to /some/path/file.log
    ERROR "Message!";

This way, the syslog daemon will solve the permission problem. 

Note that while it is possible to use syslog() without Log4perl (syslog
supports log levels, too), traditional syslog setups have a
significant drawback.

Without Log4perl's ability to activate logging in only specific
parts of a system, complex systems will trigger log events all over
the place and slow down execution to a crawl at high debug levels.

Remote-controlling logging in the hierarchical parts of an application
via Log4perl's categories is one of its most distinguished features.
It allows for enabling high debug levels in specified areas without
noticeable performance impact.

=head2 I want to use UTC instead of the local time!

If a layout defines a date, Log::Log4perl uses local time to populate it.
If you want UTC instead, set

    $Log::Log4perl::DateFormat::GMTIME = 1;

in your program before the first log statement.

=head2 Can Log4perl intercept messages written to a filehandle?

You have a function that prints to a filehandle. You want to tie
into that filehandle and forward all arriving messages to a
Log4perl logger.

First, let's write a package that ties a file handle and forwards it
to a Log4perl logger:

    package FileHandleLogger;
    use Log::Log4perl qw(:levels get_logger);

    sub TIEHANDLE {
       my($class, %options) = @_;

       my $self = {
           level    => $DEBUG,
           category => '',
           %options
       };

       $self->{logger} = get_logger($self->{category}),
       bless $self, $class;
    }

    sub PRINT {
        my($self, @rest) = @_;
        $Log::Log4perl::caller_depth++;
        $self->{logger}->log($self->{level}, @rest);
        $Log::Log4perl::caller_depth--;
    }

    sub PRINTF {
        my($self, $fmt, @rest) = @_;
        $Log::Log4perl::caller_depth++;
        $self->PRINT(sprintf($fmt, @rest));
        $Log::Log4perl::caller_depth--;
    }

    1;

Now, if you have a function like

    sub function_printing_to_fh {
        my($fh) = @_;
        printf $fh "Hi there!\n";
    }

which takes a filehandle and prints something to it, it can be used
with Log4perl:

    use Log::Log4perl qw(:easy);
    usa FileHandleLogger;

    Log::Log4perl->easy_init($DEBUG);

    tie *SOMEHANDLE, 'FileHandleLogger' or
        die "tie failed ($!)";

    function_printing_to_fh(*SOMEHANDLE);
        # prints "2007/03/22 21:43:30 Hi there!"

If you want, you can even specify a different log level or category:

    tie *SOMEHANDLE, 'FileHandleLogger',
        level => $INFO, category => "Foo::Bar" or die "tie failed ($!)";

=head2 I want multiline messages rendered line-by-line!

With the standard C<PatternLayout>, if you send a multiline message to
an appender as in

    use Log::Log4perl qw(:easy);
    Log

it gets rendered this way:

    2007/04/04 23:23:39 multi
    line
    message

If you want each line to be rendered separately according to
the layout use C<Log::Log4perl::Layout::PatternLayout::Multiline>:

    use Log::Log4perl qw(:easy);

    Log::Log4perl->init(\<<EOT);
      log4perl.category         = DEBUG, Screen
      log4perl.appender.Screen = Log::Log4perl::Appender::Screen
      log4perl.appender.Screen.layout = \\
        Log::Log4perl::Layout::PatternLayout::Multiline
      log4perl.appender.Screen.layout.ConversionPattern = %d %m %n
    EOT
    
    DEBUG "some\nmultiline\nmessage";

and you'll get 

    2007/04/04 23:23:39 some 
    2007/04/04 23:23:39 multiline 
    2007/04/04 23:23:39 message 

instead.

=head2 I'm on Windows and I'm getting all these 'redefined' messages!

If you're on Windows and are getting warning messages like

  Constant subroutine Log::Log4perl::_INTERNAL_DEBUG redefined at
    C:/Programme/Perl/lib/constant.pm line 103.
  Subroutine import redefined at
    C:/Programme/Perl/site/lib/Log/Log4Perl.pm line 69.
  Subroutine initialized redefined at
    C:/Programme/Perl/site/lib/Log/Log4Perl.pm line 207.

then chances are that you're using 'Log::Log4Perl' (wrong uppercase P) 
instead of the correct 'Log::Log4perl'. Perl on Windows doesn't
handle this error well and spits out a slew of confusing warning
messages. But now you know, just use the correct module name and
you'll be fine.

=head2 Log4perl complains that no initialization happened during shutdown!

If you're using Log4perl log commands in DESTROY methods of your objects,
you might see confusing messages like

    Log4perl: Seems like no initialization happened. Forgot to call init()?
    Use of uninitialized value in subroutine entry at
    /home/y/lib/perl5/site_perl/5.6.1/Log/Log4perl.pm line 134 during global
    destruction. (in cleanup) Undefined subroutine &main:: called at
    /home/y/lib/perl5/site_perl/5.6.1/Log/Log4perl.pm line 134 during global
    destruction.

when the program shuts down. What's going on? 

This phenomenon happens if you have circular references in your objects, 
which perl can't clean up when an object goes out of scope but waits
until global destruction instead. At this time, however, Log4perl has
already shut down, so you can't use it anymore.

For example, here's a simple class which uses a logger in its DESTROY
method:

    package A;
    use Log::Log4perl qw(:easy);
    sub new { bless {}, shift }
    sub DESTROY { DEBUG "Waaah!"; }

Now, if the main program creates a self-referencing object, like in

    package main;
    use Log::Log4perl qw(:easy);
    Log::Log4perl->easy_init($DEBUG);

    my $a = A->new();
    $a->{selfref} = $a;

then you'll see the error message shown above during global destruction.
How to tackle this problem?

First, you should clean up your circular references before global 
destruction. They will not only cause objects to be destroyed in an order
that's hard to predict, but also eat up memory until the program shuts
down.

So, the program above could easily be fixed by putting

    $a->{selfref} = undef;

at the end or in an END handler. If that's hard to do, use weak references:

    package main;
    use Scalar::Util qw(weaken);
    use Log::Log4perl qw(:easy);
    Log::Log4perl->easy_init($DEBUG);

    my $a = A->new();
    $a->{selfref} = weaken $a;

This allows perl to clean up the circular reference when the object 
goes out of scope, and doesn't wait until global destruction.

=head2 How can I access POE heap values from Log4perl's layout?

POE is a framework for creating multitasked applications running in a
single process and a single thread. POE's threads equivalents are
'sessions' and since they run quasi-simultaneously, you can't use
Log4perl's global NDC/MDC to hold session-specific data.

However, POE already maintains a data store for every session. It is called
'heap' and is just a hash storing session-specific data in key-value pairs.
To access this per-session heap data from a Log4perl layout, define a
custom cspec and reference it with the newly defined pattern in the layout:

    use strict;
    use POE;
    use Log::Log4perl qw(:easy);

    Log::Log4perl->init( \ q{
        log4perl.logger = DEBUG, Screen
        log4perl.appender.Screen = Log::Log4perl::Appender::Screen
        log4perl.appender.Screen.layout = PatternLayout
        log4perl.appender.Screen.layout.ConversionPattern = %U %m%n
        log4perl.PatternLayout.cspec.U = \
            sub { POE::Kernel->get_active_session->get_heap()->{ user } }
    } );

    for (qw( Huey Lewey Dewey )) {
        POE::Session->create(
            inline_states => {
                _start    => sub {
                    $_[HEAP]->{user} = $_;
                    POE::Kernel->yield('hello');
                },
                hello     => sub {
                    DEBUG "I'm here now";
                }
            }
        );
    }

    POE::Kernel->run();
    exit;

The code snippet above defines a new layout placeholder (called
'cspec' in Log4perl) %U which calls a subroutine, retrieves the active
session, gets its heap and looks up the entry specified ('user').

Starting with Log::Log4perl 1.20, cspecs also support parameters in 
curly braces, so you can say

    log4perl.appender.Screen.layout.ConversionPattern = %U{user} %U{id} %m%n
    log4perl.PatternLayout.cspec.U = \
            sub { POE::Kernel->get_active_session-> \
                  get_heap()->{ $_[0]->{curlies} } }

and print the POE session heap entries 'user' and 'id' with every logged
message. For more details on cpecs, read the PatternLayout manual.

=head2 I want to print something unconditionally!

Sometimes it's a script that's supposed to log messages regardless if
Log4perl has been initialized or not. Or there's a logging statement that's
not going to be suppressed under any circumstances -- many people want to
have the final word, make the executive decision, because it seems like
the only logical choice.

But think about it:
First off, if a messages is supposed to be printed, where is it supposed
to end up at? STDOUT? STDERR? And are you sure you want to set in stone
that this message needs to be printed, while someone else might
find it annoying and wants to get rid of it?

The truth is, there's always going to be someone who wants to log a 
messages at all cost, but also another person who wants to suppress it
with equal vigilance. There's no good way to serve these two conflicting 
desires, someone will always want to win at the cost of leaving 
the other party dissappointed.

So, the best Log4perl offers is the ALWAYS level for a message that even
fires if the system log level is set to $OFF:

    use Log::Log4perl qw(:easy);

    Log::Log4perl->easy_init( $OFF );
    ALWAYS "This gets logged always. Well, almost always";

The logger won't fire, though, if Log4perl hasn't been initialized or
if someone defines a custom log hurdle that's higher than $OFF. 

Bottom line: Leave the setting of the logging level to the initial Perl 
script -- let their owners decided what they want, no matter how tempting
it may be to decide it for them.

=cut 

=head1 SEE ALSO

Log::Log4perl

=head1 LICENSE

Copyright 2002-2013 by Mike Schilli E<lt>m@perlmeister.comE<gt> 
and Kevin Goess E<lt>cpan@goess.orgE<gt>.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself. 

=head1 AUTHOR

Please contribute patches to the project on Github:

    http://github.com/mschilli/log4perl

Send bug reports or requests for enhancements to the authors via our

MAILING LIST (questions, bug reports, suggestions/patches): 
log4perl-devel@lists.sourceforge.net

Authors (please contact them via the list above, not directly):
Mike Schilli <m@perlmeister.com>,
Kevin Goess <cpan@goess.org>

Contributors (in alphabetical order):
Ateeq Altaf, Cory Bennett, Jens Berthold, Jeremy Bopp, Hutton
Davidson, Chris R. Donnelly, Matisse Enzer, Hugh Esco, Anthony
Foiani, James FitzGibbon, Carl Franks, Dennis Gregorovic, Andy
Grundman, Paul Harrington, Alexander Hartmaier  David Hull, 
Robert Jacobson, Jason Kohles, Jeff Macdonald, Markus Peter, 
Brett Rann, Peter Rabbitson, Erik Selberg, Aaron Straup Cope, 
Lars Thegler, David Viner, Mac Yang.