AndroidHandler.java revision ef0996ffa36cfe9b7927e09aece801fb4f594ced
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.logging;
18
19import android.util.Log;
20
21import java.util.logging.*;
22import java.util.Date;
23import java.text.MessageFormat;
24import java.io.PrintWriter;
25import java.io.StringWriter;
26
27/**
28 * Implements a {@link java.util.logging.Logger} handler that writes to the Android log. The
29 * implementation is rather straightforward. The name of the logger serves as
30 * the log tag. Only the log levels need to be converted appropriately. For
31 * this purpose, the following mapping is being used:
32 *
33 * <table>
34 *   <tr>
35 *     <th>logger level</th>
36 *     <th>Android level</th>
37 *   </tr>
38 *   <tr>
39 *     <td>
40 *       SEVERE
41 *     </td>
42 *     <td>
43 *       ERROR
44 *     </td>
45 *   </tr>
46 *   <tr>
47 *     <td>
48 *       WARNING
49 *     </td>
50 *     <td>
51 *       WARN
52 *     </td>
53 *   </tr>
54 *   <tr>
55 *     <td>
56 *       INFO
57 *     </td>
58 *     <td>
59 *       INFO
60 *     </td>
61 *   </tr>
62 *   <tr>
63 *     <td>
64 *       CONFIG
65 *     </td>
66 *     <td>
67 *       DEBUG
68 *     </td>
69 *   </tr>
70 *   <tr>
71 *     <td>
72 *       FINE, FINER, FINEST
73 *     </td>
74 *     <td>
75 *       VERBOSE
76 *     </td>
77 *   </tr>
78 * </table>
79 */
80public class AndroidHandler extends Handler {
81    /**
82     * Holds the formatter for all Android log handlers.
83     */
84    private static final Formatter THE_FORMATTER = new Formatter() {
85        @Override
86        public String format(LogRecord r) {
87            Throwable thrown = r.getThrown();
88            if (thrown != null) {
89                StringWriter sw = new StringWriter();
90                PrintWriter pw = new PrintWriter(sw);
91                sw.write(r.getMessage());
92                sw.write("\n");
93                thrown.printStackTrace(pw);
94                pw.flush();
95                return sw.toString();
96            } else {
97                return r.getMessage();
98            }
99        }
100    };
101
102    /**
103     * Constructs a new instance of the Android log handler.
104     */
105    public AndroidHandler() {
106        setFormatter(THE_FORMATTER);
107    }
108
109    @Override
110    public void close() {
111        // No need to close, but must implement abstract method.
112    }
113
114    @Override
115    public void flush() {
116        // No need to flush, but must implement abstract method.
117    }
118
119    @Override
120    public void publish(LogRecord record) {
121        try {
122            int level = getAndroidLevel(record.getLevel());
123            String tag = record.getLoggerName();
124
125            if (tag == null) {
126                // Anonymous logger.
127                tag = "null";
128            } else {
129                // Tags must be <= 23 characters.
130                int length = tag.length();
131                if (length > 23) {
132                    // Most loggers use the full class name. Try dropping the
133                    // package.
134                    int lastPeriod = tag.lastIndexOf(".");
135                    if (length - lastPeriod - 1 <= 23) {
136                        tag = tag.substring(lastPeriod + 1);
137                    } else {
138                        // Use last 23 chars.
139                        tag = tag.substring(tag.length() - 23);
140                    }
141                }
142            }
143
144            if (!Log.isLoggable(tag, level)) {
145                return;
146            }
147
148            String message = getFormatter().format(record);
149            Log.println(level, tag, message);
150        } catch (RuntimeException e) {
151            Log.e("AndroidHandler", "Error logging message.", e);
152        }
153    }
154
155    /**
156     * Converts a {@link java.util.logging.Logger} logging level into an Android one.
157     *
158     * @param level The {@link java.util.logging.Logger} logging level.
159     *
160     * @return The resulting Android logging level.
161     */
162    static int getAndroidLevel(Level level) {
163        int value = level.intValue();
164        if (value >= 1000) { // SEVERE
165            return Log.ERROR;
166        } else if (value >= 900) { // WARNING
167            return Log.WARN;
168        } else if (value >= 800) { // INFO
169            return Log.INFO;
170        } else {
171            return Log.DEBUG;
172        }
173    }
174
175}
176