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}