summaryrefslogtreecommitdiff
path: root/toolkit/components/telemetry/gen-event-data.py
blob: 0884dbba0a8a1e6748c40f8f72ab6ace4f50970c (plain)
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
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# Write out event information for C++. The events are defined
# in a file provided as a command-line argument.

from __future__ import print_function
from shared_telemetry_utils import StringTable, static_assert

import parse_events
import sys
import itertools

# The banner/text at the top of the generated file.
banner = """/* This file is auto-generated, only for internal use in TelemetryEvent.h,
   see gen-event-data.py. */
"""

file_header = """\
#ifndef mozilla_TelemetryEventData_h
#define mozilla_TelemetryEventData_h
#include "EventInfo.h"
namespace {
"""

file_footer = """\
} // namespace
#endif // mozilla_TelemetryEventData_h
"""

def write_extra_table(events, output, string_table):
    table_name = "gExtraKeysTable"
    extra_table = []
    extra_count = 0

    print("const uint32_t %s[] = {" % table_name, file=output)

    for e in events:
        extra_index = 0
        extra_keys = e.extra_keys
        if len(extra_keys) > 0:
            extra_index = extra_count
            extra_count += len(extra_keys)
            indexes = string_table.stringIndexes(extra_keys)

            print("  // %s, [%s], [%s]" % (
                    e.category,
                    ", ".join(e.methods),
                    ", ".join(e.objects)),
                  file=output)
            print("  // extra_keys: %s" % ", ".join(extra_keys), file=output)
            print("  %s," % ", ".join(map(str, indexes)),
                  file=output)

        extra_table.append((extra_index, len(extra_keys)))

    print("};", file=output)
    static_assert(output, "sizeof(%s) <= UINT32_MAX" % table_name,
                  "index overflow")

    return extra_table

def write_common_event_table(events, output, string_table, extra_table):
    table_name = "gCommonEventInfo"
    extra_count = 0

    print("const CommonEventInfo %s[] = {" % table_name, file=output)
    for e,extras in zip(events, extra_table):
        # Write a comment to make the file human-readable.
        print("  // category: %s" % e.category, file=output)
        print("  // methods: [%s]" % ", ".join(e.methods), file=output)
        print("  // objects: [%s]" % ", ".join(e.objects), file=output)

        # Write the common info structure
        print("  {%d, %d, %d, %d, %d, %s}," %
                (string_table.stringIndex(e.category),
                 string_table.stringIndex(e.expiry_version),
                 extras[0], # extra keys index
                 extras[1], # extra keys count
                 e.expiry_day,
                 e.dataset),
              file=output)

    print("};", file=output)
    static_assert(output, "sizeof(%s) <= UINT32_MAX" % table_name,
                  "index overflow")

def write_event_table(events, output, string_table):
    table_name = "gEventInfo"
    print("const EventInfo %s[] = {" % table_name, file=output)

    for common_info_index,e in enumerate(events):
        for method_name, object_name in itertools.product(e.methods, e.objects):
            print("  // category: %s, method: %s, object: %s" %
                    (e.category, method_name, object_name),
                  file=output)

            print("  {gCommonEventInfo[%d], %d, %d}," %
                    (common_info_index,
                     string_table.stringIndex(method_name),
                     string_table.stringIndex(object_name)),
                  file=output)

    print("};", file=output)
    static_assert(output, "sizeof(%s) <= UINT32_MAX" % table_name,
                  "index overflow")

def main(output, *filenames):
    # Load the event data.
    if len(filenames) > 1:
        raise Exception('We don\'t support loading from more than one file.')
    events = parse_events.load_events(filenames[0])

    # Write the scalar data file.
    print(banner, file=output)
    print(file_header, file=output)

    # Write the extra keys table.
    string_table = StringTable()
    extra_table = write_extra_table(events, output, string_table)
    print("", file=output)

    # Write a table with the common event data.
    write_common_event_table(events, output, string_table, extra_table)
    print("", file=output)

    # Write the data for individual events.
    write_event_table(events, output, string_table)
    print("", file=output)

    # Write the string table.
    string_table_name = "gEventsStringTable"
    string_table.writeDefinition(output, string_table_name)
    static_assert(output, "sizeof(%s) <= UINT32_MAX" % string_table_name,
                  "index overflow")
    print("", file=output)

    print(file_footer, file=output)

if __name__ == '__main__':
    main(sys.stdout, *sys.argv[1:])