Create stats_buffer_writer

Move iovec* construction and noteLogLoss from stats_event_list to
stats_buffer_writer.h.
Expose write_buffer_to_statsd that takes in a byte array and writes
it to the statsd socket. Currently exposed for StatsLog.write JNI call.

This change also allows getting rid of stats_event_list once all clients
have migrated to stats_event

Bug: 145619049
Test: m -j libstatssocket
Change-Id: I0048e392c2f5039eb70dacf4e91a43d3f32e8749
This commit is contained in:
Muhammad Qureshi 2019-11-06 15:15:23 -08:00
parent 876f64cb2f
commit f9b24aef5f
7 changed files with 169 additions and 99 deletions

View File

@ -20,7 +20,10 @@
cc_library {
name: "libstatssocket",
srcs: [
"stats_buffer_writer.c",
"stats_event.c",
// TODO(b/145573568): Remove stats_event_list once stats_event
// migration is complete.
"stats_event_list.c",
"statsd_writer.c",
],

View File

@ -0,0 +1,29 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif // __CPLUSPLUS
void stats_log_close();
int write_buffer_to_statsd(void* buffer, size_t size, uint32_t atomId);
#ifdef __cplusplus
}
#endif // __CPLUSPLUS

View File

@ -76,7 +76,7 @@
#ifdef __cplusplus
extern "C" {
#endif
#endif // __CPLUSPLUS
struct stats_event;
@ -132,6 +132,6 @@ uint32_t stats_event_get_errors(struct stats_event* event);
#ifdef __cplusplus
}
#endif
#endif // __CPLUSPLUS
#endif // ANDROID_STATS_LOG_STATS_EVENT_H

View File

