diff options
Diffstat (limited to 'third_party/python/glean_parser/glean_parser/templates/go_server.jinja2')
-rw-r--r-- | third_party/python/glean_parser/glean_parser/templates/go_server.jinja2 | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/third_party/python/glean_parser/glean_parser/templates/go_server.jinja2 b/third_party/python/glean_parser/glean_parser/templates/go_server.jinja2 new file mode 100644 index 0000000000..0a26831b0f --- /dev/null +++ b/third_party/python/glean_parser/glean_parser/templates/go_server.jinja2 @@ -0,0 +1,225 @@ +{# The final Go code is autogenerated, but this template is not. Please file bugs! #} +package glean + +// 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/. + +// AUTOGENERATED BY glean_parser v{{ parser_version }}. DO NOT EDIT. + +// required imports +import ( + "encoding/json" + "fmt" + "strconv" + "time" + + "github.com/google/uuid" +) + +// log type string used to identify logs to process in the Moz Data Pipeline +var gleanEventMozlogType string = "glean-server-event" + +type GleanEventsLogger struct { + AppID string // Application Id to identify application per Glean standards + AppDisplayVersion string // Version of application emitting the event + AppChannel string // Channel to differentiate logs from prod/beta/staging/devel +} + +// exported type for public method parameters +type RequestInfo struct { + UserAgent string + IpAddress string +} + +// default empty values will be omitted in json from ping struct definition +var defaultRequestInfo = RequestInfo{ + UserAgent: "", + IpAddress: "", +} + +// structs to construct the glean ping +type clientInfo struct { + TelemetrySDKBuild string `json:"telemetry_sdk_build"` + FirstRunDate string `json:"first_run_date"` + OS string `json:"os"` + OSVersion string `json:"os_version"` + Architecture string `json:"architecture"` + AppBuild string `json:"app_build"` + AppDisplayVersion string `json:"app_display_version"` + AppChannel string `json:"app_channel"` +} + +type pingInfo struct { + Seq int `json:"seq"` + StartTime string `json:"start_time"` + EndTime string `json:"end_time"` +} + +type ping struct { + DocumentNamespace string `json:"document_namespace"` + DocumentType string `json:"document_type"` + DocumentVersion string `json:"document_version"` + DocumentID string `json:"document_id"` + UserAgent string `json:"user_agent,omitempty"` + IpAddress string `json:"ip_address,omitempty"` + Payload string `json:"payload"` +} + +type metrics map[string]map[string]interface{} + +type pingPayload struct { + ClientInfo clientInfo `json:"client_info"` + PingInfo pingInfo `json:"ping_info"` + Metrics metrics `json:"metrics"` + Events []gleanEvent `json:"events"` +} + +type gleanEvent struct { + Category string `json:"category"` + Name string `json:"name"` + Timestamp int64 `json:"timestamp"` + Extra map[string]string `json:"extra"` +} + +type logEnvelope struct { + Timestamp string + Logger string + Type string + Fields ping +} + +func (g GleanEventsLogger) createClientInfo() clientInfo { + // Fields with default values are required in the Glean schema, but not used in server context + return clientInfo{ + TelemetrySDKBuild: "glean_parser v{{ parser_version }}", + FirstRunDate: "Unknown", + OS: "Unknown", + OSVersion: "Unknown", + Architecture: "Unknown", + AppBuild: "Unknown", + AppDisplayVersion: g.AppDisplayVersion, + AppChannel: g.AppChannel, + } +} + +func createPingInfo() pingInfo { + {# times are ISO-8601 strings, e.g. "2023-12-19T22:09:17.440Z" #} + var now = time.Now().UTC().Format("2006-01-02T15:04:05.000Z") + return pingInfo{ + Seq: 0, + StartTime: now, + EndTime: now, + } +} + +func (g GleanEventsLogger) createPing(documentType string, config RequestInfo, payload pingPayload) ping { + var payloadJson, payloadErr = json.Marshal(payload) + if payloadErr != nil { + panic("Unable to marshal payload to json") + } + var documentId = uuid.New() + return ping{ + DocumentNamespace: g.AppID, + DocumentType: documentType, + DocumentVersion: "1", + DocumentID: documentId.String(), + UserAgent: config.UserAgent, + IpAddress: config.IpAddress, + Payload: string(payloadJson), + } +} + +// method called by each event method. +// construct the ping, wrap it in the envelope, and print to stdout +func (g GleanEventsLogger) record( + documentType string, + requestInfo RequestInfo, + metrics metrics, + events []gleanEvent, +) { + var telemetryPayload = pingPayload{ + ClientInfo: g.createClientInfo(), + PingInfo: createPingInfo(), + Metrics: metrics, + Events: events, + } + + var ping = g.createPing(documentType, requestInfo, telemetryPayload) + + var envelope = logEnvelope{ + Timestamp: strconv.FormatInt(time.Now().UnixNano(), 10), + Logger: "glean", + Type: gleanEventMozlogType, + Fields: ping, + } + var envelopeJson, envelopeErr = json.Marshal(envelope) + if envelopeErr != nil { + panic("Unable to marshal log envelope to json") + } + fmt.Println(string(envelopeJson)) +} + +{% for event in events_ping["event"] %} +type {{ event|event_type_name }} struct { + {% for metric_type, metrics in events_ping.items() %} + {% if metric_type != 'event' %} + {% for metric in metrics %} + {{ metric|metric_argument_name }} {{ metric.type|go_metric_type }} // {{ metric.description|clean_string }} + {% endfor %} + {% endif %} + {% endfor %} + {% for extra, metadata in event.extra_keys.items() %} + {{ extra|event_extra_name }} {{ metadata.type|go_metric_type }} // {{ metadata.description|clean_string }} + {% endfor %} +} + +// Record and submit an {{ event|event_type_name }} event. +// {{ event.description|clean_string }} +func (g GleanEventsLogger) Record{{ event|event_type_name }}( + requestInfo RequestInfo, + params {{ event|event_type_name }}, +) { + var metrics = metrics{ + {% for metric_type, metrics in events_ping.items() %} + {% if metric_type != 'event' %} + "{{ metric_type }}": { + {% for metric in metrics %} + "{{ metric|metric_name }}": params.{{ metric|metric_argument_name }}, + {% endfor %} + }, + {% endif %} + {% endfor %} + } + var extraKeys = map[string]string{ + {% for extra, metadata in event.extra_keys.items() %} + {# convert all extra fields to string for submission #} + {% if metadata.type == 'boolean' %} + "{{ extra }}": fmt.Sprintf("%t", params.{{ extra|event_extra_name }}), + {% elif metadata.type == 'quantity' %} + "{{ extra }}": fmt.Sprintf("%d", params.{{ extra|event_extra_name }}), + {% else %} + "{{ extra }}": params.{{ extra|event_extra_name }}, + {% endif %} + {% endfor %} + } + var events = []gleanEvent{ + gleanEvent{ + Category: "{{ event.category }}", + Name: "{{ event.name }}", + Timestamp: time.Now().UnixMilli(), + Extra: extraKeys, + }, + } + g.record("events", requestInfo, metrics, events) +} + +// Record and submit an {{ event|event_type_name }} event omitting user request info +// {{ event.description|clean_string }} +func (g GleanEventsLogger) Record{{ event|event_type_name }}WithoutUserInfo( + params {{ event|event_type_name }}, +) { + g.Record{{ event|event_type_name }}(defaultRequestInfo, params) +} + +{% endfor %} |