mz_sql/session/hint.rs
1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use internal::Private;
11
12/// Prometheus label for [`ApplicationNameHint::Unspecified`].
13const UNSPECIFIED_LABEL: &str = "unspecified";
14/// Prometheus label for [`ApplicationNameHint::Unrecognized`].
15const UNRECOGNIZED_LABEL: &str = "unrecognized";
16/// Prometheus label for [`ApplicationNameHint::Psql`].
17const PSQL_LABEL: &str = "psql";
18/// Prometheus label for [`ApplicationNameHint::Dbt`].
19const DBT_LABEL: &str = "dbt";
20/// Prometheus label for [`ApplicationNameHint::WebConsole`].
21const WEB_CONSOLE_LABEL: &str = "web_console";
22/// Promehteus label for [`ApplicationNameHint::WebConsoleShell`].
23const WEB_CONSOLE_SHELL_LABEL: &str = "web_console_shell";
24/// Prometheus label for [`ApplicationNameHint::MzPsql`].
25const MZ_PSQL_LABEL: &str = "mz_psql";
26/// Prometheus label for [`ApplicationNameHint::MaterializeFivetranDestination`].
27const MATERIALIZE_FIVETRAN_DESTINATION_LABEL: &str = "materialize_fivetran_destination";
28/// Prometheus label for [`ApplicationNameHint::TerraformProviderMaterialize`].
29const TERRAFORM_PROVIDER_MATERIALIZE_LABEL: &str = "terraform_provider_materialize";
30/// Prometheus label for [`ApplicationNameHint::TablePlus`].
31const TABLE_PLUS_LABEL: &str = "table_plus";
32/// Prometheus label for [`ApplicationNameHint::DataGrip`].
33const DATA_GRIP_LABEL: &str = "data_grip";
34/// Prometheus label for [`ApplicationNameHint::DBeaver`].
35const D_BEAVER_LABEL: &str = "dbeaver";
36/// Prometheus label for [`ApplicationNameHint::MzVscode`].
37const MZ_VSCODE_LABEL: &str = "mz_vscode";
38/// Prometheus label for [`ApplicationNameHint::MzGrafanaIntegration`].
39const MZ_GRAFANA_LABEL: &str = "mz_grafana";
40
41/// A hint for what application is making a request to the adapter.
42///
43/// Note: [`ApplicationNameHint`] gets logged as a label in our Prometheus metrics, and for
44/// labels we need to be conscious of the cardinality, so please be careful with how many
45/// variants we add to this enum.
46///
47/// Note: each enum variant contains an `internal::Private` to prevent creating this enum
48/// directly. To create an instance of [`ApplicationNameHint`] please see
49/// [`ApplicationNameHint::from_str`].
50#[derive(Debug, Copy, Clone)]
51pub enum ApplicationNameHint {
52 /// No `application_name` was set.
53 Unspecified(Private),
54 /// An `application_name` was set, but it's not one we recognize.
55 Unrecognized(Private),
56 /// Request came from `psql`.
57 Psql(Private),
58 /// Request came from `dbt`.
59 Dbt(Private),
60 /// Request came from our web console.
61 WebConsole(Private),
62 /// Request came from the SQL shell in our web console.
63 WebConsoleShell(Private),
64 /// Request came from the `psql` shell spawned by `mz`.
65 MzPsql(Private),
66 /// Request came from our Fivetran Destination,
67 MaterializeFivetranDestination(Private),
68 /// Request came from a version of our Terraform provider.
69 TerraformProviderMaterialize(Private),
70 /// Request came from TablePlus.
71 TablePlus(Private),
72 /// Request came from a version of DataGrip.
73 DataGrip(Private),
74 /// Request came from a version of DBeaver.
75 DBeaver(Private),
76 /// Request came from our Visual Studio Code integration.
77 MzVscode(Private),
78 /// Request came from our Grafana integration.
79 MzGrafanaIntegration(Private),
80}
81
82impl ApplicationNameHint {
83 pub fn from_str(s: &str) -> Self {
84 match s.to_lowercase().as_str() {
85 "psql" => ApplicationNameHint::Psql(Private),
86 "dbt" => ApplicationNameHint::Dbt(Private),
87 "web_console" => ApplicationNameHint::WebConsole(Private),
88 "web_console_shell" => ApplicationNameHint::WebConsoleShell(Private),
89 "mz_psql" => ApplicationNameHint::MzPsql(Private),
90 // Note: Make sure this is kept in sync with the `fivetran-destination` crate.
91 "materialize_fivetran_destination" => {
92 ApplicationNameHint::MaterializeFivetranDestination(Private)
93 }
94 "tableplus" => ApplicationNameHint::TablePlus(Private),
95 "mz_vscode" => ApplicationNameHint::MzVscode(Private),
96 "mz_grafana_integration" => ApplicationNameHint::MzGrafanaIntegration(Private),
97 // Terraform provides the version as a suffix.
98 x if x.starts_with("terraform-provider-materialize") => {
99 ApplicationNameHint::TerraformProviderMaterialize(Private)
100 }
101 // DataGrip provides the version as a suffix.
102 x if x.starts_with("datagrip") => ApplicationNameHint::DataGrip(Private),
103 // DBeaver provides the version as a suffix.
104 x if x.starts_with("dbeaver") => ApplicationNameHint::DBeaver(Private),
105 "" => ApplicationNameHint::Unspecified(Private),
106 // TODO(parkertimmerman): We should keep some record of these "unrecognized"
107 // names, and possibly support more popular ones in the future.
108 _ => ApplicationNameHint::Unrecognized(Private),
109 }
110 }
111
112 pub fn as_str(&self) -> &'static str {
113 match self {
114 ApplicationNameHint::Unspecified(_) => UNSPECIFIED_LABEL,
115 ApplicationNameHint::Unrecognized(_) => UNRECOGNIZED_LABEL,
116 ApplicationNameHint::Psql(_) => PSQL_LABEL,
117 ApplicationNameHint::Dbt(_) => DBT_LABEL,
118 ApplicationNameHint::WebConsole(_) => WEB_CONSOLE_LABEL,
119 ApplicationNameHint::WebConsoleShell(_) => WEB_CONSOLE_SHELL_LABEL,
120 ApplicationNameHint::MzPsql(_) => MZ_PSQL_LABEL,
121 ApplicationNameHint::MaterializeFivetranDestination(_) => {
122 MATERIALIZE_FIVETRAN_DESTINATION_LABEL
123 }
124 ApplicationNameHint::TablePlus(_) => TABLE_PLUS_LABEL,
125 ApplicationNameHint::MzVscode(_) => MZ_VSCODE_LABEL,
126 ApplicationNameHint::MzGrafanaIntegration(_) => MZ_GRAFANA_LABEL,
127 ApplicationNameHint::TerraformProviderMaterialize(_) => {
128 TERRAFORM_PROVIDER_MATERIALIZE_LABEL
129 }
130 ApplicationNameHint::DataGrip(_) => DATA_GRIP_LABEL,
131 ApplicationNameHint::DBeaver(_) => D_BEAVER_LABEL,
132 }
133 }
134
135 /// Returns whether or not we should trace errors for this requests with this application name.
136 pub fn should_trace_errors(&self) -> bool {
137 // Note(parkmycar): For now we only trace errors for the web console since we contol all of
138 // those queries and in general they should never fail. As opposed to user queries which
139 // are arbitrary.
140 matches!(self, ApplicationNameHint::WebConsole(_))
141 }
142}
143
144mod internal {
145 #[derive(Debug, Copy, Clone)]
146 pub struct Private;
147}