blob: 080e957b22326485c3e541315cdb58ee074c02d5 [file] [log] [blame]
/*
* 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.
*/
#ifndef ANDROID_STATS_LOG_STATS_EVENT_H
#define ANDROID_STATS_LOG_STATS_EVENT_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
/*
* Functionality to build and store the buffer sent over the statsd socket.
* This code defines and encapsulates the socket protocol.
*
* Usage:
* struct stats_event* event = stats_event_obtain();
*
* stats_event_set_atom_id(event, atomId);
* stats_event_write_int32(event, 24);
* stats_event_add_bool_annotation(event, 1, true); // annotations apply to the previous field
* stats_event_add_int32_annotation(event, 2, 128);
* stats_event_write_float(event, 2.0);
*
* stats_event_build(event);
* stats_event_write(event);
* stats_event_release(event);
*
* Notes:
* (a) write_<type>() and add_<type>_annotation() should be called in the order that fields
* and annotations are defined in the atom.
* (b) set_atom_id() can be called anytime before stats_event_write().
* (c) add_<type>_annotation() calls apply to the previous field.
* (d) If errors occur, stats_event_write() will write a bitmask of the errors to the socket.
* (e) All strings should be encoded using UTF8.
*/
/* ERRORS */
#define ERROR_NO_TIMESTAMP 0x1
#define ERROR_NO_ATOM_ID 0x2
#define ERROR_OVERFLOW 0x4
#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8
#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10
#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20
#define ERROR_INVALID_ANNOTATION_ID 0x40
#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80
#define ERROR_TOO_MANY_ANNOTATIONS 0x100
#define ERROR_TOO_MANY_FIELDS 0x200
#define ERROR_INVALID_VALUE_TYPE 0x400
#define ERROR_STRING_NOT_NULL_TERMINATED 0x800
/* TYPE IDS */
#define INT32_TYPE 0x00
#define INT64_TYPE 0x01
#define STRING_TYPE 0x02
#define LIST_TYPE 0x03
#define FLOAT_TYPE 0x04
#define BOOL_TYPE 0x05
#define BYTE_ARRAY_TYPE 0x06
#define OBJECT_TYPE 0x07
#define KEY_VALUE_PAIRS_TYPE 0x08
#define ATTRIBUTION_CHAIN_TYPE 0x09
#define ERROR_TYPE 0x0F
#ifdef __cplusplus
extern "C" {
#endif // __CPLUSPLUS
struct stats_event;
/* SYSTEM API */
struct stats_event* stats_event_obtain();
// The build function can be called multiple times without error. If the event
// has been built before, this function is a no-op.
void stats_event_build(struct stats_event* event);
int stats_event_write(struct stats_event* event);
void stats_event_release(struct stats_event* event);
void stats_event_set_atom_id(struct stats_event* event, uint32_t atomId);
void stats_event_write_int32(struct stats_event* event, int32_t value);
void stats_event_write_int64(struct stats_event* event, int64_t value);
void stats_event_write_float(struct stats_event* event, float value);
void stats_event_write_bool(struct stats_event* event, bool value);
void stats_event_write_byte_array(struct stats_event* event, const uint8_t* buf, size_t numBytes);
// Buf must be null-terminated.
void stats_event_write_string8(struct stats_event* event, const char* value);
// Tags must be null-terminated.
void stats_event_write_attribution_chain(struct stats_event* event, const uint32_t* uids,
const char* const* tags, uint8_t numNodes);
/* key_value_pair struct can be constructed as follows:
* struct key_value_pair pair = {.key = key, .valueType = STRING_TYPE,
* .stringValue = buf};
*/
struct key_value_pair {
int32_t key;
uint8_t valueType; // expected to be INT32_TYPE, INT64_TYPE, FLOAT_TYPE, or STRING_TYPE
union {
int32_t int32Value;
int64_t int64Value;
float floatValue;
const char* stringValue; // must be null terminated
};
};
void stats_event_write_key_value_pairs(struct stats_event* event, struct key_value_pair* pairs,
uint8_t numPairs);
void stats_event_add_bool_annotation(struct stats_event* event, uint8_t annotationId, bool value);
void stats_event_add_int32_annotation(struct stats_event* event, uint8_t annotationId,
int32_t value);
uint32_t stats_event_get_atom_id(struct stats_event* event);
// Size is an output parameter.
uint8_t* stats_event_get_buffer(struct stats_event* event, size_t* size);
uint32_t stats_event_get_errors(struct stats_event* event);
// This table is used by StatsEventCompat to access the stats_event API.
struct stats_event_api_table {
struct stats_event* (*obtain)(void);
void (*build)(struct stats_event*);
int (*write)(struct stats_event*);
void (*release)(struct stats_event*);
void (*set_atom_id)(struct stats_event*, uint32_t);
void (*write_int32)(struct stats_event*, int32_t);
void (*write_int64)(struct stats_event*, int64_t);
void (*write_float)(struct stats_event*, float);
void (*write_bool)(struct stats_event*, bool);
void (*write_byte_array)(struct stats_event*, const uint8_t*, size_t);
void (*write_string8)(struct stats_event*, const char*);
void (*write_attribution_chain)(struct stats_event*, const uint32_t*, const char* const*,
uint8_t);
void (*write_key_value_pairs)(struct stats_event*, struct key_value_pair*, uint8_t);
void (*add_bool_annotation)(struct stats_event*, uint8_t, bool);
void (*add_int32_annotation)(struct stats_event*, uint8_t, int32_t);
uint32_t (*get_atom_id)(struct stats_event*);
uint8_t* (*get_buffer)(struct stats_event*, size_t*);
uint32_t (*get_errors)(struct stats_event*);
};
// exposed for benchmarking only
void stats_event_truncate_buffer(struct stats_event* event, bool truncate);
#ifdef __cplusplus
}
#endif // __CPLUSPLUS
#endif // ANDROID_STATS_LOG_STATS_EVENT_H