@ -24,11 +24,9 @@ extern "C" {
#endif
void reset_log_context(android_log_context ctx);
int write_to_logger(android_log_context context, log_id_t id);
void note_log_drop(int error, int atom_tag);
void note_log_drop(int error, int atomId);
void stats_log_close();
int android_log_write_char_array(android_log_context ctx, const char* value, size_t len);
extern int (*write_to_statsd)(struct iovec* vec, size_t nr);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,130 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "include/stats_buffer_writer.h"
#ifdef __ANDROID__
#include <cutils/properties.h>
#endif
#include <errno.h>
#include <sys/time.h>
#include <sys/uio.h>
#include "statsd_writer.h"
static const uint32_t kStatsEventTag = 1937006964;
extern struct android_log_transport_write statsdLoggerWrite;
static int __write_to_statsd_init(struct iovec* vec, size_t nr);
static int (*__write_to_statsd)(struct iovec* vec, size_t nr) = __write_to_statsd_init;
void note_log_drop(int error, int atomId) {
statsdLoggerWrite.noteDrop(error, atomId);
}
void stats_log_close() {
statsd_writer_init_lock();
__write_to_statsd = __write_to_statsd_init;
if (statsdLoggerWrite.close) {
(*statsdLoggerWrite.close)();
}
statsd_writer_init_unlock();
}
int write_buffer_to_statsd(void* buffer, size_t size, uint32_t atomId) {
int ret = 1;
#ifdef __ANDROID__
bool statsdEnabled = property_get_bool("ro.statsd.enable", true);
#else
bool statsdEnabled = false;
#endif
if (statsdEnabled) {
struct iovec vecs[2];
vecs[0].iov_base = (void*)&kStatsEventTag;
vecs[0].iov_len = sizeof(kStatsEventTag);
vecs[1].iov_base = buffer;
vecs[1].iov_len = size;
ret = __write_to_statsd(vecs, 2);
if (ret < 0) {
note_log_drop(ret, atomId);
}
}
return ret;
}
static int __write_to_stats_daemon(struct iovec* vec, size_t nr) {
int save_errno;
struct timespec ts;
size_t len, i;
for (len = i = 0; i < nr; ++i) {
len += vec[i].iov_len;
}
if (!len) {
return -EINVAL;
}
save_errno = errno;
#if defined(__ANDROID__)
clock_gettime(CLOCK_REALTIME, &ts);
#else
struct timeval tv;
gettimeofday(&tv, NULL);
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000;
#endif
int ret = (int)(*statsdLoggerWrite.write)(&ts, vec, nr);
errno = save_errno;
return ret;
}
static int __write_to_statsd_initialize_locked() {
if (!statsdLoggerWrite.open || ((*statsdLoggerWrite.open)() < 0)) {
if (statsdLoggerWrite.close) {
(*statsdLoggerWrite.close)();
return -ENODEV;
}
}
return 1;
}
static int __write_to_statsd_init(struct iovec* vec, size_t nr) {
int ret, save_errno = errno;
statsd_writer_init_lock();
if (__write_to_statsd == __write_to_statsd_init) {
ret = __write_to_statsd_initialize_locked();
if (ret < 0) {
statsd_writer_init_unlock();
errno = save_errno;
return ret;
}
__write_to_statsd = __write_to_stats_daemon;
}
statsd_writer_init_unlock();
ret = __write_to_statsd(vec, nr);
errno = save_errno;
return ret;
}

View File

@ -18,7 +18,7 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "include/stats_event_list.h"
#include "stats_buffer_writer.h"
#define STATS_EVENT_TAG 1937006964
#define LOGGER_ENTRY_MAX_PAYLOAD 4068
@ -323,11 +323,5 @@ void stats_event_build(struct stats_event* event) {
void stats_event_write(struct stats_event* event) {
stats_event_build(event);
// Prepare iovecs for write to statsd.
struct iovec vecs[2];
vecs[0].iov_base = &event->tag;
vecs[0].iov_len = sizeof(event->tag);
vecs[1].iov_base = &event->buf;
vecs[1].iov_len = event->size;
write_to_statsd(vecs, 2);
write_buffer_to_statsd(&event->buf, event->size, event->atomId);
}

View File

@ -18,7 +18,7 @@
#include <string.h>
#include <sys/time.h>
#include "statsd_writer.h"
#include "stats_buffer_writer.h"
#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
@ -38,11 +38,6 @@ typedef struct {
uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD];
} android_log_context_internal;
extern struct android_log_transport_write statsdLoggerWrite;
static int __write_to_statsd_init(struct iovec* vec, size_t nr);
int (*write_to_statsd)(struct iovec* vec, size_t nr) = __write_to_statsd_init;
// Similar to create_android_logger(), but instead of allocation a new buffer,
// this function resets the buffer for resuse.
void reset_log_context(android_log_context ctx) {
@ -92,12 +87,7 @@ int stats_write_list(android_log_context ctx) {
msg += sizeof(uint8_t) + sizeof(uint8_t);
}
struct iovec vec[2];
vec[0].iov_base = &context->tag;
vec[0].iov_len = sizeof(context->tag);
vec[1].iov_base = (void*)msg;
vec[1].iov_len = len;
return write_to_statsd(vec, 2);
return write_buffer_to_statsd((void*)msg, len, 0);
}
int write_to_logger(android_log_context ctx, log_id_t id) {
@ -120,80 +110,6 @@ int write_to_logger(android_log_context ctx, log_id_t id) {
return retValue;
}
void note_log_drop(int error, int tag) {
statsdLoggerWrite.noteDrop(error, tag);
}
void stats_log_close() {
statsd_writer_init_lock();
write_to_statsd = __write_to_statsd_init;
if (statsdLoggerWrite.close) {
(*statsdLoggerWrite.close)();
}
statsd_writer_init_unlock();
}
/* log_init_lock assumed */
static int __write_to_statsd_initialize_locked() {
if (!statsdLoggerWrite.open || ((*statsdLoggerWrite.open)() < 0)) {
if (statsdLoggerWrite.close) {
(*statsdLoggerWrite.close)();
return -ENODEV;
}
}
return 1;
}
static int __write_to_stats_daemon(struct iovec* vec, size_t nr) {
int save_errno;
struct timespec ts;
size_t len, i;
for (len = i = 0; i < nr; ++i) {
len += vec[i].iov_len;
}
if (!len) {
return -EINVAL;
}
save_errno = errno;
#if defined(__ANDROID__)
clock_gettime(CLOCK_REALTIME, &ts);
#else
struct timeval tv;
gettimeofday(&tv, NULL);
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000;
#endif
int ret = (int)(*statsdLoggerWrite.write)(&ts, vec, nr);
errno = save_errno;
return ret;
}
static int __write_to_statsd_init(struct iovec* vec, size_t nr) {
int ret, save_errno = errno;
statsd_writer_init_lock();
if (write_to_statsd == __write_to_statsd_init) {
ret = __write_to_statsd_initialize_locked();
if (ret < 0) {
statsd_writer_init_unlock();
errno = save_errno;
return ret;
}
write_to_statsd = __write_to_stats_daemon;
}
statsd_writer_init_unlock();
ret = write_to_statsd(vec, nr);
errno = save_errno;
return ret;
}
static inline void copy4LE(uint8_t* buf, uint32_t val) {
buf[0] = val & 0xFF;
buf[1] = (val >> 8) & 0xFF;