File: logging.c

package info (click to toggle)
aws-crt-python 0.20.4%2Bdfsg-1~bpo12%2B1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-backports
  • size: 72,656 kB
  • sloc: ansic: 381,805; python: 23,008; makefile: 6,251; sh: 4,536; cpp: 699; ruby: 208; java: 77; perl: 73; javascript: 46; xml: 11
file content (172 lines) | stat: -rw-r--r-- 5,328 bytes parent folder | download
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
/**
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

#include <android/log.h>

#include <aws/common/clock.h>
#include <aws/common/logging.h>
#include <aws/common/string.h>

#include <inttypes.h>
#include <stdarg.h>

#define LOGCAT_MAX_BUFFER_SIZE (4 * 1024)

struct logcat_format_data {
    char *buffer;
    size_t bytes_written;
    size_t total_length;
    const char *format;
};

static size_t s_advance_and_clamp_index(size_t current_index, int amount, size_t maximum) {
    size_t next_index = current_index + amount;
    if (next_index > maximum) {
        next_index = maximum;
    }

    return next_index;
}

/* Override this for Android, as time and log level are taken care of by logcat */
static int s_logcat_format(struct logcat_format_data *formatting_data, va_list args) {
    size_t current_index = 0;

    if (formatting_data->total_length == 0) {
        return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
    }

    /*
     * Use this length for all but the last write, so we guarantee room for the newline even if we get truncated
     */
    size_t fake_total_length = formatting_data->total_length - 1;

    if (current_index < fake_total_length) {
        /*
         * Add thread id and user content separator (" - ")
         */
        aws_thread_id_t current_thread_id = aws_thread_current_thread_id();
        char thread_id[AWS_THREAD_ID_T_REPR_BUFSZ];
        if (aws_thread_id_t_to_string(current_thread_id, thread_id, AWS_THREAD_ID_T_REPR_BUFSZ)) {
            return AWS_OP_ERR;
        }
        int thread_id_written =
            snprintf(formatting_data->buffer + current_index, fake_total_length - current_index, "[%s] ", thread_id);
        if (thread_id_written < 0) {
            return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
        }
        current_index = s_advance_and_clamp_index(current_index, thread_id_written, fake_total_length);
    }

    if (current_index < fake_total_length) {
        uint64_t now = 0;
        aws_high_res_clock_get_ticks(&now);

        int current_time_written = snprintf(
            formatting_data->buffer + current_index, fake_total_length - current_index, "(HRC:%" PRIu64 ") ", now);
        if (current_time_written < 0) {
            return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
        }
        current_index = s_advance_and_clamp_index(current_index, current_time_written, fake_total_length);
    }

    if (current_index < fake_total_length) {
        int separator_written =
            snprintf(formatting_data->buffer + current_index, fake_total_length - current_index, " - ");
        current_index = s_advance_and_clamp_index(current_index, separator_written, fake_total_length);
    }

    if (current_index < fake_total_length) {
        /*
         * Now write the actual data requested by the user
         */

        int written_count = vsnprintf(
            formatting_data->buffer + current_index, fake_total_length - current_index, formatting_data->format, args);

        if (written_count < 0) {
            return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
        }

        current_index = s_advance_and_clamp_index(current_index, written_count, fake_total_length);
    }

    /*
     * End with a newline.
     */
    int newline_written_count =
        snprintf(formatting_data->buffer + current_index, formatting_data->total_length - current_index, "\n");
    if (newline_written_count < 0) {
        return aws_raise_error(AWS_ERROR_UNKNOWN); /* we saved space, so this would be crazy */
    }

    formatting_data->bytes_written = current_index + newline_written_count;

    return AWS_OP_SUCCESS;
}

static struct aws_logger_logcat { enum aws_log_level level; } s_logcat_impl;

static int s_logcat_log(
    struct aws_logger *logger,
    enum aws_log_level log_level,
    aws_log_subject_t subject,
    const char *format,
    ...) {
    (void)logger;

    va_list format_args;
    va_start(format_args, format);

    char buffer[LOGCAT_MAX_BUFFER_SIZE];
    struct logcat_format_data fmt = {
        .buffer = buffer,
        .total_length = AWS_ARRAY_SIZE(buffer),
        .format = format,
    };

    int result = s_logcat_format(&fmt, format_args);

    va_end(format_args);

    if (result != AWS_OP_SUCCESS) {
        return AWS_OP_ERR;
    }

    /* ANDROID_LOG_VERBOSE = 2, ANDROID_LOG_FATAL = 7 */
    const int prio = 0x8 - log_level;
    __android_log_write(prio, aws_log_subject_name(subject), buffer);

    return AWS_OP_SUCCESS;
}

static enum aws_log_level s_logcat_get_log_level(struct aws_logger *logger, aws_log_subject_t subject) {
    (void)subject;
    struct aws_logger_logcat *impl = logger->p_impl;
    return impl->level;
}

static void s_logcat_clean_up(struct aws_logger *logger) {
    logger->p_impl = NULL;
}

static struct aws_logger_vtable s_logcat_vtable = {
    .log = s_logcat_log,
    .get_log_level = s_logcat_get_log_level,
    .clean_up = s_logcat_clean_up,
};

int aws_logger_init_logcat(
    struct aws_logger *logger,
    struct aws_allocator *allocator,
    struct aws_logger_standard_options *options) {

    logger->allocator = allocator;
    logger->vtable = &s_logcat_vtable;
    logger->p_impl = &s_logcat_impl;
    s_logcat_impl.level = options->level;

    return AWS_OP_SUCCESS;
}